Я пытаюсь улучшить свое понимание Applicative
s и Monad
s путем реализации их экземпляров функций в Javascript. Мои знания о Haskell ограничены, и я надеюсь, что мой вопрос имеет смысл.Как интерпретировать bind/>> = экземпляра функции?
Вот мои реализации fmap
, <*>
и >>=
для Functor
, Applicative
и Monad
классов типов в Javascript:
const fmap = f => g => x => f(g(x)); // B combinator
const apply = f => g => x => f(x) (g(x)); // S combinator
const bind = f => g => x => g(f(x)) (x); // ?
Я не уверен, является ли bind
правильный перевод реализации Haskell:
(>>=) :: (r -> a) -> (a -> (r -> b)) -> r -> b
instance Monad ((->) r) where
f >>= k = \ r -> k (f r) r
При условии, что bind
верен, как оно интерпретируется? Я знаю, что Applicative
может выполнять эффективные вычисления. Я также знаю, что Monad
дополнительно позволяет вам определить следующий эффект в соответствии с результатом предыдущего.
Я могу видеть последовательности (нетерпеливый порядка оценки в Javascript):
apply
:f(x)
...g(x)
...lambda(result of g)
... результатlambda
bind
:f(x)
...g(result of f)
...lambda(x)
... результатlambda
Однако, то bind
весело ction выглядит довольно странно. Почему f
и g
вложены наоборот? Как определяется конкретное поведение Monad
(определяет следующий эффект в соответствии с предыдущим), отраженный в этой реализации? Фактически g(f(x)) (x)
выглядит как составная функция с перевернутыми аргументами, где g
является двоичной функцией.
Когда я применяю apply
/bind
с унарной и двоичной функцией, они дают тот же результат. Это не имеет большого смысла.
Посмотрите на [этот пример] (http://stackoverflow.com/q/40026018/1048572) для полезного применения 'bind' (известный как' chain' в JS) – Bergi