有人可以解释foldl
的工作原理吗?
我明白,例如,foldr (-) 0 [1,2,3]
产生(1 - (2 - (3 - 0))),而foldl (-) 0 [1,2,3]
产生(((0 - 1) - 2) - 3),但我还有一些问题:
第一个例子(带有foldr / foldl的列表的长度):
正如预期的那样foldr (\_ acc -> acc + 1) 0 [1,2,3,4,5]
产生5
foldl (\_ acc -> acc + 1) 0 [1,2,3,4,5]
产生6.:|
foldl (\_ acc -> acc + 1) 0 [2]
产生3.:|
foldl如何对这些给定的例子做出反应?
第二个例子:
foldr (:) [] [1,2,3,4]
生成[1,2,3,4] - 不用担心,但foldl (:) [] [1,2,3,4]
给了我一个错误:Occurs check: cannot construct the infinite type: a ~ [a]
foldl有什么问题?
答案 0 :(得分:4)
在foldr
中,累加器是你要折叠的函数的第二个参数,但在foldl
中,累加器是第一个参数。如果你仔细查看问题的介绍段落,你可以自己解决这个问题......
“第一个示例”代码具有误导性,因为acc
参数(其名称暗示它应该是累加器)始终是lambda的第二个参数,它应该是foldl
的第一个参数。它还令人困惑,因为样本列表元素的类型和值反映了累加器值的类型和值......正如评论所提到的,使用其他值会更好,最好还是使用其他类型!
对于“第二个示例”,您会收到类型错误,因为您的参数已被交换(并且您不能拥有其元素为其自身列表的列表)。要么手动交换参数顺序:
foldl (\xs x -> x:xs)
或者使用flip
,为此设计的库函数:
foldl (flip (:))
请注意,foldl
案例的结果应该是反向列表(不是复制列表),因为foldl
在与foldr
相反的方向上迭代。