- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
Монады как коллбеки
На джаваскриптовой конференции, о которой я писал в прошлом посте, в процессе обсуждения
ФП неизбежно встала тема монад.
Мне было интересно, насколько легко можно объяснить монады «на пальцах». Возможно, не в
той степени, чтобы человек смог сразу с ними программировать, но в той степени, чтобы понимать,
что они делают и зачем нужны.
И у меня возникла идея объяснить монады без типов. Мне кажется, главную сложность при изучении
монад вызывают именно типы (а точнее, конструкторы типов и классы конструкторов типов), т.к. многие
приходят в Haskell из языков с менее выразительной системой типов.
В то же время, монады могут существовать и в динамических языках. А если из монад убрать типы,
то останется лишь то, как они работают во время исполнения — и там все довольно прозрачно.
Вычислительная сущность монад — это continuation passing style, или коллбеки. Любая программа
на node.js написана в этом стиле.
Левый аргумент >>= — вычисление, а правый — коллбек. Коллбек принимает результат вычисления
и совершает какие-то дальнейшие вычисления
Эта аналогия особенно точно выполняется для монад Identity, IO, Maybe/Either. Каждая отдельная
монада определяет, к чему конкретно будет применен коллбек.
Но посмотрим, например, на монаду [] (список). Если руководствоваться только лишь представлением
о монаде как о вызове коллбеков, то самый простой способ определить списочную монаду — это a >>= k = map k a (что неверно).
Аналогия с коллбеками слишком «императивна» и не улавливает тонкость — структуру самой монады.
Чтобы эту структуру наглядно показать, как раз и нужны типы.