I'm new to functional programming (coming from javascript), and I'm having a hard time telling the difference between the two, which is also messing with my understand of functors vs. monads.
Functor:
class Functor f where fmap :: (a -> b) -> f a -> f b
Monad (simplified):
class Monad m where (>>=) :: m a -> (a -> m b) -> m b
fmap
takes a function and a functor, and returns a functor.>>=
takes a function and a monad, and returns a monad.The difference between the two is in the function parameter:
fmap
- (a -> b)
>>=
- (a -> m b)
>>=
takes a function parameter that returns a monad. I know that this is significant, but I'm having difficulty seeing how this one slight thing makes monads much more powerful than functors. Can someone explain?
A functor takes a pure function (and a functorial value) whereas a monad takes a Kleisli arrow, i.e. a function that returns a monad (and a monadic value). Hence you can chain two monads and the second monad can depend on the result of the previous one. You cannot do this with functors.
Applicative functors allow you to take a "normal" function (taking non-functorial arguments) use it to operate on several values that are in functor contexts. As a corollary, this gives you effectful programming without monads.
In functional programming, an applicative functor, or an applicative for short, is an intermediate structure between functors and monads.
Well, (<$>)
is an alias for fmap
, and (=<<)
is the same as (>>=)
with the arguments swapped:
(<$>) :: (x -> y) -> b x -> b y (=<<) :: (x -> b y) -> b x -> b y
The difference is now fairly clear: with the bind function, we apply a function that returns a b y
rather than a y
. So what difference does that make?
Consider this small example:
foo <$> Just 3
Notice that (<$>)
will apply foo
to 3
, and put the result back into a Just
. In other words, the result of this computation cannot be Nothing
. On the contrary:
bar =<< Just 3
This computation can return Nothing
. (For example, bar x = Nothing
will do it.)
We can do a similar thing with the list monad:
foo <$> [Red, Yellow, Blue] -- Result is guaranteed to be a 3-element list. bar =<< [Red, Yellow, Blue] -- Result can be ANY size.
In short, with (<$>)
(i.e., fmap
), the "structure" of the result is always identical to the input. But with (=<<)
(i.e., (>>=)
), the structure of the result can change. This allows conditional execution, reacting to input, and a whole bunch of other things.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With