How to use Handlers that don't have SomeException as their argument type - haskell

When using Control.Monad.Throw (i.e. exceptions package), something that confuses me that it seem that all my my throwing and catching has to work with SomeException.
E.g.
value :: Either ExitCode String
value = throwM $ ExitFailure 23
This looks to me like it should compile, because throwM :: (Exception e, MonadThrow m) => e -> m a, and ExitCode has an instance of Exception. Even this doesn't compile:
value :: Exception e => Either e String
value = throwM $ ExitFailure 23
In fact, it only compiles when I change the signature to SomeException. I know the Exception type class has a special place re
In the documentation for Control.Exception I could see examples where they use catches with handlers of signature ArithException -> m a or similiar. I tested it and it worked.
Is this not possible when using exceptions?
EDIT
The error messages are either:
Couldn't match type ExitCode with SomeException arising from a use of throwM
or
Couldn't match type e with SomeException arising from a use of throwM

The behavior you are seeing is from the type signature of throwM:
throwM :: (Exception e, MonadThrow m) => e -> m a
And the instance for Either, which is essentially:
MonadThrow (Either SomeException)
This makes throwM:
throwM :: (Exception e) => e -> Either SomeException a
throwM for Either SomeException can take any Exception e.
However, there is no MonadThrow instance for Either ExitCode, or for forall e. Exception e => Either e.
The problem is that there isn't really a way to write an instance that's polymorphic for all e. Imagine having an instance
Exception q => MonadThrow (Either q)
This would make throwM:
throwM :: (Exception e, Exception q) => e -> Either q a
which means you have to be able to take any e and convert it into any q, which is not possible using the Exception typeclass alone.
Imagine also if there was a MonadThrow instance for Either ExitCode. That would make the type signature for throwM:
throwM :: Exeption e => e -> Either ExitCode a
which you can probably see is clearly nonsensical, since there are many instances of Exception that cannot be coerced to an ExitCode. (Try writing a function with that type signature if you don't believe me!)
If you just want short-circuting exception behavior for Either, consider:
Just use Left instead of throwM, and pattern matching for catch. If you really want to use Exception still, you can use fromException to attempt to coerce a SomeException into an Exception instance of your choice.
You can use the exceptions package, and catching will still work as long as you must assume that the exception could be any instance (SomeException)
Use MonadError and ExceptT from mtl, if you want some sort of polymorphic interface with catching ability

Related

What is difference between normal functions and typeclass functions?

class (Typeable e, Show e) => Exception e where
toException :: e -> SomeException
fromException :: SomeException -> Maybe e
toException = SomeException
fromException (SomeException e) = cast e
data MyException1 = Exception1A | Exception1B
deriving (Show)
instance Exception MyException1
data MyException2 = Exception2A | Exception2B
deriving (Show)
instance Exception MyException2
It is able to define multiple exceptions. So, multiple fromException functions are able to be defined too. I think it is weird because two functions can have same name and same input.
fromException :: SomeException -> Maybe MyException1
fromException :: SomeException -> Maybe MyException2
Even if the reason why this behavior is ok is "Two functions have different type include return type (and expressions are evaluated based these all types)", it is weird, because I can't define normal functions that way.
f :: Integer -> Maybe Integer
f = cast
f :: Integer -> Maybe Char
f n = cast $ show n
What is difference between normal functions and type class functions?
The fact that you cannot define normal functions that way is the whole difference.
The whole purpose of type classes is to allow overloading - that is, defining multiple different functions with different types, but same name. And have the compiler pick the right one automatically based on types expected in the context.

How can I use `throwM` with `Except`?

There is a package transformers that features the monad Except.
This monad transformer extends a monad with the ability to throw exceptions.
There is a package exceptions that features the effect throwM.
Throw an exception. ...
So it would seem that these two should play well together. However:
λ runExcept $ throwM Overflow
<interactive>:46:13: error:
• No instance for (MonadThrow Data.Functor.Identity.Identity)
arising from a use of ‘throwM’
• In the second argument of ‘($)’, namely ‘throwM Overflow’
In the expression: runExcept $ throwM Overflow
In an equation for ‘it’: it = runExcept $ throwM Overflo
I know I can use the monad Catch. But anyway, I would like to
understand what is going on. I am not very familiar with monad transformers.
The compiler infers types this way:
Since runExcept :: Except e a -> ..., the argument of runExcept must be of type Except e a.
So, throwM Overflow :: Except e a
Except e a is a type synonym for ExceptT e Identity a.
So, throwM Overflow :: ExceptT e Identity a
Because throwM :: MonadThrow m => e -> m a, the compiler needs to find an instance of ThrowM for a type that would match ExceptT e Identity.
And look: there is such instance: MonadThrow m => MonadThrow (ExceptT e m). It matches any ExceptT e m for any m, but this m also must have an instance of MonadThrow.
Matching up the type of throwM Overflow, which is ExceptT e Identity a, and the type for which the MonadThrow instance is defined, which is Except T m, the compiler determines that m = Identity.
But wait! According to the instance definition MonadThrow m => MonadThrow (ExceptT e m), this m (which we now know to be Identity) must also have a MonadThrow instance.
So the compiler looks for that, and doesn't find it.
And displays you an error message: "No instance MonadThrow Identity"
Type class-related error messages can be vexing. The compiler doesn't always tell you the full chain of conclusions it has followed in order to reach the error. This is unfortunate, but whatchagonnado.
But the underlying problem here is that Except and throwM aren't actually compatible. That is to say, throwM throws errors in a different sense than Except contains errors. They're two different error-related mechanisms. In order to throw an Except-compatible error, use its own throwE. This should work:
> runExcept $ throwE Overflow
Left Overflow
As far as I understand at the moment, the error-handling landscape in Haskell hasn't yet settled down to a manageable state. We have Except, which got generalized to ExceptT, and then we have throw, throwTo, throwIO, throwSTM, throwE, throwError, throwM, and all of those have variants from different libraries and under different monads. Plus, the arrival of UnliftIO has complicated things even further. It sort of looks like ExceptT will be going away as a result.

MonadPlus instance for Control.Eff when Exc is member

In monad transformers, we have
instance (Monad m, Monoid e) => MonadPlus (ExceptT e m)
In extensible effects, there is no such thing as
instance (Monoid e) => MonadPlus (Eff (Exc e :> r))
I've tried implementing it, in vain. Here is what I have so far:
instance (Monoid e) => MonadPlus (Eff (Exc e :> r)) where
mzero = throwExc mempty
a `mplus` b = undefined $ do
resultA <- runExc a
case resultA of
Left l -> runExc b
Right r -> return $ Right r
There are 2 issues:
for mzero, GHC complains as follows:
Could not deduce (Monoid e0) arising from a use of ‘mempty’
from the context (Monad (Eff (Exc e :> r)), Monoid e)
Why doesn't GHC match e0 with e ?
Answer (provided in comment): turn on ScopedTypeVariables
for mplus, undefined should be replaced with the inverse function of runExc, but I can't find it in the API of extensible-effects. Did I miss something ?
Rationale: I want to be able to write a <|> b within Member (Exc e) r => Eff r a, meaning:
try a
if a throws ea, try b
if b throws eb, then throw mappend ea eb
This requires an Alternative instance, which is why I am attempting to implement a MonadPlus instance in the first place.
Note: I'm using GHC 7.8.3 .
Thank you in advance for your help.
I think you may be confused about extensible effects and the desired
instance MonadPlus (Eff (Exc e :> r)) shows the confusion.
If you wish to build a non-deterministic computation and also throw
exceptions, you can do that already without any need for new
instances. I think I may be partly responsible for the confusion by
defining separate mzero' and mplus' which are fully equivalent to
those in MonadPlus. Anyway, because of this equivalence,
you can simply write
instance Member Choose r => MonadPlus (Eff r) where
mzero = mzero'
mplus = mplus'
The instance says: A computation that has a Choose effect, among
others, is an instance of the MonadPlus computation. Let me stress
the part ``among others''. The computation may have other effects,
for example, throw exceptions. The MonadPlus instance above covers
that case, as well as all others.
Thus, to use non-determinism and exceptions, you just use mplus, mzero
(or mplus', mzero') along with throwExc. There is no need to define
any new instances - in stark contrast with Monad Transformers.
Of course you have to decide how you want your exceptions to interact
with non-determinism: should an exception discard all choices or only
remaining choices? This depends on how you order your handlers, which
effect gets handled first. Moreover, you can write a handler for both
Choose and Exc effects (to keep the already made choices upon an
exception and discard the remaining -- thus modeling Prolog's cut).
The code of the library (and the code accompanying the paper) has examples of that.
Edit in reply to the amended question:
If all you need is <|>, it can be implemented simply, without MonadPlus or cut.
This operator is merely a form of exception handling, and is implementable as the
composition of two catchError. Here is the full code
alttry :: forall e r a. (Typeable e, Monoid e, MemberU2 Exc (Exc e) r) =>
Eff r a -> Eff r a -> Eff r a
alttry ma mb =
catchError ma $ \ea ->
catchError mb $ \eb -> throwError (mappend (ea::e) eb)
If the computation ma finishes successfully, its result is returned. Otherwise,
mb is tried; it it finishes successfully, its result is returned. If both fail,
the mappend-ed exception is raised. The code directly matches the English specification.
We use MemberU2 in the signature rather than Member to
ensure that the computation throws only one type of exceptions.
Otherwise, this construction is not very useful. I used the original implementation
Eff.hs. That file also contains the test case.
BTW, with extensible effects there is no
need to define or use type classes like MonadPlus, MonadState, etc. These type classes
were intended to hide the concrete layout of the MonadTransformer stack. With extensible effects, there is nothing to hide. The crutches are no longer needed.

Could not deduce type

I am attempting to pattern match on a type in a case statement such as the following:
result <- action
case result of
Success _ -> do something
Failure e -> case e of
MyException myField -> do take another action
_ -> ...
The compiler can't deduce e ~ MyException which I understand. My question is what other information do I need to supply to the compiler to be able to match my exception type. In this particular case I know that if there is a Failure the returned type will be MyException.
EDIT:
The type of result (From the Aws package) is:
(Transaction r a, ConfigurationFetch (Info r)) =>
Configuration -> r -> IO (Response (ResponseMetadata a) a)
a is from Data.Attempt which is either a Success or Failure.
Assuming you're using extensible exceptions (which is the default in recent ghc's), your result is probably something like
data Result = Success MySuccess | Failure SomeException
You need to convert the SomeException to your own exception type. This is done with the function toException :: Exception e => SomeException -> Maybe e. Then you would handle this like:
Failure e -> case toException e of
Just (MyException myField) -> do take another action
_ -> ...
Of course this is assuming that I'm right about your Result type.

Can a custom guard mechanism be defined in Haskell?

If you look at the example for catches:
f = expr `catches` [Handler (\ (ex :: ArithException) -> handleArith ex),
Handler (\ (ex :: IOException) -> handleIO ex)]
It looks like catches has defined a custom mechanism to match on patterns (the two exception types). Am I mistaken, or can this be generalized to allow one to define a function that can take lambda functions that match on a certain pattern?
Edit: FYI below is the GHC source for catches. If someone can shed some light on how this works it would be great.
catches :: IO a -> [Handler a] -> IO a
catches io handlers = io `catch` catchesHandler handlers
catchesHandler :: [Handler a] -> SomeException -> IO a
catchesHandler handlers e = foldr tryHandler (throw e) handlers
where tryHandler (Handler handler) res
= case fromException e of
Just e' -> handler e'
Nothing -> res
This is the Scoped Type Variables GHC extension at work. Follow the link to learn more.
Basically, you define an assertion about type that have to be met by the patter before it can match. So, yeah, it is akin to guards, but not completely so.
How this particular example works? Dive into sources of "base" library to find out that:
class (Show e) => Exception e where
toException :: e -> SomeException
fromException :: SomeException -> Maybe e
data SomeException = forall e . Exception e => SomeException e
instance Exception IOException where
toException = IOException
fromException (IOException e) = Just e
fromException _ = Nothing
instance Exception ArithException where
toException = ArithException
fromException (ArithException e) = Just e
fromException _ = Nothing
We see that IOException and ArithException are different types implementing the typeclass Exception. We also see that toException/fromException is a wrapping/unwrapping mechanism that allows one to convert values of type Exception to/from values of types IOException, ArithException, etc.
So, we could've written:
f = expr `catches` [Handler handleArith,
Handler handleIO]
handleArith :: ArithException -> IO ()
handleArith ex = ....
handleIO :: IOException -> IO ()
handleIO ex = ....
Suppose that IOException happens. When catchesHandler processes first element of the handlers list, it calls tryHandler, which calls fromException. From the definition of tryHandler it follows that return type of the fromException should be the same as argument of handleArith. On the other hand, e is of type Exception, namely - (IOException ...). So, the types play out this way (this is not a valid haskell, but I hope that you get my point):
fromException :: (IOException ...) -> Maybe ArithException
From the instance Exception IOException ... it follows immediately that the result is Nothing, so this handler is skipped. By the same reasoning the following handler would be called, because fromException would return (Just (IOException ...)).
So, you've used type signatures of handleArith and handleIO to specify when each of them would be called, and fromException/toException made sure that it happened this way.
If you want to, you could also constraint types of handleIO and handleArith inside the definition of f, using scoped type variables. Arguably, this could give you better readability.
Finalizing, Scoped Type Variables are not a primary players here. They are just used for convenience. Main machinery for playing this kind of tricks is fromException/toException and friends. Scoped Type Variables just allow you to have syntax which more closely resemble guard patterns.
case () of
()| foo expr1 -> handleFooCase
| bar expr2 -> handleBarCase
| otherwise -> blah

Resources