我将回顾Monad Transformers : Step by Step作为复习,并且像许多教程一样,它使用Control.Monad.Error
。 GHC现在发出警告,不推荐使用此模块,因此我从Control.Monad.Trans.Either
库切换到either
:http://hackage.haskell.org/package/either-3.4/docs/Control-Monad-Trans-Either.html
文章中eval2
可以顺利处理所有内容,因为EitherT
是最外层的monad。但是,在此之后一切都崩溃了 - ReaderT
绝不是Either
值,而今后的所有内容都使用ErrorT
,我想将其更改为EitherT
。
然后,我的想法是定义一个MonadEither
类型的类,其中包含left
和right
以处理错误,但这并不富有成效。我真的不明白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)’
类型类似于什么的指导,如果可能的话定义。
答案 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,因为这基本上就是您要复制的内容。)