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 xThreeVector 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)


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s