HORIZON HASKELLDocslts/ghc-9.10.xc74966e2026-09-27Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27

Moduleunliftio-0.2.25.1Haskell2010

UnliftIO.Exception

Unlifted Control.Exception, with extra async exception safety and more helper functions.

This module works best when your cleanup functions adhere to certain expectations around exception safety and interruptible actions. For more details, see this exception safety tutorial.

  • 7 types
  • 2 classes
  • 55 values

Throwing

10 declarations
valuethrowIO :: (MonadIO m, Exception e) => e -> m a
#

Synchronously throw the given exception.

Note that, if you provide an exception value which is of an asynchronous type, it will be wrapped up in SyncExceptionWrapper. See toSyncException.

valuethrowString :: (MonadIO m, HasCallStack) => String -> m a
#

A convenience function for throwing a user error. This is useful for cases where it would be too high a burden to define your own exception type.

This throws an exception of type StringException. When GHC supports it (base 4.9 and GHC 8.0 and onward), it includes a call stack.

datadata StringException
#

Exception type thrown by throwString.

Note that the second field of the data constructor depends on GHC/base version. For base 4.9 and GHC 8.0 and later, the second field is a call stack. Previous versions of GHC and base do not support call stacks, and the field is simply unit (provided to make pattern matching across GHC versions easier).

Instances3Eq, Show, Exception

Catching (with recovery)

23 declarations
valuecatch
  1. :: (MonadUnliftIO m, Exception e)
  2. => m a

    action

  3. -> (e -> m a)

    handler

  4. -> m a
#

Catch a synchronous (but not asynchronous) exception and recover from it.

This is parameterized on the exception type. To catch all synchronous exceptions, use catchAny.

valuetry :: (MonadUnliftIO m, Exception e) => m a -> m (Either e a)
#

Run the given action and catch any synchronous exceptions as a Left value.

This is parameterized on the exception type. To catch all synchronous exceptions, use tryAny.

valuepureTry :: a -> Either SomeException a
#

Evaluate the value to WHNF and catch any synchronous exceptions.

The expression may still have bottom values within it; you may instead want to use pureTryDeep.

valuecatches :: MonadUnliftIO m => m a -> [Handler m a] -> m a
#

Similar to catch, but provides multiple different handler functions.

For more information on motivation, see base's catches. Note that, unlike that function, this function will not catch asynchronous exceptions.

Catching async exceptions (with recovery)

3 declarations
valuecatchSyncOrAsync
  1. :: (MonadUnliftIO m, Exception e)
  2. => m a
  3. -> e -> m a
  4. -> m a
#

A variant of catch that catches both synchronous and asynchronous exceptions.

WARNING: This function (and other *SyncOrAsync functions) is for advanced users. Most of the time, you probably want to use the non-SyncOrAsync versions.

Before attempting to use this function, be familiar with the "Rules for async safe handling" section in this blog post.

Cleanup (no recovery)

7 declarations
valuebracket :: MonadUnliftIO m => m a -> (a -> m b) -> (a -> m c) -> m c
#

Allocate and clean up a resource safely.

For more information on motivation and usage of this function, see base's bracket. This function has two differences from the one in base. The first, and more obvious, is that it works on any MonadUnliftIO instance, not just IO.

The more subtle difference is that this function will use uninterruptible masking for its cleanup handler. This is a subtle distinction, but at a high level, means that resource cleanup has more guarantees to complete. This comes at the cost that an incorrectly written cleanup function cannot be interrupted.

For more information, please see https://github.com/fpco/safe-exceptions/issues/3.

valuebracket_ :: MonadUnliftIO m => m a -> m b -> m c -> m c
#

Same as bracket, but does not pass the acquired resource to cleanup and use functions.

For more information, see base's bracket_.

valuefinally
  1. :: MonadUnliftIO m
  2. => m a

    thing

  3. -> m b

    after

  4. -> m a
#

Perform thing, guaranteeing that after will run after, even if an exception occurs.

