There is a controversy about Monad implementation in S.O .
The original question is,
Is there any counterexample that Functors cannot do what Monads can do except the robustness of functional composition by flattening the nested structure?
What's so special about Monads in Kleisli category? It seems like it's fairly possible to implement Monads with a little expansion to avoid the nested structure of Functor and without the monadic functions
a -> m bthat is the entity in Kleisli category.
An answer is
"Avoiding the nested type" is not, in fact, the purpose of join, it's just a neat side-effect. The way you put it makes it sound like join just strips the outer type, but the monad's value is unchanged.
You can think of a functor as basically a container. There's an arbitrary inner type, and around it an outer structure that allows some variance, some extra values to "decorate" your inner value. fmap allows you to work on the things inside the container, the way you would work on them normally. This is basically the limit of what you can do with a functor.
A monad is a functor with a special power: where fmap allows you to work on an inner value, bind allows you to combine outer values in a consistent way. This is much more powerful than a simple functor.
join is the heart of the monad because it encompasses everything a monad can do that a functor cannot. Since join and >>= are isomorphic and you can define each in terms of the other, defining >>= without join still provides the same degree of freedom (you could say that defining >>= indirectly defines join, and vice versa). You get the same thing either way, except that >>= is more convenient and join is more "pure". So it is really a boring question to compare the two. – DarthFennec
The objection by the questioner is,
I believe "Avoiding the nested type" is not just a neat side-effect, but a definition of "join" of Monad in category theory,
and that's exactly what my code does.
I know many people implement monads in Haskell in this manner, but the fact is, there is Maybe functor in Haskell, that does not has join, or there is Free monad that join is embedded from the first place into the defined structure. They are objects that users define Functors to do things.
Therefore, ... [your] observation does not fit the fact of the existence of Maybe functor and Free monad.
Which opinion is correct?
PS. Additional comment from DarthFennec (who answers) as below:
Free is weird, in that it's one of the few monads that doesn't actually do anything.
Free can be used to turn any functor into a monad, which allows you to use
do notation and other conveniences. However, the conceit of
Free is that
join does not combine your actions the way other monads do, instead it keeps them separate, inserting them into a list-like structure; the idea being that this structure is later processed and the actions are combined by separate code. An equivalent approach would be to move that processing code into
join itself, but that would turn the functor into a monad and there would be no point in using
Free. So the only reason
Free works is because it delegates the actual "doing things" part of the monad elsewhere; its
join opts to defer action to code running outside the monad. This is like a
+ operator that, instead of adding the numbers, returns an abstract syntax tree; one could then process that tree later in whatever way is needed.
These observation does not fit the fact of the existence of Maybe functor and Free monad.
You are incorrect. As explained,
Free fit perfectly into my previous observations:
Maybefunctor simply does not have the same expressiveness as the
Freemonad transforms functors into monads in the only way it possibly can: by not implementing a monadic behavior, and instead simply deferring it to some assumed processing code.
First of all the word he uses "
Free is weird" or "the conceit of
Free" unduly disparaging the Free monad, and this words does not justify what he insists obviously.
An equivalent approach would be to move that processing code into
joinitself, but that would turn the functor into a monad and there would be no point in using
My question would be if "join is the heart of the monad", how come the " processing code" has been moved away from the heart =
join and move-back into
join again? That is the weird.
Free is one of the generalization to abstract the "processing code" of Monad. Monad structure including
join that satisfies the monad laws are pre-defined without the "processing code" that would be functor/ or function if it's Operational monad.
So the only reason
Freeworks is because it delegates the actual "doing things" part of the monad elsewhere; its
joinopts to defer action to code running outside the monad.
In either way, again, "doing things" does not have to locate in
join. If someone strongly insists "join is the heart of the monad", maybe it's ok to do so. However, as Free-monad, it's totally reasonable a user let
join be pre-defined in a generalized structure of Monad as a functionality of flattening the structure, or other monads also does not have to move "doing things" to
join because it's not the heart of the monad anyway.