doc wibble: Haskell 98 I/O Error -> 'IOError'
[ghc-base.git] / Control / Exception / Base.hs
index 468dd49..5794de3 100644 (file)
@@ -1,5 +1,4 @@
 {-# OPTIONS_GHC -XNoImplicitPrelude #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
 
 #include "Typeable.h"
 
@@ -37,8 +36,8 @@ module Control.Exception.Base (
         NestedAtomically(..),
 #endif
 
-        BlockedOnDeadMVar(..),
-        BlockedIndefinitely(..),
+        BlockedIndefinitelyOnMVar(..),
+        BlockedIndefinitelyOnSTM(..),
         Deadlock(..),
         NoMethodError(..),
         PatternMatchFail(..),
@@ -106,10 +105,11 @@ module Control.Exception.Base (
 
 #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
 
@@ -175,8 +175,8 @@ data AssertionFailed
 data PatternMatchFail
 data NoMethodError
 data Deadlock
-data BlockedOnDeadMVar
-data BlockedIndefinitely
+data BlockedIndefinitelyOnMVar
+data BlockedIndefinitelyOnSTM
 data ErrorCall
 data RecConError
 data RecSelError
@@ -188,8 +188,8 @@ instance Show AssertionFailed
 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
@@ -233,8 +233,8 @@ INSTANCE_TYPEABLE0(ExitCode,exitCodeTc,"ExitCode")
 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
@@ -271,8 +271,8 @@ instance Exception ErrorCall 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
@@ -282,8 +282,8 @@ 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"
@@ -332,31 +332,35 @@ blocked  = return False
 -- 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).
@@ -378,7 +382,7 @@ catch   :: Exception e
         -> (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
@@ -391,11 +395,14 @@ catch m h = Hugs.Exception.catchException m h'
 -- 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
@@ -410,7 +417,7 @@ catchJust p a handler = catch a handler'
 -- | 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
@@ -436,16 +443,14 @@ mapException f v = unsafePerformIO (catch (evaluate v)
 -- '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).
@@ -465,8 +470,10 @@ tryJust p a = do
                         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)
 
 -----------------------------------------------------------------------------
@@ -484,7 +491,7 @@ onException io what = io `catch` \e -> do what
 -- > 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.:
@@ -501,7 +508,7 @@ bracket before after thing =
   block (do
     a <- before
     r <- unblock (thing a) `onException` after a
-    after a
+    _ <- after a
     return r
  )
 #endif
@@ -516,7 +523,7 @@ finally :: IO a         -- ^ computation to run first
 a `finally` sequel =
   block (do
     r <- unblock a `onException` sequel
-    sequel
+    _ <- sequel
     return r
   )
 
@@ -525,7 +532,7 @@ a `finally` sequel =
 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\")
@@ -547,6 +554,8 @@ assert False _ = throw (AssertionFailed "")
 -----
 
 #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")
 
@@ -564,6 +573,11 @@ instance Exception 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")
 
@@ -581,6 +595,9 @@ instance Exception 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")
 
@@ -598,6 +615,11 @@ instance Exception 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")
 
@@ -615,6 +637,9 @@ instance Exception 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")
 
@@ -632,6 +657,10 @@ instance Exception 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")
 
@@ -649,6 +678,8 @@ instance Exception 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")
 
@@ -659,8 +690,6 @@ instance Exception NestedAtomically
 
 -----
 
-instance Exception Dynamic
-
 #endif /* __GLASGOW_HASKELL__ || __HUGS__ */
 
 #ifdef __GLASGOW_HASKELL__