Foldl 是否比它严格的表亲 Foldl' 更好?

发布于 2024-12-17 22:00:47 字数 559 浏览 1 评论 0原文

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

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

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

然而,据我所知,foldl'在语义上等同foldl。将 foldl (+) 0 [1..5] 评估为 head 范式需要在某个时刻强制累加器。如果我们不需要 head-normal 形式,我们就不会开始评估 foldl (+) 0 [1..5]

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

Haskell has two left fold functions for lists: foldl, and a "strict" version, foldl'. The problem with the non-strict foldl is that it builds a tower of thunks:

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

This wastes memory, and may cause a stack overflow if the list has too many items. foldl', on the other hand, forces the accumulator on every item.

However, as far as I can tell, foldl' is semantically equivalent to foldl. Evaluating foldl (+) 0 [1..5] to head normal form requires forcing the accumulator at some point. If we didn't need a head-normal form, we wouldn't be evaluating foldl (+) 0 [1..5] to begin with.

Is there any compelling reason one would want the behavior of foldl over that of foldl' ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冰之心 2024-12-24 22:00:47

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'

foldl and foldl' are not semantically equivalent. Trivial counterexample:

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

In practice, however, you usually want the strict foldl' for the reasons you mentioned.

心凉 2024-12-24 22:00:47

foldlfoldl' 不会产生相同的结果时(如 hammar 的示例所示),必须根据所需的结果做出决定。除此之外,如果折叠函数是构造函数(应用构造函数会在 WHNF 中创建一个值,则没有必要强制它),则可以使用 foldl 而不是 foldl'再次变为 WHNF),并且在 foldl (.) id 函数 中,强制 WHNF 也不会获得任何结果。除了这些特殊情况外,foldl' 是首选方法。

When foldl and foldl' wouldn't produce the same result, as in hammar's example, the decision has to be made according to the desired outcome. Apart from that, you'd use foldl rather than foldl' if the folded function is a constructor (applying a constructor creates a value in WHNF, there's no point in forcing it to WHNF again), and in foldl (.) id functions where forcing WHNF doesn't gain anything either. Apart from these exceptional cases, foldl' is the method of choice.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文