add SelectT monad transformer
[packages/transformers.git] / Control / Monad / Trans / Class.hs
1 {-# LANGUAGE CPP #-}
2 #if __GLASGOW_HASKELL__ >= 702
3 {-# LANGUAGE Safe #-}
4 #endif
5 #if __GLASGOW_HASKELL__ >= 710
6 {-# LANGUAGE AutoDeriveTypeable #-}
7 #endif
8 -----------------------------------------------------------------------------
9 -- |
10 -- Module : Control.Monad.Trans.Class
11 -- Copyright : (c) Andy Gill 2001,
12 -- (c) Oregon Graduate Institute of Science and Technology, 2001
13 -- License : BSD-style (see the file LICENSE)
14 --
15 -- Maintainer : R.Paterson@city.ac.uk
16 -- Stability : experimental
17 -- Portability : portable
18 --
19 -- The class of monad transformers.
20 --
21 -- A monad transformer makes a new monad out of an existing monad, such
22 -- that computations of the old monad may be embedded in the new one.
23 -- To construct a monad with a desired set of features, one typically
24 -- starts with a base monad, such as 'Data.Functor.Identity.Identity', @[]@ or 'IO', and
25 -- applies a sequence of monad transformers.
26 -----------------------------------------------------------------------------
27
28 module Control.Monad.Trans.Class (
29 -- * Transformer class
30 MonadTrans(..)
31
32 -- * Conventions
33 -- $conventions
34
35 -- * Strict monads
36 -- $strict
37
38 -- * Examples
39 -- ** Parsing
40 -- $example1
41
42 -- ** Parsing and counting
43 -- $example2
44
45 -- ** Interpreter monad
46 -- $example3
47 ) where
48
49 -- | The class of monad transformers. Instances should satisfy the
50 -- following laws, which state that 'lift' is a monad transformation:
51 --
52 -- * @'lift' . 'return' = 'return'@
53 --
54 -- * @'lift' (m >>= f) = 'lift' m >>= ('lift' . f)@
55
56 class MonadTrans t where
57 -- | Lift a computation from the argument monad to the constructed monad.
58 lift :: (Monad m) => m a -> t m a
59
60 {- $conventions
61 Most monad transformer modules include the special case of applying
62 the transformer to 'Data.Functor.Identity.Identity'. For example,
63 @'Control.Monad.Trans.State.Lazy.State' s@ is an abbreviation for
64 @'Control.Monad.Trans.State.Lazy.StateT' s 'Data.Functor.Identity.Identity'@.
65
66 Each monad transformer also comes with an operation @run@/XXX/@T@ to
67 unwrap the transformer, exposing a computation of the inner monad.
68 (Currently these functions are defined as field labels, but in the next
69 major release they will be separate functions.)
70
71 All of the monad transformers except 'Control.Monad.Trans.Cont.ContT'
72 and 'Control.Monad.Trans.Cont.SelectT' are functors on the category
73 of monads: in addition to defining a mapping of monads, they
74 also define a mapping from transformations between base monads to
75 transformations between transformed monads, called @map@/XXX/@T@.
76 Thus given a monad transformation @t :: M a -> N a@, the combinator
77 'Control.Monad.Trans.State.Lazy.mapStateT' constructs a monad
78 transformation
79
80 > mapStateT t :: StateT s M a -> StateT s N a
81
82 For these monad transformers, 'lift' is a natural transformation in the
83 category of monads, i.e. for any monad transformation @t :: M a -> N a@,
84
85 * @map@/XXX/@T t . 'lift' = 'lift' . t@
86
87 Each of the monad transformers introduces relevant operations.
88 In a sequence of monad transformers, most of these operations.can be
89 lifted through other transformers using 'lift' or the @map@/XXX/@T@
90 combinator, but a few with more complex type signatures require
91 specialized lifting combinators, called @lift@/Op/
92 (see "Control.Monad.Signatures").
93 -}
94
95 {- $strict
96
97 A monad is said to be /strict/ if its '>>=' operation is strict in its first
98 argument. The base monads 'Maybe', @[]@ and 'IO' are strict:
99
100 >>> undefined >> return 2 :: Maybe Integer
101 *** Exception: Prelude.undefined
102
103 However the monad 'Data.Functor.Identity.Identity' is not:
104
105 >>> runIdentity (undefined >> return 2)
106 2
107
108 In a strict monad you know when each action is executed, but the monad
109 is not necessarily strict in the return value, or in other components
110 of the monad, such as a state. However you can use 'seq' to create
111 an action that is strict in the component you want evaluated.
112 -}
113
114 {- $example1
115
116 One might define a parsing monad by adding a state (the 'String' remaining
117 to be parsed) to the @[]@ monad, which provides non-determinism:
118
119 > import Control.Monad.Trans.State
120 >
121 > type Parser = StateT String []
122
123 Then @Parser@ is an instance of @MonadPlus@: monadic sequencing implements
124 concatenation of parsers, while @mplus@ provides choice. To use parsers,
125 we need a primitive to run a constructed parser on an input string:
126
127 > runParser :: Parser a -> String -> [a]
128 > runParser p s = [x | (x, "") <- runStateT p s]
129
130 Finally, we need a primitive parser that matches a single character,
131 from which arbitrarily complex parsers may be constructed:
132
133 > item :: Parser Char
134 > item = do
135 > c:cs <- get
136 > put cs
137 > return c
138
139 In this example we use the operations @get@ and @put@ from
140 "Control.Monad.Trans.State", which are defined only for monads that are
141 applications of 'Control.Monad.Trans.State.Lazy.StateT'. Alternatively one
142 could use monad classes from the @mtl@ package or similar, which contain
143 methods @get@ and @put@ with types generalized over all suitable monads.
144 -}
145
146 {- $example2
147
148 We can define a parser that also counts by adding a
149 'Control.Monad.Trans.Writer.Lazy.WriterT' transformer:
150
151 > import Control.Monad.Trans.Class
152 > import Control.Monad.Trans.State
153 > import Control.Monad.Trans.Writer
154 > import Data.Monoid
155 >
156 > type Parser = WriterT (Sum Int) (StateT String [])
157
158 The function that applies a parser must now unwrap each of the monad
159 transformers in turn:
160
161 > runParser :: Parser a -> String -> [(a, Int)]
162 > runParser p s = [(x, n) | ((x, Sum n), "") <- runStateT (runWriterT p) s]
163
164 To define the @item@ parser, we need to lift the
165 'Control.Monad.Trans.State.Lazy.StateT' operations through the
166 'Control.Monad.Trans.Writer.Lazy.WriterT' transformer.
167
168 > item :: Parser Char
169 > item = do
170 > c:cs <- lift get
171 > lift (put cs)
172 > return c
173
174 In this case, we were able to do this with 'lift', but operations with
175 more complex types require special lifting functions, which are provided
176 by monad transformers for which they can be implemented. If you use the
177 monad classes of the @mtl@ package or similar, this lifting is handled
178 automatically by the instances of the classes, and you need only use
179 the generalized methods @get@ and @put@.
180
181 We can also define a primitive using the Writer:
182
183 > tick :: Parser ()
184 > tick = tell (Sum 1)
185
186 Then the parser will keep track of how many @tick@s it executes.
187 -}
188
189 {- $example3
190
191 This example is a cut-down version of the one in
192 \"Monad Transformers and Modular Interpreters\",
193 by Sheng Liang, Paul Hudak and Mark Jones in /POPL'95/
194 (<http://web.cecs.pdx.edu/~mpj/pubs/modinterp.html>).
195
196 Suppose we want to define an interpreter that can do I\/O and has
197 exceptions, an environment and a modifiable store. We can define
198 a monad that supports all these things as a stack of monad transformers:
199
200 > import Control.Monad.Trans.Class
201 > import Control.Monad.Trans.State
202 > import qualified Control.Monad.Trans.Reader as R
203 > import qualified Control.Monad.Trans.Except as E
204 > import Control.Monad.IO.Class
205 >
206 > type InterpM = StateT Store (R.ReaderT Env (E.ExceptT Err IO))
207
208 for suitable types @Store@, @Env@ and @Err@.
209
210 Now we would like to be able to use the operations associated with each
211 of those monad transformers on @InterpM@ actions. Since the uppermost
212 monad transformer of @InterpM@ is 'Control.Monad.Trans.State.Lazy.StateT',
213 it already has the state operations @get@ and @set@.
214
215 The first of the 'Control.Monad.Trans.Reader.ReaderT' operations,
216 'Control.Monad.Trans.Reader.ask', is a simple action, so we can lift it
217 through 'Control.Monad.Trans.State.Lazy.StateT' to @InterpM@ using 'lift':
218
219 > ask :: InterpM Env
220 > ask = lift R.ask
221
222 The other 'Control.Monad.Trans.Reader.ReaderT' operation,
223 'Control.Monad.Trans.Reader.local', has a suitable type for lifting
224 using 'Control.Monad.Trans.State.Lazy.mapStateT':
225
226 > local :: (Env -> Env) -> InterpM a -> InterpM a
227 > local f = mapStateT (R.local f)
228
229 We also wish to lift the operations of 'Control.Monad.Trans.Except.ExceptT'
230 through both 'Control.Monad.Trans.Reader.ReaderT' and
231 'Control.Monad.Trans.State.Lazy.StateT'. For the operation
232 'Control.Monad.Trans.Except.throwE', we know @throwE e@ is a simple
233 action, so we can lift it through the two monad transformers to @InterpM@
234 with two 'lift's:
235
236 > throwE :: Err -> InterpM a
237 > throwE e = lift (lift (E.throwE e))
238
239 The 'Control.Monad.Trans.Except.catchE' operation has a more
240 complex type, so we need to use the special-purpose lifting function
241 @liftCatch@ provided by most monad transformers. Here we use
242 the 'Control.Monad.Trans.Reader.ReaderT' version followed by the
243 'Control.Monad.Trans.State.Lazy.StateT' version:
244
245 > catchE :: InterpM a -> (Err -> InterpM a) -> InterpM a
246 > catchE = liftCatch (R.liftCatch E.catchE)
247
248 We could lift 'IO' actions to @InterpM@ using three 'lift's, but @InterpM@
249 is automatically an instance of 'Control.Monad.IO.Class.MonadIO',
250 so we can use 'Control.Monad.IO.Class.liftIO' instead:
251
252 > putStr :: String -> InterpM ()
253 > putStr s = liftIO (Prelude.putStr s)
254
255 -}