与 foldl
这就是左侧折叠的实现方式。注意与 foldr(右侧折叠)相比,step 函数中参数的顺序是如何翻转的:
foldl :: (b -> a -> b) -> b -> [a] -> b
foldl f acc [] = acc
foldl f acc (x:xs) = foldl f (f acc x) xs -- = foldl f (acc `f` x) xs
左侧折叠 foldl 与左侧相关联。那是:
foldl (+) 0 [1, 2, 3] -- is equivalent to ((0 + 1) + 2) + 3
原因是 foldl 被评估为这样(看看 foldl 的归纳步骤):
foldl (+) 0 [1, 2, 3] -- foldl (+) 0 [ 1, 2, 3 ]
foldl (+) ((+) 0 1) [2, 3] -- foldl (+) (0 + 1) [ 2, 3 ]
foldl (+) ((+) ((+) 0 1) 2) [3] -- foldl (+) ((0 + 1) + 2) [ 3 ]
foldl (+) ((+) ((+) ((+) 0 1) 2) 3) [] -- foldl (+) (((0 + 1) + 2) + 3) []
((+) ((+) ((+) 0 1) 2) 3) -- (((0 + 1) + 2) + 3)
最后一行相当于 ((0 + 1) + 2) + 3。这是因为 (f a b) 一般与(a `f` b)相同,所以 ((+) 0 1) 特别与 (0 + 1) 相同。