Line
1{-# OPTIONS -fallow-undecidable-instances #-}
2{- |
4Copyright   :  (c) Andy Gill 2001,
5               (c) Oregon Graduate Institute of Science and Technology 2001,
6               (c) Jeff Newbern 2003-2007,
7               (c) Andriy Palamarchuk 2007
9
11Stability   :  experimental
12Portability :  non-portable (multi-param classes, functional dependencies)
13
14[Computation type:] Computations which read values from a shared environment.
15
16[Binding strategy:] Monad values are functions from the environment to a value.
17The bound function is applied to the bound value, and both have access
18to the shared environment.
19
20[Useful for:] Maintaining variable bindings, or other shared environment.
21
22[Zero and plus:] None.
23
25
27Represents a computation, which can read values from
28a shared environment, pass values from function to function,
29and execute sub-computations in a modified environment.
32
33  Inspired by the paper
35      Higher-Order Polymorphism/,
36    Mark P Jones (<http://www.cse.ogi.edu/~mpj/>)
37    Advanced School of Functional Programming, 1995.
38-}
39
51    -- * Example 1: Simple Reader Usage
53
54    -- * Example 2: Modifying Reader Content With @local@
55    -- \$localExample
56
59    ) where
60
70
71-- ----------------------------------------------------------------------------
73
76    local f m = m . f
77
78{- |
80
81The @return@ function creates a @Reader@ that ignores the environment,
82and produces the given value.
83
84The binding operator @>>=@ produces a @Reader@ that uses the environment
85to extract the value its left-hand side,
86and then applies the bound function to that value in the same environment.
87-}
89    {- |
90    Runs @Reader@ and extracts the final value from it.
91    To extract the value apply @(runReader reader)@ to an environment value.
92    Parameters:
93
94    * A @Reader@ to run.
95
96    * An initial environment.
97    -}
99}
100
103
104-- | A more general version of 'local'.
105
108
110    fmap f m = Reader \$ \r -> f (runReader m r)
111
113    return a = Reader \$ \_ -> a
115
117    mfix f = Reader \$ \r -> let a = runReader (f a) r in a
118
122
123{- |
126-}
128
129mapReaderT :: (m a -> n b) -> ReaderT w m a -> ReaderT w n b
131
134
136    fmap f m = ReaderT \$ \r -> do
137        a <- runReaderT m r
138        return (f a)
139
141    return a = ReaderT \$ \_ -> return a
142    m >>= k  = ReaderT \$ \r -> do
143        a <- runReaderT m r
145    fail msg = ReaderT \$ \_ -> fail msg
146
148    mzero       = ReaderT \$ \_ -> mzero
150
152    mfix f = ReaderT \$ \r -> mfix \$ \a -> runReaderT (f a) r
153
156    local f m = ReaderT \$ \r -> runReaderT m (f r)
157
158-- ---------------------------------------------------------------------------
159-- Instances for other mtl transformers
160
162    lift m = ReaderT \$ \_ -> m
163
165    liftIO = lift . liftIO
166
168    callCC f = ReaderT \$ \r ->
169        callCC \$ \c ->
170        runReaderT (f (\a -> ReaderT \$ \_ -> c a)) r
171
173    throwError       = lift . throwError
174    m `catchError` h = ReaderT \$ \r -> runReaderT m r
175        `catchError` \e -> runReaderT (h e) r
176
177-- Needs -fallow-undecidable-instances
179    get = lift get
180    put = lift . put
181
182-- This instance needs -fallow-undecidable-instances, because
183-- it does not satisfy the coverage condition
185    tell     = lift . tell
186    listen m = ReaderT \$ \w -> listen (runReaderT m w)
187    pass   m = ReaderT \$ \w -> pass   (runReaderT m w)
188
190
192Bindings are a 'Map' of integer variables.
193The variable @count@ contains number of variables in the bindings.
194You can see how to run a Reader monad and retrieve data from it
196
197> type Bindings = Map String Int;
198>
199>-- Returns True if the "count" variable contains correct bindings size.
200>isCountCorrect :: Bindings -> Bool
201>isCountCorrect bindings = runReader calc_isCountCorrect bindings
202>
205>calc_isCountCorrect = do
206>    count <- asks (lookupVar "count")
208>    return (count == (Map.size bindings))
209>
210>-- The selector function to  use with 'asks'.
211>-- Returns value of the variable with specified name.
212>lookupVar :: String -> Bindings -> Int
213>lookupVar name bindings = fromJust (Map.lookup name bindings)
214>
215>sampleBindings = Map.fromList [("count",3), ("1",1), ("b",2)]
216>
217>main = do
218>    putStr \$ "Count is correct for bindings " ++ (show sampleBindings) ++ ": ";
219>    putStrLn \$ show (isCountCorrect sampleBindings);
220-}
221
222{- \$localExample
223
224Shows how to modify Reader content with 'local'.
225
227>calculateContentLen = do
229>    return (length content);
230>
233>calculateModifiedContentLen = local ("Prefix " ++) calculateContentLen
234>
235>main = do
236>    let s = "12345";
237>    let modifiedLen = runReader calculateModifiedContentLen s
238>    let len = runReader calculateContentLen s
239>    putStrLn \$ "Modified 's' length: " ++ (show modifiedLen)
240>    putStrLn \$ "Original 's' length: " ++ (show len)
241-}
242
244
245Now you are thinking: 'Wow, what a great monad! I wish I could use