module MLLabs.Distance
       ( Metric
       , minkowskiMetric
       , manhattanMetric
       , euclidianMetric
       , chebyshevMetric
       ) where

import           Linear.Vector (Additive (..))

type Metric obj = obj -> obj -> Double

minkowskiMetric :: (Foldable f, Additive f) => Double -> Metric (f Double)
minkowskiMetric p l1 l2 =
    (** (1/p)) $ sum $ fmap ((** p) . abs) $ l1 ^-^ l2

manhattanMetric :: (Foldable f, Additive f) => Metric (f Double)
manhattanMetric = minkowskiMetric 1

euclidianMetric :: (Foldable f, Additive f) => Metric (f Double)
euclidianMetric = minkowskiMetric 2

chebyshevMetric :: (Foldable f, Additive f) => Metric (f Double)
chebyshevMetric l1 l2 = maximum $ fmap abs $ l1 ^-^ l2
