catch -cgi

The catch function establishes a handler that receives any IOError raised in the action protected by catch. An IOError is caught by the most recent handler established by catch. These handlers are not selective: all IOErrors are caught. Exception propagation must be explicitly provided in a handler by re-raising any unwanted exceptions. For example, in
> f = catch g (\e -> if IO.isEOFError e then return [] else ioError e)
the function f returns [] when an end-of-file exception (cf. isEOFError) occurs in g; otherwise, the exception is propagated to the next outer handler.
When an exception propagates outside the main program, the Haskell system prints the associated IOError value and exits the program.
Non-I/O exceptions are not caught by this variant; to catch all exceptions, use Control.Exception.catch from Control.Exception.

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 (openFile f ReadMode)
> (\e -> hPutStr stderr ("Couldn't open "++f++": " ++ show e))
For catching exceptions in pure (non-IO) expressions, see the function evaluate.
Note that due to Haskell's unspecified evaluation order, an expression may return one of several possible exceptions: consider the expression error "urk" + 1 `div` 0. Does catch execute the handler passing ErrorCall "urk", or ArithError DivideByZero?
The answer is "either": catch makes a non-deterministic choice about which exception to catch. If you call it again, you might get a different exception back. This is ok, because catch is an IO computation.
Note that catch catches all types of exceptions, and is generally used for "cleaning up" before passing on the exception using throwIO. It is not good practice to discard the exception and continue, without first checking the type of the exception (it might be a ThreadKilled, for example). In this case it is usually better to use catchJust and select the kinds of exceptions to catch.
Also note that the Prelude also exports a function called Prelude.catch with a similar type to catch, except that the Prelude version only catches the IO and user families of exceptions (as required by Haskell 98).
We recommend either hiding the Prelude version of Prelude.catch when importing Control.OldException:
> import Prelude hiding (catch)
or importing Control.OldException qualified, to avoid name-clashes:
> import qualified Control.OldException as C
and then using C.catch

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 previous section "Catching all exceptions" 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 propogated further up. If you call it again, you might get a the opposite behaviour. This is ok, because catch is an IO computation.
Note that the Prelude also exports a function called Prelude.catch with a similar type to Control.Exception.catch, except that the Prelude version only catches the IO and user families of exceptions (as required by Haskell 98).
We recommend either hiding the Prelude version of Prelude.catch when importing Control.Exception:
> import Prelude hiding (catch)
or importing Control.Exception qualified, to avoid name-clashes:
> import qualified Control.Exception as C
and then using C.catch

Catch dynamic exceptions of the required type. All other exceptions are re-thrown, including dynamic exceptions of the wrong type.
When using dynamic exceptions it is advisable to define a new datatype to use for your exception type, to avoid possible clashes with dynamic exceptions used in other libraries.

Sometimes you want to catch two different sorts of exception. You could do something like
> f = expr `catch` \ (ex :: ArithException) -> handleArith ex
> `catch` \ (ex :: IOException) -> handleIO ex
However, there are a couple of problems with this approach. The first is that having two exception handlers is inefficient. However, the more serious issue is that the second exception handler will catch exceptions in the first, e.g. in the example above, if handleArith throws an IOException then the second exception handler will catch it.
Instead, we provide a function catches, which would be used thus:
> f = expr `catches` [Handler (\ (ex :: ArithException) -> handleArith ex),
> Handler (\ (ex :: IOException) -> handleIO ex)]

The function catchJust is like catch, but it takes an extra argument which is an exception predicate, a function which selects which type of exceptions we're interested in. There are some predefined exception predicates for useful subsets of exceptions: ioErrors, arithExceptions, and so on. For example, to catch just calls to the error function, we could use
> result <- catchJust errorCalls thing_to_try handler
Any other exceptions which are not matched by the predicate are re-raised, and may be caught by an enclosing catch or catchJust.

The function catchJust is like catch, but it takes an extra argument which is an exception predicate, a function which selects which type of exceptions we're interested in.
> catchJust (\e -> if isDoesNotExistErrorType (ioeGetErrorType e) then Just () else Nothing)
> (readFile f)
> (\_ -> do hPutStrLn stderr ("No such file: " ++ show f)
> return "")
Any other exceptions which are not matched by the predicate are re-raised, and may be caught by an enclosing catch, catchJust, etc.