This is the simplest of the exception-catching functions. It takes a
single argument, runs it, and if an exception is raised the "handler"
is executed, with the value of the exception passed as an argument.
Otherwise, the result is returned as normal. For example:
catch (readFile f)
(\e -> do let err = show (e :: IOException)
hPutStr stderr ("Warning: Couldn't open " ++ f ++ ": " ++ err)
return "")
Note that we have to give a type signature to
e, or the
program will not typecheck as the type is ambiguous. While it is
possible to catch exceptions of any type, see the section "Catching
all exceptions" (in
Control.Exception) for an explanation of
the problems with doing so.
For catching exceptions in pure (non-
IO) expressions, see the
function
evaluate.
Note that due to Haskell's unspecified evaluation order, an expression
may throw one of several possible exceptions: consider the expression
(error "urk") + (1 `div` 0). Does the expression throw
ErrorCall "urk", or
DivideByZero?
The answer is "it might throw either"; the choice is
non-deterministic. If you are catching any type of exception then you
might catch either. If you are calling
catch with type
IO
Int -> (ArithException -> IO Int) -> IO Int then the
handler may get run with
DivideByZero as an argument, or an
ErrorCall "urk" exception may be propagated further up. If
you call it again, you might get the opposite behaviour. This is ok,
because
catch is an
IO computation.