module Data.Distance
( Distance
, meters, centimeters, millimeters, kilometers
, toMeters, toCentimeters, toMillimeters, toKilometers
)
where
-- | An abstract distance. Use the provided smart constructors to create
-- a meaningful distance. Note that on first sight a `Num` instance might
-- seem desirable, but this would defeat the purpose of having transparent
-- and explicitly constructed distances due to `fromInteger`.
newtype Distance
= Distance { unDistance :: Double } -- as meters
deriving (Show, Eq, Ord)
-- | An empty `Distance` is 0, and `mappend` is defined as addition
instance Monoid Distance where
mempty = Distance 0
mappend (Distance a) (Distance b) = Distance (a + b)
meters :: Double -> Distance
meters = Distance
centimeters :: Double -> Distance
centimeters = meters . (/ 100)
millimeters :: Double -> Distance
millimeters = centimeters . (/ 10)
kilometers :: Double -> Distance
kilometers = meters . (* 1000)
toMeters :: Distance -> Double
toMeters = unDistance
toCentimeters :: Distance -> Double
toCentimeters = (*100) . toMeters
toMillimeters :: Distance -> Double
toMillimeters = (*10) . toCentimeters
toKilometers :: Distance -> Double
toKilometers = (/1000) . toMeters