1 -----------------------------------------------------------------------------
3 -- Module : Control.Exception
4 -- Copyright : (c) The University of Glasgow 2001
5 -- License : BSD-style (see the file libraries/core/LICENSE)
7 -- Maintainer : libraries@haskell.org
8 -- Stability : experimental
9 -- Portability : non-portable
11 -- $Id: Exception.hs,v 1.2 2001/07/31 14:34:23 simonmar Exp $
13 -- The External API for exceptions. The functions provided in this
14 -- module allow catching of exceptions in the IO monad.
16 -----------------------------------------------------------------------------
18 module Control.Exception (
20 Exception(..), -- instance Eq, Ord, Show, Typeable
21 IOException, -- instance Eq, Ord, Show, Typeable
22 ArithException(..), -- instance Eq, Ord, Show, Typeable
23 ArrayException(..), -- instance Eq, Ord, Show, Typeable
24 AsyncException(..), -- instance Eq, Ord, Show, Typeable
26 try, -- :: IO a -> IO (Either Exception a)
27 tryJust, -- :: (Exception -> Maybe b) -> a -> IO (Either b a)
29 catch, -- :: IO a -> (Exception -> IO a) -> IO a
30 catchJust, -- :: (Exception -> Maybe b) -> IO a -> (b -> IO a) -> IO a
32 handle, -- :: (Exception -> IO a) -> IO a -> IO a
33 handleJust,-- :: (Exception -> Maybe b) -> (b -> IO a) -> IO a -> IO a
35 evaluate, -- :: a -> IO a
37 -- Exception predicates (for tryJust, catchJust, handleJust)
39 ioErrors, -- :: Exception -> Maybe IOError
40 arithExceptions, -- :: Exception -> Maybe ArithException
41 errorCalls, -- :: Exception -> Maybe String
42 dynExceptions, -- :: Exception -> Maybe Dynamic
43 assertions, -- :: Exception -> Maybe String
44 asyncExceptions, -- :: Exception -> Maybe AsyncException
45 userErrors, -- :: Exception -> Maybe String
47 -- Throwing exceptions
49 throw, -- :: Exception -> a
52 throwTo, -- :: ThreadId -> Exception -> a
57 throwDyn, -- :: Typeable ex => ex -> b
58 throwDynTo, -- :: Typeable ex => ThreadId -> ex -> b
59 catchDyn, -- :: Typeable ex => IO a -> (ex -> IO a) -> IO a
61 -- Async exception control
63 block, -- :: IO a -> IO a
64 unblock, -- :: IO a -> IO a
69 assert, -- :: Bool -> a -> a
73 finally, -- :: IO a -> IO b -> IO b
75 bracket, -- :: IO a -> (a -> IO b) -> (a -> IO c) -> IO ()
76 bracket_, -- :: IO a -> IO b -> IO c -> IO ()
80 #ifdef __GLASGOW_HASKELL__
81 import Prelude hiding (catch)
82 import GHC.Prim ( assert )
83 import GHC.Exception hiding (try, catch, bracket, bracket_)
84 import GHC.Conc ( throwTo, ThreadId )
85 import GHC.IOBase ( IO(..) )
89 import Prelude hiding ( catch )
90 import PrelPrim ( catchException
102 INSTANCE_TYPEABLE0(Exception,exceptionTc,"Exception")
103 INSTANCE_TYPEABLE0(IOException,ioExceptionTc,"IOException")
104 INSTANCE_TYPEABLE0(ArithException,arithExceptionTc,"ArithException")
105 INSTANCE_TYPEABLE0(ArrayException,arrayExceptionTc,"ArrayException")
106 INSTANCE_TYPEABLE0(AsyncException,asyncExceptionTc,"AsyncException")
108 -----------------------------------------------------------------------------
109 -- Catching exceptions
111 -- GHC.Exception defines 'catchException' for us.
113 catch :: IO a -> (Exception -> IO a) -> IO a
114 catch = catchException
116 catchJust :: (Exception -> Maybe b) -> IO a -> (b -> IO a) -> IO a
117 catchJust p a handler = catch a handler'
118 where handler' e = case p e of
122 handle :: (Exception -> IO a) -> IO a -> IO a
125 handleJust :: (Exception -> Maybe b) -> (b -> IO a) -> IO a -> IO a
126 handleJust p = flip (catchJust p)
128 -----------------------------------------------------------------------------
131 evaluate :: a -> IO a
132 evaluate a = a `seq` return a
134 -----------------------------------------------------------------------------
135 -- 'try' and variations.
137 try :: IO a -> IO (Either Exception a)
138 try a = catch (a >>= \ v -> return (Right v)) (\e -> return (Left e))
140 tryJust :: (Exception -> Maybe b) -> IO a -> IO (Either b a)
144 Right v -> return (Right v)
145 Left e -> case p e of
147 Just b -> return (Left b)
149 -----------------------------------------------------------------------------
150 -- Dynamic exception types. Since one of the possible kinds of exception
151 -- is a dynamically typed value, we can effectively have polymorphic
154 -- throwDyn will raise any value as an exception, provided it is in the
155 -- Typeable class (see Dynamic.lhs).
157 -- catchDyn will catch any exception of a given type (determined by the
158 -- handler function). Any raised exceptions that don't match are
161 throwDyn :: Typeable exception => exception -> b
162 throwDyn exception = throw (DynException (toDyn exception))
164 throwDynTo :: Typeable exception => ThreadId -> exception -> IO ()
165 throwDynTo t exception = throwTo t (DynException (toDyn exception))
167 catchDyn :: Typeable exception => IO a -> (exception -> IO a) -> IO a
168 catchDyn m k = catchException m handle
169 where handle ex = case ex of
170 (DynException dyn) ->
171 case fromDynamic dyn of
172 Just exception -> k exception
176 -----------------------------------------------------------------------------
177 -- Exception Predicates
179 ioErrors :: Exception -> Maybe IOError
180 arithExceptions :: Exception -> Maybe ArithException
181 errorCalls :: Exception -> Maybe String
182 dynExceptions :: Exception -> Maybe Dynamic
183 assertions :: Exception -> Maybe String
184 asyncExceptions :: Exception -> Maybe AsyncException
185 userErrors :: Exception -> Maybe String
187 ioErrors e@(IOException _) = Just e
190 arithExceptions (ArithException e) = Just e
191 arithExceptions _ = Nothing
193 errorCalls (ErrorCall e) = Just e
194 errorCalls _ = Nothing
196 assertions (AssertionFailed e) = Just e
197 assertions _ = Nothing
199 dynExceptions (DynException e) = Just e
200 dynExceptions _ = Nothing
202 asyncExceptions (AsyncException e) = Just e
203 asyncExceptions _ = Nothing
205 userErrors (UserError e) = Just e
206 userErrors _ = Nothing
208 -----------------------------------------------------------------------------
209 -- Some Useful Functions
211 bracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
212 bracket before after thing =
217 (\e -> do { after a; throw e })
222 -- finally is an instance of bracket, but it's quite common
223 -- so we give the specialised version for efficiency.
224 finally :: IO a -> IO b -> IO a
229 (\e -> do { sequel; throw e })
234 bracket_ :: IO a -> IO b -> IO c -> IO c
235 bracket_ before after thing = bracket before (const after) (const thing)