I want a function +++
that adds two mathematical vectors.
I could implement vectors as [x, y, z]
and use:
(+++) :: (Num a) => [a] -> [a] -> [a]
(+++) = zipWith (+)
And thus accomodate any n-dimensional vector (so this would work for [x, y]
too).
Or I could implement vectors as (x, y, z)
and use:
type Triple a = (a, a, a)
merge :: (a -> b -> c) -> Triple a -> Triple b -> Triple c
merge f (a, b, c) (x, y, z) = (f a x, f b y, f c z)
(+++) :: (Num a) => Triple a -> Triple a -> Triple a
(+++) = merge (+)
Of course this is slightly more complex but it when I implement all the other vector functions, that is irrelevant (50 lines instead of 40).
The problem with the list approach is that I can add a 2D vector with a 3D vector. In that case, zipWith
would simply chop off the 3D vector's z
component. While that might make sense (more likely it should expand the 2D vector to [x, y, 0]
), for other functions I'm thinking it could be problematic to have either happen silently. The problem with the tuple approach is it limits the vector to 3 components.
Intuitively, I would think that it would make more sense to represent vectors as (x, y, z)
, since a mathematical vector has a fixed number of components and it doesn't really make sense to cons (prepend) a component to a vector.
On the other hand, although it's very unlikely that I will need anything other than 3D vectors, it doesn't seem quite right to limit it to that.
I guess what I want is functions that take two lists of equal length, or better, functions that operate on tuples of arbitrary size.
Any suggestions, in terms of practicality, scalability, elegance, etc.?