    \begin{code}
    {-# OPTIONS_GHC -fno-implicit-prelude #-}
    -----------------------------------------------------------------------------
    -- |
    -- Module      :  GHC.Exception
    -- Copyright   :  (c) The University of Glasgow, 1998-2002
    -- License     :  see libraries/base/LICENSE
    --
    -- Maintainer  :  cvs-ghc@haskell.org
    -- Stability   :  internal
    -- Portability :  non-portable (GHC extensions)
    --
    -- Exceptions and exception-handling functions.
    --
    -----------------------------------------------------------------------------

    -- #hide
    module GHC.Exception
    	( module GHC.Exception,
    	  Exception(..), AsyncException(..),
    	  IOException(..), ArithException(..), ArrayException(..),
    	  throw, throwIO, ioError )
      where

    import GHC.Base
    import GHC.IOBase
    \end{code}

    %*********************************************************
    %*							*
    \subsection{Primitive catch}
    %*							*
    %*********************************************************

    catchException used to handle the passing around of the state to the
    action and the handler.  This turned out to be a bad idea - it meant
    that we had to wrap both arguments in thunks so they could be entered
    as normal (remember IO returns an unboxed pair...).

    Now catch# has type

        catch# :: IO a -> (b -> IO a) -> IO a

    (well almost; the compiler doesn't know about the IO newtype so we
    have to work around that in the definition of catchException below).

    \begin{code}
    catchException :: IO a -> (Exception -> IO a) -> IO a
    catchException (IO m) k =  IO $ \s -> catch# m (\ex -> unIO (k ex)) s

    -- | 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 'IOError's 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. 'System.IO.Error.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".
    catch           :: IO a -> (IOError -> IO a) -> IO a
    catch m k	=  catchException m handler
      where handler (IOException err)   = k err
    	handler other               = throw other
    \end{code}

    %*********************************************************
    %*							*
    \subsection{Controlling asynchronous exception delivery}
    %*							*
    %*********************************************************

    \begin{code}
    -- | Applying 'block' to a computation will
    -- execute that computation with asynchronous exceptions
    -- /blocked/.  That is, any thread which
    -- attempts to raise an exception in the current thread with 'Control.Exception.throwTo' will be
    -- blocked until asynchronous exceptions are enabled again.  There\'s
    -- no need to worry about re-enabling asynchronous exceptions; that is
    -- done automatically on exiting the scope of
    -- 'block'.
    --
    -- Threads created by 'Control.Concurrent.forkIO' inherit the blocked
    -- state from the parent; that is, to start a thread in blocked mode,
    -- use @block $ forkIO ...@.  This is particularly useful if you need to
    -- establish an exception handler in the forked thread before any
    -- asynchronous exceptions are received.
    block :: IO a -> IO a

    -- | To re-enable asynchronous exceptions inside the scope of
    -- 'block', 'unblock' can be
    -- used.  It scopes in exactly the same way, so on exit from
    -- 'unblock' asynchronous exception delivery will
    -- be disabled again.
    unblock :: IO a -> IO a

    block (IO io) = IO $ blockAsyncExceptions# io
    unblock (IO io) = IO $ unblockAsyncExceptions# io
    \end{code}

    \begin{code}
    -- | Forces its argument to be evaluated when the resultant 'IO' action
    -- is executed.  It can be used to order evaluation with respect to
    -- other 'IO' operations; its semantics are given by
    --
    -- >   evaluate x `seq` y    ==>  y
    -- >   evaluate x `catch` f  ==>  (return $! x) `catch` f
    -- >   evaluate x >>= f      ==>  (return $! x) >>= f
    --
    -- /Note:/ the first equation implies that @(evaluate x)@ is /not/ the
    -- same as @(return $! x)@.  A correct definition is
    --
    -- >   evaluate x = (return $! x) >>= return
    --
    evaluate :: a -> IO a
    evaluate a = IO $ \s -> case a `seq` () of () -> (# s, a #)
            -- NB. can't write
            --      a `seq` (# s, a #)
            -- because we can't have an unboxed tuple as a function argument
    \end{code}