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