理解Haskell中的折叠

Jac*_*ley 2 haskell functional-programming binary-operators fold associativity

据我了解有关Haskell的褶皱,foldl (-) 0 [1..5]给出的结果是-15通过计算0-1-2-3-4-5,并foldr (-) 0 [1..5]给出了结果-5的计算5-4-3-2-1-0.为什么那么这两个foldl (++) "" ["a", "b", "c"]foldr (++) "" ["a", "b", "c"]给出的结果"abc",而结果foldr是不,相反,"cba"

有什么我缺少理解之间的差异foldlfoldr

Car*_*ate 12

我认为文档中的这一部分更清楚:


对于列表,foldr,当应用于二元运算符时,起始值(通常是运算符的右侧标识)和列表使用二元运算符从右到左减少列表:

foldr f z [x1, x2, ..., xn] == x1 `f` (x2 `f` ... (xn `f` z)...)
Run Code Online (Sandbox Code Playgroud)

...

对于列表,foldl,当应用于二元运算符时,起始值(通常是运算符的左侧标识)和列表,使用二元运算符从左到右减少列表:

foldl f z [x1, x2, ..., xn] == (...((z `f` x1) `f` x2) `f`...) `f` xn
Run Code Online (Sandbox Code Playgroud)

如果查看示例细分,则串联foldr等效于:

"a" ++ ("b" ++ ("c" ++ ""))
Run Code Online (Sandbox Code Playgroud)

而且foldl,它等同于:

(("" ++ "a") ++ "b") ++ "c"
Run Code Online (Sandbox Code Playgroud)

对于字符串连接,这些是相同的.


但是对于减法,

1 - (2 - (3 - 0))
Run Code Online (Sandbox Code Playgroud)

给出与以下不同的结果:

((0 - 1) - 2) - 3
Run Code Online (Sandbox Code Playgroud)


Igo*_*dov 7

实际上是foldr (-) 0 [1..5]等于3,因为它是:

(1 - (2 - (3 - (4 - (5 - 0))))
Run Code Online (Sandbox Code Playgroud)

这个问题的答案是foldr功能类型:

foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
Run Code Online (Sandbox Code Playgroud)

正如我们所见,(a -> b -> b)函数迭代元素作为第一个参数,累加器作为第二个参数.这就是为什么foldr (++) "" ["a", "b", "c"]我们有:

("a" ++ ("b" ++ ("c" ++ "")))
Run Code Online (Sandbox Code Playgroud)