MonadPlus instance for Control.Eff when Exc is member - haskell

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.

Related

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.

How could we know that an applicative can't be a Monad?

From the example of Validation (https://hackage.haskell.org/package/Validation), I'm trying to get an intuition of detecting how/why an applicative could not be a Monad (Why can AccValidation not have a Monad instance?)
Could you challenge my reasoning ?
I think about a monad in the way we handle behind the join (m ( m b) -> m b), let's develop my understanding with an example like Validation:
in data Validation err a, the functor structure is (Validation err). When you look at the definition of the bind for Monad and specializing the types for Validation you get the following :
(>>=) :: m a -> (a -> m b) -> m b
(>>=) :: (Validation err) a -> ( a -> (Validation err) b) -> (Validation err) b
if you beta reduce (>>=) you'll get :
m a -> (a -> m b) -> m b // if we apply (m a) in the monadic function
m ( m b) -> m b
then to get the result of (>>=) which is m b, you'll use join :
join :: (Monad m) => m (m a) -> m a
join x = x >>= id
If you play with the types you'll get :
join m ( m b ) = m ( m b) >>= (\(m b) -> m b -> m b) which gives m b
So that join just drop the outermost structure, only the value in the innermost type (the value of the innermost functor) is kept/transmitted through the sequence.
In a monad we can't pass some information from the functor structure (e.g Validation err) to the next 'action', the only think we can pass is the value. The only think you could do with that structure is short-circuiting the sequence to get information from it.
You can't perform a sequence of action on the information from the functor structure (e.g accumulating something like error..)
So I would say that an applicative that is squashing its structure with some logic on its structure could be suspicious as not being able to become a Monad ?
This isn't really an answer, but it's too long for a comment.
This and other referenced discussions in that thread are relevant. I think the question is posed sort of backwards: all Monads naturally give rise to an Applicative (where pure = return, etc); the issue is that most users expect/assume that (where a type is instance Monad) the Applicative instance is semantically equivalent to the instance to which the Monad gives rise.
This is documented in the Applicative class as a sort of law, but I'm not totally convinced it's justified. The argument seems to be that having an Applicative and Monad that don't agree in this way is confusing.
My experience using Validation is that it's a nightmare to do anything large with it, both because the notation becomes a mess and because you find you have some data dependencies (e.g. you need to parse and validate one section based on the parse of a previous section). You end up defining bindV which behave like an Error monad >>= since a proper Monad instance is considered dubious.
And yet using a Monad/Applicative pair like this does what you want: especially when using ApplicativeDo (I imagine; haven't tried this), the effect of writing your parser (e.g.) in Monadic style is that you can accumulate as many errors as possible at every level, based on the data dependencies of your parsing code. Haxl arguably fudges this "law" in a similar way.
I don't have enough experience with other types that are Applicative but not Monad to know whether there's a sensible rule for when it's "okay" for the Applicative to disagree in this way. Maybe it's totally arbitrary that Validation seems to work sensibly.
In any case...
I'm not sure how to directly answer your question. I think you start by taking the laws documented at the bottom of Applicative class docs, and flip them, so you get:
return = pure
ap m1 m2 = m1 <*> m2
If ap were a method of Monad and the above was a minimal complete definition then you'd simply have to test whether the above passed the Monad laws to answer your question for any Applicative, but that's not the case of course.

Control.Exception.Safe, why do ExceptT and Either behave so differently?

I'm trying to use Control.Exception.Safe with Control.Monad.Except.
throwString "Foo" :: Except String a
-- error, no instance for `MonadTrow Identity`
Ok, so apparently Except throws its error into its underlying monad in the transformer stack?
But why is that? Isn't Except basically designed to handle exceptions? Why this weird behavior? Why not the equivalent of Left "Foo"
EDIT:
Okay to further illustrate my problem:
I thought ExceptT e m a was to Either e a what ReaderT a m b is to a -> b. Control.Monad.Except.throwError, and catchError work exactly like Control.Exception.Safe.throw, and catch do with Either e a.
However they suddenly work different when applied to Except e a.
What do I do, when I want to use the behaviour of Either e a that is supplied by Control.Exception.Safe but in the context of monad transformers?
My context is that I do "Write yourself a Scheme in 48 hours" and wanted to generalize errors (with MonadThrow), so that I can do some IO stuff with it.
EDIT2:
Example:
data CountError = CountError deriving (Show, Except)
x :: String -> ExceptT CountError (Writer [String]) Int
x str = do { lift $ writer (length "str", return str); }
Now this count characters and collects the strings in the writer. This could be extended however much you want. The error could signal "wrong character in string", or "too many characters", or whatever.
y :: MonadThrow m => m a
y = throw CountError
This is a very general exception, which I could use for composition with any other kind of exception, except for ExceptT:
y >> x
-- No instance for MonadThrow Identity
-- But what I want is (Left CountError, [])
Ok, so apparently Except throws its error into its underlying monad in the transformer stack?
As I said in the comment: Except doesn't "throw it's error into the underlying monad", that's just what the MonadThrow instances is doing.
But why is that?
The instance of MonadThrow can not throw a String exception into ExceptT e for all types e and rather than have an instance just for ExceptT String it appears the author lifted to throw an exception on the next higher monad.
Isn't Except basically designed to handle exceptions?
Indeed Except is designed to allow for failure in exceptional cases.
Being pedantic, I'd call it an alternative to exceptions. A monad plumbing an alternative notion of return (an error case) and calling itself "Except" doesn't actually mean any of the typical exception options, such as a low level stack unwinding, is in use.
Why this weird behavior?
Because of the MonadThrow instance, which is re-exported from Control.Monad.Throw:
-- | Throws exceptions into the base monad.
instance MonadThrow m => MonadThrow (ExceptT e m) where
throwM = lift . throwM
Why not the equivalent of Left "Foo"
Because then the instance would have to be for ExceptT String instead of ExceptT e. Or, that is why I think the author of exceptions (Edward Kmett) decided on this design.
Instead, consider using Control.Monad.Except.throwError which does what it sounds like you want.
What do I do, when I want to use the behaviour of Either e a that is supplied by Control.Exception.Safe but in the context of monad transformers?
What "behavior of Either e a are you talking about? How is what you are looking for different from throwError? As far as I can tell, you are looking for an unnecessary extra layer of abstraction.
This is a bit of an old question but I think there is room to improve on this answer as I recently ran into this topic at work. Let's see, I believe that your expectation of having ExceptT behave similar to Either makes sense, but unfortunately the author of MonadThrow chose a different stance and decided that "passing" the decision on how to "throw" a failure to the underlying monad (or transformer) was the right way to go. Without attempting to speculate why decision was made, I agree that this behavior defeats the purpose of using a "failable" transformer such as 'MaybeT' or 'ExceptT' as an instance of an error class like MonadThrow, which is to give "Maybe" or "Either" like semantics to a different monad.
For this reason I have donned my flame vest and took a stab at Control.Monad.Failable , which would do exactly what you (and I) would expect, which is to return something like Left e where e is an instance of Exception.
Control.Monad.Failable

Use MonadRef to implement MonadCont

There is a well known issue that we cannot use forall types in the Cont return type.
However it should be OK to have the following definition:
class Monad m => MonadCont' m where
callCC' :: ((a -> forall b. m b) -> m a) -> m a
shift :: (forall r.(a -> m r) -> m r) -> m a
reset :: m a -> m a
and then find an instance that makes sense. In this paper the author claimed that we can implement MonadFix on top of ContT r m providing that m implemented MonadFix and MonadRef. But I think if we do have a MonadRef we can actually implement callCC' above like the following:
--satisfy law: mzero >>= f === mzero
class Monad m => MonadZero m where
mzero :: m a
instance (MonadZero m, MonadRef r m) => MonadCont' m where
callCC' k = do
ref <- newRef Nothing
v <- k (\a -> writeRef ref (Just a) >> mzero)
r <- readRef ref
return $ maybe v id r
shift = ...
reset = ...
(Unfortunately I am not familiar with the semantic of shift and reset so I didn't provide implementations for them)
This implementation seems OK for me. Intuitively, when callCC' being called, we feed k which a function that its own effect is always fail (although we are not able to provide a value of arbitrary type b, but we can always provide mzero of type m b and according to the law it should effectively stop all further effects being computed), and it captures the received value as the final result of callCC'.
So my question is:
Is this implementation works as expected for an ideal callCC? Can we implement shift and reset with proper semantic as well?
In addition to the above, I want to know:
To ensure the proper behaviour we have to assume some property of MonadRef. So what would the laws a MonadRef to have in order to make the above implementation behave as expected?
UPDATE
It turn out that the above naive implementation is not good enough. To make it satisfy "Continuation current"
callCC $\k -> k m === callCC $ const m === m
We have to adjust the implementation to
instance (MonadPlus m, MonadRef r m) => MonadCont' m where
callCC' k = do
ref <- newRef mzero
mplus (k $ \a -> writeRef ref (return a) >> mzero) (join (readRef ref))
In other words, the original MonadZero is not enough, we have to be able to combind a mzero value with a normal computation without cancelling the whole computation.
The above does not answer the question, it is just adjusted as the original attempt was falsified to be a candidate. But for the updated version, the original questions are still questions. Especially, reset and shift are still up to be implemented.
(This is not yet an answer, but only some clues came up in my mind. I hope this will lead to the real answer, by myself or by someone else.)
Call-by-Value is Dual to Call-by-Name -- Philip Wadler
In the above paper the author introduced the "Dual Calculus", a typed calculus that is corresponding to the classical logic. In the last section, there is a segment says
A strategy dual to call-by-need could
avoid this inefficiency by overwriting a coterm with its covalue
the first time it is evaluated.
As stated in Wadler's paper, call-by-name evaluating the continuations eagerly (it returns before all values being evaluated) whilst call-by-value evaluating the continuations lazily (it only returns after all values being evaluated).
Now, take a look at the callCC' above, I believe this is an example of the dual of call-by-need in the continuation side. The strategy of the evaluation, is that provide a fake "continuation" to the function given, but cache the state at this point to call the "true" continuation later on. This is somehow like making a cache of the continuation, and so once the computation finishes we restore that continuation. But cache the evaluated value is what it mean by call-by-need.
In general I suspect, state (computation up to the current point of time) is dual to continuation (the future computation). This will explain a few phenomenons. If this is true, it is not a surprise that MonadRef (correspond to a global and polymorphic state) is dual to MoncadCont (correspond to global and polymorphic continuations), and so they can be used to implement each other.

Transformation under Transformers

I'm having a bit of difficulty with monad transformers at the moment. I'm defining a few different non-deterministic relations which make use of transformers. Unfortunately, I'm having trouble understanding how to translate cleanly from one effectful model to another.
Suppose these relations are "foo" and "bar". Suppose that "foo" relates As and Bs to Cs; suppose "bar" relates Bs and Cs to Ds. We will define "bar" in terms of "foo". To make matters more interesting, the computation of these relations will fail in different ways. (Since the bar relation depends on the foo relation, its failure cases are a superset.) I therefore give the following type definitions:
data FooFailure = FooFailure String
data BarFailure = BarSpecificFailure | BarFooFailure FooFailure
type FooM = ListT (EitherT FooFailure (Reader Context))
type BarM = ListT (EitherT BarFailure (Reader Context))
I would then expect to be able to write the relations with the following function signatures:
foo :: A -> B -> FooM C
bar :: B -> C -> BarM D
My problem is that, when writing the definition for "bar", I need to be able to receive errors from the "foo" relation and properly represent them in "bar" space. So I'd be fine with a function of the form
convert :: (e -> e') -> ListT (EitherT e (Reader Context) a
-> ListT (EitherT e' (Reader Context) a
I can even write that little beast by running the ListT, mapping on EitherT, and then reassembling the ListT (because it happens that m [a] can be converted to ListT m a). But this seems... messy.
There's a good reason I can't just run a transformer, do some stuff under it, and generically "put it back"; the transformer I ran might have effects and I can't magically undo them. But is there some way in which I can lift a function just far enough into a transformer stack to do some work for me so I don't have to write the convert function shown above?
I think convert is a good answer, and using Control.Monad.Morph and Control.Monad.Trans.Either it's (almost) really simple to write:
convert :: (Monad m, Functor m, MFunctor t)
=> (e -> e')
-> t (EitherT e m) b -> t (EitherT e' m) b
convert f = hoist (bimapEitherT f id)
the slight problem is that ListT isn't an instance of MFunctor. I think this is the author boycotting ListT because it doesn't follow the monad transformer laws though because it's easy to write a type-checking instance
instance MFunctor ListT where hoist nat (ListT mas) = ListT (nat mas)
Anyway, generally take a look at Control.Monad.Morph for dealing with natural transformations on (parts of) transformer stacks. I'd say that fits the definition of lifting a function "just enough" into a stack.

Resources