[project @ 2000-01-18 14:40:06 by simonmar]
[ghc-hetmet.git] / ghc / docs / libraries / Exception.sgml
1 <sect> <idx/Exception/ 
2 <label id="sec:Exception">
3 <p>
4
5 The Exception library provides an interface for raising and catching
6 both built-in and user defined exceptions.
7
8 Exceptions are defined by the following (non-abstract) datatype:
9
10 <tscreen><verb>
11 data Exception
12   = IOException         IOError         -- IO exceptions (from 'fail')
13   | ArithException      ArithException  -- Arithmetic exceptions
14   | ErrorCall           String          -- Calls to 'error'
15   | NoMethodError       String          -- A non-existent method was invoked
16   | PatternMatchFail    String          -- A pattern match failed
17   | NonExhaustiveGuards String          -- A guard match failed
18   | RecSelError         String          -- Selecting a non-existent field
19   | RecConError         String          -- Field missing in record construction
20   | RecUpdError         String          -- Record doesn't contain updated field
21   | AssertionFailed     String          -- Assertions
22   | DynException        Dynamic         -- Dynamic exceptions
23   | AsyncException      AsyncException  -- Externally generated errors
24
25 instance Eq   Exception
26 instance Ord  Exception
27 instance Show Exception
28
29 data ArithException
30   = Overflow
31   | Underflow
32   | LossOfPrecision
33   | DivideByZero
34   | Denormal
35
36 instance Eq   ArithError
37 instance Ord  ArithError
38 instance Show ArithError
39
40 data AsyncException
41   = StackOverflow
42   | HeapOverflow
43   | ThreadKilled
44   deriving (Eq, Ord)
45
46 instance Eq   AsyncException
47 instance Ord  AsyncException
48 instance Show AsyncException
49 </verb></tscreen>
50
51 An implementation should raise the appropriate exception when one of
52 the above conditions arises.  <em>Note: GHC currently doesn't generate
53 the arithmetic or the async exceptions.</em>
54
55 Exceptions may be thrown explicitly from anywhere:
56
57 <tscreen><verb>
58 throw :: Exception -> a
59 </verb></tscreen>
60
61 <sect1> The <tt/try/ functions
62 <p>
63
64 There are several functions for catching and examining exceptions; all
65 of them may only be used from within the <tt/IO/ monad.  Firstly the
66 <tt/try/ family of functions:
67
68 <tscreen><verb>
69 tryAll    :: a    -> IO (Either Exception a)
70 tryAllIO  :: IO a -> IO (Either Exception a)
71 try       :: (Exception -> Maybe b) -> a    -> IO (Either b a)
72 tryIO     :: (Exception -> Maybe b) -> IO a -> IO (Either b a)
73 </verb></tscreen>
74
75 The simplest version is <tt/tryAll/.  It takes a single argument,
76 evaluates it (as if you'd applied <tt/seq/ to it), and returns either
77 <tt/Right a/ if the evaluation succeeded with result <tt/a/, or
78 <tt/Left e/ if an exception was raised, where <tt/e/ is the exception.
79 Note that due to Haskell's unspecified evaluation order, an expression
80 may return one of several possible exceptions: consider the expression
81 <tt/error "urk" + 1 `div` 0/.  Does <tt/tryAll/ return <tt/Just
82 (ErrorCall "urk")/ or <tt/Just (ArithError DivideByZero)/?  The answer
83 is "either": <tt/tryAll/ makes a non-deterministic choice about which
84 exception to return.  If you call it again, you might get a different
85 exception back.  This is ok, because <tt/tryAll/ is an IO
86 computation.
87
88 <tt/tryAllIO/ is the same as <tt/tryAll/ except that the argument to
89 evaluate is an <tt/IO/ computation.  Don't try to use <tt/tryAll/ to
90 catch exceptions in <tt/IO/ computations: in GHC an expression of type
91 <tt/IO a/ is in fact a function, so evaluating it does nothing at all
92 (and therefore raises no exceptions).  Hence the need for
93 <tt/tryAllIO/, which runs <tt/IO/ computations properly.
94
95 The functions <tt/try/ and <tt/tryIO/ take an extra argument which is
96 an <em/exception predicate/, a function which selects which type of
97 exceptions we're interested in.  The full set of exception predicates
98 is given below:
99
100 <tscreen><verb>
101 justIoErrors            :: Exception -> Maybe IOError
102 justArithExceptions     :: Exception -> Maybe ArithException
103 justErrors              :: Exception -> Maybe String
104 justDynExceptions       :: Exception -> Maybe Dynamic
105 justAssertions          :: Exception -> Maybe String
106 justAsyncExceptions     :: Exception -> Maybe AsyncException
107 </verb></tscreen>
108
109 For example, to catch just calls to 'error' we could use something
110 like
111
112 <tscreen><verb>
113     result <- try justErrors thing_to_try
114 </verb></tscreen>
115
116 Any other exceptions which aren't matched by the predicate are
117 re-raised, and may be caught by an enclosing <tt/try/ or <tt/catch/.
118
119 <sect1> The <tt/catch/ functions
120 <p>
121
122 The <tt/catch/ family is similar to the <tt/try/ family:
123
124 <tscreen><verb>
125 catchAll   :: a    -> (Exception -> IO a) -> IO a
126 catchAllIO :: IO a -> (Exception -> IO a) -> IO a
127 catch      :: (Exception -> Maybe b) -> a    -> (b -> IO a) -> IO a
128 catchIO    :: (Exception -> Maybe b) -> IO a -> (b -> IO a) -> IO a
129 </verb></tscreen>
130
131 The difference is that instead of returning an <tt/Either/ type as the
132 result, the <tt/catch/ functions take a <em/handler/ argument which is
133 invoked in the case that an exception was raised while evaluating the
134 first argument.
135
136 <tt/catch/ and <tt/catchIO/ take exception predicate arguments in the
137 same way as <tt/try/ and <tt/tryIO/.
138
139 Note that <tt/catchIO justIoErrors/ is identical to <tt/IO.catch/.  In
140 fact, the implementation of <tt/IO/ errors in GHC uses exceptions
141 "under the hood".
142
143 Also, don't forget to <tt/import Prelude hidiing (catch)/ when using
144 this library, to avoid the name clash between <tt/Exception.catch/ and
145 <tt/IO.catch/.
146
147 <sect1> <idx/Dynamic Exceptions/ 
148 <label id="sec:Dynamic-Exceptions">
149 <p>
150
151 Because the <tt/Exception/ datatype isn't extendible, we added an
152 interface for throwing and catching exceptions of type <tt/Dynamic/
153 (see Section <ref name="Dynamic" id="sec:Dynamic">), which allows
154 exception values of any type in the <tt/Typeable/ class to be thrown
155 and caught.
156
157 <tscreen><verb>
158 throwDyn :: Typeable exception => exception -> b
159 catchDyn :: Typeable exception => IO a -> (exception -> IO a) -> IO a
160 </verb></tscreen>
161
162 The <tt/catchDyn/ function only catches exceptions of the required
163 type; all other exceptions are re-thrown as with <tt/catchIO/ and
164 friends above.
165
166 <sect1> Other Utilities
167 <p>
168
169 The <tt/bracket/ functions are useful for making sure that resources are
170 released properly by code that may raise exceptions:
171
172 <tscreen><verb>
173         bracket         :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
174         bracket_        :: IO a -> IO b -> IO c -> IO c
175         finally         :: IO a -> IO b -> IO b
176 </verb></tscreen>
177
178 For example, to open a file, do some work on it and then close it
179 again, we might use something like:
180
181 <tscreen><verb>
182 process_file = bracket (openFile "filename") closeFile 
183                (do 
184                  ...
185                 )
186 </verb></tscreen>
187
188 <tt/bracket/ works as follows: it executes its first argument
189 ("open"), then its third argument, followed finally by its second
190 argument ("close").  If the third argument happened to raise an
191 exception, then the close operation will still be performed, and the
192 exception will be re-raised.  
193
194 This means that in the example above the file will always be closed,
195 even if an error occurs during processing.
196
197 The arguments to <tt/bracket/ are in this order so that we can
198 partially apply it, like:
199
200 <tscreen><verb>
201 withFile name = bracket (openFile name) closeFile
202 </verb></tscreen>
203
204 The <tt/bracket_/ function is a variant of <tt/bracket/ that throws
205 away the result of the open, and <tt/finally/ is an even simpler
206 version where we just want some closing code.