I'm trying to improve my understanding of Applicative
s and Monad
s by implementing their function instances in Javascript. My knowledge of Haskell is limited and I hope that my question makes sense at all.
Here are my implementations of fmap
, <*>
and >>=
for the Functor
, Applicative
and Monad
typeclasses in 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); // ?
I am not sure whether bind
is the correct translation of the Haskell implementation:
(>>=) :: (r -> a) -> (a -> (r -> b)) -> r -> b
instance Monad ((->) r) where
f >>= k = \ r -> k (f r) r
Provided that bind
is correct, how is it interpreted? I know that an Applicative
can sequence effectful computations. I also know that a Monad
in addition allows you to determine a next effect according to the result of a previous one.
I can see the sequences (eager evaluation order in Javascript):
apply
:f(x)
...g(x)
...lambda(result of g)
... result oflambda
bind
:f(x)
...g(result of f)
...lambda(x)
... result oflambda
However, the bind
function looks pretty weird. Why are f
and g
nested the other way around? How is the specific Monad
behavior (determines a next effect according to a previous one) reflected in this implementation? Actually g(f(x)) (x)
looks like a function composition with flipped arguments, where g
is a binary function.
When I apply apply
/bind
with an unary and a binary function, they yield the same result. This doesn't make much sense.