Внимание: перед тем как читать текст ниже, вы уже должны иметь представление о том, что такое монады. Если это не так, то прежде прочитайте вот этот пост!
Перед нами функция half
:

И мы можем применить её несколько раз:
half . half $ 8
=> 2
Всё работает как и ожидалось. Но вот вы решили, что хорошо бы иметь лог того, что происходит с этой функцией:

half x = (x `div` 2, "Я только что располовинил " ++ (show x) ++ "!")
Что ж, отлично. Но что будет если вы теперь захотите применить half
несколько раз?
half . half $ 8
Вот то, что мы хотели бы, чтобы происходило:

Спойлер: автоматически так не сделается. Придётся всё расписывать ручками:
finalValue = (val2, log1 ++ log2)
where (val1, log1) = half 8
(val2, log2) = half val1
Фу! Это ни капли не похоже на лаконичное
half . half $ 8
А что, если у вас есть ещё функции, имеющие лог? Напрашивается такая схема: для каждой функции, возвращающей вместе со значением лог, мы бы хотели объединять эти логи. Это побочный эффект, а никто не силён в побочных эффектах так, как монады!
Читать полностью »