我将回顾 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
的 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)’
再说一次,我不确定我在做什么。我不太了解函数依赖关系,所以我只是在寻找一些关于适当的
MonadEither
类型类可能是什么样子的指导,如果可能的话。 最佳答案
怎么样
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,因为这实际上是您要复制的内容。)关于haskell - 定义一个 MonadEither 类型类,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24741750/