I've read this Q&A but don't understand the category theory part.
Here is my reasoning so far: When I look at the types
F (a -> b) -> F a -> F b
(a -> M b) -> M a -> M b
a -> F a
a -> M a
the only portion that resembles a monoid at the type level is the type constructor, i.e. the applicative/monadic context:
// binary operation
F -> F -> F
M -> M -> M
// identity element
F
M
So I'd say applicatives/monads are monoidal in terms of their contexts, because they combine two contexts of the same type into one. pure
/return
creates a most minimal context, so we can think of it as the identity context similar to the identity element of a monoid, which creates a "most minimal value".
However, monads/applicatives are not monoidal in their type parameter, because they include a transformation from a
to b
.
I am not sure my reasoning makes any sense. What baffles me is that monoids on the one hand and applicatives/monads on the other combine things differently:
Nothing <> (Just "bar") -- Just "bar"
(++) <$> Nothing <*> (Just "bar") -- Nothing
Nothing >>= (\x -> (Just "bar") >>= (return . (++) x)) -- Nothing
However, I guess the different result values are due to monoids interpret expressions as ordinary values whereas applicatives/monads interpret expressions as computations (one that may fail in the above example).
Now in the aforementioned Q&A is stated monads are monoidal in the category of endofunctors and applicatives are lax monoidal functors. I don't fully understand that but clearly applicatives only partially preserve the monoidal structure whereas monads fully preserve it. What are the practical implications of this difference from a perspective of a functional programmer?
I ask this question as part of the attempt to better understand applicative/monads and what causes there different expressiveness.