我不明白为什么2个以下的情况有所不同?因为懒惰的评价?列表理解评估
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]]
我不明白为什么2个以下的情况有所不同?因为懒惰的评价?列表理解评估
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]]
它们是通过定义不同。展示这一点的最佳方式就是一个例子。列表理解试图找到所有可能的变量集合,可以从列表中选择而不违反条件。如果你有多个变量,它会返回它们的每个组合。例如:
[(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的方法。
因此你的第二个陈述当然必须得到第二个结果。
不,与懒惰评价无关。
考虑第三种情况:
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]]
另一种方式来看待它:
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],[]]
你的第一个理解绘制x
和xs
为“配对”,有点让他们“压缩”一起。
ghci> zipWith (:) l1 l2
[[1,2,3],[2,3],[3]]
你的第二个理解绘制的x
和xs
所有组合,将它们与(:)
结合。
ghci> (:) <$> l1 <*> l2
[[1,2,3],[1,3],[1],[2,2,3],[2,3],[2],[3,2,3],[3,3],[3]]
list source are different?案例1的来源是一个,案例2的来源是两个。 – runnerhigh 2011-03-05 13:08:28
@runnerhigh:你是什么意思? Haskell不关心列表是否相等。 – fuz 2011-03-05 13:35:09