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 ::Exception
e => AppException deriving stock instanceShow
AppException instanceException
AppExceptionmkHierarchy
''AppException
Now, we can try
to catch all of the Exception
s that we define
ourselves:
tryApp ::IO
a ->IO
(Either
AppException 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:
instanceHierarchy
ExceptionWrapper wheretoParent
= ExceptionWrapperfromParent
(ExceptionWrapper e) =cast
e
You can skip the boilerplate with the mkHierarchy
Template Haskell
function.
Since: 0.1.0.0