Что касается монады функций, я обнаружил, что (<*>)
и _2 _ / _ 3_ имеют два поразительно похожих типа. В частности, (=<<)
делает сходство более очевидным:
(<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b)
(=<<) :: (a -> r -> b) -> (r -> a) -> (r -> b)
Это похоже на то, что и (<*>)
, и _7 _ / _ 8_ берут двоичную функцию и унарную функцию и ограничивают один из двух аргументов первого должен быть определен из другого через последний. В конце концов, мы знаем, что для функции аппликатив / монада
f <*> g = \x -> f x (g x)
f =<< g = \x -> f (g x) x
И они выглядят настолько поразительно похожими (или симметричными, если хотите), что я не могу не думать о вопросе в названии.
Что касается того, что монады более мощные, чем аппликативные функторы, в твердой копии LYAH For a Несколько монад Подробнее главы говорится следующее:
[…]
join
нельзя реализовать, просто используя функции, которые предоставляют функторы и аппликативы.
т.е. join
не может быть реализовано в терминах (<*>)
, pure
и fmap
.
Но как насчет упомянутой выше функции Applicative / mondad?
Я знаю, что join === (>>= id)
и что для функциональной монады, которая сводится к \f x -> f x x
, т.е. двоичная функция становится унарной, если один аргумент последней вводится как оба аргумента первой.
Могу я выразить это через (<*>)
? Ну, вообще-то я думаю, что могу: разве flip ($) <*> f === join f
не правильно? Разве flip ($) <*> f
не реализация join
, которая обходится без _21 _ / _ 22_ и return
?
Однако, думая о аппликативной / монаде списка, я могу выразить join
без явного использования _25 _ / _ 26_ и return
(и даже не (<*>)
, fwiw): join = concat
; так что, вероятно, реализация join f = flip ($) <*> f
- это своего рода трюк, который на самом деле не показывает, полагаюсь я только на Applicative
или также на Monad
.