While monads are represented in Haskell using the bind
and return
functions, they can also have another representation using the join
function, such as discussed here. I know the type of this function is M(M(X))->M(X)
, but what does this actually do?
Actually, in a way, join
is where all the magic really happens--(>>=)
is used mostly for convenience.
All Functor
-based type classes describe additional structure using some type. With Functor
this extra structure is often thought of as a "container", while with Monad
it tends to be thought of as "side effects", but those are just (occasionally misleading) shorthands--it's the same thing either way and not really anything special[0].
The distinctive feature of Monad
compared to other Functor
s is that it can embed control flow into the extra structure. The reason it can do this is that, unlike fmap
which applies a single flat function over the entire structure, (>>=)
inspects individual elements and builds new structure from that.
With a plain Functor
, building new structure from each piece of the original structure would instead nest the Functor
, with each layer representing a point of control flow. This obviously limits the utility, as the result is messy and has a type that reflects the structure of flow control used.
Monadic "side effects" are structures that have a few additional properties[1]:
The join
function is nothing more than that grouping operation: A nested monad type like m (m a)
describes two side effects and the order they occur in, and join
groups them together into a single side effect.
So, as far as monadic side effects are concerned, the bind operation is a shorthand for "take a value with associated side effects and a function that introduces new side effects, then apply the function to the value while combining the side effects for each".
[0]: Except IO
. IO
is very special.
[1]: If you compare these properties to the rules for an instance of Monoid
you'll see close parallels between the two--this is not a coincidence, and is in fact what that "just a monoid in the category of endofunctors, what's the problem?" line is referring to.