1 {-# OPTIONS_GHC -XNoImplicitPrelude #-}
5 -----------------------------------------------------------------------------
7 -- Module : Control.Exception.Base
8 -- Copyright : (c) The University of Glasgow 2001
9 -- License : BSD-style (see the file libraries/base/LICENSE)
11 -- Maintainer : libraries@haskell.org
12 -- Stability : experimental
13 -- Portability : non-portable (extended exceptions)
15 -- Extensible exceptions, except for multiple handlers.
17 -----------------------------------------------------------------------------
19 module Control.Exception.Base (
21 -- * The Exception type
34 #if __GLASGOW_HASKELL__ || __HUGS__
39 BlockedIndefinitelyOnMVar(..),
40 BlockedIndefinitelyOnSTM(..),
49 -- * Throwing exceptions
53 #ifdef __GLASGOW_HASKELL__
57 -- * Catching Exceptions
59 -- ** The @catch@ functions
63 -- ** The @handle@ functions
67 -- ** The @try@ functions
72 -- ** The @evaluate@ function
75 -- ** The @mapException@ function
78 -- * Asynchronous Exceptions
80 -- ** Asynchronous exception control
90 -- ** (deprecated) Asynchronous exception control
108 #ifdef __GLASGOW_HASKELL__
109 -- * Calls for GHC runtime
110 recSelError, recConError, irrefutPatError, runtimeError,
111 nonExhaustiveGuardsError, patError, noMethodBindingError,
112 nonTermination, nestedAtomically,
116 #ifdef __GLASGOW_HASKELL__
118 import GHC.IO hiding (finally,onException)
119 import GHC.IO.Exception
122 -- import GHC.Exception hiding ( Exception )
127 import Prelude hiding (catch)
128 import Hugs.Prelude (ExitCode(..))
129 import Hugs.IOExts (unsafePerformIO)
130 import Hugs.Exception (SomeException(DynamicException, IOException,
131 ArithException, ArrayException, ExitException),
132 evaluate, IOException, ArithException, ArrayException)
133 import qualified Hugs.Exception
141 import qualified IO as H'98 (catch)
142 import IO (bracket,ioError)
143 import DIOError -- defn of IOError type
144 import System (ExitCode())
145 import System.IO.Unsafe (unsafePerformIO)
146 import Unsafe.Coerce (unsafeCoerce)
148 -- minimum needed for nhc98 to pretend it has Exceptions
151 data Exception = IOException IOException
152 | ArithException ArithException
153 | ArrayException ArrayException
154 | AsyncException AsyncException
155 | ExitException ExitCode
158 class ({-Typeable e,-} Show e) => Exception e where
159 toException :: e -> SomeException
160 fromException :: SomeException -> Maybe e
162 data SomeException = forall e . Exception e => SomeException e
164 INSTANCE_TYPEABLE0(SomeException,someExceptionTc,"SomeException")
166 instance Show SomeException where
167 showsPrec p (SomeException e) = showsPrec p e
168 instance Exception SomeException where
172 type IOException = IOError
173 instance Exception IOError where
174 toException = SomeException
175 fromException (SomeException e) = Just (unsafeCoerce e)
177 instance Exception ExitCode where
178 toException = SomeException
179 fromException (SomeException e) = Just (unsafeCoerce e)
185 data PatternMatchFail
188 data BlockedIndefinitelyOnMVar
189 data BlockedIndefinitelyOnSTM
194 instance Show ArithException
195 instance Show ArrayException
196 instance Show AsyncException
197 instance Show AssertionFailed
198 instance Show PatternMatchFail
199 instance Show NoMethodError
200 instance Show Deadlock
201 instance Show BlockedIndefinitelyOnMVar
202 instance Show BlockedIndefinitelyOnSTM
203 instance Show ErrorCall
204 instance Show RecConError
205 instance Show RecSelError
206 instance Show RecUpdError
209 => IO a -- ^ The computation to run
210 -> (e -> IO a) -- ^ Handler to invoke if an exception is raised
212 catch io h = H'98.catch io (h . fromJust . fromException . toException)
214 throwIO :: Exception e => e -> IO a
215 throwIO = ioError . fromJust . fromException . toException
217 throw :: Exception e => e -> a
218 throw = unsafePerformIO . throwIO
220 evaluate :: a -> IO a
221 evaluate x = x `seq` return x
223 assert :: Bool -> a -> a
225 assert False _ = throw (toException (UserError "" "Assertion failed"))
227 mask :: ((IO a-> IO a) -> IO a) -> IO a
228 mask action = action restore
229 where restore act = act
234 class (Typeable e, Show e) => Exception e where
235 toException :: e -> SomeException
236 fromException :: SomeException -> Maybe e
238 toException e = DynamicException (toDyn e) (flip showsPrec e)
239 fromException (DynamicException dyn _) = fromDynamic dyn
240 fromException _ = Nothing
242 INSTANCE_TYPEABLE0(SomeException,someExceptionTc,"SomeException")
243 INSTANCE_TYPEABLE0(IOException,iOExceptionTc,"IOException")
244 INSTANCE_TYPEABLE0(ArithException,arithExceptionTc,"ArithException")
245 INSTANCE_TYPEABLE0(ArrayException,arrayExceptionTc,"ArrayException")
246 INSTANCE_TYPEABLE0(ExitCode,exitCodeTc,"ExitCode")
247 INSTANCE_TYPEABLE0(ErrorCall,errorCallTc,"ErrorCall")
248 INSTANCE_TYPEABLE0(AssertionFailed,assertionFailedTc,"AssertionFailed")
249 INSTANCE_TYPEABLE0(AsyncException,asyncExceptionTc,"AsyncException")
250 INSTANCE_TYPEABLE0(BlockedIndefinitelyOnMVar,blockedIndefinitelyOnMVarTc,"BlockedIndefinitelyOnMVar")
251 INSTANCE_TYPEABLE0(BlockedIndefinitelyOnSTM,blockedIndefinitelyOnSTM,"BlockedIndefinitelyOnSTM")
252 INSTANCE_TYPEABLE0(Deadlock,deadlockTc,"Deadlock")
254 instance Exception SomeException where
258 instance Exception IOException where
259 toException = IOException
260 fromException (IOException e) = Just e
261 fromException _ = Nothing
263 instance Exception ArrayException where
264 toException = ArrayException
265 fromException (ArrayException e) = Just e
266 fromException _ = Nothing
268 instance Exception ArithException where
269 toException = ArithException
270 fromException (ArithException e) = Just e
271 fromException _ = Nothing
273 instance Exception ExitCode where
274 toException = ExitException
275 fromException (ExitException e) = Just e
276 fromException _ = Nothing
278 data ErrorCall = ErrorCall String
280 instance Show ErrorCall where
281 showsPrec _ (ErrorCall err) = showString err
283 instance Exception ErrorCall where
284 toException (ErrorCall s) = Hugs.Exception.ErrorCall s
285 fromException (Hugs.Exception.ErrorCall s) = Just (ErrorCall s)
286 fromException _ = Nothing
288 data BlockedIndefinitelyOnMVar = BlockedIndefinitelyOnMVar
289 data BlockedIndefinitelyOnSTM = BlockedIndefinitelyOnSTM
290 data Deadlock = Deadlock
291 data AssertionFailed = AssertionFailed String
299 instance Show BlockedIndefinitelyOnMVar where
300 showsPrec _ BlockedIndefinitelyOnMVar = showString "thread blocked indefinitely"
302 instance Show BlockedIndefinitely where
303 showsPrec _ BlockedIndefinitely = showString "thread blocked indefinitely"
305 instance Show Deadlock where
306 showsPrec _ Deadlock = showString "<<deadlock>>"
308 instance Show AssertionFailed where
309 showsPrec _ (AssertionFailed err) = showString err
311 instance Show AsyncException where
312 showsPrec _ StackOverflow = showString "stack overflow"
313 showsPrec _ HeapOverflow = showString "heap overflow"
314 showsPrec _ ThreadKilled = showString "thread killed"
315 showsPrec _ UserInterrupt = showString "user interrupt"
317 instance Exception BlockedOnDeadMVar
318 instance Exception BlockedIndefinitely
319 instance Exception Deadlock
320 instance Exception AssertionFailed
321 instance Exception AsyncException
323 throw :: Exception e => e -> a
324 throw e = Hugs.Exception.throw (toException e)
326 throwIO :: Exception e => e -> IO a
327 throwIO e = Hugs.Exception.throwIO (toException e)
330 #ifndef __GLASGOW_HASKELL__
331 -- Dummy definitions for implementations lacking asynchonous exceptions
333 block :: IO a -> IO a
335 unblock :: IO a -> IO a
338 blocked = return False
341 -----------------------------------------------------------------------------
342 -- Catching exceptions
344 -- |This is the simplest of the exception-catching functions. It
345 -- takes a single argument, runs it, and if an exception is raised
346 -- the \"handler\" is executed, with the value of the exception passed as an
347 -- argument. Otherwise, the result is returned as normal. For example:
349 -- > catch (readFile f)
350 -- > (\e -> do let err = show (e :: IOException)
351 -- > hPutStr stderr ("Warning: Couldn't open " ++ f ++ ": " ++ err)
354 -- Note that we have to give a type signature to @e@, or the program
355 -- will not typecheck as the type is ambiguous. While it is possible
356 -- to catch exceptions of any type, see the previous section \"Catching all
357 -- exceptions\" for an explanation of the problems with doing so.
359 -- For catching exceptions in pure (non-'IO') expressions, see the
360 -- function 'evaluate'.
362 -- Note that due to Haskell\'s unspecified evaluation order, an
363 -- expression may throw one of several possible exceptions: consider
364 -- the expression @(error \"urk\") + (1 \`div\` 0)@. Does
365 -- the expression throw
366 -- @ErrorCall \"urk\"@, or @DivideByZero@?
368 -- The answer is \"it might throw either\"; the choice is
369 -- non-deterministic. If you are catching any type of exception then you
370 -- might catch either. If you are calling @catch@ with type
371 -- @IO Int -> (ArithException -> IO Int) -> IO Int@ then the handler may
372 -- get run with @DivideByZero@ as an argument, or an @ErrorCall \"urk\"@
373 -- exception may be propogated further up. If you call it again, you
374 -- might get a the opposite behaviour. This is ok, because 'catch' is an
377 -- Note that the "Prelude" also exports a function called
378 -- 'Prelude.catch' with a similar type to 'Control.Exception.catch',
379 -- except that the "Prelude" version only catches the IO and user
380 -- families of exceptions (as required by Haskell 98).
382 -- We recommend either hiding the "Prelude" version of 'Prelude.catch'
383 -- when importing "Control.Exception":
385 -- > import Prelude hiding (catch)
387 -- or importing "Control.Exception" qualified, to avoid name-clashes:
389 -- > import qualified Control.Exception as C
391 -- and then using @C.catch@
395 => IO a -- ^ The computation to run
396 -> (e -> IO a) -- ^ Handler to invoke if an exception is raised
398 #if __GLASGOW_HASKELL__
399 catch = GHC.IO.catchException
401 catch m h = Hugs.Exception.catchException m h'
402 where h' e = case fromException e of
408 -- | The function 'catchJust' is like 'catch', but it takes an extra
409 -- argument which is an /exception predicate/, a function which
410 -- selects which type of exceptions we\'re interested in.
412 -- > catchJust (\e -> if isDoesNotExistErrorType (ioeGetErrorType e) then Just () else Nothing)
414 -- > (\_ -> do hPutStrLn stderr ("No such file: " ++ show f)
417 -- Any other exceptions which are not matched by the predicate
418 -- are re-raised, and may be caught by an enclosing
419 -- 'catch', 'catchJust', etc.
422 => (e -> Maybe b) -- ^ Predicate to select exceptions
423 -> IO a -- ^ Computation to run
424 -> (b -> IO a) -- ^ Handler
426 catchJust p a handler = catch a handler'
427 where handler' e = case p e of
431 -- | A version of 'catch' with the arguments swapped around; useful in
432 -- situations where the code for the handler is shorter. For example:
434 -- > do handle (\NonTermination -> exitWith (ExitFailure 1)) $
436 handle :: Exception e => (e -> IO a) -> IO a -> IO a
439 -- | A version of 'catchJust' with the arguments swapped around (see
441 handleJust :: Exception e => (e -> Maybe b) -> (b -> IO a) -> IO a -> IO a
442 handleJust p = flip (catchJust p)
444 -----------------------------------------------------------------------------
447 -- | This function maps one exception into another as proposed in the
448 -- paper \"A semantics for imprecise exceptions\".
450 -- Notice that the usage of 'unsafePerformIO' is safe here.
452 mapException :: (Exception e1, Exception e2) => (e1 -> e2) -> a -> a
453 mapException f v = unsafePerformIO (catch (evaluate v)
456 -----------------------------------------------------------------------------
457 -- 'try' and variations.
459 -- | Similar to 'catch', but returns an 'Either' result which is
460 -- @('Right' a)@ if no exception of type @e@ was raised, or @('Left' ex)@
461 -- if an exception of type @e@ was raised and its value is @ex@.
462 -- If any other type of exception is raised than it will be propogated
463 -- up to the next enclosing exception handler.
465 -- > try a = catch (Right `liftM` a) (return . Left)
467 -- Note that "System.IO.Error" also exports a function called
468 -- 'System.IO.Error.try' with a similar type to 'Control.Exception.try',
469 -- except that it catches only the IO and user families of exceptions
470 -- (as required by the Haskell 98 @IO@ module).
472 try :: Exception e => IO a -> IO (Either e a)
473 try a = catch (a >>= \ v -> return (Right v)) (\e -> return (Left e))
475 -- | A variant of 'try' that takes an exception predicate to select
476 -- which exceptions are caught (c.f. 'catchJust'). If the exception
477 -- does not match the predicate, it is re-thrown.
478 tryJust :: Exception e => (e -> Maybe b) -> IO a -> IO (Either b a)
482 Right v -> return (Right v)
483 Left e -> case p e of
485 Just b -> return (Left b)
487 -- | Like 'finally', but only performs the final action if there was an
488 -- exception raised by the computation.
489 onException :: IO a -> IO b -> IO a
490 onException io what = io `catch` \e -> do _ <- what
491 throw (e :: SomeException)
493 -----------------------------------------------------------------------------
494 -- Some Useful Functions
496 -- | When you want to acquire a resource, do some work with it, and
497 -- then release the resource, it is a good idea to use 'bracket',
498 -- because 'bracket' will install the necessary exception handler to
499 -- release the resource in the event that an exception is raised
500 -- during the computation. If an exception is raised, then 'bracket' will
501 -- re-raise the exception (after performing the release).
503 -- A common example is opening a file:
506 -- > (openFile "filename" ReadMode)
508 -- > (\fileHandle -> do { ... })
510 -- The arguments to 'bracket' are in this order so that we can partially apply
513 -- > withFile name mode = bracket (openFile name mode) hClose
517 :: IO a -- ^ computation to run first (\"acquire resource\")
518 -> (a -> IO b) -- ^ computation to run last (\"release resource\")
519 -> (a -> IO c) -- ^ computation to run in-between
520 -> IO c -- returns the value from the in-between computation
521 bracket before after thing =
522 mask $ \restore -> do
524 r <- restore (thing a) `onException` after a
529 -- | A specialised variant of 'bracket' with just a computation to run
532 finally :: IO a -- ^ computation to run first
533 -> IO b -- ^ computation to run afterward (even if an exception
535 -> IO a -- returns the value from the first computation
537 mask $ \restore -> do
538 r <- restore a `onException` sequel
542 -- | A variant of 'bracket' where the return value from the first computation
544 bracket_ :: IO a -> IO b -> IO c -> IO c
545 bracket_ before after thing = bracket before (const after) (const thing)
547 -- | Like 'bracket', but only performs the final action if there was an
548 -- exception raised by the in-between computation.
550 :: IO a -- ^ computation to run first (\"acquire resource\")
551 -> (a -> IO b) -- ^ computation to run last (\"release resource\")
552 -> (a -> IO c) -- ^ computation to run in-between
553 -> IO c -- returns the value from the in-between computation
554 bracketOnError before after thing =
555 mask $ \restore -> do
557 restore (thing a) `onException` after a
559 #if !(__GLASGOW_HASKELL__ || __NHC__)
560 assert :: Bool -> a -> a
562 assert False _ = throw (AssertionFailed "")
567 #if __GLASGOW_HASKELL__ || __HUGS__
568 -- |A pattern match failed. The @String@ gives information about the
569 -- source location of the pattern.
570 data PatternMatchFail = PatternMatchFail String
571 INSTANCE_TYPEABLE0(PatternMatchFail,patternMatchFailTc,"PatternMatchFail")
573 instance Show PatternMatchFail where
574 showsPrec _ (PatternMatchFail err) = showString err
577 instance Exception PatternMatchFail where
578 toException (PatternMatchFail err) = Hugs.Exception.PatternMatchFail err
579 fromException (Hugs.Exception.PatternMatchFail err) = Just (PatternMatchFail err)
580 fromException _ = Nothing
582 instance Exception PatternMatchFail
587 -- |A record selector was applied to a constructor without the
588 -- appropriate field. This can only happen with a datatype with
589 -- multiple constructors, where some fields are in one constructor
590 -- but not another. The @String@ gives information about the source
591 -- location of the record selector.
592 data RecSelError = RecSelError String
593 INSTANCE_TYPEABLE0(RecSelError,recSelErrorTc,"RecSelError")
595 instance Show RecSelError where
596 showsPrec _ (RecSelError err) = showString err
599 instance Exception RecSelError where
600 toException (RecSelError err) = Hugs.Exception.RecSelError err
601 fromException (Hugs.Exception.RecSelError err) = Just (RecSelError err)
602 fromException _ = Nothing
604 instance Exception RecSelError
609 -- |An uninitialised record field was used. The @String@ gives
610 -- information about the source location where the record was
612 data RecConError = RecConError String
613 INSTANCE_TYPEABLE0(RecConError,recConErrorTc,"RecConError")
615 instance Show RecConError where
616 showsPrec _ (RecConError err) = showString err
619 instance Exception RecConError where
620 toException (RecConError err) = Hugs.Exception.RecConError err
621 fromException (Hugs.Exception.RecConError err) = Just (RecConError err)
622 fromException _ = Nothing
624 instance Exception RecConError
629 -- |A record update was performed on a constructor without the
630 -- appropriate field. This can only happen with a datatype with
631 -- multiple constructors, where some fields are in one constructor
632 -- but not another. The @String@ gives information about the source
633 -- location of the record update.
634 data RecUpdError = RecUpdError String
635 INSTANCE_TYPEABLE0(RecUpdError,recUpdErrorTc,"RecUpdError")
637 instance Show RecUpdError where
638 showsPrec _ (RecUpdError err) = showString err
641 instance Exception RecUpdError where
642 toException (RecUpdError err) = Hugs.Exception.RecUpdError err
643 fromException (Hugs.Exception.RecUpdError err) = Just (RecUpdError err)
644 fromException _ = Nothing
646 instance Exception RecUpdError
651 -- |A class method without a definition (neither a default definition,
652 -- nor a definition in the appropriate instance) was called. The
653 -- @String@ gives information about which method it was.
654 data NoMethodError = NoMethodError String
655 INSTANCE_TYPEABLE0(NoMethodError,noMethodErrorTc,"NoMethodError")
657 instance Show NoMethodError where
658 showsPrec _ (NoMethodError err) = showString err
661 instance Exception NoMethodError where
662 toException (NoMethodError err) = Hugs.Exception.NoMethodError err
663 fromException (Hugs.Exception.NoMethodError err) = Just (NoMethodError err)
664 fromException _ = Nothing
666 instance Exception NoMethodError
671 -- |Thrown when the runtime system detects that the computation is
672 -- guaranteed not to terminate. Note that there is no guarantee that
673 -- the runtime system will notice whether any given computation is
674 -- guaranteed to terminate or not.
675 data NonTermination = NonTermination
676 INSTANCE_TYPEABLE0(NonTermination,nonTerminationTc,"NonTermination")
678 instance Show NonTermination where
679 showsPrec _ NonTermination = showString "<<loop>>"
682 instance Exception NonTermination where
683 toException NonTermination = Hugs.Exception.NonTermination
684 fromException Hugs.Exception.NonTermination = Just NonTermination
685 fromException _ = Nothing
687 instance Exception NonTermination
692 -- |Thrown when the program attempts to call @atomically@, from the @stm@
693 -- package, inside another call to @atomically@.
694 data NestedAtomically = NestedAtomically
695 INSTANCE_TYPEABLE0(NestedAtomically,nestedAtomicallyTc,"NestedAtomically")
697 instance Show NestedAtomically where
698 showsPrec _ NestedAtomically = showString "Control.Concurrent.STM.atomically was nested"
700 instance Exception NestedAtomically
704 #endif /* __GLASGOW_HASKELL__ || __HUGS__ */
706 #ifdef __GLASGOW_HASKELL__
707 recSelError, recConError, irrefutPatError, runtimeError,
708 nonExhaustiveGuardsError, patError, noMethodBindingError
709 :: Addr# -> a -- All take a UTF8-encoded C string
711 recSelError s = throw (RecSelError ("No match in record selector "
712 ++ unpackCStringUtf8# s)) -- No location info unfortunately
713 runtimeError s = error (unpackCStringUtf8# s) -- No location info unfortunately
715 nonExhaustiveGuardsError s = throw (PatternMatchFail (untangle s "Non-exhaustive guards in"))
716 irrefutPatError s = throw (PatternMatchFail (untangle s "Irrefutable pattern failed for pattern"))
717 recConError s = throw (RecConError (untangle s "Missing field in record construction"))
718 noMethodBindingError s = throw (NoMethodError (untangle s "No instance nor default method for class operation"))
719 patError s = throw (PatternMatchFail (untangle s "Non-exhaustive patterns in"))
721 -- GHC's RTS calls this
722 nonTermination :: SomeException
723 nonTermination = toException NonTermination
725 -- GHC's RTS calls this
726 nestedAtomically :: SomeException
727 nestedAtomically = toException NestedAtomically