Revert "Batch merge"
[ghc.git] / compiler / utils / Exception.hs
1 {-# OPTIONS_GHC -fno-warn-deprecations #-}
2 module Exception
3 (
4 module Control.Exception,
5 module Exception
6 )
7 where
8
9 import GhcPrelude
10
11 import Control.Exception
12 import Control.Monad.IO.Class
13
14 catchIO :: IO a -> (IOException -> IO a) -> IO a
15 catchIO = Control.Exception.catch
16
17 handleIO :: (IOException -> IO a) -> IO a -> IO a
18 handleIO = flip catchIO
19
20 tryIO :: IO a -> IO (Either IOException a)
21 tryIO = try
22
23 -- | A monad that can catch exceptions. A minimal definition
24 -- requires a definition of 'gcatch'.
25 --
26 -- Implementations on top of 'IO' should implement 'gmask' to
27 -- eventually call the primitive 'Control.Exception.mask'.
28 -- These are used for
29 -- implementations that support asynchronous exceptions. The default
30 -- implementations of 'gbracket' and 'gfinally' use 'gmask'
31 -- thus rarely require overriding.
32 --
33 class MonadIO m => ExceptionMonad m where
34
35 -- | Generalised version of 'Control.Exception.catch', allowing an arbitrary
36 -- exception handling monad instead of just 'IO'.
37 gcatch :: Exception e => m a -> (e -> m a) -> m a
38
39 -- | Generalised version of 'Control.Exception.mask_', allowing an arbitrary
40 -- exception handling monad instead of just 'IO'.
41 gmask :: ((m a -> m a) -> m b) -> m b
42
43 -- | Generalised version of 'Control.Exception.bracket', allowing an arbitrary
44 -- exception handling monad instead of just 'IO'.
45 gbracket :: m a -> (a -> m b) -> (a -> m c) -> m c
46
47 -- | Generalised version of 'Control.Exception.finally', allowing an arbitrary
48 -- exception handling monad instead of just 'IO'.
49 gfinally :: m a -> m b -> m a
50
51 gbracket before after thing =
52 gmask $ \restore -> do
53 a <- before
54 r <- restore (thing a) `gonException` after a
55 _ <- after a
56 return r
57
58 a `gfinally` sequel =
59 gmask $ \restore -> do
60 r <- restore a `gonException` sequel
61 _ <- sequel
62 return r
63
64 instance ExceptionMonad IO where
65 gcatch = Control.Exception.catch
66 gmask f = mask (\x -> f x)
67
68 gtry :: (ExceptionMonad m, Exception e) => m a -> m (Either e a)
69 gtry act = gcatch (act >>= \a -> return (Right a))
70 (\e -> return (Left e))
71
72 -- | Generalised version of 'Control.Exception.handle', allowing an arbitrary
73 -- exception handling monad instead of just 'IO'.
74 ghandle :: (ExceptionMonad m, Exception e) => (e -> m a) -> m a -> m a
75 ghandle = flip gcatch
76
77 -- | Always executes the first argument. If this throws an exception the
78 -- second argument is executed and the exception is raised again.
79 gonException :: (ExceptionMonad m) => m a -> m b -> m a
80 gonException ioA cleanup = ioA `gcatch` \e ->
81 do _ <- cleanup
82 liftIO $ throwIO (e :: SomeException)
83