module Control.Monad.Reader.Class (
    MonadReader(..),
    asks,
    ) where
import Control.Monad.Trans.Cont as Cont
import Control.Monad.Trans.Error
import Control.Monad.Trans.Identity
import Control.Monad.Trans.List
import Control.Monad.Trans.Maybe
import Control.Monad.Trans.Reader (ReaderT)
import qualified Control.Monad.Trans.Reader as ReaderT (ask, local)
import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS (RWST, ask, local)
import qualified Control.Monad.Trans.RWS.Strict as StrictRWS (RWST, ask, local)
import Control.Monad.Trans.State.Lazy as Lazy
import Control.Monad.Trans.State.Strict as Strict
import Control.Monad.Trans.Writer.Lazy as Lazy
import Control.Monad.Trans.Writer.Strict as Strict
import Control.Monad.Trans
import Control.Monad
import Data.Monoid
class (Monad m) => MonadReader m where
    type EnvType m
    
    ask   :: m (EnvType m)
    
    local :: (EnvType m -> EnvType m)
			
          -> m a	
          -> m a
asks :: (MonadReader m)
    => (EnvType m -> a)	
    -> m a
asks f = do
    r <- ask
    return (f r)
instance MonadReader ((->) r) where
    type EnvType ((->) r) = r
    ask       = id
    local f m = m . f
instance (Monad m) => MonadReader (ReaderT r m) where
    type EnvType (ReaderT r m) = r
    ask = ReaderT.ask
    local = ReaderT.local
instance (Monoid w, Monad m) => MonadReader (LazyRWS.RWST r w s m) where
    type EnvType (LazyRWS.RWST r w s m) = r
    ask = LazyRWS.ask
    local = LazyRWS.local
instance (Monoid w, Monad m) => MonadReader (StrictRWS.RWST r w s m) where
    type EnvType (StrictRWS.RWST r w s m) = r
    ask = StrictRWS.ask
    local = StrictRWS.local
instance (MonadReader m) => MonadReader (ContT r m) where
    type EnvType (ContT r m) = EnvType m
    ask   = lift ask
    local = Cont.liftLocal ask local
instance (Error e, MonadReader m) => MonadReader (ErrorT e m) where
    type EnvType (ErrorT e m) = EnvType m
    ask   = lift ask
    local = mapErrorT . local
instance (MonadReader m) => MonadReader (IdentityT m) where
    type EnvType (IdentityT m) = EnvType m
    ask   = lift ask
    local = mapIdentityT . local
instance (MonadReader m) => MonadReader (ListT m) where
    type EnvType (ListT m) = EnvType m
    ask   = lift ask
    local = mapListT . local
instance (MonadReader m) => MonadReader (MaybeT m) where
    type EnvType (MaybeT m) = EnvType m
    ask   = lift ask
    local = mapMaybeT . local
instance (MonadReader m) => MonadReader (Lazy.StateT s m) where
    type EnvType (Lazy.StateT s m) = EnvType m
    ask   = lift ask
    local = Lazy.mapStateT . local
instance (MonadReader m) => MonadReader (Strict.StateT s m) where
    type EnvType (Strict.StateT s m) = EnvType m
    ask   = lift ask
    local = Strict.mapStateT . local
instance (Monoid w, MonadReader m) => MonadReader (Lazy.WriterT w m) where
    type EnvType (Lazy.WriterT w m) = EnvType m
    ask   = lift ask
    local = Lazy.mapWriterT . local
instance (Monoid w, MonadReader m) => MonadReader (Strict.WriterT w m) where
    type EnvType (Strict.WriterT w m) = EnvType m
    ask   = lift ask
    local = Strict.mapWriterT . local