与 foldr 相比,foldl 的定义方式让我有点困惑。 foldr 与 foldl 的不同之处不仅在于结合性,还在于折叠函数的参数顺序:

foldr :: (a -> b -> b) -> b -> [a] -> b
foldl :: (b -> a -> b) -> b -> [a] -> b

我看不出为什么 foldl 不能这样定义的任何原因:
foldl :: (a -> b -> b) -> b -> [a] -> b
foldl f acc [] = acc
foldl f acc (x:xs) = foldl f (f x acc) xs

因此 foldl 可以应用于非交换折叠函数以及
文件夹:
Prelude> foldr (:) [] [1..5]
[1,2,3,4,5]
Prelude> foldl (:) [] [1..5]
<interactive>:4:7: error:
<...>
Prelude> myfoldl (:) [] [1..5]
[5,4,3,2,1]

使用标准 foldl 定义,我们需要使用 flip 来获得与 foldr 相同的行为

最佳答案

您可以通过该顺序获得以下很好的等式属性:

foldl (+) z [a, b, c] = (((z + a) + b) + c)
foldr (+) z [a, b, c] = a + (b + (c + z))

关于haskell - foldr 类型签名与 foldl one 不同有什么原因吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52613180/

10-10 22:21