-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use annotated-exception #131
Merged
Merged
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
d008424
use annotated-exception
chris-martin 6e20a59
split MonadThrow/MonadUnliftIO modules, bless IO
chris-martin 335e23e
rename 'catch' to 'catches' and flip
chris-martin 82641db
add throwString
chris-martin a78401d
upstream fromJustNoteM from megarepo core
chris-martin a4196f3
add 'catch'
chris-martin 8be7990
remove StringException, just use userError
chris-martin 9262d97
remove Impossible, add 'impossible' throwing action instead
chris-martin 1378460
rename throw to throwM
chris-martin 87ac58e
remove unnecessary 'catches'
chris-martin 1ac089e
add catchJust
chris-martin 5ac9917
make catchJust conform to standard oddities
chris-martin da28f59
add tryJust
chris-martin 940f3b0
add tryJust to prelude
chris-martin 80fd248
apply more withFrozenCallStack
chris-martin 5cc736a
constraint consistency
chris-martin 8b289eb
demote version bump to minor
chris-martin ab8aa8b
more constraint consistency
chris-martin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
module Freckle.App.Exception.MonadThrow | ||
( throwM | ||
, throwString | ||
, fromJustNoteM | ||
, impossible | ||
, catch | ||
, catchJust | ||
, catches | ||
, try | ||
, tryJust | ||
, checkpointCallStack | ||
|
||
-- * Miscellany | ||
, MonadThrow | ||
, MonadCatch | ||
, MonadMask | ||
, module Freckle.App.Exception.Types | ||
) where | ||
|
||
import Freckle.App.Exception.Types | ||
|
||
import Control.Applicative (pure) | ||
import Control.Monad.Catch (MonadCatch, MonadMask, MonadThrow) | ||
import Data.Either (Either (..)) | ||
import Data.Function (($), (.)) | ||
import Data.Functor (fmap, (<$>)) | ||
import Data.Maybe (Maybe, maybe) | ||
import Data.String (String) | ||
import GHC.IO.Exception (userError) | ||
import GHC.Stack (withFrozenCallStack) | ||
|
||
import qualified Control.Exception.Annotated as Annotated | ||
import qualified Control.Monad.Catch | ||
|
||
-- Throws an exception, wrapped in 'AnnotatedException' which includes a call stack | ||
throwM :: forall e m a. (Exception e, MonadThrow m, HasCallStack) => e -> m a | ||
throwM = Annotated.throw | ||
|
||
throwString :: forall m a. (MonadThrow m, HasCallStack) => String -> m a | ||
throwString = throwM . userError | ||
|
||
fromJustNoteM | ||
:: forall m a. (MonadThrow m, HasCallStack) => String -> Maybe a -> m a | ||
fromJustNoteM err = maybe (throwString err) pure | ||
|
||
impossible :: forall m a. (MonadThrow m, HasCallStack) => m a | ||
impossible = throwString "Impossible" | ||
|
||
catch | ||
:: forall e m a | ||
. (Exception e, MonadCatch m, HasCallStack) | ||
=> m a | ||
-> (e -> m a) | ||
-> m a | ||
catch = withFrozenCallStack Annotated.catch | ||
|
||
catchJust | ||
:: forall e b m a | ||
. (Exception e, MonadCatch m, HasCallStack) | ||
=> (e -> Maybe b) | ||
-> m a | ||
-> (b -> m a) | ||
-> m a | ||
catchJust test action handler = | ||
withFrozenCallStack $ Annotated.catch action $ \e -> | ||
maybe (Control.Monad.Catch.throwM e) handler (test e) | ||
|
||
catches | ||
:: forall m a | ||
. (MonadCatch m, HasCallStack) | ||
=> m a | ||
-- ^ Action to run | ||
-> [ExceptionHandler m a] | ||
-- ^ Recovery actions to run if the first action throws an exception | ||
-- with a type of either @e@ or @'AnnotatedException' e@ | ||
-> m a | ||
catches action handlers = | ||
withFrozenCallStack $ | ||
Annotated.catches | ||
action | ||
(fmap (\case (ExceptionHandler f) -> Annotated.Handler f) handlers) | ||
|
||
try | ||
:: forall e m a | ||
. (Exception e, MonadCatch m, HasCallStack) | ||
=> m a | ||
-- ^ Action to run | ||
-> m (Either e a) | ||
-- ^ Returns 'Left' if the action throws an exception with a type | ||
-- of either @e@ or @'AnnotatedException' e@ | ||
try = withFrozenCallStack Annotated.try | ||
|
||
tryJust | ||
:: forall e b m a | ||
. (Exception e, MonadCatch m, HasCallStack) | ||
=> (e -> Maybe b) | ||
-> m a | ||
-- ^ Action to run | ||
-> m (Either b a) | ||
tryJust test action = | ||
withFrozenCallStack $ Annotated.catch (Right <$> action) $ \e -> | ||
maybe (Control.Monad.Catch.throwM e) (pure . Left) (test e) | ||
|
||
-- | When dealing with a library that does not use 'AnnotatedException', | ||
-- apply this function to augment its exceptions with call stacks. | ||
checkpointCallStack | ||
:: forall m a | ||
. (MonadCatch m, HasCallStack) | ||
=> m a | ||
-- ^ Action that might throw whatever types of exceptions | ||
-> m a | ||
-- ^ Action that only throws 'AnnotatedException', | ||
-- where the annotations include a call stack | ||
checkpointCallStack = | ||
withFrozenCallStack Annotated.checkpointCallStack |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
module Freckle.App.Exception.MonadUnliftIO | ||
( throwM | ||
, throwString | ||
, fromJustNoteM | ||
, impossible | ||
, catch | ||
, catchJust | ||
, catches | ||
, try | ||
, tryJust | ||
, checkpointCallStack | ||
|
||
-- * Miscellany | ||
, IO | ||
, MonadIO | ||
, MonadUnliftIO | ||
, module Freckle.App.Exception.Types | ||
) where | ||
|
||
import Freckle.App.Exception.Types | ||
|
||
import Control.Applicative (pure) | ||
import Data.Either (Either (..)) | ||
import Data.Function (($), (.)) | ||
import Data.Functor (fmap, (<$>)) | ||
import Data.Maybe (Maybe, maybe) | ||
import Data.String (String) | ||
import GHC.IO.Exception (userError) | ||
import GHC.Stack (withFrozenCallStack) | ||
import System.IO (IO) | ||
import UnliftIO (MonadIO, MonadUnliftIO) | ||
import qualified UnliftIO.Exception | ||
|
||
import qualified Control.Exception.Annotated.UnliftIO as Annotated | ||
|
||
-- Throws an exception, wrapped in 'AnnotatedException' which includes a call stack | ||
throwM :: forall e m a. (Exception e, MonadIO m, HasCallStack) => e -> m a | ||
throwM = Annotated.throw | ||
|
||
throwString :: forall m a. (MonadIO m, HasCallStack) => String -> m a | ||
throwString = throwM . userError | ||
|
||
fromJustNoteM | ||
:: forall m a. (MonadIO m, HasCallStack) => String -> Maybe a -> m a | ||
fromJustNoteM err = maybe (throwString err) pure | ||
|
||
impossible :: forall m a. (MonadIO m, HasCallStack) => m a | ||
impossible = throwString "Impossible" | ||
|
||
catch | ||
:: forall e m a | ||
. (Exception e, MonadUnliftIO m, HasCallStack) | ||
=> m a | ||
-> (e -> m a) | ||
-> m a | ||
catch = withFrozenCallStack Annotated.catch | ||
|
||
catchJust | ||
:: forall e b m a | ||
. (Exception e, MonadUnliftIO m, HasCallStack) | ||
=> (e -> Maybe b) | ||
-> m a | ||
-> (b -> m a) | ||
-> m a | ||
catchJust test action handler = | ||
withFrozenCallStack $ Annotated.catch action $ \e -> | ||
maybe (UnliftIO.Exception.throwIO e) handler (test e) | ||
|
||
catches | ||
:: forall m a | ||
. (MonadUnliftIO m, HasCallStack) | ||
=> m a | ||
-- ^ Action to run | ||
-> [ExceptionHandler m a] | ||
-- ^ Recovery actions to run if the first action throws an exception | ||
-- with a type of either @e@ or @'AnnotatedException' e@ | ||
-> m a | ||
catches action handlers = | ||
withFrozenCallStack $ | ||
Annotated.catches | ||
action | ||
(fmap (\case (ExceptionHandler f) -> Annotated.Handler f) handlers) | ||
|
||
try | ||
:: forall e m a | ||
. (Exception e, MonadUnliftIO m, HasCallStack) | ||
=> m a | ||
-- ^ Action to run | ||
-> m (Either e a) | ||
-- ^ Returns 'Left' if the action throws an exception with a type | ||
-- of either @e@ or @'AnnotatedException' e@ | ||
try = withFrozenCallStack Annotated.try | ||
|
||
tryJust | ||
:: forall e b m a | ||
. (Exception e, MonadUnliftIO m, HasCallStack) | ||
=> (e -> Maybe b) | ||
-> m a | ||
-- ^ Action to run | ||
-> m (Either b a) | ||
tryJust test action = | ||
withFrozenCallStack $ Annotated.catch (Right <$> action) $ \e -> | ||
maybe (UnliftIO.Exception.throwIO e) (pure . Left) (test e) | ||
|
||
-- | When dealing with a library that does not use 'AnnotatedException', | ||
-- apply this function to augment its exceptions with call stacks. | ||
checkpointCallStack | ||
:: forall m a | ||
. (MonadUnliftIO m, HasCallStack) | ||
=> m a | ||
-- ^ Action that might throw whatever types of exceptions | ||
-> m a | ||
-- ^ Action that only throws 'AnnotatedException', | ||
-- where the annotations include a call stack | ||
checkpointCallStack = | ||
withFrozenCallStack Annotated.checkpointCallStack |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
module Freckle.App.Exception.Types | ||
( ExceptionHandler (..) | ||
, AnnotatedException (..) | ||
, Exception (..) | ||
, SomeException (..) | ||
, HasCallStack | ||
) where | ||
|
||
import Control.Exception (Exception (..), SomeException (..)) | ||
import Control.Exception.Annotated (AnnotatedException (..)) | ||
import GHC.Stack (HasCallStack) | ||
|
||
-- Renamed just so that it can go into Freckle.App.Prelude and have a less generic name than 'Handler' | ||
data ExceptionHandler m a | ||
= forall e. Exception e => ExceptionHandler (e -> m a) | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We did something very similar! But we used a
type
andpattern
combination to retain backwards compatibility.