{-# LANGUAGE UndecidableInstances #-} {- | 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 libraries/base/LICENSE) Maintainer : libraries@haskell.org Stability : experimental Portability : non-portable (multi-param classes, functional dependencies) [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://www.cse.ogi.edu/~mpj/>) Advanced School of Functional Programming, 1995. -} module Control.Monad.Reader.Class ( MonadReader(..), asks, ) where import Control.Monad.Trans.All import qualified Control.Monad.Trans.All.Strict as Strict import Control.Monad.Trans.Class {- | 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. Parameters: * The function to modify the environment. * @Reader@ to run. * The resulting @Reader@. -} local :: (EnvType m -> EnvType m) -> m a -> m a {- | Retrieves a function of the current environment. Parameters: * The selector function to apply to the environment. See an example in "Control.Monad.Reader". -} asks :: (MonadReader m) => (EnvType m -> a) -> m a asks f = f <$> ask instance (Monad m) => MonadReader (ReaderT r m) where type EnvType (ReaderT r m) = r ask = ReaderT return local f m = ReaderT $ \r -> runReaderT m (f r) -- ---------------------------------------------------------------------------- -- The partially applied function type is a simple reader monad instance MonadReader ((->) r) where type EnvType ((->) r) = r ask = id local f m = m . f -- --------------------------------------------------------------------------- -- Instances for other mtl transformers instance (MonadReader m) => MonadReader (ContT r m) where type EnvType (ContT r m) = EnvType m ask = lift ask local f m = ContT $ \c -> do r <- ask local f (runContT m (local (const r) . c)) instance (MonadReader m) => MonadReader (ExceptT e m) where type EnvType (ExceptT e m) = EnvType m ask = lift ask local f m = ExceptT $ local f (runExceptT m) instance (Monoid w, Monad m) => MonadReader (RWST r w s m) where type EnvType (RWST r w s m) = r ask = RWST $ \r s -> return (r, s, mempty) local f m = RWST $ \r s -> runRWST m (f r) s instance (Monoid w, Monad m) => MonadReader (Strict.RWST r w s m) where type EnvType (Strict.RWST r w s m) = r ask = Strict.RWST $ \r s -> return (r, s, mempty) local f m = Strict.RWST $ \r s -> Strict.runRWST m (f r) s instance (MonadReader m) => MonadReader (StateT s m) where type EnvType (StateT s m) = EnvType m ask = lift ask local f m = StateT $ \s -> local f (runStateT m s) instance (MonadReader m) => MonadReader (Strict.StateT s m) where type EnvType (Strict.StateT s m) = EnvType m ask = lift ask local f m = Strict.StateT $ \s -> local f (Strict.runStateT m s) instance (Monoid w, MonadReader m) => MonadReader (WriterT w m) where type EnvType (WriterT w m) = EnvType m ask = lift ask local f m = WriterT $ local f (runWriterT m) instance (Monoid w, MonadReader m) => MonadReader (Strict.WriterT w m) where type EnvType (Strict.WriterT w m) = EnvType m ask = lift ask local f m = Strict.WriterT $ local f (Strict.runWriterT m)