module Control.Monad.Trans.MonadFix (MonadF, TransF(..), instF, mfix') where
import Control.Monad.Reader
import Control.Monad.State
import Control.Monad.Trans.Category
import Control.Monad.Trans.Monad
import Control.Monad.Writer
newtype MonadF m x = MonadF {bindF :: forall n. MonadFix n => (m :-> n) -> n x}
instF :: MonadFix m => Inst MonadF m
instF mmx = bindF mmx id
mfix' :: Inst MonadF m -> (x -> m x) -> m x
mfix' i f = i $ MonadF {bindF = \mor -> mfix $ mor . f}
class TransM t => TransF t where
transFInst :: MonadFix m => Inst MonadF (t m)
instance (MonadFix m, TransF t) => MonadFix (t :$ m) where
mfix f = ApplyF {runApplyF = mfix' transFInst $ runApplyF . f}
deriving instance (MonadFix m, TransF t1, TransF t2) => MonadFix ((t2 :. t1) m)
instance (TransF t1, TransF t2) => TransF (t2 :. t1) where transFInst = instF
instance TransF (ReaderT r) where transFInst = instF
instance TransF (StateT s) where transFInst = instF
instance Monoid w => TransF (WriterT w) where transFInst = instF