我发现将折叠操作视为对一系列操作的概括是有帮助的
a + b + c + d + e
fold_right (+) 0
适用于+
右结合运算,使用0
作为基本情况:
(a + (b + (c + (d + (e + 0)))))
fold_left 0 (+)
以左关联方式应用它:
(((((0 + a) + b) + c) + d) + e)
现在考虑如果替换会发生什么+
with ::
and 0
with []
右折和左折。
思考一下方法也可能很有用fold_left
and fold_right
充当“替代”::
and []
列表中的运算符。例如,列表[1,2,3,4,5]
实际上只是简写1::(2::(3::(4::(5::[]))))
。考虑一下可能会有用fold_right op base
就像让你“替换”一样::
with op
and []
with base
: 例如
fold_right (+) 0 1::(2::(3::(4::(5::[]))))
becomes
1 + (2 + (3 + (4 + (5 + 0))))
::
became +
, []
became 0
。从这个角度来看,很容易看出fold_right (::) []
只是给你回原来的清单。fold_left base op
做了一些有点奇怪的事情:它重写了列表周围的所有括号以向另一个方向移动[]
从列表的后面到前面,并且then取代::
with op
and []
with base
。例如:
fold_left 0 (+) 1::(2::(3::(4::(5::[]))))
becomes
(((((0 + 1) + 2) + 3) + 4) + 5)
With +
and 0
, fold_left
and fold_right
产生相同的结果。但在其他情况下,情况并非如此:例如,如果而不是+
你用过-
结果会有所不同: 1 - (2 - (3 - (4 - (5 - 0)))) = 3,但是 (((((0 - 1) - 2) - 3) - 4) - 5) =-15。