Я считаю полезным рассматривать операции сгиба как обобщение того, что делать с последовательностью операций
a + b + c + d + e
fold_right (+) 0
применяет операцию +
вправо-ассоциативно, используя 0
в качестве базового варианта:
(a + (b + (c + (d + (e + 0)))))
fold_left 0 (+)
применяет его левоассоциативно:
(((((0 + a) + b) + c) + d) + e)
Теперь рассмотрим, что произойдет, если вы замените +
на ::
и 0
с []
в правом и левом сгибах.
Может быть также полезно подумать о том, как fold_left
и fold_right
работают как "замена" ::
и[]
операторов в списке.Например, список [1,2,3,4,5]
- это просто сокращение для 1::(2::(3::(4::(5::[]))))
.Может быть полезно думать о fold_right op base
как о том, что он позволяет "заменить" ::
на op
и []
на base
: например,
fold_right (+) 0 1::(2::(3::(4::(5::[]))))
становится
1 + (2 + (3 + (4 + (5 + 0))))
::
стало +
, []
стало 0
.С этой точки зрения легко увидеть, что fold_right (::) []
просто возвращает вам ваш первоначальный список.fold_left base op
делает что-то немного страннее: он переписывает все скобки вокруг списка, чтобы переместиться в другом направлении, перемещается []
из задней части списка вперед, а , а затем заменяет ::
наop
и []
с base
.Так, например:
fold_left 0 (+) 1::(2::(3::(4::(5::[]))))
становится
(((((0 + 1) + 2) + 3) + 4) + 5)
С +
и 0
, fold_left
и fold_right
дают одинаковый результат.Но в других случаях это не так: например, если вместо +
вы использовали -
, результаты будут другими: 1 - (2 - (3 - (4 - (5 - 0)))) = 3,но ((((((0 - 1) - 2) - 3) - 4) - 5) = -15.