Last active
October 14, 2020 23:55
-
-
Save evanrelf/d9ed5de06ea91766a73c8084ada0d0b9 to your computer and use it in GitHub Desktop.
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
-- Error message with scoping annotation | |
newtype Error (s :: k) = Error Text | |
deriving newtype IsString | |
-- Explicitly opt-in to bubbling up unhandled errors | |
rethrowError | |
:: Functor f | |
=> ExceptT (Error s1) f a | |
-> ExceptT (Error s2) f a | |
rethrowError = Except.withExceptT coerce | |
-- Handle errors (use instead of `catchError` from `MonadError`) | |
handleError | |
:: Functor f | |
=> ExceptT (Error s1) f a | |
-> (Error s -> ExceptT (Error s) f a) | |
-> ExceptT (Error s2) f a | |
handleError = handleError . rethrowError | |
-- Example function which may throw | |
divide :: Monad m => Int -> Int -> ExceptT (Error "divide") m Int | |
divide x y = do | |
when (y == 0) do | |
Except.throwError "Cannot divide by zero" | |
pure (x `div` y) | |
-- Example of explicitly opting-in to exception bubbling | |
-- (would not compile without wrapping in `rethrowError`) | |
showMyNumber :: Monad m => ExceptT (Error "showMyNumber") m String | |
showMyNumber = do | |
number <- rethrowError (divide 42 0) | |
pure (show number) | |
-- Example of being forced to handle errors if you opt not to bubble them up | |
-- (would not compile without `handleError`) | |
topLevel :: ExceptT (Error "topLevel") IO () | |
topLevel = do | |
string <- showMyNumber `handleError` \_ -> pure "handled failure" | |
putStrLn string |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment