MIT licensed and maintained by Nikita Volkov
This version can be pinned in stack with:partial-handler-0.1.0@sha256:30dcb7f4190d779bcc35e9bfa48bb3620b8c48fbfa8627ab8a9a4633409e3288,2417

Module documentation for 0.1.0

  • PartialHandler
Depends on 1 package(full list with versions):
Used by 1 package in lts-0.7(full list with versions):

If you have ever had to compose an exception handler for exceptions of multiple types, you know how frustraiting it can get. This library approaches this issue by providing a composable exception handler type, which has a Monoid instance.

Composability means that you can define custom partial handlers and reuse them by composing other handlers from them.

Here is an example of a composable partial handler, which only defines what to do in case of a ThreadKilled exception (the code uses the LambdaCase extension):

ignoreThreadKilled :: PartialHandler ()
ignoreThreadKilled =
  typed $ \case
    ThreadKilled -> Just $ return ()
    _ -> Nothing

Here's how you can construct a handler of type SomeException -> IO a using this library:

totalizeRethrowing $
  ignoreThreadKilled <>
  onAlreadyExists (putStrLn "Already exists")

and here is how you would do it traditionally (with the MultiWayIf extension):

\e -> if
  | Just ThreadKilled <- fromException e ->
      return ()
  | Just e' <- fromException e, isAlreadyExistsError e' ->
      putStrLn "Already exists"
  | otherwise ->
      throwIO e

Putting all the syntactic trickery to make it shorter aside, this handler is a monolith block of code. Unlike with PartialHandler you can neither decompose it into simpler ones, or compose it with other handlers to form a more complex one.