Use an extensible-exceptions package when bootstrapping
[ghc-hetmet.git] / compiler / utils / Exception.hs
1
2 module Exception
3     (
4     module Control.Exception,
5     module Exception
6     )
7     where
8
9 import Prelude hiding (catch)
10
11 #if __GLASGOW_HASKELL__ < 609
12 import Control.Exception.Extensible as Control.Exception
13 #else
14 import Control.Exception
15 #endif
16
17 catchIO :: IO a -> (IOException -> IO a) -> IO a
18 catchIO = catch
19
20 handleIO :: (IOException -> IO a) -> IO a -> IO a
21 handleIO = flip catchIO
22
23 tryIO :: IO a -> IO (Either IOException a)
24 tryIO = try
25
26 -- | A monad that can catch exceptions.  A minimal definition
27 -- requires a definition of 'gcatch'.
28 --
29 -- Although, 'gbracket' and 'gfinally' could be modelled on top of 'gcatch',
30 -- they are included in the type class since GHC needs special implementations
31 -- of these in order to properly handle asynchronous exceptions.
32 class Monad m => ExceptionMonad m where
33   -- | Generalised version of 'Control.Exception.catch', allowing an arbitrary
34   -- exception handling monad instead of just 'IO'.
35   gcatch :: Exception e => m a -> (e -> m a) -> m a
36
37   -- | Generalised version of 'Control.Exception.bracket', allowing an arbitrary
38   -- exception handling monad instead of just 'IO'.
39   gbracket :: m a -> (a -> m b) -> (a -> m c) -> m c
40
41   -- | Generalised version of 'Control.Exception.finally', allowing an arbitrary
42   -- exception handling monad instead of just 'IO'.
43   gfinally :: m a -> m b -> m a
44
45   gbracket acquire release in_between = do
46       a <- acquire
47       r <- in_between a `gonException` release a
48       release a
49       return r
50
51   gfinally thing cleanup = do
52       r <- thing `gonException` cleanup
53       cleanup
54       return r
55
56 instance ExceptionMonad IO where
57   gcatch    = catch
58   gbracket  = bracket
59   gfinally  = finally
60
61
62 gtry :: (ExceptionMonad m, Exception e) => m a -> m (Either e a)
63 gtry act = gcatch (act >>= \a -> return (Right a))
64                   (\e -> return (Left e))
65
66 -- | Generalised version of 'Control.Exception.handle', allowing an arbitrary
67 -- exception handling monad instead of just 'IO'.
68 ghandle :: (ExceptionMonad m, Exception e) => (e -> m a) -> m a -> m a
69 ghandle = flip gcatch
70
71 -- | Always executes the first argument.  If this throws an exception the
72 -- second argument is executed and the exception is raised again.
73 gonException :: (ExceptionMonad m) => m a -> m b -> m a
74 gonException ioA cleanup = ioA `gcatch` \e ->
75                              do cleanup
76                                 throw (e :: SomeException)
77