52700.fb2
data Writer msg b = Writer (b, msg)
runWriter :: Writer msg b -> (b, msg)
runWriter (Writer a) = a
Тип функции примет вид:
a -> Writer msg b
Значения типа msg мы будем называть сообщениями. Смысл функций a -> Writer msg b заключается
в том, что при вычислении они накапливают в значении msg какую-нибудь информацию. Это могут быть
отладочные сообщения. Или база данных, которая открыта для всех функций на запись.
Класс Monoid
Как мы будем накапливать результат? Пока мы умеем лишь возвращать из функции пару значений. Одно
из них нам нужно передать в следующую функцию, а что делать с другим?
На помощь нам придёт класс Monoid, он определён в модуле Data.Monoid:
class Monoid a where
mempty
:: a
mappend :: a -> a -> a
В этом классе определено пустое значение mempty и бинарная функция соединения двух значений в одно.
Этот класс очень похож на класс Category и Kleisli. Там тоже было значение, которое ничего не делает и
операция составления нового значения из двух простейших значений. Даже свойства класса похожи:
mempty
‘mappend‘ f
= f
f
‘mappend‘ mempty
= f
f ‘mappend‘ (g ‘mappend‘ h) =
(f ‘mappend‘ g) ‘mappend‘ h
a
g
f
b
b
c
msg
msg
b
a
g
f
c
MsgG
++
MsgF ++ MsgG
MsgF
a
f*>g
c
msg
Рис. 6.11: Композиция функций-накопителей