定义MonadEither类型类

时间:2014-07-14 16:57:24

标签: haskell error-handling monad-transformers

我将回顾Monad Transformers : Step by Step作为复习,并且像许多教程一样,它使用Control.Monad.Error。 GHC现在发出警告,不推荐使用此模块,因此我从Control.Monad.Trans.Either库切换到eitherhttp://hackage.haskell.org/package/either-3.4/docs/Control-Monad-Trans-Either.html

文章中eval2可以顺利处理所有内容,因为EitherT是最外层的monad。但是,在此之后一切都崩溃了 - ReaderT绝不是Either值,而今后的所有内容都使用ErrorT,我想将其更改为EitherT

然后,我的想法是定义一个MonadEither类型的类,其中包含leftright以处理错误,但这并不富有成效。我真的不明白mtl中的类型类是如何工作的,特别是这个实例必须在多个值上进行参数化,这是令人困惑的。我提出了以下内容,它包括一些语法扩展后编译:

class (Monad m) => MonadEither l r m | m -> r where
  right :: r -> m r
  left  :: l -> m r

但我无法找出MonadEither的{​​{1}}个实例:

EitherT

编辑:我更改了实例声明以正确匹配instance Monad m => MonadEither l r (E.EitherT l m) where right = E.right left = E.left ,并收到以下错误消息:

E.EitherT

同样,我不确定我在做什么。我并不真正理解函数依赖性,所以我只是在寻找一些关于适当的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)’ 类型类似于什么的指导,如果可能的话定义。

1 个答案:

答案 0 :(得分:4)

怎么样

instance Monad m => MonadEither l r (E.EitherT l m)

也就是说,它应该是l而不是r

然而,一旦你完成了这个,你就会遇到一个单独的错误。根本原因是right没有意义;它只是return。这意味着您需要删除类的r参数。

class Monad m => MonadEither l m where
    left  :: l -> m a

您的实例声明应该成为

instance Monad m => MonadEither l (E.EitherT l m)

(您也可以查看MonadError class,因为这基本上就是您要复制的内容。)