annotated-exception
Exceptions, with checkpoints and context.
https://github.com/parsonsmatt/annotated-exception#readme
| LTS Haskell 24.33: | 0.3.0.4 |
| Stackage Nightly 2026-03-13: | 0.3.0.4 |
| Latest on Hackage: | 0.3.0.4 |
annotated-exception-0.3.0.4@sha256:16aebcbf355df14ce39b676c54fb2bf415e94a24a785a7f557d753f158c09e4d,1785Module documentation for 0.3.0.4
- Control
- Control.Exception
- Control.Exception.Annotated
- Control.Exception.Annotated.UnliftIO
- Control.Exception.Annotated
- Control.Exception
- Data
- Data.Annotation
annotated-exception
This library provides a special AnnotatedException type which allows you to decorate Haskell exceptions with additional information.
This decoration is totally transparent, and even works with exceptions thrown outside of your application code.
To provide an annotation, you’d use the function checkpoint.
This will attach the provided value to any exception that bubbles up through it.
import Control.Exception.Annotated
data MyException = MyException
deriving (Show, Exception)
main :: IO ()
main = do
checkpoint "Foo" $ do
throw MyException
When this program crashes, it will crash with an AnnotatedException that contains the annotation "Foo".
λ> checkpoint "Foo" $ throw MyException
*** Exception: AnnotatedException {annotations = ["Foo"], exception = MyException}
These annotations survive, even if you catch and rethrow with a different exception.
data OtherException = OtherException
deriving (Show, Exception)
woah :: IO ()
woah = do
let
checkpointed =
checkpoint "Foo" (throw MyException)
handler MyException =
throw OtherException
checkpointed
`catch`
handler
Notice how the checkpoint call doesn’t cover the throw OtherException - the exception [Annotation] lives on the thrown exception itself, and this library’s catch function ensures that we don’t lose that context.
λ> (checkpoint "Foo" (throw MyException)) `catch` \MyException -> throw OtherException
*** Exception: AnnotatedException {annotations = ["Foo"], exception = OtherException}
You can also attach a CallStack to any exception using throwWithCallStack.
Now, you’re about to report your exceptions, up near main.
We can use try in this module to always get the annotations.
main = do
eresult <- try $ myProgram
case eresult of
Left (AnnotatedException annotations exception) ->
reportException annotations exception
Right a ->
pure a
Changes
Changelog for annotated-exception
0.3.0.4
- #37
- Removed a trailing newline from the
AnnotatedExceptiondisplayExceptionimplementation (this was a regression introduced in 0.3.0.3).
- Removed a trailing newline from the
0.3.0.3
- #36
- Improved the
AnotatedExceptiondisplayExceptionimplementation.
- Improved the
0.3.0.2
- #32
- Fixed the tests for GHC 9.10
0.3.0.1
- #31
- The
Showinstance forAnnotatedExceptionattempts to peek into theSomeExceptionto provide a more useful exception type. Also gives the output ofshow.
- The
0.3.0.0
- #30
- The
ShowanddisplayExceptionnow render the annotated exception in a much nicer way.
- The
0.2.0.5
- #27
- Ensure that
flattencombinesCallStacks even when the callstack is attached manually.
- Ensure that
0.2.0.4
- #18
- Add
checkpointCallStackeven whencatchdoesn’t catch anAnnotatedException
- Add
0.2.0.3
- #17
- Add
HasCallStacktocatchandcatches
- Add
0.2.0.2
- #14
- Define
Control.Exception.Annotated.UnliftIO.checkpointCallStackwithout re-exporting theMonadCatchvariant. Sigh.
- Define
0.2.0.1
- #13
- Fixed a bug in
UnliftIO.catcheswhere it would infinitely recurse.
- Fixed a bug in
0.2.0.0
- #12
- Removed the
Eqinstance forAnnotationas well as theEqconstraint inAnnC. These instances were only used for testing, and prevented the natural use ofCallStackin a[Annotation]. - Removed the
Eqinstance forAnnotatedExceptionas a consequence of dropping theEqinstance onAnnotation. - Removed the
newfunction. UsepureorexceptionWithCallStackinstead. - Fixed a double-annotation bug in
checkpointCallStackWith. checkpointCallStackappends to the call-site list.- Pretty much everything now merges the
CallStacks together.throwincludes aCallStack, as docheckpointandcheckpointMany.
- Removed the
0.1.2.1
- #8
- There was a bug where catching or trying to catch an exception of the
wrong type would trigger an infinite loop as the
fromExceptionmethod kept digging and digging and would be unable to make things work out. ThefromExceptioncode no longer tries to flatten out these exceptions. However,toExceptiondoes flatten it, so all tests still pass.
- There was a bug where catching or trying to catch an exception of the
wrong type would trigger an infinite loop as the
0.1.2.0
- #6
- Add
Control.Exception.Annotated.UnliftIOthat usesMonadUnliftIOinstead ofMonadCatchandMonadThrow. - Actually expose
catches
- Add
0.1.1.0
- #4
- Add
catches - Replace
Control.Exception.Safe.trywithtrythat can get anAnnotatedException eor a regular, un-Annotatede.
- Add
0.1.0.0
- Initial Release