The Exception library provides an interface for raising and catching both built-in and user defined exceptions.
Exceptions are defined by the following (non-abstract) datatype:
data Exception
= IOException IOError -- IO exceptions (from 'fail')
| ArithException ArithError -- Arithmetic exceptions
| ErrorCall String -- Calls to 'error'
| NoMethodError String -- A non-existent method was invoked
| PatternMatchFail String -- A pattern match failed
| NonExhaustiveGuards String -- A guard match failed
| RecSelError String -- Selecting a non-existent field
| RecConError String -- Field missing in record construction
| RecUpdError String -- Record doesn't contain updated field
| AssertionFailed String -- Assertions
| DynException Dynamic -- Dynamic exceptions
| ExternalException ExtError -- External exceptions
instance Eq Exception
instance Ord Exception
instance Show Exception
data ArithError
= Overflow
| Underflow
| LossOfPrecision
| DivideByZero
| Denormal
instance Eq ArithError
instance Ord ArithError
instance Show ArithError
data ExtError
= StackOverflow
| HeapOverflow
| ThreadKilled
instance Eq ExtError
instance Ord ExtError
instance Show ExtError
An implementation should raise the appropriate exception when one of the above conditions arises. Note: GHC currently doesn't generate the arithmetic or the external exceptions.
Exceptions may be thrown explicitly from anywhere:
throw :: Exception -> a
Exceptions may be caught and examined in the IO monad:
catch :: IO a -> (Exception -> IO a) -> IO a
catchIO :: IO a -> (IOError -> IO a) -> IO a
catchArith :: IO a -> (ArithError -> IO a) -> IO a
catchError :: IO a -> (String -> IO a) -> IO a
getException :: a -> IO (Maybe Exception)
getExceptionIO :: IO a -> IO (Either Exception a)
Each of the functions catchIO, catchArith, and
catchError only catch a specific type of exception. All other
exceptions are effectively re-thrown. An uncaught exception will
normally cause the program to terminate, with the offending exception
displayed.
Note that catchIO is identical to IO.catch. The
implementation of IO errors in GHC and Hugs uses exceptions for
speed.
Also, don't forget to import Prelude hidiing (catch) when using
this library, to avoid the name clash between Exception.catch and
IO.catch.
The getException function is useful for evaluating a non-IO typed
value and testing for exceptions. getException evaluates its
first argument (as if you'd applied seq to it), returning
Just <exception> if an exception was raised, or
Nothing otherwise. 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
getException return Just (ErrorCall "urk") or Just
(ArithError DivideByZero)? The answer is "either": getException
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 getException is an IO computation.
getExceptionIO is the equivalent function for IO computations
--- it runs its first argument, and returns either the return value or
the exception if one was raised. Passing a value of type IO a to
getException won't work, because the IO type is represented
by a function, and getException will only evaluate its argument
to head normal form, hence the IO computation won't be
performed. Use getExceptionIO instead.
Because the Exception datatype isn't extendible, we added an
interface for throwing and catching exceptions of type Dynamic
(see Section
Dynamic), which allows
exception values of any type in the Typeable class to be thrown
and caught.
throwDyn :: Typeable exception => exception -> b
catchDyn :: Typeable exception => IO a -> (exception -> IO a) -> IO a
The catchDyn function only catches exceptions of the required
type; all other exceptions are re-thrown as with catchIO and
friends above.