foldl比其严格的堂兄,foldl'更受欢迎吗?

Joe*_*ams 22 haskell fold strictness

Haskell有两个左侧折叠函数用于列表:foldl和"严格"版本foldl'.非严格的问题foldl是它构建了一个thunk的塔:

    foldl (+) 0 [1..5]
--> ((((0 + 1) + 2) + 3) + 4) + 5
--> 15
Run Code Online (Sandbox Code Playgroud)

这会浪费内存,如果列表中的项目太多,可能会导致堆栈溢出. foldl'另一方面,强制累加器在每个项目上.

但是,就我所知,foldl'语义上等同foldl.评估foldl (+) 0 [1..5]头部正常形式需要在某个时刻强制累加器.如果我们不需要头部正常形式,我们就不会foldl (+) 0 [1..5]开始评估.

有没有令人信服的理由,人们会想要foldl超过那个的行为foldl'

ham*_*mar 25

foldl并且foldl'在语义上不等同.琐碎的反例:

Prelude Data.List> foldl (\x y -> y) 0 [undefined, 1]
1
Prelude Data.List> foldl' (\x y -> y) 0 [undefined, 1]
*** Exception: Prelude.undefined
Run Code Online (Sandbox Code Playgroud)

然而,在实践中,foldl'由于您提到的原因,您通常需要严格.


Dan*_*her 13

foldl并且foldl'不会产生相同的结果时,如在hammar的例子中,必须根据期望的结果做出决定.除此之外,你要使用foldl而不是foldl'折叠函数是构造函数(应用构造函数在WHNF中创建一个值,没有必要再次强制它到WHNF),并foldl (.) id functions强迫WHNF也没有获得任何东西.除了这些特殊情况,foldl'是选择的方法.

  • @DanBurton,信息流的顺序可能与按值语言调用的顺序相反.`f(gx)`只会在你的脑海中执行`g`".事实上,它是第一次有机会产生信息的`f`.考虑`fx = 1:x`; `gx = gx`. (8认同)