CRIP: the Curiously Reoccuring Instance Pattern
2012-07-31 01:38:31 GMT
With apologies to Jim Coplien :)
I've been seeing this pattern in a surprising number of instance definitions lately:
instance (a ~ ar, b ~ br) => Mcomp a ar b br 
instance (b ~ c, CanFilterFunc b a) => CanFilter (b -> c) a 
The trick is that since instance selection is done entirely on the instance head, these instances are strictly more general than the ones they replace:
instance Mcomp a a b b
instance CanFilterFunc b => CanFilter (b -> b) a
The compiler has to do a lot more work to select these instances; it has to prove that the matching types actually match before it can select the instance; if it can't, it won't select an instance, and instead will complain about no instance "CLASS Int a". But with the CRIP, you help the compiler--it chooses the general instance, and then gets a constraint to solve. The constraint forces the two types to unify, or else there is a type error.
What I'm wondering is--are there many cases where you really want the non-constraint-generating behavior? It seems like (aside from contrived, ahem, instances) whenever you have instance CLASS A B where A and B share some type variables, that there aren't any valid instances of the same class where they don't share the types in that way. For example, I've never really seen a class in practice with instances like
class Foo a b
instance Foo a a
instance Foo ConcreteTypeA ConcreteTypeB
Note that it's very difficult to use polymorphic types in the second instance without risking overlap.
TL;DR: I, for one, welcome our new type equality constraint overlords.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe <at> haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe