[project @ 1998-12-02 13:17:09 by simonm]
[ghc-hetmet.git] / ghc / lib / exts / Exception.lhs
1 % -----------------------------------------------------------------------------
2 % $Id: Exception.lhs,v 1.2 1998/12/02 13:26:30 simonm Exp $
3 %
4 % (c) The GRAP/AQUA Project, Glasgow University, 1998
5 %
6
7 The External API for exceptions.  The functions provided in this
8 module allow catching of exceptions in the IO monad.
9
10 \begin{code}
11 module Exception (
12
13         Exception(..),          -- instance Show
14         ArithError(..),         -- instance Show
15
16         -- Throwing exceptions
17
18         throw,                  -- :: Exception -> a
19
20         -- Catching exceptions: The IO interface
21
22         catchException,         -- :: IO a -> (Exception       -> IO a) -> IO a
23         catch,                  -- :: IO a -> (IOError         -> IO a) -> IO a
24
25         catchArith,             -- :: IO a -> (ArithError      -> IO a) -> IO a
26         catchError,             -- :: IO a -> (String          -> IO a) -> IO a
27
28         getException,           -- :: a    -> IO (Maybe Exception)
29         getExceptionIO,         -- :: IO a -> IO (Either Exception a)
30
31         throwDyn,               -- :: Typeable exception => exception -> b
32         catchDyn,               -- :: Typeable exception => 
33                                 --    IO a -> (exception -> IO a) -> IO a
34
35   ) where
36
37 #ifdef __HUGS__
38 import PreludeBuiltin hiding (catch)
39 import Prelude        hiding (catch)
40 #else
41 import Prelude hiding (catch)
42 import PrelGHC (catch#)
43 import PrelException hiding (catch)
44 #endif
45
46 import Dynamic
47 \end{code}
48
49 -----------------------------------------------------------------------------
50 Catch certain types of exception.
51
52 The following family of functions provide exception handling functions
53 for particular kinds of exceptions; all non-matching exceptions being
54 re-raised.
55
56 \begin{code}
57 catchIO = Prelude.catch
58 #ifdef __HUGS__
59 catch   = PreludeBuiltin.catchException
60 #else
61 catch   = PrelException.catchException
62 #endif
63
64 catchArith      :: IO a -> (ArithError -> IO a) -> IO a
65 catchArith m k  = catch m handler
66   where handler (ArithException err) = k err
67         handler other                = throw other
68
69 catchError      :: IO a -> (String -> IO a) -> IO a
70 catchError m k  = catch m handler
71   where handler (ErrorCall err) = k err
72         handler other           = throw other
73 \end{code}
74
75 -----------------------------------------------------------------------------
76 Dynamic exception types.  Since one of the possible kinds of exception
77 is a dynamically typed value, we can effectively have polymorphic
78 exceptions.
79
80 throwDyn will raise any value as an exception, provided it is in the
81 Typeable class (see Dynamic.lhs).  
82
83 catchDyn will catch any exception of a given type (determined by the
84 handler function).  Any raised exceptions that don't match are
85 re-raised.
86
87 \begin{code}
88 throwDyn :: Typeable exception => exception -> b
89 throwDyn exception = throw (DynException (toDyn exception))
90
91 catchDyn :: Typeable exception => IO a -> (exception -> IO a) -> IO a
92 catchDyn m k = catchException m handle
93   where handle ex = case ex of
94                            (DynException dyn) ->
95                                 case fromDynamic dyn of
96                                     Just exception  -> k exception
97                                     Nothing -> throw ex
98                            other -> throw ex
99 \end{code}
100
101 -----------------------------------------------------------------------------
102 Some Useful Functions
103
104 \begin{code}
105 #ifdef __HUGS__
106 getException :: a -> IO (Maybe Exception)
107 getException a = primCatch' (case primForce a of { () -> return Nothing}) (\e -> return (Just e))
108 #else
109 getException :: a -> IO (Maybe Exception)
110 getException a = catch# (a `seq` return Nothing) (\e -> return (Just e))
111 #endif
112
113 getExceptionIO :: IO a -> IO (Either Exception a)
114 getExceptionIO m = catchException (m >>= \ r -> return (Right r)) 
115                                         (\ e -> return (Left  e))
116 \end{code}