
I think what you want are functional dependencies. On Mon, 18 Aug 2003, Konrad Hinsen wrote:
On Monday 18 August 2003 09:25, Bernard James POPE wrote:
The kinds are there to help the compiler check whether types are well formed (including such things as instance declarations).
The syntax for kinds is very simple: ...
Thanks for the explanation! It seems that what I need (but what apparently doesn't exist) is the equivalent of a lambda expression for type constructors, then I could write something like
instance Vect (\a -> [Vector a]) a where ...
One way around this might be to define a new type:
newtype ListVector a = LV [Vector a]
instance Vect ListVector a where (<+>) (LV l1) (LV l2) = LV $ zipWith (<+>) l1 l2
Though is is bit ugly to have to mention the LV constructor all the time.
It's not just ugly, it destroys the generality of my code. I would like to be able to have generic list processing functions (think of "map") produce lists of vectors and then be able to apply the functions in class "Vect" to them. If I introduce a new type, then I will have to put wrapper functions in many places. I really want a type that is a list *and* an instance of class Vect.
In fact, what I'd really like to have is even more general:
instance Vect v a => Vect [Vect v a] where ...
i.e. defining that a list of any Vect instance is itself a Vect instance. But I could live with the case that I presented initially.
Konrad.
The class you had, class (Num a) => Vector v a where <+> :: v a -> v a -> v a <*> :: a -> va -> v a requires that v be a type constructor that gives vectors when applied to a ring. Using functional dependencies you can write a types class that says a type is a vector containing elements of type a: class (Num a) => Vector v a | v -> a where <+> :: v -> v -> v <*> :: a -> v -> v The type of <+> wouldn't be allowed without the dependancy v -> a, becuase a is never mentioned in the type so there would be no way to figure out what instance to use. The dependancy says "knowing the v type of an instance uniquely determines the a type". The compiler checks that your instance declarations satisfy this, and use the information when resolving overloading. you can still declare an instance for your vector type instance (Num a) => Vector (Vector a) a where <+> = ... <*> = ... (Notice that this declare an instance for all a) You can also declare instances for v that are not type constructors data Point = Point Float Float Float instance Vector Point Float where (Point x y z) <+> (Point x2 y2 z2) = Point (x+x2) (y+y2) (z+z2) a <*> (Point x y z) = Point (a*x) (a*y) (a*z) And, you can declare an instance for lists: instance (Vector v a) => Vector [v] a where as <+> bs = zipWith (<+>) as bs a <*> vs = map (a<*>) vs With GHC this requires -fglasgow-exts (and maybe -fundecidable-instances), with Hugs you need +98. The GHC users guide, the Haskell Wiki, and the paper "Type Classes: Exploring the Design Space" are all good places for more information. Brandon