
class RingTy a b where order :: a -> Integer units :: a -> [b]
class VectorSpaceTy a b | a - > b where dimension :: a -> Integer basis :: (Field c) => a -> [b c]
where `b' is a vector space over the field `c'.
It looks like you are using the first (of two) type arguments to the RingTy and VectorSpaceTy type classes as abstract types; in other words, operations on rings and vector spaces don't really care what the type "a" is in "RingTy a b" and "VectorSpaceTy a b". Is that true? Assuming so, if I may strip away the (extremely sweet) syntactic sugar afforded by type classes for a moment, what you seem to be doing is to pass dictionaries of types data RingTy a b = RingTy { order :: a -> Integer, units :: a -> [b] } data VectorSpaceTy a b = VectorSpaceTy { dimension :: a -> Integer, basis :: forall c. (Field c) => a -> [b c] } to operations on rings and vector spaces. Because the type "a" is abstract, you may as well pass dictionaries of types data RingTy b = RingTy { order :: Integer, units :: [b] } data VectorSpaceTy b = VectorSpaceTy { dimension :: Integer, basis :: forall c. (Field c) => [b c] } to these operations. The information that you want computed just once per ring or per vector space can be defined as lexically scoped variables where you create these dictionaries in the first place. To add back the syntactic sugar (i.e., to make the dictionary arguments implicit) and to make the type system check that elements of different vector spaces are not confused, you may find Dylan Thurston's technique useful: http://www.cs.rutgers.edu/~ccshan/prepose/prepose.pdf -- Edit this signature at http://www.digitas.harvard.edu/cgi-bin/ken/sig 2008-07-04 Independence from America! http://caab.org.uk/ 2008-07-05 International Co-operative Day http://ica.coop/ http://www.guardian.co.uk/politics/2008/jul/02/labour.tradeunions