【发布时间】:2014-04-26 15:59:58
【问题描述】:
我已经阅读了很多关于弱头正常形式和序列的内容。但是我仍然无法想象 Haskell 评估顺序背后的逻辑
一个演示何时以及如何使用的常见示例,但我仍然不明白常见示例是如何使用的
foldl (+) 0 [1..5000000]
可能导致堆栈溢出。而另一个使用 seq 的折叠定义没有
foldl' _ a [] = a
foldl' f a (x:xs) = let a' = f a x in a' `seq` foldl' f a' xs
foldl' (+) 0 [0..5000000]
从我读过的对 seq 的解释来看,作者非常小心地说明了以下几点:
-
seq的第一个参数不能保证在第二个参数之前被计算 -
seq的第一个参数只会被评估为弱头范式 -
seq的第一个参数的评估只会在第二个评估为 WHNF 时发生
那么,如果以上是正确的(是吗?)那么为什么foldl' 不会像foldl 那样溢出?
当我们减少一个步时,不应该是这样的吧?
foldl' (+) 0 (1:xs) = let a' = (+) 0 1 in a' `seq` foldl' (+) a' xs
在上面,seq 的第二个参数不在 WHNF 中,因为需要完成一个函数应用程序。在到达第二个参数的 WHNF 之前,我们是否保证在这里评估 seq 的第一个参数?
【问题讨论】:
标签: haskell stack-overflow lazy-evaluation strictness weak-head-normal-form