Remove Overlapping pragmas
Use a closed type family to avoid the need for overlapping instances. This shouldn't really affect anything, but it makes instance selection more explict.
Hmm... This actually seems to prevent some things from working. Some things that maybe shouldn't work? I need to consider this a bit more.
Specifically, GHC seems happy to fall back on the overlapping "not this one" instance quite readily when confronted with the question of whether, e.g., a ~ (a,b). However, it's more conservative about type family reduction out of fear of type families that loop and thus can produce infinite types like (a,(a,(a,..... But this affects the type accepted for, e.g., \a b -> genericShrink (a, b). It's not clear to me whether this can actually cause problems for realistic uses of genericShrink.
Hi,
It is quite worrying if genericShrink can miss shrink candidates because of GHC picking the wrong instance. Do you have an example (even if it's artificial) where this can happen? I'd like to understand this better.
Note that a ~ (a, b) is indeed impossible because the only solutions are infinite types. So GHC is right to pick the other instance in this case.
I can't merge this change directly because closed type families are only supported from GHC 7.8 upwards. But if there are cases where GHC picks the wrong instance with OverlappingInstances, then we could use the preprocessor to select either this implementation or the existing one depending on the GHC version.
I don't actually know if this can go wrong. Type family reduction is very conservative because GHC can't always recognize infinite types. You can write
type family Ugh a where
Ugh a = (a, Ugh a)
This can, of course, throw the type checker into an infinite loop when it's reduced, which is okay. But the existence of such families precludes GHC from implementing a general a /~ (a,b) rule, so when you apply
type family (==) a b where
a == a = 'True
a == b = 'False
as a == (a,b) for unknown a, it refuses to reduce and considers itself stuck. This is (at least for now) necessary to maintain type safety. The overlapping instance mechanism is more liberal. It seems satisfied to conclude that they're not equal and select the more general instance. This, at worst, risks incoherence, but not type safety failure.
I prefer closed type families to overlapping instances as a matter of taste (though I don't really love either). It would, I think, take some experimentation to determine whether the type family implementation reduces under circumstances typical for Arbitrary instances.
Yikes, I see. That's quite nasty!
I also prefer closed type families to overlapping instances. But I don't want to break QuickCheck on GHC 7.6 (still the default version on e.g. Debian stable) so let's make this change in the future.
Closing this as completed via #370