{-# OPTIONS -XRank2Types #-}



module Control.Monatron.MonadT (

  MonadT(..), FMonadT(..), MMonadT(..), FComp(..), FunctorD(..), tmap, mtmap,

  module Control.Monad

) where



import Control.Monad





----------------------------------------------------------

-- Class of monad transformers with 

-- a lifting of first-order operations

----------------------------------------------------------



class MonadT t where

    lift    :: Monad m  => m a -> t m a

    treturn :: Monad m => a -> t m a

    treturn =  lift. return

    tbind   :: Monad m => t m a -> (a -> t m b) -> t m b



newtype FunctorD f = FunctorD {fmapD :: forall a b . (a -> b) -> f a -> f b}



functor :: Functor f => FunctorD f

functor = FunctorD fmap



class MonadT t => FMonadT t where

    tmap' :: FunctorD m -> FunctorD n -> (a -> b) -> (forall x. m x -> n x) -> t m a -> t n b

    

tmap :: (FMonadT t, Functor m, Functor n) => (forall b. m b -> n b) -> t m a -> t n a

tmap = tmap' functor functor id



mtmap :: FMonadT t => FunctorD f -> (a -> b) -> t f a -> t f b

mtmap fd f = tmap' fd fd f id



class FMonadT t => MMonadT t where

    flift      :: Functor f => f a -> t f a --should coincide with lift!

    monoidalT  :: (Functor f, Functor g) => t f (t g a) -> t (FComp f g) a 



----------------------------------------

-- Functor Composition

----------------------------------------

      

newtype (FComp f g) a = Comp {deComp :: (f (g a)) }



instance (Functor f, Functor g) => Functor (FComp f g) where

    fmap f (Comp fga) = Comp (fmap (fmap f) fga)