{-# LANGUAGE CPP #-}#if __GLASGOW_HASKELL__ >= 702 {-# LANGUAGE Safe #-}#endif #if __GLASGOW_HASKELL__ >= 710 {-# LANGUAGE AutoDeriveTypeable #-}#endif ------------------------------------------------------------------------------- |-- Module : Control.Monad.Trans.Reader-- Copyright : (c) Andy Gill 2001,-- (c) Oregon Graduate Institute of Science and Technology, 2001-- License : BSD-style (see the file LICENSE)---- Maintainer : R.Paterson@city.ac.uk-- Stability : experimental-- Portability : portable---- Declaration of the 'ReaderT' monad transformer, which adds a static-- environment to a given monad.---- If the computation is to modify the stored information, use-- "Control.Monad.Trans.State" instead.-----------------------------------------------------------------------------moduleControl.Monad.Trans.Reader(-- * The Reader monadReader ,reader ,runReader ,mapReader ,withReader ,-- * The ReaderT monad transformerReaderT (..),mapReaderT ,withReaderT ,-- * Reader operationsask ,local ,asks ,-- * Lifting other operationsliftCallCC ,liftCatch ,)whereimportControl.Monad.IO.ClassimportControl.Monad.Signatures importControl.Monad.Trans.Class #if MIN_VERSION_base(4,12,0) importData.Functor.Contravariant#endif importData.Functor.IdentityimportControl.ApplicativeimportControl.Monad#if MIN_VERSION_base(4,9,0) importqualifiedControl.Monad.FailasFail#endif importControl.Monad.Fix#if !(MIN_VERSION_base(4,6,0)) importControl.Monad.Instances()-- deprecated from base-4.6#endif #if MIN_VERSION_base(4,4,0) importControl.Monad.Zip(MonadZip(mzipWith))#endif #if MIN_VERSION_base(4,2,0) importData.Functor(Functor(..))#endif -- | The parameterizable reader monad.---- Computations are functions of a shared environment.---- The 'return' function ignores the environment, while @>>=@ passes-- the inherited environment to both subcomputations.typeReader r =ReaderT r Identity-- | Constructor for computations in the reader monad (equivalent to 'asks').reader::(Monadm )=>(r ->a )->ReaderT r m a reader f =ReaderT (return.f ){-# INLINEreader#-}-- | Runs a @Reader@ and extracts the final value from it.-- (The inverse of 'reader'.)runReader::Reader r a -- ^ A @Reader@ to run.->r -- ^ An initial environment.->a runReader m =runIdentity.runReaderTm {-# INLINErunReader#-}-- | Transform the value returned by a @Reader@.---- * @'runReader' ('mapReader' f m) = f . 'runReader' m@mapReader::(a ->b )->Reader r a ->Reader r b mapReader f =mapReaderT (Identity.f .runIdentity){-# INLINEmapReader#-}-- | Execute a computation in a modified environment-- (a specialization of 'withReaderT').---- * @'runReader' ('withReader' f m) = 'runReader' m . f@withReader::(r' ->r )-- ^ The function to modify the environment.->Reader r a -- ^ Computation to run in the modified environment.->Reader r' a withReader =withReaderT {-# INLINEwithReader#-}-- | The reader monad transformer,-- which adds a read-only environment to the given monad.---- The 'return' function ignores the environment, while @>>=@ passes-- the inherited environment to both subcomputations.newtypeReaderT r m a =ReaderT {runReaderT ::r ->m a }-- | Transform the computation inside a @ReaderT@.---- * @'runReaderT' ('mapReaderT' f m) = f . 'runReaderT' m@mapReaderT::(m a ->n b )->ReaderT r m a ->ReaderT r n b mapReaderT f m =ReaderT $f .runReaderTm {-# INLINEmapReaderT#-}-- | Execute a computation in a modified environment-- (a more general version of 'local').---- * @'runReaderT' ('withReaderT' f m) = 'runReaderT' m . f@withReaderT::(r' ->r )-- ^ The function to modify the environment.->ReaderT r m a -- ^ Computation to run in the modified environment.->ReaderT r' m a withReaderT f m =ReaderT $runReaderTm .f {-# INLINEwithReaderT#-}instance(Functorm )=>Functor(ReaderT r m )wherefmap f =mapReaderT (fmapf ){-# INLINEfmap#-}#if MIN_VERSION_base(4,2,0) x <$ v =mapReaderT (x <$)v {-# INLINE(<$)#-}#endif instance(Applicativem )=>Applicative(ReaderT r m )wherepure =liftReaderT .pure{-# INLINEpure#-}f <*> v =ReaderT $\r ->runReaderTf r <*>runReaderTv r {-# INLINE(<*>)#-}#if MIN_VERSION_base(4,2,0) u *> v =ReaderT $\r ->runReaderTu r *>runReaderTv r {-# INLINE(*>)#-}u <* v =ReaderT $\r ->runReaderTu r <*runReaderTv r {-# INLINE(<*)#-}#endif #if MIN_VERSION_base(4,10,0) liftA2 f x y =ReaderT $\r ->liftA2f (runReaderTx r )(runReaderTy r ){-# INLINEliftA2#-}#endif instance(Alternativem )=>Alternative(ReaderT r m )whereempty =liftReaderT empty{-# INLINEempty#-}m <|> n =ReaderT $\r ->runReaderTm r <|>runReaderTn r {-# INLINE(<|>)#-}instance(Monadm )=>Monad(ReaderT r m )where#if !(MIN_VERSION_base(4,8,0)) return=lift.return{-# INLINEreturn#-}#endif m >>= k =ReaderT $\r ->doa <-runReaderTm r runReaderT(k a )r {-# INLINE(>>=)#-}#if MIN_VERSION_base(4,8,0) (>> )=(*>)#else m>>k=ReaderT$\r->runReaderTmr>>runReaderTkr#endif {-# INLINE(>>)#-}#if !(MIN_VERSION_base(4,13,0)) fail msg =lift (failmsg ){-# INLINEfail#-}#endif #if MIN_VERSION_base(4,9,0) instance(Fail.MonadFailm )=>Fail.MonadFail(ReaderT r m )wherefail msg =lift (Fail.failmsg ){-# INLINEfail#-}#endif instance(MonadPlusm )=>MonadPlus(ReaderT r m )wheremzero =lift mzero{-# INLINEmzero#-}m `mplus `n =ReaderT $\r ->runReaderTm r `mplus`runReaderTn r {-# INLINEmplus#-}instance(MonadFixm )=>MonadFix(ReaderT r m )wheremfix f =ReaderT $\r ->mfix$\a ->runReaderT(f a )r {-# INLINEmfix#-}instanceMonadTrans (ReaderT r )wherelift =liftReaderT {-# INLINElift#-}instance(MonadIOm )=>MonadIO(ReaderT r m )whereliftIO =lift .liftIO{-# INLINEliftIO#-}#if MIN_VERSION_base(4,4,0) instance(MonadZipm )=>MonadZip(ReaderT r m )wheremzipWith f (ReaderT m )(ReaderT n )=ReaderT $\a ->mzipWithf (m a )(n a ){-# INLINEmzipWith#-}#endif #if MIN_VERSION_base(4,12,0) instanceContravariantm =>Contravariant(ReaderT r m )wherecontramap f =ReaderT .fmap(contramapf ).runReaderT{-# INLINEcontramap#-}#endif liftReaderT::m a ->ReaderT r m a liftReaderT m =ReaderT (constm ){-# INLINEliftReaderT#-}-- | Fetch the value of the environment.ask::(Monadm )=>ReaderT r m r ask =ReaderT return{-# INLINEask#-}-- | Execute a computation in a modified environment-- (a specialization of 'withReaderT').---- * @'runReaderT' ('local' f m) = 'runReaderT' m . f@local::(r ->r )-- ^ The function to modify the environment.->ReaderT r m a -- ^ Computation to run in the modified environment.->ReaderT r m a local =withReaderT {-# INLINElocal#-}-- | Retrieve a function of the current environment.---- * @'asks' f = 'liftM' f 'ask'@asks::(Monadm )=>(r ->a )-- ^ The selector function to apply to the environment.->ReaderT r m a asks f =ReaderT (return.f ){-# INLINEasks#-}-- | Lift a @callCC@ operation to the new monad.liftCallCC::CallCC m a b ->CallCC (ReaderT r m )a b liftCallCC callCC f =ReaderT $\r ->callCC $\c ->runReaderT(f (ReaderT .const.c ))r {-# INLINEliftCallCC#-}-- | Lift a @catchE@ operation to the new monad.liftCatch::Catch e m a ->Catch e (ReaderT r m )a liftCatch f m h =ReaderT $\r ->f (runReaderTm r )(\e ->runReaderT(h e )r ){-# INLINEliftCatch#-}