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 _______________________________________________ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe