Monads not with "flatMap" but "flatUnit"? [closed]

In this answer, I won’t dwell on flatUnit. As others have pointed out, join . return = id for any monad (it is one of the monad laws), and so there isn’t much to talk about it in and of itself. Instead, I will discuss some of the surrounding themes raised in the discussion here.

Quoting a comment:

in other words, functor with a flat structure, it’s a monad.

This, I believe, is the heart of the question. A monad need not be a functor with a flat structure, but a functor whose values can be flattened (with join) in a way that follows certain laws (“a monoid in the category of endofunctors”, as the saying goes). It isn’t required for the flattening to be a lossless operation (i.e. for join to be an isomorphism).

Monads whose join is an isomorphism are called, in category theory parlance, idempotent monads 1. For a Haskell Monad to be idempotent, though, the monadic values must have no extra structure. That means most monads of immediate interest to a programmer won’t be idempotent (in fact, I’m having trouble to think of idempotent Haskell Monads that aren’t Identity or identity-like). One example already raised in the comments was that of lists:

join [[1,2],[3,4,5]] = [1,2,3,4,5] -- Grouping information discarded

The function/reader monad gives what I’d say is an even more dramatic illustration:

join (+) = \x -> x + x

This recent question gives an interesting illustration involving Maybe. The OP there had a function with signature…

appFunc :: Integer -> Integer -> Bool -> Maybe (Integer,Integer)

… and used it like this…

appFunc <$> u <*> v <*> w

… thus obtaining a Maybe (Maybe (Integer, Integer)) result. The two layers of Maybe correspond to two different ways of failing: if u, v or w are Nothing, we get Nothing; if the three of them are Just-values but appFunc results in Nothing, we get Just Nothing; finally, if everything succeeds we get a Just-value within a Just. Now, it might be the case that we, like the author of that question, didn’t care about which layer of Maybe led to the failure; in that case, we would discard that information, either by using join on the result or by rewriting it as u >>= \x -> v >>= \y -> w >>= \b -> appFunc x y b. In any case, the information is there for us to use or discard.


Note 1: In Combining Monads by King and Wadler (one of Wadler’s papers about monads), the authors introduce a different, and largely unrelated, meaning for “idempotent monad”. In their sense, an idempotent monad is one for which (in applicative notation) f <$> u <*> u = (\x -> f x x) <$> u — one example would be Maybe.

Leave a Comment