{-# LANGUAGE TypeFamilies, DataKinds, TypeOperators, PolyKinds,
UndecidableInstances #-}
module Data.Metrology.Validity where
import Data.Metrology.LCSU
import Data.Metrology.Factor
import Data.Metrology.Dimensions
import Data.Metrology.Units
import Data.Metrology.Set
import Data.Metrology.Combinators
import GHC.Exts ( Constraint )
type family MultDimFactors (facts :: [Factor *]) where
MultDimFactors '[] = Dimensionless
MultDimFactors (F d z ': ds) = (d :^ z) :* MultDimFactors ds
type family MultUnitFactors (facts :: [Factor *]) where
MultUnitFactors '[] = Number
MultUnitFactors (F unit z ': units) = (unit :^ z) :* MultUnitFactors units
type family UnitOfDimFactors (dims :: [Factor *]) (lcsu :: LCSU *) :: * where
UnitOfDimFactors dims lcsu = MultUnitFactors (LookupList dims lcsu)
type family ValidDLU (dfactors :: [Factor *]) (lcsu :: LCSU *) (unit :: *) where
ValidDLU dfactors lcsu unit =
( dfactors ~ DimFactorsOf (DimOfUnit unit)
, UnitFactor (LookupList dfactors lcsu)
, Unit unit
, UnitFactorsOf unit *~ LookupList dfactors lcsu )
type family ValidDL (dfactors :: [Factor *]) (lcsu :: LCSU *) :: Constraint where
ValidDL dfactors lcsu = ValidDLU dfactors lcsu (UnitOfDimFactors dfactors lcsu)
type family ConvertibleLCSUs (dfactors :: [Factor *])
(l1 :: LCSU *) (l2 :: LCSU *) :: Constraint where
ConvertibleLCSUs dfactors l1 l2 =
( LookupList dfactors l1 *~ LookupList dfactors l2
, ValidDL dfactors l1
, ValidDL dfactors l2
, UnitFactor (LookupList dfactors l1)
, UnitFactor (LookupList dfactors l2) )
type family ConvertibleLCSUs_D (dim :: *) (l1 :: LCSU *) (l2 :: LCSU *) :: Constraint where
ConvertibleLCSUs_D dim l1 l2 = ConvertibleLCSUs (DimFactorsOf dim) l1 l2
infix 4 *~
type family (units1 :: [Factor *]) *~ (units2 :: [Factor *]) :: Constraint where
units1 *~ units2 =
CanonicalUnitsOfFactors units1 `SetEqual` CanonicalUnitsOfFactors units2
type family CanonicalUnitsOfFactors (fs :: [Factor *]) :: [*] where
CanonicalUnitsOfFactors '[] = '[]
CanonicalUnitsOfFactors (F u z ': fs) = (CanonicalUnit u) ': CanonicalUnitsOfFactors fs
type family CompatibleUnit (lcsu :: LCSU *) (unit :: *) :: Constraint where
CompatibleUnit lcsu unit
= ( ValidDLU (DimFactorsOf (DimOfUnit unit)) lcsu unit
, UnitFactor (LookupList (DimFactorsOf (DimOfUnit unit)) lcsu) )
type family CompatibleDim (lcsu :: LCSU *) (dim :: *) :: Constraint where
CompatibleDim lcsu dim
= ( UnitFactor (LookupList (DimFactorsOf dim) lcsu)
, DimOfUnit (Lookup dim lcsu) ~ dim )
type family DefaultConvertibleLCSU_D (dim :: *) (l :: LCSU *) :: Constraint where
DefaultConvertibleLCSU_D dim l =
( ValidDL (DimFactorsOf dim) DefaultLCSU
, ConvertibleLCSUs (DimFactorsOf dim) DefaultLCSU l )
type family DefaultConvertibleLCSU_U (unit :: *) (l :: LCSU *) :: Constraint where
DefaultConvertibleLCSU_U unit l =
DefaultConvertibleLCSU_D (DimOfUnit unit) l