module Data.Metrology.Combinators where
import Data.Singletons ( Sing, SingI, sing )
import Data.Metrology.Dimensions
import Data.Metrology.Units
import Data.Metrology.Factor
import Data.Metrology.Z
import Data.Type.Equality
import Data.Metrology.LCSU
infixl 7 :*
data u1 :* u2 = u1 :* u2
instance (Dimension d1, Dimension d2) => Dimension (d1 :* d2) where
type DimFactorsOf (d1 :* d2) = (DimFactorsOf d1) @+ (DimFactorsOf d2)
instance (Unit u1, Unit u2) => Unit (u1 :* u2) where
type BaseUnit (u1 :* u2) = Canonical
type DimOfUnit (u1 :* u2) = DimOfUnit u1 :* DimOfUnit u2
conversionRatio _ = undefined
type UnitFactorsOf (u1 :* u2) = (UnitFactorsOf u1) @+ (UnitFactorsOf u2)
canonicalConvRatio _ = canonicalConvRatio (undefined :: u1) *
canonicalConvRatio (undefined :: u2)
type instance DefaultUnitOfDim (d1 :* d2) =
DefaultUnitOfDim d1 :* DefaultUnitOfDim d2
infixl 7 :/
data u1 :/ u2 = u1 :/ u2
instance (Dimension d1, Dimension d2) => Dimension (d1 :/ d2) where
type DimFactorsOf (d1 :/ d2) = (DimFactorsOf d1) @- (DimFactorsOf d2)
instance (Unit u1, Unit u2) => Unit (u1 :/ u2) where
type BaseUnit (u1 :/ u2) = Canonical
type DimOfUnit (u1 :/ u2) = DimOfUnit u1 :/ DimOfUnit u2
conversionRatio _ = undefined
type UnitFactorsOf (u1 :/ u2) = (UnitFactorsOf u1) @- (UnitFactorsOf u2)
canonicalConvRatio _ = canonicalConvRatio (undefined :: u1) /
canonicalConvRatio (undefined :: u2)
type instance DefaultUnitOfDim (d1 :/ d2) =
DefaultUnitOfDim d1 :/ DefaultUnitOfDim d2
infixr 8 :^
data unit :^ (power :: Z) = unit :^ Sing power
instance Dimension dim => Dimension (dim :^ power) where
type DimFactorsOf (dim :^ power) = (DimFactorsOf dim) @* power
instance (Unit unit, SingI power) => Unit (unit :^ power) where
type BaseUnit (unit :^ power) = Canonical
type DimOfUnit (unit :^ power) = DimOfUnit unit :^ power
conversionRatio _ = undefined
type UnitFactorsOf (unit :^ power) = (UnitFactorsOf unit) @* power
canonicalConvRatio _ = canonicalConvRatio (undefined :: unit) ^^ (szToInt (sing :: Sing power))
type instance DefaultUnitOfDim (d :^ z) = DefaultUnitOfDim d :^ z
infixr 9 :@
data prefix :@ unit = prefix :@ unit
class UnitPrefix prefix where
multiplier :: Fractional f => prefix -> f
instance ( (unit == Canonical) ~ False
, Unit unit
, UnitPrefix prefix ) => Unit (prefix :@ unit) where
type BaseUnit (prefix :@ unit) = unit
conversionRatio _ = multiplier (undefined :: prefix)