Re: [Haskell-cafe] How to define an operation in terms of itself (but of different type)?

But you know it doesn't make too much sense because I also have to define
addition Scalar + Vector (that means construct vector from scalar and add a
vector), Vector + Scalar and so on. And as we are not able to overload
operations in C++ like way we have to create several different operations
even if their meaning is pretty close. Probably it's possible with ad hoc
overloading but I don't know is it good idea.
On Sat, Jan 24, 2009 at 1:56 PM, Alberto G. Corona
What about making your Vector a instance of Num? you have + and * well defined , although * is not commutative in this case
2009/1/24 Olex P
Yeah guys. I confused myself. I forgot why I had to implement several "+" operators (^+^, ^+, ^+. etc.) for Vector class. Now I've got an idea again. Different names make a perfect sense.
Thanks a lot.
On Sat, Jan 24, 2009 at 6:34 AM, Luke Palmer
wrote: 2009/1/23 Brandon S. Allbery KF8NH
On 2009 Jan 23, at 17:58, Olex P wrote:
class Vector v where (^+^) :: v -> v -> v
class Matrix m where (^+^) :: m -> m -> m
You can't reuse the same operator in different classes. Vector "owns" (^+^), so Matrix can't use it itself. You could say
instance Matrix m => Vector m where (^+^) = ...
No you can't! Stop thinking you can do that!
It would be sane to do:
class Vector m => Matrix m where -- matrix ops that don't make sense on vector
Thus anything that implements Matrix must first implement Vector. Which is sane because matrices are square vectors with some additional structure, in some sense.
Luke
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

* Olex P
But you know it doesn't make too much sense because I also have to define addition Scalar + Vector (that means construct vector from scalar and add a vector), Vector + Scalar and so on. And as we are not able to overload operations in C++ like way we have to create several different operations even if their meaning is pretty close. Probably it's possible with ad hoc overloading but I don't know is it good idea.
Consider defining functions with meaningful names (like scalarPlusVector), you then can use them as infix operators: 5 `scalarPlusVector` Vector 1 2 3 -- Roman I. Cheplyaka :: http://ro-che.info/ "Don't let school get in the way of your education." - Mark Twain

2009/1/24 Olex P
But you know it doesn't make too much sense because I also have to define addition Scalar + Vector (that means construct vector from scalar and add a vector), Vector + Scalar and so on. And as we are not able to overload operations in C++ like way we have to create several different operations even if their meaning is pretty close.
Well, yeah, but their meaning isn't *the same*, so we don't give them the same name. For vectors, putting a carat (or other signifier like a dot) on the side of the operation which has the vector is relatively common practice. Scalar +^ Vector Vector ^+^ Vector And so on. And also, I wonder, what are you going and adding scalars to vectors for!? (I've heard of multiplying scalars by vectors -- that's in the definition of a vector space, but adding...?) Oh, instead of overloading a million operations that just work component-wise on vectors the way C++ guys do it, you can just define a higher-order function: vmap :: (Vector v) => (Double -> Double) -> v -> v Or however it works out in your situation. Then you can reserve those precious symbols for things that are actually vectory, like inner products. Luke

Concerning Scalar + Vector i.e. +^ it's just a shortcut. Very useful even if
it's not good (?) from the design point of view. Also one could find useful
shortcut like .<, .<=, .>, .>= which mean compare length of vector. It's not
usual for vector algebra but probably still make sense.
What I want to ask you guys can we define a function with arbitrary number
of parameters? Actually not really arbitrary but just several possibilities
(as we have with value constructors).
For instance cross product can have 1, 2 or 3 vectors as inputs depends on
the dimension. Is it 2d, 3d or 4d case.
On Sat, Jan 24, 2009 at 3:59 PM, Luke Palmer
2009/1/24 Olex P
But you know it doesn't make too much sense because I also have to define addition Scalar + Vector (that means construct vector from scalar and add a vector), Vector + Scalar and so on. And as we are not able to overload operations in C++ like way we have to create several different operations even if their meaning is pretty close.
Well, yeah, but their meaning isn't *the same*, so we don't give them the same name.
For vectors, putting a carat (or other signifier like a dot) on the side of the operation which has the vector is relatively common practice.
Scalar +^ Vector Vector ^+^ Vector
And so on.
And also, I wonder, what are you going and adding scalars to vectors for!? (I've heard of multiplying scalars by vectors -- that's in the definition of a vector space, but adding...?)
Oh, instead of overloading a million operations that just work component-wise on vectors the way C++ guys do it, you can just define a higher-order function:
vmap :: (Vector v) => (Double -> Double) -> v -> v
Or however it works out in your situation. Then you can reserve those precious symbols for things that are actually vectory, like inner products.
Luke

2009/1/24 Olex P
What I want to ask you guys can we define a function with arbitrary number of parameters? Actually not really arbitrary but just several possibilities (as we have with value constructors). For instance cross product can have 1, 2 or 3 vectors as inputs depends on the dimension. Is it 2d, 3d or 4d case.
You need type classes plus some language extension to do this properly. Here's an example using type families: class Vector v => Cross v where type CrossResult v cross :: v -> CrossResult v instance Cross Vector2 where type CrossResult v = Vector2 cross (Vector2 x y) = Vector2 (-y) x -- is this the right operation? instance Cross Vector3 where type CrossResult v = Vector3 -> Vector3 cross (Vector3 x1 y1 z1) (Vector3 x2 y2 z2) = Vector3 (y1*z2 - z1*y2) (z1*x2 - x1*z2) (x1*y2 - y1*x2) etc. A difficult exercise is to define these operations in terms of each other inductively so that it works for arbitrary vector types; you need vectors indexed on some type-level natural, plus a bunch of hackery in the instances to make it work. -- ryan

Cool! Thanks Ryan!
On Sat, Jan 24, 2009 at 8:31 PM, Ryan Ingram
What I want to ask you guys can we define a function with arbitrary number of parameters? Actually not really arbitrary but just several
2009/1/24 Olex P
: possibilities (as we have with value constructors). For instance cross product can have 1, 2 or 3 vectors as inputs depends on the dimension. Is it 2d, 3d or 4d case.
You need type classes plus some language extension to do this properly. Here's an example using type families:
class Vector v => Cross v where type CrossResult v cross :: v -> CrossResult v
instance Cross Vector2 where type CrossResult v = Vector2 cross (Vector2 x y) = Vector2 (-y) x -- is this the right operation?
instance Cross Vector3 where type CrossResult v = Vector3 -> Vector3 cross (Vector3 x1 y1 z1) (Vector3 x2 y2 z2) = Vector3 (y1*z2 - z1*y2) (z1*x2 - x1*z2) (x1*y2 - y1*x2)
etc.
A difficult exercise is to define these operations in terms of each other inductively so that it works for arbitrary vector types; you need vectors indexed on some type-level natural, plus a bunch of hackery in the instances to make it work.
-- ryan

2009/1/24 Luke Palmer
And also, I wonder, what are you going and adding scalars to vectors for!? (I've heard of multiplying scalars by vectors -- that's in the definition of a vector space, but adding...?)
You can do that in geometric algebra. The result is a multivector.
But in that case, you'd probably be using a single multivector type.
--
Dave Menendez
participants (5)
-
David Menendez
-
Luke Palmer
-
Olex P
-
Roman Cheplyaka
-
Ryan Ingram