-- | A demonstration that if monads commuted, then the composition of
-- monads would be a monad.
module CommuteM where
import Control.Monad
import Data.Functor.Compose
-- | We undefine the undefinable.
commuteM :: (Monad m, Monad n) => m (n a) -> n (m a)
commuteM = undefined
-- | Use the undefinable to implement an impossible natural join for
-- composed monads.
joinC :: (Monad m, Monad n)
=> Compose m n (Compose m n a)
-> Compose m n a
joinC = Compose
. (join <$>)
. join
. (commuteM <$>)
. getCompose
. (getCompose <$>)
-- | Use the impossible join for composed monads to create the
-- impossible Monad instance for composed monads.
instance (Monad m, Monad n) => Monad (Compose m n) where
mna >>= f = joinC (f <$> mna) where