error-context 0.1.1.0 → 0.1.2.0
raw patch · 4 files changed
+83/−10 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Control.Error.Context: catchAnyWithoutContext :: MonadCatch m => m a -> (SomeException -> m a) -> m a
Files
- README.md +9/−8
- error-context.cabal +2/−2
- src/Control/Error/Context.hs +16/−0
- test/Control/Error/Context/Test.hs +56/−0
README.md view
@@ -5,15 +5,15 @@ ## What problem does *error-context* attempt to solve? -Good error handling is hard. Sometimes it happens that when-propagating errors some context is lost. Call traces sometimes help,-but the current solutions in Haskell-land for accessing call traces-are rather limited. Furthermore, sometimes call traces that at written-by and for humans are more convenient to read.+Good error handling is hard. In the case of failures it is important+to keep as much context as necessary for a proper problem analysis.+Call traces sometimes help, but the current solutions in Haskell-land+for accessing call traces are rather limited. The *error-context* library allows you to easily attach call traces ('error contexts') to errors, in particular to exceptions. Special-catch-functions are provided for accessing these contexts.+`catch`- and `try`-functions are provided for accessing these+contexts. ## How to use it? @@ -32,14 +32,15 @@ The `ErrorContextT` transformer implements `MonadThrow` and `MonadIO`, therefore exceptions thrown by `throwM` and via `liftIO` are-automatically context-enriched. But the story for exceptional values+automatically context-enriched. On the other hand, exceptional values created via ```haskell throw :: Exception e => e -> a ``` -are not context-enriched. But there is a workaround for this use-case:+are not context-enriched per se. But there is a workaround for this+use-case: ```haskell ensureExceptionContext :: (MonadCatch m, MonadErrorContext m) => m a -> m a
error-context.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 369905ea93b6cf094576c09b64bd7e22102e1f70d9b188d9386b7b6171d00077+-- hash: f55dae8d67d5460e15eb0ff2f407d2c336439b95b1e21c8573a1458bb40350fd name: error-context-version: 0.1.1.0+version: 0.1.2.0 synopsis: Provides API for enriching errors with contexts description: Please see the README on Github at <https://github.com/mtesseract/error-context#readme> category: Control, Error Handling
src/Control/Error/Context.hs view
@@ -32,6 +32,7 @@ , catchWithoutContext , catchWithContext , catchAnyWithContext+ , catchAnyWithoutContext , ensureExceptionContext , tryAnyWithContext , tryAnyWithoutContext@@ -281,6 +282,21 @@ Just exn Nothing -> Just (ErrorWithContext (ErrorContext []) someExn)++-- | Context aware version of 'catchAny'.+catchAnyWithoutContext+ :: MonadCatch m+ => m a+ -> (SomeException -> m a)+ -> m a+catchAnyWithoutContext m handler = catchJust pre m handler+ where pre :: SomeException -> Maybe SomeException+ pre someExn =+ case fromException someExn :: Maybe (ErrorWithContext SomeException) of+ Just (ErrorWithContext _ctx exnWithoutContext) ->+ Just exnWithoutContext+ Nothing ->+ Just someExn ensureExceptionContext :: (MonadCatch m, MonadErrorContext m) => m a -> m a ensureExceptionContext m =
test/Control/Error/Context/Test.hs view
@@ -25,6 +25,12 @@ testThrow , testCase "catchAnyWithContext" testCatchAnyWithContext+ , testCase "catchAnyWithContext/pure"+ testCatchAnyWithContextPure+ , testCase "catchAnyWithoutContext"+ testCatchAnyWithoutContext+ , testCase "catchAnyWithoutContext/pure"+ testCatchAnyWithoutContextPure , testCase "Catch context-enriched exception without context" testCatchWithoutContext , testCase "Contextualize error value"@@ -43,12 +49,20 @@ testCatchHeadException , testCase "tryAnyWithoutContext" testTryAnyWithoutContext+ , testCase "tryAnyWithoutContext/pure"+ testTryAnyWithoutContextPure , testCase "tryAnyWithContext" testTryAnyWithContext+ , testCase "tryAnyWithContext/pure"+ testTryAnyWithContextPure , testCase "tryWithContext" testTryWithContext+ , testCase "tryWithContext/pure"+ testTryWithContextPure , testCase "tryWithoutContext" testTryWithoutContext+ , testCase "tryWithoutContext/pure"+ testTryWithoutContextPure , testCase "Throw and catch" testThrowAndCatch ]@@ -119,6 +133,24 @@ \ (ErrorWithContext _ctx someExn) -> do Just TestException @=? fromException someExn +testCatchAnyWithContextPure :: Assertion+testCatchAnyWithContextPure = do+ catchAnyWithContext (runErrorContextT (throw TestException)) $+ \ (ErrorWithContext _ctx someExn) -> do+ Just TestException @=? fromException someExn++testCatchAnyWithoutContext :: Assertion+testCatchAnyWithoutContext = do+ catchAnyWithoutContext (runErrorContextT (throwM TestException)) $+ \ someExn -> do+ Just TestException @=? fromException someExn++testCatchAnyWithoutContextPure :: Assertion+testCatchAnyWithoutContextPure = do+ catchAnyWithoutContext (runErrorContextT (throw TestException)) $+ \ someExn -> do+ Just TestException @=? fromException someExn+ testNonContextualizedCatchWithContext :: Assertion testNonContextualizedCatchWithContext = do ErrorWithContext (ErrorContext ctx) TestException <- runErrorContextT $@@ -156,6 +188,12 @@ pure () Just TestException @=? fromException someExn +testTryAnyWithContextPure :: Assertion+testTryAnyWithContextPure = do+ Left (ErrorWithContext _ctx someExn) <- tryAnyWithContext . runErrorContextT $+ seq (throw TestException) (pure ())+ Just TestException @=? fromException someExn+ testTryAnyWithoutContext :: Assertion testTryAnyWithoutContext = do Left someExn <- tryAnyWithoutContext . runErrorContextT $ do@@ -163,6 +201,12 @@ pure () Just TestException @=? fromException someExn +testTryAnyWithoutContextPure :: Assertion+testTryAnyWithoutContextPure = do+ Left someExn <- tryAnyWithoutContext . runErrorContextT $+ seq (throw TestException) (pure ())+ Just TestException @=? fromException someExn+ testTryWithContext :: Assertion testTryWithContext = do Left (ErrorWithContext _ctx exn) <- tryWithContext . runErrorContextT $ do@@ -170,11 +214,23 @@ pure () TestException @=? exn +testTryWithContextPure :: Assertion+testTryWithContextPure = do+ Left (ErrorWithContext _ctx exn) <- tryWithContext . runErrorContextT $+ seq (throw TestException) (pure ())+ TestException @=? exn+ testTryWithoutContext :: Assertion testTryWithoutContext = do Left exn <- tryWithoutContext . runErrorContextT $ do void $ throwM TestException pure ()+ TestException @=? exn++testTryWithoutContextPure :: Assertion+testTryWithoutContextPure = do+ Left exn <- tryWithoutContext . runErrorContextT $+ seq (throw TestException) (pure ()) TestException @=? exn -- testTryAnyWithoutContext :: Assertion