flexible contexts and context reduction

Simon Peyton-Jones simonpj at microsoft.com
Thu Mar 27 04:43:58 EDT 2008

| >> 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.


More information about the Glasgow-haskell-users mailing list