Просматривая главы учебника Haskell, посвященные различным монадам, я постоянно теряюсь, когда авторы переходят от объяснения деталей bind и законов монад к фактическому использованию монад. Внезапно всплывают такие выражения, как «запуск функции в монадическом контексте» или «запуск монады». Точно так же в документации к библиотеке и в дискуссиях о стеках преобразователей монад я читал утверждения, что некоторые функции «могут быть запущены в любой монаде». Что именно означает это «работа внутри монады»?
Есть две вещи, которые я, кажется, не понимаю прямо:
- Монада — это класс типов с функциями (
return
,>>=
) и законами. Таким образом, «запустить» что-то внутри монады может означать либо (а) предоставить это в качестве аргумента дляreturn
, либо (б) упорядочить его с помощью>>=
. Если монада имеет типm a
, то в случае а) это что-то должно быть типаa
, чтобы соответствовать типу функцииreturn
. В случае б) что-то должно быть функцией типаa -> m b
, чтобы соответствовать типу функции>>=
. Из этого я не понимаю, как я могу «запустить» какую-то функцию внутри произвольной монады, потому что функции, которые я последовательно использую с помощью>>=
, должны иметь сигнатуру одного и того же типа, а значения, которые я поднимаю с помощьюreturn
, должны иметь определенный параметр типа монады. . - Насколько я понимаю, в функциональном языке нет понятия выполнения или запуска вычисления — есть только приложение функции к некоторому аргументу и вычисление функции (замена ее на его значение). Тем не менее, многие конкретные монады поставляются с функцией
run
, такой какrunReader
,runState
и т. д. Эти функции не являются частью определения монады, и они являются простыми функциями, ни в коем случае не специальными императивными операторами вне функционального ядра языка. . Так что же они "бегут"?
Я чувствую, что четкое понимание этих концепций является ключом к пониманию стеков преобразования монад или подобных конструкций, которые кажутся необходимыми для понимания любых существенных библиотек и любых нетривиальных программ на Haskell. Большое спасибо за то, что помогли мне совершить скачок от простого написания функционального кода к действительному пониманию того, что это значит.