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...
- Just enable the extension? Can somebody elaborate on what kinds of trouble it can get me into?
- Add another parameter to
Foo
, so that the last instance declaration becomes something likeFoo c d (Bar a d)
? A problem with this is that I might have other instances ofFoo
that never make any reference to any such "fourth type parameter" (i.e. there are instances of the forminstance Foo A B
in unrelated parts of my code), so these would break. I'd rather fix my instance, not my class. - 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?
Yes, your code does not adhere to (from here):
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 goIncoherentInstances
.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: