- Synchronous exceptions
Generated as a result of a failing action in IO (same thread). Usually thrown using
- Impure exceptions
Thrown in pure code by partial function. Ideally, we would not use such functions, a better practice is to return an
Eithertype in this situation.
- Asynchronous exceptions
Can occur anywhere, including in pure code. Generated when another thread or the runtime system is trying to kill the current thread (via throwTo) or report an “unrecoverable” situation like a StackOverflow.
- Interruptible actions
Some operations are interruptible by async exceptions even within a mask. This is the case for blocking functions such as
takeMVarbut also for most I/O operations dealing with the outside world.
throwIO :: Exception e => e -> IO a (1)
|1||you should always prefer
try :: Exception e => IO a -> IO (Either e a) catch :: Exception e => IO a -- ^ computation -> (e -> IO a) -- ^ handler -> IO a
finally :: IO a -- ^ computation -> IO b -- ^ computation to run afterward even if an exception was raised -> IO a a `finally` sequel = mask $ \restore -> do r <- restore a `onException` sequel _ <- sequel return r -- | 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 throwIO (e :: SomeException)
bracket :: IO a -- ^ acquire resource -> (a -> IO b) -- ^ release resource -> (a -> IO c) -- ^ use resource -> IO c bracket before after use = mask $ \restore -> do a <- before r <- restore (use a) `onException` after a _ <- after a return r
exceptions package defines
class Monad m => MonadThrow m where throwM :: Exception e => e -> m a
class MonadThrow m => MonadCatch m where catch :: Exception e => m a -> (e -> m a) -> m a
class MonadCatch m => MonadMask m where mask :: ((forall a. m a -> m a) -> m b) -> m b uninterruptibleMask :: ((forall a. m a -> m a) -> m b) -> m b
Instances should ensure that, in the following code
f ‘finally’ g, the action
gis called regardless of what occurs within
f, including async exceptions.
ExceptTis not an instance of MonadMask. See MonadMask vs MonadBracket