【问题标题】:Is foldl ever preferable to its strict cousin, foldl'?foldl 是否比它严格的表亲 foldl' 更可取?
【发布时间】:2012-01-04 08:49:33
【问题描述】:

Haskell 有两个用于列表的左折叠函数:foldl,和一个“严格”版本,foldl'。非严格 foldl 的问题在于它构建了一个 thunk 塔:

    foldl (+) 0 [1..5]
--> ((((0 + 1) + 2) + 3) + 4) + 5
--> 15

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

不过,据我所知,foldl'foldl 在语义上是等效的。将foldl (+) 0 [1..5] 评估为头部正常形式需要在某个时候强制累加器。如果我们不需要 head-normal 形式,我们就不会一开始就评估 foldl (+) 0 [1..5]

是否有任何令人信服的理由希望foldl 的行为优于foldl' 的行为?

【问题讨论】:

    标签: haskell fold strictness


    【解决方案1】:

    foldlfoldl' 在语义上不等价。微不足道的反例:

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

    但实际上,由于您提到的原因,您通常需要严格的 foldl'

    【讨论】:

      【解决方案2】:

      foldlfoldl' 不会产生相同的结果时,如在hammar 的示例中,必须根据期望的结果做出决定。除此之外,如果折叠函数是构造函数(应用构造函数在 WHNF 中创建一个值,再次将其强制为 WHNF 没有意义),您将使用 foldl 而不是 foldl',并且在 foldl (.) id functions 中强制 WHNF 也没有任何好处。除了这些例外情况,foldl' 是首选方法。

      【讨论】:

      • 我认为没有理由使用foldl (.) id functions 而非foldr (.) id functions。它们在语义上是等价的,当前者不是_|_ 时,所以只有后者允许延迟使用函数。我弄错了吗?
      • @luqui:我认为恰恰相反。 foldr 版本看起来像:(\x acc -> x . acc),这实质上意味着:首先执行 rightmost 功能,从而禁止懒惰消费。我弄错了吗? :)
      • @DanBurton 如果函数可以在不知道它们的参数的情况下开始产生输出,foldr 允许懒惰消费(考虑foldr (.) id [(string++) | string <- strings]。@luqui 现在你提到它,我不知道为什么要@ 987654334@ (.) id 函数。
      • @DanBurton,信息流的顺序可能与按值调用语言中的顺序相反。 f (g x) 只在你的脑海中执行g“第一”。事实上,f 最先有机会产生信息。考虑f x = 1:xg x = g x.
      • @luqui:是的,这很有道理。玩这个想法让我问a new question
      猜你喜欢
      • 2012-11-12
      • 2020-11-26
      • 1970-01-01
      • 2010-09-27
      • 2021-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多