Функции лифта лишены своей монадической c сущности? - PullRequest
4 голосов
/ 13 февраля 2020

Разница между монадой и аппликативным состоит в том, что первый может выбрать следующее вычисление в зависимости от предыдущего результата:

(\x -> if x == 1 then (\_ -> []) else (\y -> (\z -> \w -> [x,y,z]) =<< sqr) =<< (+1)) =<< (+1) $ 0
--                      ^

(\w x -> if x == 1 then (\_ _ -> []) else (\y z -> [x,y,z])) <*> (+1) <*> (+1) <*> sqr $ 0
--                        ^^^

Вычисление monadi c может замкнуть вычисление, тогда как с аппликативным мы Я должен использовать всю вычислительную структуру и запускать все эффекты независимо от того, какой ввод мы предоставляем.

Давайте сравним это с liftM:

liftM3 (\x -> if x == 1 then (\_ _ -> []) else (\y z -> [x,y,z])) (+1) (+1) sqr $ 0
--                             ^^^

Это, кажется, скрытый аппликативный стиль. Даже если я заменю оператор лифта на аппликатор monadi c, кажется, что вся структура теряет свое свойство monadi c:

appM3 w f x g y h z =
  f(\x' -> g(\y' -> h(\z' -> w x' y' z') z) y) x

appM3 (\x -> if x == 1 then (\_ _ _ -> []) else (\y z _ -> [x, y, z])) (=<<) (+1) (=<<) (+1) (=<<) sqr $ 0
--                            ^^^^^

Означает ли это, что правильное вычисление monadi c всегда должно быть кодироваться вручную? Я знаю обозначения, но основной механизм кажется похожим на расширение макроса (пожалуйста, исправьте меня, если это чепуха), так что это не опровергает мое предположение.

1 Ответ

11 голосов
/ 13 февраля 2020

Ты прав. liftM это просто fmap, а liftM2 это просто liftA2. Их существование является историческим артефактом, все еще окаменелым в стандартных библиотеках, а не чем-то, что действительно требует силы операции связывания monadi c.

Предыдущие версии стандартных библиотек не делали Functor и Applicative суперклассов Monad. (Если вы go вернулись достаточно далеко, Applicative даже не существовало.) Поэтому для удобства были созданы функции, которые выполняли те же функции для использования с Monad. Они пережили переход в предложении Applicative-Monad, потому что они остаются полезными для одной цели - если вы реализуете все классы вручную, вы можете использовать их для реализации экземпляров типа Functor и Applicative в терминах Monad код.

...