| Safe Haskell | Safe-Inferred |
|---|---|
| Language | Haskell2010 |
ExceptionVia
Description
Hierarchical exceptions are a powerful and useful tool in the Haskell toolbox, but they're not used anywhere near often enough. I suspect it's because they're a) not very commonly understood and b) a lot of boilerplate to write. This library is intended to help the latter problem.
Let's look at an example. We'll define a type for all of our application's exceptions:
data AppException where AppException ::Exceptione => AppException deriving stock instanceShowAppException instanceExceptionAppExceptionmkHierarchy''AppException
Now, we can try to catch all of the Exceptions that we define
ourselves:
tryApp ::IOa ->IO(EitherAppException a) tryApp =try
Now let's define a problem that might happen in our domain. We're going
to derive Exception through our subtype wrapper.
data HttpException = HttpException
deriving stock Show
deriving
via (HttpException <!!! AppException)
Exception HttpException
Now, we can throw an HttpException, and catch it as part of
AppException:
throwHttp :: IO x
throwHttp = throwIO HttpException
main = do
eresult <- tryApp throwHttp
case result of
Left (AppException err) ->
putStrLn "I caught it!"
Right _ ->
putStrLn "Wait what??
For each "step" in the hierarchy, you define a GADT like AppException
above. Define an instance of Hierarchy for it, either via the Template
Haskell helper mkHierarchy, or manually.
Synopsis
- type (<!!!) lil big = ExceptionVia big lil
- newtype ExceptionVia big lil = ExceptionVia {
- unExceptionVia :: lil
- mkHierarchy :: Name -> DecsQ
- class Typeable big => Hierarchy big where
- toParent :: Exception lil => lil -> big
- fromParent :: Exception lil => big -> Maybe lil
Deriving Via Helpers
type (<!!!) lil big = ExceptionVia big lil Source #
A concise operator alias for ExceptionVia.
Given a wrapper exception type like SomeCompilerException, you can
derive an instance of Exception like so:
data MismatchedParentheses = MismatchedParentheses
deriving stock Show
deriving
via (MismatchedParentheses <!!! SomeCompilerException)
Exception MismatchedParentheses
Since: 0.1.0.0
newtype ExceptionVia big lil Source #
This is the explicit word version of (<!!!). You can use this if you
don't like TypeOperators.
Given a wrapper exception type like SomeCompilerException, you can
derive an instance of Exception like so:
data MismatchedParentheses = MismatchedParentheses
deriving stock Show
deriving
via (ExceptionVia SomeCompilerException MismatchedParentheses)
Exception MismatchedParentheses
Since: 0.1.0.0
Constructors
| ExceptionVia | |
Fields
| |
Instances
| (Hierarchy big, Exception big, Exception lil) => Exception (ExceptionVia big lil) Source # | |
Defined in ExceptionVia Methods toException :: ExceptionVia big lil -> SomeException # fromException :: SomeException -> Maybe (ExceptionVia big lil) # displayException :: ExceptionVia big lil -> String # | |
| Show lil => Show (ExceptionVia big lil) Source # | |
Defined in ExceptionVia Methods showsPrec :: Int -> ExceptionVia big lil -> ShowS # show :: ExceptionVia big lil -> String # showList :: [ExceptionVia big lil] -> ShowS # | |
Establishing Hierarchy
mkHierarchy :: Name -> DecsQ Source #
class Typeable big => Hierarchy big where Source #
This class tells us how to wrap and unwrap values from our
hierarchical wrapper types. It is very similar to Exception, but
instead of specifying how to put some value into a SomeException or
cast a value from a SomeException, we say how to put any value into
this big type or cast any value out of the big type.
Instances are very straightforward. For any type:
data ExceptionWrapper where ExceptionWrapper :: Exception e => e -> ExceptionWrapper
The instance will look like this:
instanceHierarchyExceptionWrapper wheretoParent= ExceptionWrapperfromParent(ExceptionWrapper e) =caste
You can skip the boilerplate with the mkHierarchy Template Haskell
function.
Since: 0.1.0.0