列表理解评估

时间:2011-03-05 12:15:37

标签: haskell list-comprehension

我不明白为什么以下两种情况有所不同?因为懒惰的评价?

1)

Main> [x:xs | x:xs <- tails [1,2,3]]
=> [[1,2,3], [2,3], [3]]

2)

Main> [x:xs | x:xs' <- tails [1,2,3], x':xs <- tails [1,2,3]]
=> [[1,2,3],[1,3],[1], [2,2,3],[2,3],[2],[3,2,3],[3,3],[3]]

3 个答案:

答案 0 :(得分:2)

根据定义它们是不同的。展示这个的最好方法就是一个例子。列表推导尝试查找所有可能的变量集,可以从列表中选择而不违反条件。如果您有多个变量,则返回它们的每个组合。例如:

[(x,y) | x <- [1,2,3], y <- [1,2,3]]

的产率:

[(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)]

我们能看到什么?首先,选择第一列表的元素,而不是第二列表中的一个。结果是选择x和y的所有可能方式的列表

所以你的第二个陈述当然必须产生第二个结果。

答案 1 :(得分:1)

不,与懒惰评估无关。

考虑第三种情况:

Prelude Data.List> [x:xs | x:xs' <- tails [1,2,3], x':xs <- tails [1,2,3], x == x']
[[1,2,3],[2,3],[3]]

答案 2 :(得分:0)

另一种看待它的方式:

ghci> :m +Data.List
ghci> :m +Control.Applicative
ghci> let l1 = [x | x:xs <- tails [1,2,3]]
ghci> l1
[1,2,3]
ghci> let l2 = [xs | x:xs <- tails [1,2,3]]
ghci> l2
[[2,3],[3],[]]

您的第一次理解将xxs描绘为“对”,将它们“压缩”在一起。

ghci> zipWith (:) l1 l2
[[1,2,3],[2,3],[3]]

您的第二次理解会得出xxs的所有组合,并将它们与(:)合并。

ghci> (:) <$> l1 <*> l2
[[1,2,3],[1,3],[1],[2,2,3],[2,3],[2],[3,2,3],[3,3],[3]]