Haskell foldl比它严格的表亲foldl更可取吗;?

Haskell foldl比它严格的表亲foldl更可取吗;?,haskell,fold,strictness,Haskell,Fold,Strictness,Haskell有两个用于列表的左折叠函数:foldl,以及一个“严格”版本,foldl'。非严格的foldl的问题在于它构建了一个thunks塔: foldl (+) 0 [1..5] --> ((((0 + 1) + 2) + 3) + 4) + 5 --> 15 这会浪费内存,如果列表中的项太多,可能会导致堆栈溢出foldl'强制每个项目上的累加器 然而,据我所知,foldl'在语义上等同于foldl。计算foldl(+)0[1..5]到头部标准形式需要在某个点强制累加

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

    foldl (+) 0 [1..5]
--> ((((0 + 1) + 2) + 3) + 4) + 5
--> 15
这会浪费内存,如果列表中的项太多,可能会导致堆栈溢出<另一方面,code>foldl'强制每个项目上的累加器

然而,据我所知,
foldl'
在语义上等同于
foldl
。计算
foldl(+)0[1..5]
到头部标准形式需要在某个点强制累加器。如果我们不需要head范式,我们就不会首先计算
foldl(+)0[1..5]


是否有任何令人信服的理由认为
foldl
的行为比
foldl'
的行为更重要?

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

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

foldl
foldl'
不能产生相同的结果时,就像哈马尔的例子一样,必须根据期望的结果做出决定。除此之外,如果折叠函数是一个构造函数(应用构造函数在WHNF中创建一个值,没有必要再次将其强制到WHNF),那么在
foldl(.)id函数中使用
foldl而不是
foldl'
,强制WHNF也不会获得任何结果。除了这些例外情况外,
foldl'
是选择的方法。

我不认为有任何理由使用
foldl(.)id函数
而不是
foldr(.)id函数
。当前者不是
124;
时,它们在语义上是等价的,因此只有后者才允许延迟使用函数。“我错了吗?”卢基:我想恰恰相反。foldr版本看起来像:
(\x acc->x.acc)
,这本质上意味着:首先执行最右边的函数,从而禁止延迟消费。我弄错了吗?:)@DanBurton如果函数可以在不知道其参数的情况下开始生成输出,
foldr
允许延迟消费(考虑
foldr(.)id[(string++)| string@DanBurton,信息流的顺序可能与按值调用语言中的顺序相反。
f(gx)
只执行
g
“第一个”事实上,它是<代码> F < /代码>,它有第一个产生信息的机会。考虑<代码> f x=1:x< /代码>;<代码> g x= g x< /代码>。@卢奎:啊,是的,这是有意义的。玩这个想法已经让我问了。