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

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

Related

How to get the “inflexible semantics of monad transformers” using extensible effects?

Consider the following example.
newtype TooBig = TooBig Int deriving Show
choose :: MonadPlus m => [a] -> m a
choose = msum . map return
ex1 :: (MonadPlus m, MonadError TooBig m) => m Int
ex1 = do
x <- choose [5,7,1]
if x > 5
then throwError (TooBig x)
else return x
ex2 :: (MonadPlus m, MonadError TooBig m) => m Int
ex2 = ex1 `catchError` handler
where
handler (TooBig x) = if x > 7
then throwError (TooBig x)
else return x
ex3 :: Either TooBig [Int]
ex3 = runIdentity . runExceptT . runListT $ ex2
What should the value of ex3 be? If we use MTL then the answer is Right [7] which makes sense because ex1 is terminated since it throws an error, and the handler simply returns the pure value return 7 which is Right [7].
However, in the paper “Extensible Effects: An Alternative to Monad Transformers” by Oleg Kiselyov, et al. the authors say that this is “a surprising and undesirable result.” They expected the result to be Right [5,7,1] because the handler recovers from the exception by not re-throwing it. Essentially, they expected the catchError to be moved into ex1 as follows.
newtype TooBig = TooBig Int deriving Show
choose :: MonadPlus m => [a] -> m a
choose = msum . map return
ex1 :: (MonadPlus m, MonadError TooBig m) => m Int
ex1 = do
x <- choose [5,7,1]
if x > 5
then throwError (TooBig x) `catchError` handler
else return x
where
handler (TooBig x) = if x > 7
then throwError (TooBig x)
else return x
ex3 :: Either TooBig [Int]
ex3 = runIdentity . runExceptT . runListT $ ex1
Indeed, this is what extensible effects do. They change the semantics of the program by moving the effect handlers closer to the effect source. For example, local is moved closer to ask and catchError is moved closer to throwError. The authors of the paper tout this as one of the advantages of extensible effects over monad transformers, claiming that monad transformers have “inflexible semantics”.
But, what if I want the result to be Right [7] instead of Right [5,7,1] for whatever reason? As shown in the examples above, monad transformers can be used to get both results. However, because extensible effects always seem to move effect handlers closer to the effect source, it seems impossible to get the result Right [7].
So, the question is how to get the “inflexible semantics of monad transformers” using extensible effects? Is it possible to prevent individual effect handlers from moving closer to the effect source when using extensible effects? If not, then is this a limitation of extensible effects that needs to be addressed?
I'm also a little confused about the nuance in those excerpts from that particular paper. I think it's more useful to take a few steps back and to explain the motivations behind the enterprise of algebraic effects, to which that paper belongs.
The MTL approach is in some sense the most obvious and general: you have an interface (or "effect"), put it in a type class and call it a day. The cost of that generality is that it is unprincipled: you don't know what happens when you combine interfaces together. This issue appears most concretely when you implement an interface: you must implement all of them simultaneously. We like to think that each interface can be implemented in isolation in a dedicated transformer, but if you have two interfaces, say MonadPlus and MonadError, implemented by transformers ListT and ExceptT, in order to compose them, you will also have to either implement MonadError for ListT or MonadPlus for ExceptT. This O(n^2) instance problem is popularly understood as "just boilerplate", but the deeper issue is that if we allow interfaces to be of any shape, there is no telling what danger could hide in that "boilerplate", if it can even be implemented at all.
We must put more structure on those interfaces. For some definition of "lift" (lift from MonadTrans), the effects we can lift uniformly through transformers are exactly the algebraic effects. (See also, Monad Transformers and Modular Algebraic Effects, What Binds Them Together.)
This is not truly a restriction. While some interfaces are not algebraic in a technical sense, such as MonadError (because of catch), they can usually still be expressed within the framework of algebraic effects, just less literally. While restricting the definition of an "interface", we also gain richer ways of using them.
So I think algebraic effects are a different, more precise way of thinking about interfaces before all. As a way of thinking, it can thus be adopted without changing anything about your code, which is why comparisons tend to look at the same code twice and it is difficult to see the point without having a grasp on the surrounding context and motivations. If you think the O(n^2) instances problem is a trivial "boilerplate" problem, you already believe in the principle that interfaces ought to be composable; algebraic effects are one way of explicitly designing libraries and languages around that principle.
"Algebraic effects" are a fuzzy notion without a fixed definition. Nowadays they are most recognizable by syntax featuring a call and a handle construct (or op/perform/throw/raise and catch/match). call is the one construct to use interfaces and handle is how we implement them. The idea common to such languages is that there are equations (hence "algebraic") that provide a basic intuition of how call and handle behave in a way that's independent of the interface, notably via the interaction of handle with sequential composition (>>=).
Semantically, the meaning of a program can be denoted by a tree of calls, and a handle is a transformation of such trees. That's why many incarnations of "algebraic effects" in Haskell start with free monads, types of trees parameterized by the type of nodes f:
data Free f a
= Pure a
| Free (f (Free f a))
From that point of view, the program ex2 is a tree with three branches, with the branch labeled 7 ending in an exception:
ex2 :: Free ([] :+: Const Int) Int -- The functor "Const e" models exceptions (the equivalent of "MonadError e")
ex2 = Free [Pure 5, Free (Const 7), Pure 1]
-- You can write this with do notation to look like the original ex2, I'd say "it's just notation".
-- NB: constructors for (:+:) omitted
And each of the effects [] and Const Int corresponds to some way of transforming the tree, eliminating that effect from the tree (possibly introducing others, including itself).
"Catching" an exception corresponds to handling the Const effect by converting Free (Const x) nodes into some new tree h x.
To handle the [] effect, one way is to compose all children of a Free [...] node using (>>=), collecting their results in a final list. This can be seen as a generalization of depth-first search.
You get the result [7] or [5,7,1] depending on how those transformations are ordered.
Of course, there is a correspondence to the two orders of monad transformers in a MTL approach, but that intuition of programs as trees, which is generally applicable to all algebraic effects, is not as obvious when you're in the middle of implementing an instance such as MonadError e for ListT. That intuition might make sense a posteriori, but it is a priori obfuscated because type class instances are not first-class values like handlers, and monad transformers are typically expressed in terms of the final interpretation (hidden in the monad m they transform) instead of the initial syntax.

