【问题标题】:Empty list generators空列表生成器
【发布时间】:2016-12-12 02:00:29
【问题描述】:

Haskell 如何处理列表生成器?具体来说,为什么会这样

f n = [x:xs | x <- [1..n], xs <- []]

产生空列表?每次“迭代”中的x:xs 中的xs 是什么?

【问题讨论】:

  • 对于“每个‘迭代’中的x:xs 中的xs 是什么?”没有答案。因为没有x:xs 的“迭代”。冥想这个表达:[undefined | _ &lt;- []] == [].
  • @duplode 给出了一个很好的答案,说明它为什么不起作用。但我假设,您想创建列表列表,每个列表都包含一个元素;你可以用f n = [x:xs | x &lt;- [1..n], xs &lt;- [[]] ]
  • 这会创建单元素列表,但你为什么要这样做呢?只需f n = [[x] | x &lt;- [1..n]]f n = map pure [1..n]

标签: haskell


【解决方案1】:

缩小的答案是……

[x:xs | x <- [1..n], xs <- []]

... 包含通过从 [1..n] 中选择一个元素 (x) 以及从 [] 中选择一个元素 (xs) 并将一个附加到另一个生成的所有可能列表。由于[]中没有元素,所以这种方式可以生成的列表数量为零。

放大后的答案是list comprehensions are sugar for the list monad,所以这个...

[x:xs | x <- [1..n], xs <- []]

...等价于...

do
    x <- [1..n]
    xs <- []
    return (x:xs)

...也就是说(在去除do-notation之后)...

[1..n] >>= \x ->
[] >>= \xs ->
return (x:xs)

-- Or, without the line breaks:
[1..n] >>= \x -> [] >>= \xs -> return (x:xs)

...即(在将 (&gt;&gt;=)return 的定义替换为 list monad 之后):

concatMap (\x -> concatMap (\xs -> [x:xs]) []) [1..n]

concatMap(顾名思义,只是map,后跟concat)在一个空列表上给出一个空列表,所以它变成...

concatMap (\x -> []) [1..n]

...这相当于将[1..n] 的每个元素替换为一个空列表,然后concat-ing 结果,生成一个空列表。

【讨论】:

    猜你喜欢
    • 2020-08-07
    • 2017-03-07
    • 1970-01-01
    • 2013-08-12
    • 2020-12-15
    • 2015-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多