繁体   English   中英

弱头正常形式和评估顺序

[英]Weak head normal form and order of evaluation

我读过很多关于弱头正常形式和seq的书。 但是我仍然无法想象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的第一个参数只会被评估为弱头正常形式
  • 只有当第二个参数被评估为WHNF时才会对seq的第一个参数进行评估

那么,如果以上是正确的(是吗?)那么为什么foldl'不像foldl那样溢出?

当我们减少一步时,不应该看起来像这样,对吧?

foldl' (+) 0 (1:xs) = let a' = (+) 0 1 in a' `seq` foldl' (+) a' xs

在上面, seq的第二个参数不在WHNF中,因为有一个需要完成的函数应用程序。 在我们达到第二个参数的WHNF之前,我们是否可以保证在这里评估seq的第一个参数?

  • seq的第一个参数不保证在第二个参数之前进行求值
    保证 ,但编译器会尝试通常这样做,如果它可以防止thunk建立。 这种方法效果不佳的情况是并行性,因此需要pseq - 但对于foldl'而言并不相关。
  • seq的第一个参数只会被评估为弱头正常形式
    是的,但对于内置数字类型WHNF = NF。
  • 只有当第二个参数被评估为WHNF时才会对seq的第一个参数进行评估
    实际上,这往往会造成混乱。 但是in a' `seq` foldl' fa' xs表示,如果你要求任何结果,它将触发seq
    当我们减少一步时,不应该看起来像这样,对吧? ... seq的第二个参数不在WHNF中
    确切地说,这是迫使seq原因,因为要评估foldl' (+) 0 (1:xs)你需要foldl' (+) a' xs a'xs为WHNF,而seq确保在a'之前不会发生这种情况WHNF。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM