How do I write the type of 'inverse'?
Sat, 17 Nov 2001 06:29:54 +1300 (NZDT)

I have a class whose instances can extract a field of type a.
Is there a way of referring to that type 'a' in the signatures
of functions that use the class?   Sigh!  That wasn't very clear. 
I'll try explaining via example:
I am trying to define a `Pairable' class, which is an abstraction
of all kinds of pairs:  (a,b),   Pair a b,  etc.

> class Ord p => Pairable p where
>     is_pair      :: p -> Bool
>     pair_fst     :: Ord a => p -> a    -- Precondition: is_pair
>     pair_snd     :: Ord b => p -> b    -- Precondition: is_pair
>     make_pair    :: (Ord a, Ord b) => a -> b -> p

> instance (Ord a, Ord b) => Pairable (a,b) where
>     is_pair  (a,b) = True
>     pair_fst (a,b) = a
>     pair_snd (a,b) = b
>     make_pair a b  = (a,b)

I then want to define a `Relation' to be a set of Pairable values.
> newtype Pairable p => Reln p = Reln [p] 

This works okay for many of my relation operations.
But I run into an interesting problem with `inverse'
(which swaps the components of each pair).

inverse   :: (Pairable p, Pairable p2) => Reln p -> Reln p2
inverse rs = Reln[make_pair (pair_snd p) (pair_fst p) | p <- reln2list rs]

Hugs gives the error:

ERROR /home/utting/jaza/tmp.hs:19 - Cannot justify constraints in explicitly
typed binding
*** Expression    : inverse
*** Type          : (Pairable a, Pairable b) => Reln a -> Reln b
*** Given context : (Pairable a, Pairable b)
*** Constraints   : (Ord c, Ord d)

which I can understand.

BUT, I cannot see any way of naming the `component types', c and d,
in the signature of inverse!

It seems like I want to pass the component types into the
class definition somehow:   class Pairable (p a b)

How does one normally get around this kind of problem?

Mark Utting
Professeur Invité
Laboratoire d'Informatique de l'Université de Franch-Comté
16, route de Gray - 25000 Besançon, cedex, FRANCE
Tel:  (33) 3 81 66 20 69
Fax:  (33) 3 81 66 64 50