annotated-exception
Exceptions, with checkpoints and context.
https://github.com/parsonsmatt/annotated-exception#readme
Version on this page: | 0.3.0.2 |
LTS Haskell 23.27: | 0.3.0.4 |
Stackage Nightly 2025-07-12: | 0.3.0.4 |
Latest on Hackage: | 0.3.0.4 |
annotated-exception-0.3.0.2@sha256:ade1d768120f867b7c35f8c5531167e455306b7b75381a64875cea04d994fe10,1785
Module documentation for 0.3.0.2
- Control
- Control.Exception
- Data
annotated-exception
This library provides a specialAnnotatedException
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 functioncheckpoint
.This will attach the provided value to any exception that bubbles up through it.
import Control.Exception.Annotateddata MyException = MyException deriving (Show, Exception)main :: IO ()main = do checkpoint "Foo" $ do throw MyException
When this program crashes, it will crash with anAnnotatedException
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 thecheckpoint
call doesn’t cover thethrow OtherException
- the exception[Annotation]
lives on the thrown exception itself, and this library’scatch
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 aCallStack
to any exception usingthrowWithCallStack
.
Now, you’re about to report your exceptions, up nearmain
.We can usetry
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 forannotated-exception
0.3.0.2
- #32
- Fixed the tests for GHC 9.10
0.3.0.1
- #31
- The
Show
instance forAnnotatedException
attempts to peek into theSomeException
to provide a more useful exception type. Also gives theoutput ofshow
.
- The
0.3.0.0
- #30
- The
Show
anddisplayException
now render the annotated exception in amuch nicer way.
- The
0.2.0.5
- #27
- Ensure that
flatten
combinesCallStack
s even when the callstack isattached manually.
- Ensure that
0.2.0.4
- #18
- Add
checkpointCallStack
even whencatch
doesn’t catch anAnnotatedException
- Add
0.2.0.3
- #17
- Add
HasCallStack
tocatch
andcatches
- Add
0.2.0.2
- #14
- Define
Control.Exception.Annotated.UnliftIO.checkpointCallStack
withoutre-exporting theMonadCatch
variant. Sigh.
- Define
0.2.0.1
- #13
- Fixed a bug in
UnliftIO.catches
where it would infinitely recurse.
- Fixed a bug in
0.2.0.0
- #12
- Removed the
Eq
instance forAnnotation
as well as theEq
constraintinAnnC
. These instances were only used for testing, and prevented thenatural use ofCallStack
in a[Annotation]
. - Removed the
Eq
instance forAnnotatedException
as a consequence ofdropping theEq
instance onAnnotation
. - Removed the
new
function. Usepure
orexceptionWithCallStack
instead. - Fixed a double-annotation bug in
checkpointCallStackWith
. checkpointCallStack
appends to the call-site list.- Pretty much everything now merges the
CallStack
s together.throw
includes aCallStack
, as docheckpoint
andcheckpointMany
.
- Removed the
0.1.2.1
- #8
- There was a bug where catching or trying to catch an exception of thewrong type would trigger an infinite loop as the
fromException
methodkept digging and digging and would be unable to make things work out. ThefromException
code no longer tries to flatten out these exceptions.However,toException
does flatten it, so all tests still pass.
- There was a bug where catching or trying to catch an exception of thewrong type would trigger an infinite loop as the
0.1.2.0
- #6
- Add
Control.Exception.Annotated.UnliftIO
that usesMonadUnliftIO
instead ofMonadCatch
andMonadThrow
. - Actually expose
catches
- Add
0.1.1.0
- #4
- Add
catches
- Replace
Control.Exception.Safe.try
withtry
that can get anAnnotatedException e
or a regular, un-Annotated
e
.
- Add
0.1.0.0
- Initial Release