Haskell foldr类型签名与foldl类型签名不同,有什么原因吗?

Haskell foldr类型签名与foldl类型签名不同,有什么原因吗?,haskell,fold,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 f

与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]
前奏曲>文件夹(:)[[1..5]
:4:7:错误:
前奏曲>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))

参数的“翻转”实际上是合乎逻辑的:你可以将其视为折叠发生方式的“提示”。此外,如果你意外使用了错误的版本,你会得到一个错误。在我看来没有什么不同:
myfoldl(+)z[a,b,c]=(c+(b+(a+z))
@aryndin这不是本文中列出的任何一件事。它看起来可能是这样的,因为
(+)
是可交换的,但大多数操作都不是。不过,你需要记住颠倒列表,这只是一点知识,但仍然比现状多一点。
foldl (+) z [a, b, c] = (((z + a) + b) + c)
foldr (+) z [a, b, c] = a + (b + (c + z))