{-# OPTIONS_GHC -XNoImplicitPrelude #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
#include "Typeable.h"
NestedAtomically(..),
#endif
- BlockedOnDeadMVar(..),
- BlockedIndefinitely(..),
+ BlockedIndefinitelyOnMVar(..),
+ BlockedIndefinitelyOnSTM(..),
Deadlock(..),
NoMethodError(..),
PatternMatchFail(..),
#ifdef __GLASGOW_HASKELL__
import GHC.Base
-import GHC.IOBase
+import GHC.IO hiding (finally,onException)
+import GHC.IO.Exception
+import GHC.Exception
import GHC.Show
-import GHC.IOBase
-import GHC.Exception hiding ( Exception )
+-- import GHC.Exception hiding ( Exception )
import GHC.Conc
#endif
data PatternMatchFail
data NoMethodError
data Deadlock
-data BlockedOnDeadMVar
-data BlockedIndefinitely
+data BlockedIndefinitelyOnMVar
+data BlockedIndefinitelyOnSTM
data ErrorCall
data RecConError
data RecSelError
instance Show PatternMatchFail
instance Show NoMethodError
instance Show Deadlock
-instance Show BlockedOnDeadMVar
-instance Show BlockedIndefinitely
+instance Show BlockedIndefinitelyOnMVar
+instance Show BlockedIndefinitelyOnSTM
instance Show ErrorCall
instance Show RecConError
instance Show RecSelError
INSTANCE_TYPEABLE0(ErrorCall,errorCallTc,"ErrorCall")
INSTANCE_TYPEABLE0(AssertionFailed,assertionFailedTc,"AssertionFailed")
INSTANCE_TYPEABLE0(AsyncException,asyncExceptionTc,"AsyncException")
-INSTANCE_TYPEABLE0(BlockedOnDeadMVar,blockedOnDeadMVarTc,"BlockedOnDeadMVar")
-INSTANCE_TYPEABLE0(BlockedIndefinitely,blockedIndefinitelyTc,"BlockedIndefinitely")
+INSTANCE_TYPEABLE0(BlockedIndefinitelyOnMVar,blockedIndefinitelyOnMVarTc,"BlockedIndefinitelyOnMVar")
+INSTANCE_TYPEABLE0(BlockedIndefinitelyOnSTM,blockedIndefinitelyOnSTM,"BlockedIndefinitelyOnSTM")
INSTANCE_TYPEABLE0(Deadlock,deadlockTc,"Deadlock")
instance Exception SomeException where
fromException (Hugs.Exception.ErrorCall s) = Just (ErrorCall s)
fromException _ = Nothing
-data BlockedOnDeadMVar = BlockedOnDeadMVar
-data BlockedIndefinitely = BlockedIndefinitely
+data BlockedIndefinitelyOnMVar = BlockedIndefinitelyOnMVar
+data BlockedIndefinitelyOnSTM = BlockedIndefinitelyOnSTM
data Deadlock = Deadlock
data AssertionFailed = AssertionFailed String
data AsyncException
| UserInterrupt
deriving (Eq, Ord)
-instance Show BlockedOnDeadMVar where
- showsPrec _ BlockedOnDeadMVar = showString "thread blocked indefinitely"
+instance Show BlockedIndefinitelyOnMVar where
+ showsPrec _ BlockedIndefinitelyOnMVar = showString "thread blocked indefinitely"
instance Show BlockedIndefinitely where
showsPrec _ BlockedIndefinitely = showString "thread blocked indefinitely"
-- 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))
+-- > 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 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.
+-- expression may throw one of several possible exceptions: consider
+-- the expression @(error \"urk\") + (1 \`div\` 0)@. Does
+-- the expression throw
+-- @ErrorCall \"urk\"@, or @DivideByZero@?
--
--- 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.
+-- 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.
--
--- Also note that the "Prelude" also exports a function called
+-- 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).
-> (e -> IO a) -- ^ Handler to invoke if an exception is raised
-> IO a
#if __GLASGOW_HASKELL__
-catch = GHC.IOBase.catchException
+catch = GHC.IO.catchException
#elif __HUGS__
catch m h = Hugs.Exception.catchException m h'
where h' e = case fromException e of
-- argument which is an /exception predicate/, a function which
-- selects which type of exceptions we\'re interested in.
--
--- > result <- catchJust errorCalls thing_to_try handler
+-- > 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' or 'catchJust'.
+-- 'catch', 'catchJust', etc.
catchJust
:: Exception e
=> (e -> Maybe b) -- ^ Predicate to select exceptions
-- | A version of 'catch' with the arguments swapped around; useful in
-- situations where the code for the handler is shorter. For example:
--
--- > do handle (\e -> exitWith (ExitFailure 1)) $
+-- > do handle (\NonTermination -> exitWith (ExitFailure 1)) $
-- > ...
handle :: Exception e => (e -> IO a) -> IO a -> IO a
handle = flip catch
-- 'try' and variations.
-- | Similar to 'catch', but returns an 'Either' result which is
--- @('Right' a)@ if no exception was raised, or @('Left' e)@ if an
--- exception was raised and its value is @e@.
+-- @('Right' a)@ if no exception of type @e@ was raised, or @('Left' ex)@
+-- if an exception of type @e@ was raised and its value is @ex@.
+-- If any other type of exception is raised than it will be propogated
+-- up to the next enclosing exception handler.
--
-- > try a = catch (Right `liftM` a) (return . Left)
--
--- Note: as with 'catch', it is only polite to use this variant if you intend
--- to re-throw the exception after performing whatever cleanup is needed.
--- Otherwise, 'tryJust' is generally considered to be better.
---
--- Also note that "System.IO.Error" also exports a function called
+-- Note that "System.IO.Error" also exports a function called
-- 'System.IO.Error.try' with a similar type to 'Control.Exception.try',
-- except that it catches only the IO and user families of exceptions
-- (as required by the Haskell 98 @IO@ module).
Nothing -> throw e
Just b -> return (Left b)
+-- | Like 'finally', but only performs the final action if there was an
+-- exception raised by the computation.
onException :: IO a -> IO b -> IO a
-onException io what = io `catch` \e -> do what
+onException io what = io `catch` \e -> do _ <- what
throw (e :: SomeException)
-----------------------------------------------------------------------------
-- > bracket
-- > (openFile "filename" ReadMode)
-- > (hClose)
--- > (\handle -> do { ... })
+-- > (\fileHandle -> do { ... })
--
-- The arguments to 'bracket' are in this order so that we can partially apply
-- it, e.g.:
block (do
a <- before
r <- unblock (thing a) `onException` after a
- after a
+ _ <- after a
return r
)
#endif
a `finally` sequel =
block (do
r <- unblock a `onException` sequel
- sequel
+ _ <- sequel
return r
)
bracket_ :: IO a -> IO b -> IO c -> IO c
bracket_ before after thing = bracket before (const after) (const thing)
--- | Like bracket, but only performs the final action if there was an
+-- | Like 'bracket', but only performs the final action if there was an
-- exception raised by the in-between computation.
bracketOnError
:: IO a -- ^ computation to run first (\"acquire resource\")
-----
#if __GLASGOW_HASKELL__ || __HUGS__
+-- |A pattern match failed. The @String@ gives information about the
+-- source location of the pattern.
data PatternMatchFail = PatternMatchFail String
INSTANCE_TYPEABLE0(PatternMatchFail,patternMatchFailTc,"PatternMatchFail")
-----
+-- |A record selector was applied to a constructor without the
+-- appropriate field. This can only happen with a datatype with
+-- multiple constructors, where some fields are in one constructor
+-- but not another. The @String@ gives information about the source
+-- location of the record selector.
data RecSelError = RecSelError String
INSTANCE_TYPEABLE0(RecSelError,recSelErrorTc,"RecSelError")
-----
+-- |An uninitialised record field was used. The @String@ gives
+-- information about the source location where the record was
+-- constructed.
data RecConError = RecConError String
INSTANCE_TYPEABLE0(RecConError,recConErrorTc,"RecConError")
-----
+-- |A record update was performed on a constructor without the
+-- appropriate field. This can only happen with a datatype with
+-- multiple constructors, where some fields are in one constructor
+-- but not another. The @String@ gives information about the source
+-- location of the record update.
data RecUpdError = RecUpdError String
INSTANCE_TYPEABLE0(RecUpdError,recUpdErrorTc,"RecUpdError")
-----
+-- |A class method without a definition (neither a default definition,
+-- nor a definition in the appropriate instance) was called. The
+-- @String@ gives information about which method it was.
data NoMethodError = NoMethodError String
INSTANCE_TYPEABLE0(NoMethodError,noMethodErrorTc,"NoMethodError")
-----
+-- |Thrown when the runtime system detects that the computation is
+-- guaranteed not to terminate. Note that there is no guarantee that
+-- the runtime system will notice whether any given computation is
+-- guaranteed to terminate or not.
data NonTermination = NonTermination
INSTANCE_TYPEABLE0(NonTermination,nonTerminationTc,"NonTermination")
-----
+-- |Thrown when the program attempts to call @atomically@, from the @stm@
+-- package, inside another call to @atomically@.
data NestedAtomically = NestedAtomically
INSTANCE_TYPEABLE0(NestedAtomically,nestedAtomicallyTc,"NestedAtomically")
-----
-instance Exception Dynamic
-
#endif /* __GLASGOW_HASKELL__ || __HUGS__ */
#ifdef __GLASGOW_HASKELL__