Extract a real or default value from a Monad with fmap or <$> or the likes -- how? [duplicate]

Is there a built-in function with signature :: (Monad m) => m a -> a ?
Hoogle tells that there is no such function.
Can you explain why?
A monad only supplies two functions:
return :: Monad m => a -> m a
(>>=) :: Monad m => m a -> (a -> m b) -> m b
Both of these return something of type m a, so there is no way to combine these in any way to get a function of type Monad m => m a -> a. To do that, you'll need more than these two functions, so you need to know more about m than that it's a monad.
For example, the Identity monad has runIdentity :: Identity a -> a, and several monads have similar functions, but there is no way to provide it generically. In fact, the inability to "escape" from the monad is essential for monads like IO.
There is probably a better answer than this, but one way to see why you cannot have a type (Monad m) => m a -> a is to consider a null monad:
data Null a = Null
instance Monad Null where
return a = Null
ma >>= f = Null
Now (Monad m) => m a -> a means Null a -> a, ie getting something out of nothing. You can't do that.
This doesn't exist because Monad is a pattern for composition, not a pattern for decomposition. You can always put more pieces together with the interface it defines. It doesn't say a thing about taking anything apart.
Asking why you can't take something out is like asking why Java's Iterator interface doesn't contain a method for adding elements to what it's iterating over. It's just not what the Iterator interface is for.
And your arguments about specific types having a kind of extract function follows in the exact same way. Some particular implementation of Iterator might have an add function. But since it's not what Iterators are for, the presence that method on some particular instance is irrelevant.
And the presence of fromJust is just as irrelevant. It's not part of the behavior Monad is intended to describe. Others have given lots of examples of types where there is no value for extract to work on. But those types still support the intended semantics of Monad. This is important. It means that Monad is a more general interface than you are giving it credit for.
Suppose there was such a function:
extract :: Monad m => m a -> a
Now you could write a "function" like this:
appendLine :: String -> String
appendLine str = str ++ extract getLine
Unless the extract function was guaranteed never to terminate, this would violate referential transparency, because the result of appendLine "foo" would (a) depend on something other than "foo", (b) evaluate to different values when evaluated in different contexts.
Or in simpler words, if there was an actually useful extract operation Haskell would not be purely functional.
Is there a build-in function with signature :: (Monad m) => m a -> a ?
If Hoogle says there isn't...then there probably isn't, assuming your definition of "built in" is "in the base libraries".
Hoogle tells that there is no such function. Can you explain why?
That's easy, because Hoogle didn't find any function in the base libraries that matches that type signature!
More seriously, I suppose you were asking for the monadic explanation. The issues are safety and meaning. (See also my previous thoughts on magicMonadUnwrap :: Monad m => m a -> a)
Suppose I tell you I have a value which has the type [Int]. Since we know that [] is a monad, this is similar to telling you I have a value which has the type Monad m => m Int. So let's suppose you want to get the Int out of that [Int]. Well, which Int do you want? The first one? The last one? What if the value I told you about is actually an empty list? In that case, there isn't even an Int to give you! So for lists, it is unsafe to try and extract a single value willy-nilly like that. Even when it is safe (a non-empty list), you need a list-specific function (for example, head) to clarify what you mean by desiring f :: [Int] -> Int. Hopefully you can intuit from here that the meaning of Monad m => m a -> a is simply not well defined. It could hold multiple meanings for the same monad, or it could mean absolutely nothing at all for some monads, and sometimes, it's just simply not safe.
Because it may make no sense (actually, does make no sense in many instances).
For example, I might define a Parser Monad like this:
data Parser a = Parser (String ->[(a, String)])
Now there is absolutely no sensible default way to get a String out of a Parser String. Actually, there is no way at all to get a String out of this with just the Monad.
There is a useful extract function and some other functions related to this at http://hackage.haskell.org/package/comonad-5.0.4/docs/Control-Comonad.html
It's only defined for some functors/monads and it doesn't necessarily give you the whole answer but rather gives an answer. Thus there will be possible subclasses of comonad that give you intermediate stages of picking the answer where you could control it. Probably related to the possible subclasses of Traversable. I don't know if such things are defined anywhere.
Why hoogle doesn't list this function at all appears to be because the comonad package isn't indexed otherwise I think the Monad constraint would be warned and extract would be in the results for those Monads with a Comonad instance. Perhaps this is because the hoogle parser is incomplete and fails on some lines of code.
My alternative answers:
you can perform a - possibly recursive - case analysis if you've imported the type's constructors
You can slink your code that would use the extracted values into the monad using monad >>= \a -> return $ your code uses a here as an alternative code structure and as long as you can convert the monad to "IO ()" in a way that prints your outputs you're done. This doesn't look like extraction but maths isn't the same as the real world.
Well, technicaly there is unsafePerformIO for the IO monad.
But, as the name itself suggests, this function is evil and you should only use it if you really know what you are doing (and if you have to ask wether you know or not then you don't)

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.

How to preserve information when failing?

I'm writing some code that uses the StateT monad transformer to keep track of some stateful information (logging and more).
The monad I'm passing to StateT is very simple:
data CheckerError a = Bad {errorMessage :: Log} | Good a
deriving (Eq, Show)
instance Monad CheckerError where
return x = Good x
fail msg = Bad msg
(Bad msg) >>= f = Bad msg
(Good x) >>= f = f x
type CheckerMonad a = StateT CheckerState CheckerError a
It's just a Left and Right variant.
What troubles me is the definition of fail. In my computation I produce a lot of information inside this monad and I'd like to keep this information even when failing.
Currently the only thing I can do is to convert everything to a String and create a Bad instance with the String passed as argument to fail.
What I'd like to do is something like:
fail msg = do
info <- getInfoOutOfTheComputation
return $ Bad info
However everything I tried until now gives type errors, probably because this would mix different monads.
Is there anyway in which I can implement fail in order to preserve the information I need without having to convert all of it into a String?
I cannot believe that the best Haskell can achieve is using show+read to pass all the information as the string to fail.
Your CheckerError monad is very similar to the Either monad. I will use the Either monad (and its monad transformer counterpart ErrorT) in my answer.
There is a subtlety with monad trasformers: order matters. Effects in the "inner" monad have primacy over effects caused by the "outer" layers. Consider these two alternative definitions of CheckerMonad:
import Control.Monad.State
import Control.Monad.Error
type CheckerState = Int -- dummy definitions for convenience
type CheckerError = String
type CheckerMonad a = StateT CheckerState (Either String) a
type CheckerMonad' a = ErrorT String (State CheckerState) a
In CheckerMonad, Either is the inner monad, and this means a failure will wipe the whole state. Notice the type of this run function:
runCM :: CheckerMonad a -> CheckerState -> Either CheckerError (a,CheckerState)
runCM m s = runStateT m s
You either fail, or return a result along with the state up to that point.
In CheckerMonad', State is the inner monad. This means the state will be preserved even in case of failures:
runCM' :: CheckerMonad' a -> CheckerState -> (Either CheckerError a,CheckerState)
runCM' m s = runState (runErrorT m) s
A pair is returned, which contains the state up to that point, and either a failure or a result.
It takes a bit of practice to develop an intuition of how to properly order monad transformers. The chart in the Type juggling section of this Wikibook page is a good starting point.
Also, it is better to avoid using fail directly, because it is considered a bit of a wart in the language. Instead, use the specialized functions for throwing errors provided by the error transformer. When working with ErrorT or some other instance of MonadError, use throwError.
sillycomp :: CheckerMonad' Bool
sillycomp = do
modify (+1)
s <- get
if s == 3
then throwError "boo"
else return True
*Main> runCM' sillycomp 2
Loading package transformers-0.3.0.0 ... linking ... done.
Loading package mtl-2.1.2 ... linking ... done.
(Left "boo",3)
*Main> runCM' sillycomp 3
(Right True,4)
ErrorT is sometimes annoying to use because, unlike Either, it requires an Error constraint on the error type. The Error typeclass forces you to define two error constructors noMsg and strMsg, which may or may not make sense for your type.
You can use EitherT from the either package instead, which lets you use any type whatsoever as the error. When working with EitherT, use the left function to throw errors.

#djinn MonadError e m => m ()

Is it possible to give an expression of type
MonadError e m => m ()
that raises an error, that can be handled with catchError? Note the absence of an Error e requirement.
Under what circumstances can an error created with fail be handled with catchError? What can lead to a fail not being caught by catchError? In what way did these circumstances change with respect to GHC releases? (There is a mention that the behaviour changed in base 4.3.)
The background of this question is a larger piece of code (Igor2 function nomatch) where an error created with fail "some message" passes by catchError and terminates the program, but replacing the fail invocation with throwError undefined results in the error being caught as expected. Of course throwError undefined is an ugly hack and this question aims to understand the background and correct solution.
There are several separate issues here, so I'll go through them in order.
MonadError e m => m ()
The problem with the above is that if e is not constrained in any way, it is impossible to create a value of type e which you need for throwError. So no, the only valid value for the above type that raises an error would need to include
throwError undefined
which is a cop-out (and not very useful). The Error e constraint lets you leave e abstract by providing a mechanism to construct a value of type e from a string.
Under what circumstances can an error created with fail be handled with catchError? What can lead to a fail not being caught by catchError?
This depends entirely of the monad in question. Different instances of MonadError might have a different implementation for fail so there is no generic answer. Or to put it another way, there are no guarantees that the error triggered by fail can be handled by catchError unless you are using a specific instance of MonadError that makes that promise. For example:
{-# LANGUAGE FlexibleContexts #-}
import Control.Monad.Error
example :: (Error e, MonadError e m) => m String
example = fail "This is a failure" `catchError` const (return "Error was caught")
main = do
example >>= putStrLn
either putStrLn putStrLn example
In the first line of main, example uses the MonadError instance of IO and the second line uses the MonadError instance of Either String. fail results in a catchable error in IO but not in Either so the program outputs
Error was caught
*** Exception: This is a failure
However, if we replace example with
example :: (Error e, MonadError e m) => m String
example = throwError (strMsg "This is a failure")
`catchError` const (return "Error was caught")
Then we get the desired output
Error was caught
Error was caught
And this would work the same for any (valid) instance of MonadError, unlike fail.
In what way did these circumstances change with respect to GHC releases? (There is a mention that the behaviour changed in base 4.3.)
The change in base 4.3 refers to how fail works in the Either monad. In previous versions fail returned a Left value which could be caught with catchError but in 4.3 and after it uses error and triggers an exception that has to be handled in IO (with e.g. catch).
The problem in Igor2 sounds like it uses the Either monad and assumes the old behavior of fail when it should be using throwError (or simply Left if there is no suitable Error instance).

Resources