{-# LANGUAGE RankNTypes, TypeOperators, DefaultSignatures #-} -- | Compare to indexed.Control.Monad.Indexed (IxMonad) module MHask.Indexed.Monad where import MHask.Arrow import qualified MHask.Indexed.Pointed as MHask import qualified MHask.Indexed.Functor as MHask -- | Indexed version of "MHask.Monad". -- Dual of "MHask.Indexed.Comonad" class (MHask.IxPointed t) => IxMonad t where ijoin :: (Monad m) => t i j (t j k m) ~> t i k m default ijoin :: (Monad m, Monad (t j k m)) => t i j (t j k m) ~> t i k m ijoin = ibind id ibind :: (Monad m, Monad n) => (m ~> t j k n) -> (t i j m ~> t i k n) default ibind :: (Monad m, Monad n, Monad (t i j m), Monad (t j k n), Monad (t i k n), Monad (t i j (t j k n))) => (m ~> t j k n) -> (t i j m ~> t i k n) ibind f = MHask.imap f ~>~ ijoin -- | If you define your IxMonad in terms of ibind and ireturn, -- then you get a free implementation of imap which can -- be used for IxFunctor. imapMonad :: (Monad m, Monad n, Monad (t j j n), IxMonad t) => (m ~> n) -> (t i j m ~> t i j n) imapMonad f = ibind (f ~>~ MHask.ireturn)