Haskell 和惰性评估

Haskell and lazy evaluation

因为他的懒惰,可以Haskell计算下一个表达式吗?

    take 3 (reverse [1..])

如果是这样,你能解释一下怎么做吗? 提前致谢

答案是 - Haskell 将无法对此进行评估(在我的系统上,它会消耗大量内存并在某些时候崩溃;) )

原因是您无法反转无限列表。要看到这一点 - 假设 reverse 定义为:

reverse [] = []
reverse (x:xs) = reverse xs ++ [x]

你现在会评估

reverse [1..]
= reverse 1:[2..]
{ 2nd case }
= reverse [2..] ++ [1]
= reverse (2:[3..]) ++ [1]
{ 2nd case }
= reverse [3..] ++ [2] ++ [1]
= ...

所以你总是会看到另一个 reverse [n..] 随着 n 的增加,但从来没有 reverse []

因此评估永远不会结束 - 因此您永远无法判断第一个(或第二个或第三个)元素是什么


有趣的事实

Haskell评价没有问题

take 0 (reverse [1..])

虽然 - 这次懒惰 赢得了胜利 - 你能明白为什么吗?

不,那会 运行 永远,但是 可能 编写一个反向函数来生成列表的 脊柱 懒惰地,因此给出

reverse' [1..] = repeat undefined
               = undefined : undefined : undefined : ...

而不是实际实现给出的内容,

reverse [1..] = undefined

具体

-- Take two lists and return the second with its
-- length fixed (perhaps truncated) to that of the
-- first. Blows up (eventually) if the second list
-- is shorter.
withLengthOf :: [a] -> [b] -> [b]
withLengthOf [] _ = []
withLengthOf (_ : xs) ~(y : ys) =
   y : withLengthOf xs ys

reverse' :: [a] -> [a]
reverse' xs = withLengthOf xs (reverse xs)

这通常不是最有用的东西(因为列表的脊椎很无聊)而且效率有点低。这就是为什么真正的 reverse 不会打扰。