
| >> To use bar, you need (Ord a, Ord b). You're assuming that Ord (a, b) | >> implies that, but it's the other way round. | | Logically, the implication holds. There's an equivalence: | | Ord a /\ Ord b <=> Ord (a,b) | ... | The problem with dictionaries is that you have to store the superclass | dictionaries, here Ord a and Ord b, in the dictionary, here Ord (a,b). | However, what superclass dictionaries you have to store depends on the | instance, e.g. Ord Int doesn't have any superclass and Ord [a] has | superclass Ord a. In Haskell the "superclass(es)", if any, are declared in the class decl. Thus class Eq a => Ord a where ... Here Eq is the superclass of Ord. You're talking about something else: the dictionaries (Ord a, Ord b) from which the Ord (a,b) dictionary were constructed. We don't have a very good name for these guys, but "superclass" isn't a good one. Otherwise I agree with all you say. Your idea of using type families is cool. | data OrdDict a = | { (<) :: a -> a -> Bool | , ... | , super :: Super a | } | | type family Super a :: * | type instance Super Int = () | type instance Super [a] = OrdDict a | type instance Super (a,b) = (OrdDict a, OrdDict b) | | A similar solution is possible with a data family Super (but obviously I'm | in favor of type families :) Can you say why? A data family would work fine here. But it's not a big deal. So the other question is whether this is useful. How often do people write stuff like this? f :: Ord [a] => a -> a -> Bool f x y = x>y Nevertheless, I hadn't realised it was possible before, and now I can see it is. Simon