简体   繁体   English

弱头正常形式和评估顺序

[英]Weak head normal form and order of evaluation

I've read lots on weak head normal form and seq. 我读过很多关于弱头正常形式和seq的书。 But I'm still have trouble imagining the logic behind Haskell's order of evaluation 但是我仍然无法想象Haskell评估顺序背后的逻辑

A common example demonstrating when and how to use but I still don't understand how the common example 一个常见的例子说明何时以及如何使用,但我仍然不明白常见的例子

foldl (+) 0 [1..5000000]

can result in a stack overflow. 可能导致堆栈溢出。 While another fold definition using seq doesn't 而使用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]

From explanations of seq that I've read, authors are very careful to make the following clear: 从我读过的seq的解释,作者非常谨慎地做出如下清楚:

  • The first argument of seq is not guaranteed to be evaluated before the second argument seq的第一个参数不保证在第二个参数之前进行求值
  • The first argument of seq will only be evaluated to weak head normal form seq的第一个参数只会被评估为弱头正常形式
  • The evaluation of the first argument of seq will only happen when the second is evaluated to WHNF 只有当第二个参数被评估为WHNF时才会对seq的第一个参数进行评估

So, if the above is correct (is it?) then why does foldl' not overflow like foldl ? 那么,如果以上是正确的(是吗?)那么为什么foldl'不像foldl那样溢出?

When we reduce one step, shouldn't it looks like this, right? 当我们减少一步时,不应该看起来像这样,对吧?

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

In the above, the second argument of seq is not in WHNF since there is a function application which needs to be done. 在上面, seq的第二个参数不在WHNF中,因为有一个需要完成的函数应用程序。 Are we guaranteed to evaluate the first argument of seq here before we reach the WHNF of the second argument? 在我们达到第二个参数的WHNF之前,我们是否可以保证在这里评估seq的第一个参数?

  • The first argument of seq is not guaranteed to be evaluated before the second argument seq的第一个参数不保证在第二个参数之前进行求值
    Not guaranteed , but the compiler will try and usually do it if it prevents thunk buildup. 保证 ,但编译器会尝试通常这样做,如果它可以防止thunk建立。 The scenario where this doesn't work so well is parallelism, hence the need for pseq – but for foldl' that's not relevant. 这种方法效果不佳的情况是并行性,因此需要pseq - 但对于foldl'而言并不相关。
  • The first argument of seq will only be evaluated to weak head normal form seq的第一个参数只会被评估为弱头正常形式
    Yeah, but for built-in number types WHNF = NF. 是的,但对于内置数字类型WHNF = NF。
  • The evaluation of the first argument of seq will only happen when the second is evaluated to WHNF 只有当第二个参数被评估为WHNF时才会对seq的第一个参数进行评估
    Indeed, and that often causes confusion. 实际上,这往往会造成混乱。 But in a' `seq` foldl' fa' xs means, if you request any result at all it'll trigger the seq . 但是in a' `seq` foldl' fa' xs表示,如果你要求任何结果,它将触发seq
    When we reduce one step, shouldn't it looks like this, right? 当我们减少一步时,不应该看起来像这样,对吧? ... the second argument of seq is not in WHNF ... seq的第二个参数不在WHNF中
    Precisely that's what forces the seq , because to evaluate the result of foldl' (+) 0 (1:xs) you need foldl' (+) a' xs to be WHNF, and seq ensures this won't happen before a' is 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