开发者

When is UndecidableInstances safe? Some general questions regarding the GHC extension

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?


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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