Vector
Vector is a module designed to facilitate mathematical vector operations in the hermitian-style. For simplicity, I model only 3 dimensional vectors but allow the underlying fields to be arbitrary. Complex and Double serve as example fields throughout. The data type ThreeVector has a vector constructor: V3 x x x
and a scalar constructor: S x
. ThreeVector then extends the Functor class with fmap mapping over the components in the obvious way.
import Data.Complex
data ThreeVector a = V3 a a a | S a deriving (Eq, Show)
instance Functor ThreeVector where
fmap f (V3 x y z) = V3 (f x) (f y) (f z)
fmap f (S x) = S $ f x
The Comp class introduces conjugation for ThreeVectors. Complex types are conjugated while Double types are left invariant.
class Comp c where
conj :: c -> c
instance Num a => Comp (Complex a) where
conj = conjugate
instance Comp Double where
conj = id
instance Comp a => Comp (ThreeVector a) where
conj = fmap conj
conj (2 :+ 3)
conj $ V3 (1 :+ 2) (3 :+ (-3)) (0 :+ 1)
conj $ V3 1 2 3
Now for the heart and soul of any module daring enough to call itself Vector.
The class Vector provides for the four base methods:
- innerproduct,
()
- norm, norm
- evaluation, eval
- projections, prs
Simultaneously, I extend Num to include ThreeVector. Extending provides meaning for summing, differencing, multiplying and taking the absolute value wrt ThreeVector. Notice that abs
relies on and
norm
relies and abs
. This mutual dependency simplifies the code, but requires that both extensions are present at the time of compilation.
instance (Floating a, Num a, Comp a) => Num (ThreeVector a) where
(+) (V3 a b c) (V3 x y z) = V3 (a+x) (b+y) (c+z)
(-) (V3 a b c) (V3 x y z) = V3 (a-x) (b-y) (c-z)
(*) (V3 a b c) (S x) = V3 (a*x) (b*x) (x*x)
(*) (S x) (V3 a b c) = V3 (a*x) (b*x) (x*x)
abs vect = fmap sqrt (vect vect)
class Vector v where
(<|>) :: (Num a, Comp a) => v a -> v a -> v a
norm :: (Floating a, Comp a) => v a -> v a
eval :: Num a => v a -> v a
prs :: v a -> [a]
instance Vector ThreeVector where
(<|>) (V3 a b c) (V3 x y z) = V3 (conj a *x) (conj b *y) (conj c*z) -- Hermitian
eval (V3 a b c) = S $ a + b + c
prs (V3 a b c) = [a, b, c]
norm = eval.abs
Now we can take the Hermitian innerproduct of two complex vectors and return their evaluation.
x = V3 (1 :+ 2) (3 :+ (-3)) (0 :+ 1)
y = V3 (3 :+ 2) (1 :+ 2) (5 :+ (-2))
eval $ x <|> y