It is well-known that applicative functors are closed under composition but monads are not. However, I have been having trouble finding a concrete counterexample showing that monads do not always compose.
This answer gives [String -> a] as an example of a non-monad. After playing around with it for a bit, I believe it intuitively, but that answer just says “join cannot be implemented” without really giving any justification. I would like something more formal. Of course there are lots of functions with type [String -> [String -> a]] -> [String -> a]; one must show that any such function necessarily does not satisfy the monad laws.
Any example (with accompanying proof) will do; I am not necessarily looking for a proof of the above example in particular.
Consider this monad which is isomorphic to the
(Bool ->)monad:and compose it with the
Maybemonad:I claim that
Badcannot be a monad.Partial proof:
There’s only one way to define
fmapthat satisfiesfmap id = id:Recall the monad laws:
For the definition of
return x, we have two choices:B NothingorB (Just (P x x)). It’s clear that in order to have any hope of returningxfrom (1) and (2), we can’t throw awayx, so we have to pick the second option.That leaves
join. Since there are only a few possible inputs, we can make a case for each:Since the output has type
Bad a, the only options areB NothingorB (Just (P y1 y2))wherey1,y2have to be chosen fromx1 ... x4.In cases (A) and (B), we have no values of type
a, so we’re forced to returnB Nothingin both cases.Case (E) is determined by the (1) and (2) monad laws:
In order to return
B (Just (P y1 y2))in case (E), this means we must picky1from eitherx1orx3,and
y2from eitherx2orx4.Likewise, this says that we must pick
y1from eitherx1orx2, andy2from eitherx3orx4. Combining the two,we determine that the right hand side of (E) must be
B (Just (P x1 x4)).So far it’s all good, but the problem comes when you try to fill in the right hand sides for (C) and (D).
There are 5 possible right hand sides for each, and none of the combinations work. I don’t have a nice argument for this yet, but I do have a program that exhaustively tests all the combinations: