Why is join standalone, instead of part of the minimal implementation of the Monad typeclass?
Sadly, join
is not a part of the Monad
typeclass in GHC’s standard library because of technical restrictions related to generalized newtype deriving and the roles system. Long story short, given some newtype newtype T m a = MkT (m a)
, GHC is not smart enough to figure out how to prove representational equality between m (m a)
and m (T m a)
, which is necessary for proving representational equality for the first argument of join
(which has type m (m a) -> m a
).
Fortunately, a recent extension to GHC Haskell, QuantifiedConstraints
, might make it possible to make the roles system smart enough to support this. For a more detailed treatment of both the problem and its potential solution, see Ryan Scott’s blog post, How QuantifiedConstraints can let us put join back in Monad.
join
is not in Monad
because it would break GeneralizedNewtypeDeriving
in a subtle way for newtype-wrapped monad transformers, a very common use case. See the GHC wiki for details.