packages feed

aviation-weight-balance-0.0.2: src/Data/Aviation/WB/Volume.hs

{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TemplateHaskell #-}

module Data.Aviation.WB.Volume(
  Volume
, HasVolume(..)
, HasVolumes(..)
, SetVolume(..)
, HasVolume0(..)
, usgallonsV
, litresV
, imperialgallonsV
) where

import Control.Category((.))
import Control.Lens(makeClassy, Traversal', Setter', Lens', Iso', iso)
import Data.Aviation.Units.ImperialGallons(ImperialGallons(imperialgallons))
import Data.Aviation.Units.USGallons(USGallons(usgallons))
import Data.Aviation.Units.Litres(Litres(litres))
import Data.Eq(Eq)
import Data.Maybe(Maybe)
import Data.Monoid(Monoid(mempty, mappend))
import Data.Ord(Ord)
import Data.Ratio((%))
import Data.Semigroup(Semigroup((<>)))
import Numeric.Lens(multiplying, dividing)
import Prelude(Show, Rational, (+), (*))

newtype Volume =
  Volume
    Rational
  deriving (Eq, Ord, Show)

makeClassy ''Volume

class HasVolumes a where
  volumes ::
    Traversal'
      a
      Volume

instance HasVolumes Volume where
  volumes =
    volume

class SetVolume a where
  setVolume ::
    Setter'
      a
      Volume

instance SetVolume Volume where
  setVolume =
    volume

class HasVolume0 a where
  volume0 ::
    Lens'
      a
      (Maybe Volume)

instance Semigroup Volume where
  (<>) =
    mappend

instance Monoid Volume where
  mempty =
    Volume 0
  Volume w1 `mappend` Volume w2 =
    Volume (w1 + w2)

instance USGallons Volume where
  usgallons =
    iso
      Volume
      (\(Volume x) -> x)

instance Litres Volume where
  litres =
    dividing ((254 * 254 * 254 * 231) % 1000000000) . usgallons

instance ImperialGallons Volume where
  imperialgallons =
    multiplying (454609 % 100000) . litres

usgallonsV ::
  Iso'
    Rational
    Volume
usgallonsV =
  usgallons

litresV ::
  Iso'
    Rational
    Volume
litresV =
  litres

imperialgallonsV ::
  Iso'
    Rational
    Volume
imperialgallonsV =
  imperialgallons