我想让我的 monad 转换器成为 MonadError
的一个实例如果转换后的 monad 是一个实例。基本上我希望我的变压器表现得像内置变压器一样,例如有一个 MonadError
StateT
的实例:
MonadError e m => MonadError e (StateT s m)
我尝试这样做:
instance MonadError e m => MonadError e (MyMonadT m)
但是 GHC 开始提示不可判定的实例,显然 MTL 库只是启用不可判定的实例,但是有什么办法可以避免呢?或者在这种情况下可以,并且不会引起任何问题?
最佳答案
这基本上没问题。 UndecidableInstances
是不是都那么可怕;这意味着编译器可以进入无限循环,而不是找到一个实例。这听起来很糟糕,直到您意识到 GHC 实际上对查找实例所需的步骤数有限制;除非你写了一个错误的实例,否则什么都不会出错,而且你得到的错误消息通常会很明显地说明哪里出了问题。1 当然,它没有像 OverlappingInstances
这样的东西那么可怕。 (或更糟的是, IncoherentInstances
)。
它提示的原因是因为MonadError
具有来自 m
的函数依赖至 e
.那意味着选择m
决定什么e
必须是;即每个 m
仅与一个 e
相关联.对此(覆盖条件)的检查是保守的,因此很容易遇到这样的问题,您尝试“向下递归”以指定 e
.
1 它将列出它查看的所有实例,以尝试找到它正在寻找的实例,因此您会看到一堆重复的行。但通常你一开始就不会遇到这样的麻烦。
关于haskell - 使自定义 monad 转换器成为 MonadError 的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9951382/