Defining a MonadEither type class
error-handling, haskell, monad-transformers
Solution
How about
instance Monad m => MonadEither l r (E.EitherT l m)
That is, it should be `l` instead of `r`.
However once you've done this you'll come up across a separate error. The root cause is that there's no point to `right`; it's just `return`. This means you need to get rid of the `r` parameter to the class.
class Monad m => MonadEither l m where
left :: l -> m a
Your instance declaration should then become
instance Monad m => MonadEither l (E.EitherT l m)
(You also may want to look at the `MonadError` class since this is essentially what you are replicating.)
Problem
I'm going back through Monad Transformers : Step by Step as a refresher, and like many tutorials out there, it uses `Control.Monad.Error`. GHC now gives a warning that this module is deprecated, so I switched over to `Control.Monad.Trans.Either` from the `either` library: http://hackage.haskell.org/package/either-3.4/docs/Control-Monad-Trans-Either.html Everything is handled smoothly with `eval2` in the paper, since `EitherT` is the outermost monad. However, after that everything falls apart -- `ReaderT` is in no way an `Either` value, and everything henceforth uses `ErrorT`, which I'd like to change to `EitherT`. My idea, then, was to define a `MonadEither` type class that boxed `left` and `right` in order to handle errors, but this hasn't been fruitful. I don't really understand how the type classes in `mtl` work, and this instance in particular has to be parameterized over multiple values, which is confusing. I came up with the following, which compiles after including some syntactic extensions: ``` class (Monad m) => MonadEither l r m | m -> r where right :: r -> m r left :: l -> m r ``` But I can't figure out a `MonadEither` instance of `EitherT`: ``` instance Monad m => MonadEither l r (E.EitherT l m) where right = E.right left = E.left ``` Edit: I changed the instance declaration to match `E.EitherT` properly, and get the following error message: ``` Illegal instance declaration for ‘MonadEither l r (E.EitherT l m)’ The coverage condition fails in class ‘MonadEither’ for functional dependency: ‘m -> r’ Reason: lhs type ‘E.EitherT l m’ does not determine rhs type ‘r’ In the instance declaration for ‘MonadEither l r (E.EitherT l m)’ ``` Again, I'm not really sure what I'm doing. I don't really understand functional dependencies, so I'm just looking for some guidance as to what an appropriate `MonadEither` type class might look like, if possible to define.