Next Previous Contents

6.1 The try functions

There are several functions for catching and examining exceptions; all of them may only be used from within the IO monad. Firstly the try family of functions:

tryAll    :: a    -> IO (Either Exception a)
tryAllIO  :: IO a -> IO (Either Exception a)
try       :: (Exception -> Maybe b) -> a    -> IO (Either b a)
tryIO     :: (Exception -> Maybe b) -> IO a -> IO (Either b a)

The simplest version is tryAll. It takes a single argument, evaluates it (as if you'd applied seq to it), and returns either Right a if the evaluation succeeded with result a, or Left e if an exception was raised, where e is the exception. 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 tryAll return Just (ErrorCall "urk") or Just (ArithError DivideByZero)? The answer is "either": tryAll makes a non-deterministic choice about which exception to return. If you call it again, you might get a different exception back. This is ok, because tryAll is an IO computation.

tryAllIO is the same as tryAll except that the argument to evaluate is an IO computation. Don't try to use tryAll to catch exceptions in IO computations: in GHC an expression of type IO a is in fact a function, so evaluating it does nothing at all (and therefore raises no exceptions). Hence the need for tryAllIO, which runs IO computations properly.

The functions try and tryIO take an extra argument which is an exception predicate, a function which selects which type of exceptions we're interested in. The full set of exception predicates is given below:

justIoErrors            :: Exception -> Maybe IOError
justArithExceptions     :: Exception -> Maybe ArithException
justErrors              :: Exception -> Maybe String
justDynExceptions       :: Exception -> Maybe Dynamic
justAssertions          :: Exception -> Maybe String
justAsyncExceptions     :: Exception -> Maybe AsyncException

For example, to catch just calls to 'error' we could use something like

    result <- try justErrors thing_to_try

Any other exceptions which aren't matched by the predicate are re-raised, and may be caught by an enclosing try or catch.


Next Previous Contents