# 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
```
`2 :+ (-3)`
`V3 (1 :+ (-2)) (3 :+ 3) (0 :+ (-1))`
`V3 1.0 2.0 3.0`

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
```
`S (2.0 :+ 0.0)`