# How do I write the type of 'inverse'?

**marku@cs.waikato.ac.nz
**
marku@cs.waikato.ac.nz

*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?
Thanks.
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
Email: marku@cs.waikato.ac.nz