我不明白爲什麼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