Same interruptible vs uninterrupible points apply as with bracket. See base's finally for more information.

Coercion to sync and async

5 declarations

In version 0.2.23.0, these were changed with aliases to the values from Control.Exception.Safe in the safe-exceptions package.

Convert an exception into a synchronous exception.

For synchronous exceptions, this is the same as toException. For asynchronous exceptions, this will wrap up the exception with SyncExceptionWrapper.

Convert an exception into an asynchronous exception.

For asynchronous exceptions, this is the same as toException. For synchronous exceptions, this will wrap up the exception with AsyncExceptionWrapper.

Check exception type

2 declarations

Masking

4 declarations

Evaluation

2 declarations

Reexports

8 declarations
classclass (Typeable e, Show e) => Exception e where
#

Any type that you wish to throw or catch as an exception must be an instance of the Exception class. The simplest case is a new exception type directly below the root:

data MyException = ThisException | ThatException
    deriving Show

instance Exception MyException

The default method definitions in the Exception class do what we need in this case. You can now throw and catch ThisException and ThatException as exceptions:

*Main> throw ThisException `catch` \e -> putStrLn ("Caught " ++ show (e :: MyException))
Caught ThisException

In more complicated examples, you may wish to define a whole hierarchy of exceptions:

---------------------------------------------------------------------
-- Make the root exception type for all the exceptions in a compiler

data SomeCompilerException = forall e . Exception e => SomeCompilerException e

instance Show SomeCompilerException where
    show (SomeCompilerException e) = show e

instance Exception SomeCompilerException

compilerExceptionToException :: Exception e => e -> SomeException
compilerExceptionToException = toException . SomeCompilerException

compilerExceptionFromException :: Exception e => SomeException -> Maybe e
compilerExceptionFromException x = do
    SomeCompilerException a <- fromException x
    cast a

---------------------------------------------------------------------
-- Make a subhierarchy for exceptions in the frontend of the compiler

data SomeFrontendException = forall e . Exception e => SomeFrontendException e

instance Show SomeFrontendException where
    show (SomeFrontendException e) = show e

instance Exception SomeFrontendException where
    toException = compilerExceptionToException
    fromException = compilerExceptionFromException

frontendExceptionToException :: Exception e => e -> SomeException
frontendExceptionToException = toException . SomeFrontendException

frontendExceptionFromException :: Exception e => SomeException -> Maybe e
frontendExceptionFromException x = do
    SomeFrontendException a <- fromException x
    cast a

---------------------------------------------------------------------
-- Make an exception type for a particular frontend compiler exception

data MismatchedParentheses = MismatchedParentheses
    deriving Show

instance Exception MismatchedParentheses where
    toException   = frontendExceptionToException
    fromException = frontendExceptionFromException

We can now catch a MismatchedParentheses exception as MismatchedParentheses, SomeFrontendException or SomeCompilerException, but not other types, e.g. IOException:

*Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: MismatchedParentheses))
Caught MismatchedParentheses
*Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: SomeFrontendException))
Caught MismatchedParentheses
*Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: SomeCompilerException))
Caught MismatchedParentheses
*Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: IOException))
*** Exception: MismatchedParentheses

Methods

Instances41Exception, …
classclass Typeable (a :: k) where
#

The class Typeable allows a concrete representation of a type to be calculated.

datadata IOException
#

Exceptions that occur in the IO monad. An IOException records a more specific error type, a descriptive string and maybe the handle that was used when the error was flagged.

Instances4Eq, Show, Exception, MonadError
valueassert :: Bool -> a -> a
#

If the first argument evaluates to True, then the result is the second argument. Otherwise an AssertionFailed exception is raised, containing a String with the source file and line number of the call to assert.

Assertions can normally be turned on or off with a compiler flag (for GHC, assertions are normally on unless optimisation is turned on with -O or the -fignore-asserts option is given). When assertions are turned off, the first argument to assert is ignored, and the second argument is returned as the result.