таков:
>foldl :: (a –> b –> a) –> a –> [b] –> a
Тогда как функция >foldM
имеет такой тип:
>foldM :: (Monad m) => (a –> b –> m a) –> a –> [b] –> m a
Значение, которое возвращает бинарная функция, является монадическим, поэтому результат всей свёртки тоже является монадическим. Давайте сложим список чисел с использованием свёртки:
>ghci> foldl (\acc x –> acc + x) 0 [2,8,3,1]
>14
Исходный аккумулятор равен >0
, затем к аккумулятору прибавляется >2
, что даёт в результате новый аккумулятор со значением >2
. К этому аккумулятору прибавляется >8
, что даёт в результате аккумулятор равный >10
и т. д. Когда мы доходим до конца, результатом является окончательный аккумулятор.
А ну как мы захотели бы сложить список чисел, но с дополнительным условием: если какое-то число в списке больше >9
, всё должно окончиться неудачей? Имело бы смысл использовать бинарную функцию, которая проверяет, больше ли текущее число, чем >9
. Если больше, то функция оканчивается неудачей; если не больше – продолжает свой радостный путь. Из-за этой добавленной возможности неудачи давайте заставим нашу бинарную функцию возвращать аккумулятор >Maybe
вместо обычного.
Вот бинарная функция:
>binSmalls :: Int –> Int –> Maybe Int
>binSmalls acc x
> | x > 9 = Nothing
> | otherwise = Just (acc + x)
Поскольку наша бинарная функция теперь является монадической, мы не можем использовать её с обычной функцией >foldl
; следует использовать функцию >foldM
. Приступим:
>ghci> foldM binSmalls 0 [2,8,3,1]
>Just 14
>ghci> foldM binSmalls 0 [2,11,3,1]
>Nothing
Клёво! Поскольку одно число в списке было больше >9
, всё дало в результате значение >Nothing
. Свёртка с использованием бинарной функции, которая возвращает значение >Writer
, – тоже круто, потому что в таком случае вы журналируете что захотите по ходу работы вашей свёртки.