我将回顾 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 类型类,将 leftright 装箱以处理错误,但这并没有取得成果。我不太明白 mtl 中的类型类是如何工作的,尤其是这个实例必须通过多个值进行参数化,这很令人困惑。我想出了以下内容,在包含一些语法扩展后进行编译:

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

但我想不出 MonadEitherEitherT 实例:
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/

10-13 03:07