使MonadError的实例成为一个自定义Monad变换器 [英] Making a custom monad transformer an instance of MonadError

查看:104
本文介绍了使MonadError的实例成为一个自定义Monad变换器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  MonadError em => MonadError e(StateT sm)

我试过这样做:

  instance MonadError em => MonadError e(MyMonadT m)

但GHC开始抱怨不可判定的实例,显然MTL库只能启用不可判定实例,但有什么办法可以避免这种情况?或者在这种情况下可以,它不会引起任何问题吗?

解决方案

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

它抱怨的原因是因为 MonadError 具有从 m e 的函数依赖关系。这意味着 m 的选择决定了 e 必须是什么;即每个 m 仅与一个 e 相关联。对这个(Coverage Condition)的检查是保守的,所以很容易遇到这样的问题,在这里你试着和递减一个级别来指定 e



1 它会列出所有正在查找的实例并找到它正在查找的实例,因此您会看到一堆重复线条。但通常情况下,你甚至不会像这样遇到麻烦。


I want to make my monad transformer to be an instance of MonadError if the transformed monad is an instance. Basically I want my transformer to behave as the built-in transformers do, for example there is a MonadError instance for StateT:

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

I tried doing this:

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

But GHC started complaining about undecidable instances, apparently the MTL library just enables undecidable instances, but is there any way to avoid that? Or it is OK in this case and it won't cause any problems?

解决方案

This is basically fine. UndecidableInstances isn't all that scary; all it means is that the compiler could, instead of finding an instance, go into an infinite loop. That sounds pretty bad, until you realise that GHC actually has a limit to the number of steps it'll take to find an instance; nothing will go wrong unless you write a bad instance, and the error messages you get will generally make it very obvious what's gone wrong.1 Certainly it's a lot less scary than things like OverlappingInstances (or worse, IncoherentInstances).

The reason it complains is because MonadError has a functional dependency from m to e. That means that the choice of m determines what e must be; i.e. every m is associated with only one e. The check for this (the Coverage Condition) is conservative, so it's easy to run into problems like this, where you try and "recurse down a level" to specify e.

1 It'll list all the instances it looked at to try and find the one it's looking for, so you'll see a bunch of repeating lines. But usually you won't even run into trouble like this in the first place.

这篇关于使MonadError的实例成为一个自定义Monad变换器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