    {- |
    Module      :  Control.Monad.Reader.Class
    Copyright   :  (c) Andy Gill 2001,
                   (c) Oregon Graduate Institute of Science and Technology 2001,
                   (c) Jeff Newbern 2003-2007,
                   (c) Andriy Palamarchuk 2007
    License     :  BSD-style (see the file LICENSE)

    Maintainer  :  ross@soi.city.ac.uk
    Stability   :  experimental
    Portability :  non-portable (type families)

    [Computation type:] Computations which read values from a shared environment.

    [Binding strategy:] Monad values are functions from the environment to a value.
    The bound function is applied to the bound value, and both have access
    to the shared environment.

    [Useful for:] Maintaining variable bindings, or other shared environment.

    [Zero and plus:] None.

    [Example type:] @'Reader' [(String,Value)] a@

    The 'Reader' monad (also called the Environment monad).
    Represents a computation, which can read values from
    a shared environment, pass values from function to function,
    and execute sub-computations in a modified environment.
    Using 'Reader' monad for such computations is often clearer and easier
    than using the 'Control.Monad.State.State' monad.

      Inspired by the paper
      /Functional Programming with Overloading and Higher-Order Polymorphism/,
        Mark P Jones (<http://web.cecs.pdx.edu/~mpj/>)
        Advanced School of Functional Programming, 1995.
    -}

    module Control.Monad.Reader.Class (
        MonadReader(..),
        asks,
        ) where

    import Control.Monad.Trans.Cont as Cont
    import Control.Monad.Trans.Except
    import Control.Monad.Trans.Identity
    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

    -- ----------------------------------------------------------------------------
    -- class MonadReader
    --  asks for the internal (non-mutable) state.

    -- | See examples in "Control.Monad.Reader".
    -- Note, the partially applied function type @(->) r@ is a simple reader monad.
    -- See the @instance@ declaration below.
    class (Monad m) => MonadReader m where
        type EnvType m

        -- | Retrieves the monad environment.
        ask   :: m (EnvType m)

        -- | Executes a computation in a modified environment.
        local :: (EnvType m -> EnvType m)
                            -- ^ The function to modify the environment.
              -> m a        -- ^ @Reader@ to run in the modified environment.
              -> m a

    -- | Retrieves a function of the current environment.
    asks :: (MonadReader m)
        => (EnvType m -> a) -- ^ The selector function to apply to the environment.
        -> m a
    asks :: forall (m :: * -> *) a. MonadReader m => (EnvType m -> a) -> m a
    asks EnvType m -> a
    f = do
        r <- m (EnvType m)
    forall (m :: * -> *). MonadReader m => m (EnvType m)
    ask
        return (f r)

    -- ----------------------------------------------------------------------------
    -- The partially applied function type is a simple reader monad

    instance MonadReader ((->) r) where
        type EnvType ((->) r) = r
        ask :: r -> EnvType ((->) r)
    ask       = r -> r
    r -> EnvType ((->) r)
    forall a. a -> a
    id
        local :: forall a.
    (EnvType ((->) r) -> EnvType ((->) r)) -> (r -> a) -> r -> a
    local EnvType ((->) r) -> EnvType ((->) r)
    f r -> a
    m = r -> a
    m (r -> a) -> (r -> r) -> r -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . r -> r
    EnvType ((->) r) -> EnvType ((->) r)
    f

    instance (Monad m) => MonadReader (ReaderT r m) where
        type EnvType (ReaderT r m) = r
        ask :: ReaderT r m (EnvType (ReaderT r m))
    ask = ReaderT r m r
    ReaderT r m (EnvType (ReaderT r m))
    forall (m :: * -> *) r. Monad m => ReaderT r m r
    ReaderT.ask
        local :: forall a.
    (EnvType (ReaderT r m) -> EnvType (ReaderT r m))
    -> ReaderT r m a -> ReaderT r m a
    local = (r -> r) -> ReaderT r m a -> ReaderT r m a
    (EnvType (ReaderT r m) -> EnvType (ReaderT r m))
    -> ReaderT r m a -> ReaderT r m a
    forall r (m :: * -> *) a.
    (r -> r) -> ReaderT r m a -> ReaderT r m a
    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 :: RWST r w s m (EnvType (RWST r w s m))
    ask = RWST r w s m r
    RWST r w s m (EnvType (RWST r w s m))
    forall w (m :: * -> *) r s. (Monoid w, Monad m) => RWST r w s m r
    LazyRWS.ask
        local :: forall a.
    (EnvType (RWST r w s m) -> EnvType (RWST r w s m))
    -> RWST r w s m a -> RWST r w s m a
    local = (r -> r) -> RWST r w s m a -> RWST r w s m a
    (EnvType (RWST r w s m) -> EnvType (RWST r w s m))
    -> RWST r w s m a -> RWST r w s m a
    forall r w s (m :: * -> *) a.
    (r -> r) -> RWST r w s m a -> RWST r w s m a
    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 :: RWST r w s m (EnvType (RWST r w s m))
    ask = RWST r w s m r
    RWST r w s m (EnvType (RWST r w s m))
    forall w (m :: * -> *) r s. (Monoid w, Monad m) => RWST r w s m r
    StrictRWS.ask
        local :: forall a.
    (EnvType (RWST r w s m) -> EnvType (RWST r w s m))
    -> RWST r w s m a -> RWST r w s m a
    local = (r -> r) -> RWST r w s m a -> RWST r w s m a
    (EnvType (RWST r w s m) -> EnvType (RWST r w s m))
    -> RWST r w s m a -> RWST r w s m a
    forall r w s (m :: * -> *) a.
    (r -> r) -> RWST r w s m a -> RWST r w s m a
    StrictRWS.local

    -- ---------------------------------------------------------------------------
    -- Instances for other mtl transformers

    instance (MonadReader m) => MonadReader (ContT r m) where
        type EnvType (ContT r m) = EnvType m
        ask :: ContT r m (EnvType (ContT r m))
    ask   = m (EnvType m) -> ContT r m (EnvType m)
    forall (m :: * -> *) a. Monad m => m a -> ContT r m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift m (EnvType m)
    forall (m :: * -> *). MonadReader m => m (EnvType m)
    ask
        local :: forall a.
    (EnvType (ContT r m) -> EnvType (ContT r m))
    -> ContT r m a -> ContT r m a
    local = m (EnvType m)
    -> ((EnvType m -> EnvType m) -> m r -> m r)
    -> (EnvType m -> EnvType m)
    -> ContT r m a
    -> ContT r m a
    forall (m :: * -> *) r' r a.
    Monad m =>
    m r'
    -> ((r' -> r') -> m r -> m r)
    -> (r' -> r')
    -> ContT r m a
    -> ContT r m a
    Cont.liftLocal m (EnvType m)
    forall (m :: * -> *). MonadReader m => m (EnvType m)
    ask (EnvType m -> EnvType m) -> m r -> m r
    forall a. (EnvType m -> EnvType m) -> m a -> m a
    forall (m :: * -> *) a.
    MonadReader m =>
    (EnvType m -> EnvType m) -> m a -> m a
    local

    instance (MonadReader m) => MonadReader (ExceptT e m) where
        type EnvType (ExceptT e m) = EnvType m
        ask :: ExceptT e m (EnvType (ExceptT e m))
    ask   = m (EnvType m) -> ExceptT e m (EnvType m)
    forall (m :: * -> *) a. Monad m => m a -> ExceptT e m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift m (EnvType m)
    forall (m :: * -> *). MonadReader m => m (EnvType m)
    ask
        local :: forall a.
    (EnvType (ExceptT e m) -> EnvType (ExceptT e m))
    -> ExceptT e m a -> ExceptT e m a
    local = (m (Either e a) -> m (Either e a))
    -> ExceptT e m a -> ExceptT e m a
    forall (m :: * -> *) e a (n :: * -> *) e' b.
    (m (Either e a) -> n (Either e' b))
    -> ExceptT e m a -> ExceptT e' n b
    mapExceptT ((m (Either e a) -> m (Either e a))
     -> ExceptT e m a -> ExceptT e m a)
    -> ((EnvType m -> EnvType m) -> m (Either e a) -> m (Either e a))
    -> (EnvType m -> EnvType m)
    -> ExceptT e m a
    -> ExceptT e m a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (EnvType m -> EnvType m) -> m (Either e a) -> m (Either e a)
    forall a. (EnvType m -> EnvType m) -> m a -> m a
    forall (m :: * -> *) a.
    MonadReader m =>
    (EnvType m -> EnvType m) -> m a -> m a
    local

    instance (MonadReader m) => MonadReader (IdentityT m) where
        type EnvType (IdentityT m) = EnvType m
        ask :: IdentityT m (EnvType (IdentityT m))
    ask   = m (EnvType m) -> IdentityT m (EnvType m)
    forall (m :: * -> *) a. Monad m => m a -> IdentityT m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift m (EnvType m)
    forall (m :: * -> *). MonadReader m => m (EnvType m)
    ask
        local :: forall a.
    (EnvType (IdentityT m) -> EnvType (IdentityT m))
    -> IdentityT m a -> IdentityT m a
    local = (m a -> m a) -> IdentityT m a -> IdentityT m a
    forall {k1} {k2} (m :: k1 -> *) (a :: k1) (n :: k2 -> *) (b :: k2).
    (m a -> n b) -> IdentityT m a -> IdentityT n b
    mapIdentityT ((m a -> m a) -> IdentityT m a -> IdentityT m a)
    -> ((EnvType m -> EnvType m) -> m a -> m a)
    -> (EnvType m -> EnvType m)
    -> IdentityT m a
    -> IdentityT m a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (EnvType m -> EnvType m) -> m a -> m a
    forall a. (EnvType m -> EnvType m) -> m a -> m a
    forall (m :: * -> *) a.
    MonadReader m =>
    (EnvType m -> EnvType m) -> m a -> m a
    local

    instance (MonadReader m) => MonadReader (MaybeT m) where
        type EnvType (MaybeT m) = EnvType m
        ask :: MaybeT m (EnvType (MaybeT m))
    ask   = m (EnvType m) -> MaybeT m (EnvType m)
    forall (m :: * -> *) a. Monad m => m a -> MaybeT m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift m (EnvType m)
    forall (m :: * -> *). MonadReader m => m (EnvType m)
    ask
        local :: forall a.
    (EnvType (MaybeT m) -> EnvType (MaybeT m))
    -> MaybeT m a -> MaybeT m a
    local = (m (Maybe a) -> m (Maybe a)) -> MaybeT m a -> MaybeT m a
    forall (m :: * -> *) a (n :: * -> *) b.
    (m (Maybe a) -> n (Maybe b)) -> MaybeT m a -> MaybeT n b
    mapMaybeT ((m (Maybe a) -> m (Maybe a)) -> MaybeT m a -> MaybeT m a)
    -> ((EnvType m -> EnvType m) -> m (Maybe a) -> m (Maybe a))
    -> (EnvType m -> EnvType m)
    -> MaybeT m a
    -> MaybeT m a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (EnvType m -> EnvType m) -> m (Maybe a) -> m (Maybe a)
    forall a. (EnvType m -> EnvType m) -> m a -> m a
    forall (m :: * -> *) a.
    MonadReader m =>
    (EnvType m -> EnvType m) -> m a -> m a
    local

    instance (MonadReader m) => MonadReader (Lazy.StateT s m) where
        type EnvType (Lazy.StateT s m) = EnvType m
        ask :: StateT s m (EnvType (StateT s m))
    ask   = m (EnvType m) -> StateT s m (EnvType m)
    forall (m :: * -> *) a. Monad m => m a -> StateT s m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift m (EnvType m)
    forall (m :: * -> *). MonadReader m => m (EnvType m)
    ask
        local :: forall a.
    (EnvType (StateT s m) -> EnvType (StateT s m))
    -> StateT s m a -> StateT s m a
    local = (m (a, s) -> m (a, s)) -> StateT s m a -> StateT s m a
    forall (m :: * -> *) a s (n :: * -> *) b.
    (m (a, s) -> n (b, s)) -> StateT s m a -> StateT s n b
    Lazy.mapStateT ((m (a, s) -> m (a, s)) -> StateT s m a -> StateT s m a)
    -> ((EnvType m -> EnvType m) -> m (a, s) -> m (a, s))
    -> (EnvType m -> EnvType m)
    -> StateT s m a
    -> StateT s m a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (EnvType m -> EnvType m) -> m (a, s) -> m (a, s)
    forall a. (EnvType m -> EnvType m) -> m a -> m a
    forall (m :: * -> *) a.
    MonadReader m =>
    (EnvType m -> EnvType m) -> m a -> m a
    local

    instance (MonadReader m) => MonadReader (Strict.StateT s m) where
        type EnvType (Strict.StateT s m) = EnvType m
        ask :: StateT s m (EnvType (StateT s m))
    ask   = m (EnvType m) -> StateT s m (EnvType m)
    forall (m :: * -> *) a. Monad m => m a -> StateT s m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift m (EnvType m)
    forall (m :: * -> *). MonadReader m => m (EnvType m)
    ask
        local :: forall a.
    (EnvType (StateT s m) -> EnvType (StateT s m))
    -> StateT s m a -> StateT s m a
    local = (m (a, s) -> m (a, s)) -> StateT s m a -> StateT s m a
    forall (m :: * -> *) a s (n :: * -> *) b.
    (m (a, s) -> n (b, s)) -> StateT s m a -> StateT s n b
    Strict.mapStateT ((m (a, s) -> m (a, s)) -> StateT s m a -> StateT s m a)
    -> ((EnvType m -> EnvType m) -> m (a, s) -> m (a, s))
    -> (EnvType m -> EnvType m)
    -> StateT s m a
    -> StateT s m a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (EnvType m -> EnvType m) -> m (a, s) -> m (a, s)
    forall a. (EnvType m -> EnvType m) -> m a -> m a
    forall (m :: * -> *) a.
    MonadReader m =>
    (EnvType m -> EnvType m) -> m a -> m a
    local

    instance (Monoid w, MonadReader m) => MonadReader (Lazy.WriterT w m) where
        type EnvType (Lazy.WriterT w m) = EnvType m
        ask :: WriterT w m (EnvType (WriterT w m))
    ask   = m (EnvType m) -> WriterT w m (EnvType m)
    forall (m :: * -> *) a. Monad m => m a -> WriterT w m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift m (EnvType m)
    forall (m :: * -> *). MonadReader m => m (EnvType m)
    ask
        local :: forall a.
    (EnvType (WriterT w m) -> EnvType (WriterT w m))
    -> WriterT w m a -> WriterT w m a
    local = (m (a, w) -> m (a, w)) -> WriterT w m a -> WriterT w m a
    forall (m :: * -> *) a w (n :: * -> *) b w'.
    (m (a, w) -> n (b, w')) -> WriterT w m a -> WriterT w' n b
    Lazy.mapWriterT ((m (a, w) -> m (a, w)) -> WriterT w m a -> WriterT w m a)
    -> ((EnvType m -> EnvType m) -> m (a, w) -> m (a, w))
    -> (EnvType m -> EnvType m)
    -> WriterT w m a
    -> WriterT w m a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (EnvType m -> EnvType m) -> m (a, w) -> m (a, w)
    forall a. (EnvType m -> EnvType m) -> m a -> m a
    forall (m :: * -> *) a.
    MonadReader m =>
    (EnvType m -> EnvType m) -> m a -> m a
    local

    instance (Monoid w, MonadReader m) => MonadReader (Strict.WriterT w m) where
        type EnvType (Strict.WriterT w m) = EnvType m
        ask :: WriterT w m (EnvType (WriterT w m))
    ask   = m (EnvType m) -> WriterT w m (EnvType m)
    forall (m :: * -> *) a. Monad m => m a -> WriterT w m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift m (EnvType m)
    forall (m :: * -> *). MonadReader m => m (EnvType m)
    ask
        local :: forall a.
    (EnvType (WriterT w m) -> EnvType (WriterT w m))
    -> WriterT w m a -> WriterT w m a
    local = (m (a, w) -> m (a, w)) -> WriterT w m a -> WriterT w m a
    forall (m :: * -> *) a w (n :: * -> *) b w'.
    (m (a, w) -> n (b, w')) -> WriterT w m a -> WriterT w' n b
    Strict.mapWriterT ((m (a, w) -> m (a, w)) -> WriterT w m a -> WriterT w m a)
    -> ((EnvType m -> EnvType m) -> m (a, w) -> m (a, w))
    -> (EnvType m -> EnvType m)
    -> WriterT w m a
    -> WriterT w m a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (EnvType m -> EnvType m) -> m (a, w) -> m (a, w)
    forall a. (EnvType m -> EnvType m) -> m a -> m a
    forall (m :: * -> *) a.
    MonadReader m =>
    (EnvType m -> EnvType m) -> m a -> m a
    local