UndecidableInstances 什么时候安全?有关 GHC 扩展的一些常见问题

发布于 2024-10-17 16:14:48 字数 1108 浏览 3 评论 0原文

我知道 -XUndecidableInstances 的文档 ,但我想我应该要求详细说明。

假设我有两个多参数类型类(允许 -XMultiParamTypeClasses< /a>)

class Foo a b
class Goo a b

现在,假设我有一个参数化数据类型

data Bar a b

,当它的参数之一是 Goo 实例的一部分时,我想创建一个 Foo 实例。我不确定前一句使用了确切的术语,所以这就是我想写的内容:

instance (Goo c d) => Foo d (Bar a d)

如果没有 UndecidableInstances 扩展,我就不允许这样做。我是否正确地认为这是因为实例没有引用 c 类型?

我应该...

  1. 只启用扩展吗?有人可以详细说明它会给我带来什么样的麻烦吗?
  2. Foo 添加另一个参数,以便最后一个实例声明变成类似于 Foo cd (Bar ad)?这样做的一个问题是,我可能有其他 Foo 实例,它们从未对任何此类“第四类型参数”进行任何引用(即存在 instance Foo A B 形式的实例> 在我的代码的不相关部分),所以这些会破坏。我宁愿修复我的实例,而不是我的类。
  3. 创建一个具有足够参数的新类 FooGoo?在这种情况下,我会觉得我在重复自己,但至少我不会破坏不相关的课程。

有没有人有什么至理名言?

I know of the documentation for -XUndecidableInstances, but I thought I'd ask for an elaboration.

Suppose I have two multi-parameter typeclasses (allowed with -XMultiParamTypeClasses)

class Foo a b
class Goo a b

Now, suppose I have a parameterized data type

data Bar a b

which I want to make an instance of Foo when one of its parameters is part of an instance of Goo. I'm not sure the previous sentence uses exact terminology, so here's what I want to write:

instance (Goo c d) => Foo d (Bar a d)

I'm not allowed to without the UndecidableInstances extension. Am I correct in thinking this is because the instance doesn't refer to the c type?

Should I...

  1. Just enable the extension? Can somebody elaborate on what kinds of trouble it can get me into?
  2. Add another parameter to Foo, so that the last instance declaration becomes something like Foo c d (Bar a d)? A problem with this is that I might have other instances of Foo that never make any reference to any such "fourth type parameter" (i.e. there are instances of the form instance Foo A B in unrelated parts of my code), so these would break. I'd rather fix my instance, not my class.
  3. Create a new class FooGoo with enough parameters? I would feel like I'm repeating myself in that case, but at least I wouldn't break unrelated classes.

Does anyone have any words of wisdom?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我们的影子 2024-10-24 16:14:48

我认为这是因为实例不引用 c 类型是否正确?

是的,您的代码不符合(来自此处< /a>):

对于上下文中的每个断言:否
类型变量出现的次数较多
断言比头部的断言

您应该是安全的。当涉及到OverlappingInstances时,事情只会变得非常棘手(并且依赖于编译器),而当你使用IncoherentInstances时,事情就会变得非常糟糕。

如果不了解更多关于您想要完成的任务,就很难提供合理的设计建议,但首先要检查的是您是否真的需要将 c 作为 Goo 的参数。你也许可以这样表达你想要完成的事情:

class Goo d where
    bar :: d c -> Int
    baz :: Quux c => d c -> Int

Am I correct in thinking this is because the instance doesn't refer to the c type?

Yes, your code does not adhere to (from here):

For each assertion in the context: No
type variable has more occurrences in
the assertion than in the head

In general, you should be safe unless you add other instances that would, together, form a loop. Things only get really hairy (and compiler-dependent) when it comes to OverlappingInstances, and rightout evil when you go IncoherentInstances.

Without knowing more about what you're trying to accomplish it's hard to give sound design advice, but the first thing to check is whether you really, really need to have c as a parameter to Goo. You might be able to do express what you want to accomplish like this:

class Goo d where
    bar :: d c -> Int
    baz :: Quux c => d c -> Int
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文