Library for vectors

From HaskellWiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.


Most people just use (Int,Int) or similar for a 2-vector. However, if you find yourself wanting to do lots of vector arithmetic, that becomes annoying quite quickly. Below is what I use; feel free to adapt it to your needs.

module Vector where

type Scalar = Double

class Vector v where
  vmap  :: (Scalar -> Scalar) -> v -> v
  vzip  :: (Scalar -> Scalar -> Scalar) -> v -> v -> v
  vfold :: (x -> Scalar -> x) -> x -> v -> x

vdot :: Vector v => v -> v -> Scalar
vdot v0 v1 = vfold (+) 0 $ vzip (*) v0 v1

vmag_sqr :: Vector v => v -> Scalar
vmag_sqr v = v `vdot` v

vmag :: Vector v => v -> Scalar
vmag = sqrt . vmag_sqr

vscale :: Vector v => Scalar -> v -> v
vscale s = vmap (s*)

vunit :: Vector v => v -> v
vunit v =
  if vmag v == 0
    then v
    else vscale (1 / vmag v) v


data Vector2 = Vector2 {v2x, v2y :: Scalar} deriving (Eq)

instance Show Vector2 where
  show (Vector2 x y) = "<" ++ (show x) ++ ", " ++ (show y) ++ ">"

instance Vector Vector2 where
  vmap  f   (Vector2 x y) = Vector2 (f x) (f y)
  vfold f i (Vector2 x y) = (i `f` x) `f` y
  vzip  f   (Vector2 x0 y0) (Vector2 x1 y1) = Vector2 (f x0 x1) (f y0 y1)

instance Num Vector2 where
  (+) = vzip (+)
  (-) = vzip (-)
  (*) = vzip (*)
  negate = vmap negate
  fromInteger s = Vector2 (fromInteger s) (fromInteger s)

instance Fractional Vector2 where
  (/) = vzip (/)
  fromDouble s = Vector2 s s


data Vector3 = Vector3 {v3x, v3y, v3z :: Scalar} deriving (Eq)

instance Show Vector3 where
  show (Vector3 x y z) = "<" ++ (show x) ++ ", " ++ (show y) ++ ", " ++ (show z) ++ ">"

instance Vector Vector3 where
  vmap  f   (Vector3 x y z) = Vector3 (f x) (f y) (f z)
  vfold f i (Vector3 x y z) = ((i `f` x) `f` y) `f` z
  vzip  f   (Vector3 x0 y0 z0) (Vector3 x1 y1 z1) = Vector3 (f x0 x1) (f y0 y1) (f z0 z1)

instance Num Vector3 where
  (+) = vzip (+)
  (-) = vzip (-)
  (*) = vzip (*)
  negate = vmap negate
  fromInteger s = Vector3 (fromInteger s) (fromInteger s) (fromInteger s)

instance Fractional Vector3 where
  (/) = vzip (/)
  fromDouble s = Vector3 s s s

v3cross (Vector3 x0 y0 z0) (Vector3 x1 y1 z1) = Vector3 (y0*z1 - y1*z0) (x0*z1 - x1*z0) (x0*y1 - x1*y0)

PS. If anybody knows a way to make every instance of Vector automatically become an instance of Num, etc., let me know!