import Data.Monoid ((<>))

type Vector a = [a]

type Scalar a = a

a, b, c, d :: Vector Int
a = [3, 4, 5]

b = [4, 3, 5]

c = [-5, -12, -13]

d = [3, 4, 5, 6]

dot
  :: (Num t)
  => Vector t -> Vector t -> Scalar t
dot u v
  | length u == length v = sum $ zipWith (*) u v
  | otherwise = error "Dotted Vectors must be of equal dimension."

cross
  :: (Num t)
  => Vector t -> Vector t -> Vector t
cross u v
  | length u == 3 && length v == 3 =
    [ u !! 1 * v !! 2 - u !! 2 * v !! 1
    , u !! 2 * head v - head u * v !! 2
    , head u * v !! 1 - u !! 1 * head v
    ]
  | otherwise = error "Crossed Vectors must both be three dimensional."

scalarTriple
  :: (Num t)
  => Vector t -> Vector t -> Vector t -> Scalar t
scalarTriple q r s = dot q $ cross r s

vectorTriple
  :: (Num t)
  => Vector t -> Vector t -> Vector t -> Vector t
vectorTriple q r s = cross q $ cross r s

main :: IO ()
main =
  mapM_
    putStrLn
    [ "a . b     = " <> show (dot a b)
    , "a x b     = " <> show (cross a b)
    , "a . b x c = " <> show (scalarTriple a b c)
    , "a x b x c = " <> show (vectorTriple a b c)
    , "a . d     = " <> show (dot a d)
    ]