【问题标题】:Weak head normal form and order of evaluation弱头范式和求值顺序
【发布时间】: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


    【解决方案1】:
    • seq 的第一个参数不能保证在第二个参数之前被评估
      保证,但编译器会尝试并且通常会这样做,如果它可以防止 thunk 累积。不能很好地工作的场景是并行性,因此需要 pseq - 但对于 foldl' 这无关紧要。
    • seq 的第一个参数只会被计算为弱头范式
      是的,但是对于内置数字类型 WHNF = NF。
    • seq 的第一个参数的评估只会在第二个参数评估为 WHNF 时发生
      确实,这通常会导致混淆。但是in a' `seq` foldl' f a' xs 的意思是,如果您请求任何结果,它将触发seq
      当我们减少一个步时,不应该是这样的吧? ...seq 的第二个参数 不在 WHNF 中
      这正是强制seq 的原因,因为要评估foldl' (+) 0 (1:xs) 的结果,您需要foldl' (+) a' xs 成为WHNF,而seq 确保这不会在a' 成为WHNF 之前发生。李>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-20
      • 2011-10-15
      • 1970-01-01
      • 2015-09-03
      • 1970-01-01
      • 1970-01-01
      • 2015-04-25
      • 1970-01-01
      相关资源
      最近更新 更多