折叠器类型签名与折叠器类型签名有什么区别吗?

时间:2018-10-02 17:10:33

标签: haskell fold

与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]

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

1 个答案:

答案 0 :(得分:5)

您将获得以下具有良好顺序的方程式属性:

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