1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
{- |
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.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 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 f = do
r <- ask
return (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
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
-- ---------------------------------------------------------------------------
-- Instances for other mtl transformers
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
|