Chung-chieh Shan ccshan at post.harvard.edu
Mon Jul 7 14:56:36 EDT 2008

```> 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/