repository initialized
[packages/mtl.git] / Control / Monad / Error / Class.hs
1 {-# LANGUAGE UndecidableInstances #-}
2
3 {- |
4 Module : Control.Monad.Error.Class
5 Copyright : (c) Michael Weber <michael.weber@post.rwth-aachen.de> 2001,
6 (c) Jeff Newbern 2003-2006,
7 (c) Andriy Palamarchuk 2006
8 License : BSD-style (see the file LICENSE)
9
10 Maintainer : libraries@haskell.org
11 Stability : experimental
12 Portability : non-portable (multi-parameter type classes)
13
14 [Computation type:] Computations which may fail or throw exceptions.
15
16 [Binding strategy:] Failure records information about the cause\/location
17 of the failure. Failure values bypass the bound function,
18 other values are used as inputs to the bound function.
19
20 [Useful for:] Building computations from sequences of functions that may fail
21 or using exception handling to structure error handling.
22
23 [Zero and plus:] Zero is represented by an empty error and the plus operation
24 executes its second argument if the first fails.
25
26 [Example type:] @'Either' 'String' a@
27
28 The Error monad (also called the Exception monad).
29 -}
30
31 {-
32 Rendered by Michael Weber <mailto:michael.weber@post.rwth-aachen.de>,
33 inspired by the Haskell Monad Template Library from
34 Andy Gill (<http://web.cecs.pdx.edu/~andy/>)
35 -}
36 module Control.Monad.Error.Class (
37 Error(..),
38 MonadError(..),
39 ) where
40
41 import Control.Monad.Trans.Error (Error(..), ErrorT)
42 import qualified Control.Monad.Trans.Error as ErrorT (throwError, catchError)
43 import Control.Monad.Trans.Identity as Identity
44 import Control.Monad.Trans.List as List
45 import Control.Monad.Trans.Maybe as Maybe
46 import Control.Monad.Trans.Reader as Reader
47 import Control.Monad.Trans.RWS.Lazy as LazyRWS
48 import Control.Monad.Trans.RWS.Strict as StrictRWS
49 import Control.Monad.Trans.State.Lazy as LazyState
50 import Control.Monad.Trans.State.Strict as StrictState
51 import Control.Monad.Trans.Writer.Lazy as LazyWriter
52 import Control.Monad.Trans.Writer.Strict as StrictWriter
53
54 import Control.Monad.Trans.Class (lift)
55 import Control.Exception (IOException)
56 import Control.Monad
57 import Control.Monad.Instances ()
58 import Data.Monoid
59
60 {- |
61 The strategy of combining computations that can throw exceptions
62 by bypassing bound functions
63 from the point an exception is thrown to the point that it is handled.
64
65 Is parameterized over the type of error information and
66 the monad type constructor.
67 It is common to use @'Data.Either' String@ as the monad type constructor
68 for an error monad in which error descriptions take the form of strings.
69 In that case and many other common cases the resulting monad is already defined
70 as an instance of the 'MonadError' class.
71 You can also define your own error type and\/or use a monad type constructor
72 other than @'Either' 'String'@ or @'Either' 'IOError'@.
73 In these cases you will have to explicitly define instances of the 'Error'
74 and\/or 'MonadError' classes.
75 -}
76 class (Monad m) => MonadError e m | m -> e where
77 -- | Is used within a monadic computation to begin exception processing.
78 throwError :: e -> m a
79
80 {- |
81 A handler function to handle previous errors and return to normal execution.
82 A common idiom is:
83
84 > do { action1; action2; action3 } `catchError` handler
85
86 where the @action@ functions can call 'throwError'.
87 Note that @handler@ and the do-block must have the same return type.
88 -}
89 catchError :: m a -> (e -> m a) -> m a
90
91 instance MonadError IOException IO where
92 throwError = ioError
93 catchError = catch
94
95 -- ---------------------------------------------------------------------------
96 -- Our parameterizable error monad
97
98 instance (Error e) => MonadError e (Either e) where
99 throwError = Left
100 Left l `catchError` h = h l
101 Right r `catchError` _ = Right r
102
103 instance (Monad m, Error e) => MonadError e (ErrorT e m) where
104 throwError = ErrorT.throwError
105 catchError = ErrorT.catchError
106
107 -- ---------------------------------------------------------------------------
108 -- Instances for other mtl transformers
109 --
110 -- All of these instances need UndecidableInstances,
111 -- because they do not satisfy the coverage condition.
112
113 instance (MonadError e m) => MonadError e (IdentityT m) where
114 throwError = lift . throwError
115 catchError = Identity.liftCatch catchError
116
117 instance (MonadError e m) => MonadError e (ListT m) where
118 throwError = lift . throwError
119 catchError = List.liftCatch catchError
120
121 instance (MonadError e m) => MonadError e (MaybeT m) where
122 throwError = lift . throwError
123 catchError = Maybe.liftCatch catchError
124
125 instance (MonadError e m) => MonadError e (ReaderT r m) where
126 throwError = lift . throwError
127 catchError = Reader.liftCatch catchError
128
129 instance (Monoid w, MonadError e m) => MonadError e (LazyRWS.RWST r w s m) where
130 throwError = lift . throwError
131 catchError = LazyRWS.liftCatch catchError
132
133 instance (Monoid w, MonadError e m) => MonadError e (StrictRWS.RWST r w s m) where
134 throwError = lift . throwError
135 catchError = StrictRWS.liftCatch catchError
136
137 instance (MonadError e m) => MonadError e (LazyState.StateT s m) where
138 throwError = lift . throwError
139 catchError = LazyState.liftCatch catchError
140
141 instance (MonadError e m) => MonadError e (StrictState.StateT s m) where
142 throwError = lift . throwError
143 catchError = StrictState.liftCatch catchError
144
145 instance (Monoid w, MonadError e m) => MonadError e (LazyWriter.WriterT w m) where
146 throwError = lift . throwError
147 catchError = LazyWriter.liftCatch catchError
148
149 instance (Monoid w, MonadError e m) => MonadError e (StrictWriter.WriterT w m) where
150 throwError = lift . throwError
151 catchError = StrictWriter.liftCatch catchError