使自定义monad转换器成为MonadError的实例

时间:2012-03-30 22:58:25

标签: haskell monad-transformers

如果转换的monad是一个实例,我想让我的monad转换器成为MonadError的实例。基本上我希望我的变换器能够像内置变换器一样工作,例如MonadError有一个StateT实例:

MonadError e m => MonadError e (StateT s m)

我试过这样做:

instance MonadError e m => MonadError e (MyMonadT m)

但是GHC开始抱怨不可判断的实例,显然MTL库只是启用了不可判定的实例,但有没有办法避免这种情况?或者在这种情况下可以,它不会导致任何问题吗?

1 个答案:

答案 0 :(得分:8)

这基本上没问题。 UndecidableInstances并不那么可怕;这意味着编译器可以进入无限循环而不是查找实例。 听起来非常糟糕,直到你意识到GHC实际上对查找实例所需的步骤数量有限制;除非你写了一个不好的实例,否则什么都不会出错,而你得到的错误信息通常会让你明白出现了什么问题。 1 当然,这比OverlappingInstances之类的事情要少得多(或者更糟,IncoherentInstances)。

它抱怨的原因是MonadError具有从me的功能依赖性。这意味着m的选择决定了e必须是什么;即每m只与一个e相关联。对此进行检查(覆盖条件)是保守的,因此很容易遇到这样的问题,您尝试“递减一级”以指定e

1 它会列出它所看到的所有实例,试图找到它正在寻找的那个,所以你会看到一堆重复的行。但通常你一开始就不会遇到这样的麻烦。