{-# OPTIONS_HADDOCK not-home #-}

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE NumDecimals #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}

module Numeric.Units.Dimensional.UnitNames.Internal
where

import Control.DeepSeq
import Control.Monad (join)
import Data.Coerce
import Data.Data hiding (Prefix)
import Data.Foldable (toList)
import Data.Ord
import GHC.Generics hiding (Prefix)
import Numeric.Units.Dimensional.Dimensions.TermLevel (Dimension', asList, HasDimension(..))
import Numeric.Units.Dimensional.UnitNames.InterchangeNames hiding (isAtomic)
import qualified Numeric.Units.Dimensional.UnitNames.InterchangeNames as I
import Numeric.Units.Dimensional.Variants (Metricality(..))
import Prelude hiding ((*), (/), (^), product)
import qualified Prelude as P

-- | The name of a unit.
data UnitName (m :: Metricality) where
  -- | The name of the unit of dimensionless values.
  One :: UnitName 'NonMetric
  -- | A name of an atomic unit to which metric prefixes may be applied.
  MetricAtomic :: NameAtom ('UnitAtom 'Metric) -> UnitName 'Metric
  -- | A name of an atomic unit to which metric prefixes may not be applied.
  Atomic :: NameAtom ('UnitAtom 'NonMetric) -> UnitName 'NonMetric
  -- | A name of a prefixed unit.
  Prefixed :: PrefixName -> UnitName 'Metric -> UnitName 'NonMetric
  -- | A compound name formed from the product of two names.
  Product :: UnitName 'NonMetric -> UnitName 'NonMetric -> UnitName 'NonMetric
  -- | A compound name formed from the quotient of two names.
  Quotient :: UnitName 'NonMetric -> UnitName 'NonMetric -> UnitName 'NonMetric
  -- | A compound name formed by raising a unit name to an integer power.
  Power :: UnitName 'NonMetric -> Int -> UnitName 'NonMetric
  -- | A compound name formed by grouping another name, which is generally compound.
  Grouped :: UnitName 'NonMetric -> UnitName 'NonMetric
  -- | A weakened name formed by forgetting that it could accept a metric prefix.
  --
  -- Also available is the smart constructor `weaken` which accepts any `UnitName` as input.
  Weaken :: UnitName 'Metric -> UnitName 'NonMetric
  deriving (Typeable)

deriving instance Eq (UnitName m)

-- As it is for a GADT, this instance cannot be derived or use the generic default implementation
instance NFData (UnitName m) where
  rnf :: UnitName m -> ()
rnf UnitName m
n = case UnitName m
n of
    UnitName m
One -> ()
    MetricAtomic NameAtom ('UnitAtom 'Metric)
a -> NameAtom ('UnitAtom 'Metric) -> ()
forall a. NFData a => a -> ()
rnf NameAtom ('UnitAtom 'Metric)
a
    Atomic NameAtom ('UnitAtom 'NonMetric)
a -> NameAtom ('UnitAtom 'NonMetric) -> ()
forall a. NFData a => a -> ()
rnf NameAtom ('UnitAtom 'NonMetric)
a
    Prefixed PrefixName
p UnitName 'Metric
n' -> PrefixName -> ()
forall a. NFData a => a -> ()
rnf PrefixName
p () -> () -> ()
`seq` UnitName 'Metric -> ()
forall a. NFData a => a -> ()
rnf UnitName 'Metric
n'
    Product UnitName 'NonMetric
n1 UnitName 'NonMetric
n2 -> UnitName 'NonMetric -> ()
forall a. NFData a => a -> ()
rnf UnitName 'NonMetric
n1 () -> () -> ()
`seq` UnitName 'NonMetric -> ()
forall a. NFData a => a -> ()
rnf UnitName 'NonMetric
n2
    Quotient UnitName 'NonMetric
n1 UnitName 'NonMetric
n2 -> UnitName 'NonMetric -> ()
forall a. NFData a => a -> ()
rnf UnitName 'NonMetric
n1 () -> () -> ()
`seq` UnitName 'NonMetric -> ()
forall a. NFData a => a -> ()
rnf UnitName 'NonMetric
n2
    Power UnitName 'NonMetric
n' Int
e -> UnitName 'NonMetric -> ()
forall a. NFData a => a -> ()
rnf UnitName 'NonMetric
n' () -> () -> ()
`seq` Int -> ()
forall a. NFData a => a -> ()
rnf Int
e
    Grouped UnitName 'NonMetric
n' -> UnitName 'NonMetric -> ()
forall a. NFData a => a -> ()
rnf UnitName 'NonMetric
n'
    Weaken UnitName 'Metric
n' -> UnitName 'Metric -> ()
forall a. NFData a => a -> ()
rnf UnitName 'Metric
n'

-- | `UnitName`s are shown with non-breaking spaces.
instance Show (UnitName m) where
  show :: UnitName m -> String
show UnitName m
One = String
"1"
  show (MetricAtomic NameAtom ('UnitAtom 'Metric)
a) = NameAtom ('UnitAtom 'Metric) -> String
forall (m :: NameAtomType). NameAtom m -> String
abbreviation_en NameAtom ('UnitAtom 'Metric)
a
  show (Atomic NameAtom ('UnitAtom 'NonMetric)
a) = NameAtom ('UnitAtom 'NonMetric) -> String
forall (m :: NameAtomType). NameAtom m -> String
abbreviation_en NameAtom ('UnitAtom 'NonMetric)
a
  show (Prefixed PrefixName
a UnitName 'Metric
n) = PrefixName -> String
forall (m :: NameAtomType). NameAtom m -> String
abbreviation_en PrefixName
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ UnitName 'Metric -> String
forall a. Show a => a -> String
show UnitName 'Metric
n
  show (Product UnitName 'NonMetric
n1 UnitName 'NonMetric
n2) = UnitName 'NonMetric -> String
forall a. Show a => a -> String
show UnitName 'NonMetric
n1 String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"\xA0" String -> ShowS
forall a. [a] -> [a] -> [a]
++ UnitName 'NonMetric -> String
forall a. Show a => a -> String
show UnitName 'NonMetric
n2
  show (Quotient UnitName 'NonMetric
n1 UnitName 'NonMetric
n2) = UnitName 'NonMetric -> String
forall a. Show a => a -> String
show UnitName 'NonMetric
n1 String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"\xA0/\xA0" String -> ShowS
forall a. [a] -> [a] -> [a]
++ UnitName 'NonMetric -> String
forall a. Show a => a -> String
show UnitName 'NonMetric
n2
  show (Power UnitName 'NonMetric
x Int
n) = UnitName 'NonMetric -> String
forall a. Show a => a -> String
show UnitName 'NonMetric
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"^" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
n
  show (Grouped UnitName 'NonMetric
n) = String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ UnitName 'NonMetric -> String
forall a. Show a => a -> String
show UnitName 'NonMetric
n String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
  show (Weaken UnitName 'Metric
n) = UnitName 'Metric -> String
forall a. Show a => a -> String
show UnitName 'Metric
n

-- | Converts a 'UnitName' to a 'NameAtom', if possible.
asAtomic :: UnitName m -> Maybe (NameAtom ('UnitAtom m))
asAtomic :: UnitName m -> Maybe (NameAtom ('UnitAtom m))
asAtomic (MetricAtomic NameAtom ('UnitAtom 'Metric)
a) = NameAtom ('UnitAtom 'Metric)
-> Maybe (NameAtom ('UnitAtom 'Metric))
forall a. a -> Maybe a
Just NameAtom ('UnitAtom 'Metric)
a
asAtomic (Atomic NameAtom ('UnitAtom 'NonMetric)
a) = NameAtom ('UnitAtom 'NonMetric)
-> Maybe (NameAtom ('UnitAtom 'NonMetric))
forall a. a -> Maybe a
Just NameAtom ('UnitAtom 'NonMetric)
a
asAtomic (Weaken UnitName 'Metric
n) = NameAtom ('UnitAtom 'Metric) -> NameAtom ('UnitAtom m)
coerce (NameAtom ('UnitAtom 'Metric) -> NameAtom ('UnitAtom m))
-> Maybe (NameAtom ('UnitAtom 'Metric))
-> Maybe (NameAtom ('UnitAtom m))
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> UnitName 'Metric -> Maybe (NameAtom ('UnitAtom 'Metric))
forall (m :: Metricality).
UnitName m -> Maybe (NameAtom ('UnitAtom m))
asAtomic UnitName 'Metric
n
asAtomic UnitName m
_ = Maybe (NameAtom ('UnitAtom m))
forall a. Maybe a
Nothing

-- | Returns 'True' if the 'UnitName' is atomic.
isAtomic :: UnitName m -> Bool
isAtomic :: UnitName m -> Bool
isAtomic UnitName m
One = Bool
True
isAtomic (MetricAtomic NameAtom ('UnitAtom 'Metric)
_) = Bool
True
isAtomic (Atomic NameAtom ('UnitAtom 'NonMetric)
_) = Bool
True
isAtomic (Prefixed PrefixName
_ UnitName 'Metric
_) = Bool
True
isAtomic (Grouped UnitName 'NonMetric
_) = Bool
True
isAtomic (Weaken UnitName 'Metric
n) = UnitName 'Metric -> Bool
forall (m :: Metricality). UnitName m -> Bool
isAtomic UnitName 'Metric
n
isAtomic UnitName m
_ = Bool
False

isAtomicOrProduct :: UnitName m -> Bool
isAtomicOrProduct :: UnitName m -> Bool
isAtomicOrProduct (Product UnitName 'NonMetric
_ UnitName 'NonMetric
_) = Bool
True
isAtomicOrProduct UnitName m
n = UnitName m -> Bool
forall (m :: Metricality). UnitName m -> Bool
isAtomic UnitName m
n

-- | Reduce a 'UnitName' by algebraic simplifications.
reduce :: UnitName m -> UnitName m
reduce :: UnitName m -> UnitName m
reduce UnitName m
One = UnitName m
UnitName 'NonMetric
One
reduce n :: UnitName m
n@(MetricAtomic NameAtom ('UnitAtom 'Metric)
_) = UnitName m
n
reduce n :: UnitName m
n@(Atomic NameAtom ('UnitAtom 'NonMetric)
_) = UnitName m
n
reduce n :: UnitName m
n@(Prefixed PrefixName
_ UnitName 'Metric
_) = UnitName m
n
reduce (Product UnitName 'NonMetric
n1 UnitName 'NonMetric
n2) = UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName m
reduce' (UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName m
reduce UnitName 'NonMetric
n1 UnitName 'NonMetric -> UnitName 'NonMetric -> UnitName 'NonMetric
forall (m1 :: Metricality) (m2 :: Metricality).
UnitName m1 -> UnitName m2 -> UnitName 'NonMetric
* UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName m
reduce UnitName 'NonMetric
n2)
reduce (Quotient UnitName 'NonMetric
n1 UnitName 'NonMetric
n2) = UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName m
reduce' (UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName m
reduce UnitName 'NonMetric
n1 UnitName 'NonMetric -> UnitName 'NonMetric -> UnitName 'NonMetric
forall (m1 :: Metricality) (m2 :: Metricality).
UnitName m1 -> UnitName m2 -> UnitName 'NonMetric
* UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName m
reduce UnitName 'NonMetric
n2)
reduce (Power UnitName 'NonMetric
n Int
x) = UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName m
reduce' (UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName m
reduce UnitName 'NonMetric
n UnitName 'NonMetric -> Int -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> Int -> UnitName 'NonMetric
^ Int
x)
reduce (Grouped UnitName 'NonMetric
n) = UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName m
reduce' (UnitName 'NonMetric -> UnitName 'NonMetric
Grouped (UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName m
reduce UnitName 'NonMetric
n))
reduce (Weaken UnitName 'Metric
n) = UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName m
reduce' (UnitName 'Metric -> UnitName 'NonMetric
Weaken (UnitName 'Metric -> UnitName 'Metric
forall (m :: Metricality). UnitName m -> UnitName m
reduce UnitName 'Metric
n))

-- reduce, knowing that subterms are already in reduced form
reduce' :: UnitName m -> UnitName m
reduce' :: UnitName m -> UnitName m
reduce' (Product UnitName 'NonMetric
One UnitName 'NonMetric
n) = UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName m
reduce' UnitName 'NonMetric
n
reduce' (Product UnitName 'NonMetric
n UnitName 'NonMetric
One) = UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName m
reduce' UnitName 'NonMetric
n
reduce' (Power (Power UnitName 'NonMetric
n Int
x1) Int
x2) = UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName m
reduce (UnitName 'NonMetric
n UnitName 'NonMetric -> Int -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> Int -> UnitName 'NonMetric
^ (Int
x1 Int -> Int -> Int
forall a. Num a => a -> a -> a
P.* Int
x2))
reduce' (Power (Grouped (Power UnitName 'NonMetric
n Int
x1)) Int
x2) = UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName m
reduce (UnitName 'NonMetric
n UnitName 'NonMetric -> Int -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> Int -> UnitName 'NonMetric
^ (Int
x1 Int -> Int -> Int
forall a. Num a => a -> a -> a
P.* Int
x2))
reduce' (Power UnitName 'NonMetric
_ Int
0) = UnitName m
UnitName 'NonMetric
One
reduce' (Power UnitName 'NonMetric
n Int
1) = UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName m
reduce' UnitName 'NonMetric
n
reduce' (Grouped UnitName 'NonMetric
n) = UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName m
reduce' UnitName 'NonMetric
n
reduce' n :: UnitName m
n@(Weaken (MetricAtomic NameAtom ('UnitAtom 'Metric)
_)) = UnitName m
n
reduce' UnitName m
n = UnitName m
n

data NameAtomType = UnitAtom Metricality
                  | PrefixAtom
  deriving (NameAtomType -> NameAtomType -> Bool
(NameAtomType -> NameAtomType -> Bool)
-> (NameAtomType -> NameAtomType -> Bool) -> Eq NameAtomType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NameAtomType -> NameAtomType -> Bool
$c/= :: NameAtomType -> NameAtomType -> Bool
== :: NameAtomType -> NameAtomType -> Bool
$c== :: NameAtomType -> NameAtomType -> Bool
Eq, Eq NameAtomType
Eq NameAtomType
-> (NameAtomType -> NameAtomType -> Ordering)
-> (NameAtomType -> NameAtomType -> Bool)
-> (NameAtomType -> NameAtomType -> Bool)
-> (NameAtomType -> NameAtomType -> Bool)
-> (NameAtomType -> NameAtomType -> Bool)
-> (NameAtomType -> NameAtomType -> NameAtomType)
-> (NameAtomType -> NameAtomType -> NameAtomType)
-> Ord NameAtomType
NameAtomType -> NameAtomType -> Bool
NameAtomType -> NameAtomType -> Ordering
NameAtomType -> NameAtomType -> NameAtomType
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: NameAtomType -> NameAtomType -> NameAtomType
$cmin :: NameAtomType -> NameAtomType -> NameAtomType
max :: NameAtomType -> NameAtomType -> NameAtomType
$cmax :: NameAtomType -> NameAtomType -> NameAtomType
>= :: NameAtomType -> NameAtomType -> Bool
$c>= :: NameAtomType -> NameAtomType -> Bool
> :: NameAtomType -> NameAtomType -> Bool
$c> :: NameAtomType -> NameAtomType -> Bool
<= :: NameAtomType -> NameAtomType -> Bool
$c<= :: NameAtomType -> NameAtomType -> Bool
< :: NameAtomType -> NameAtomType -> Bool
$c< :: NameAtomType -> NameAtomType -> Bool
compare :: NameAtomType -> NameAtomType -> Ordering
$ccompare :: NameAtomType -> NameAtomType -> Ordering
$cp1Ord :: Eq NameAtomType
Ord, Typeable NameAtomType
DataType
Constr
Typeable NameAtomType
-> (forall (c :: Type -> Type).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> NameAtomType -> c NameAtomType)
-> (forall (c :: Type -> Type).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c NameAtomType)
-> (NameAtomType -> Constr)
-> (NameAtomType -> DataType)
-> (forall (t :: Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c NameAtomType))
-> (forall (t :: Type -> Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c NameAtomType))
-> ((forall b. Data b => b -> b) -> NameAtomType -> NameAtomType)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> NameAtomType -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> NameAtomType -> r)
-> (forall u. (forall d. Data d => d -> u) -> NameAtomType -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> NameAtomType -> u)
-> (forall (m :: Type -> Type).
    Monad m =>
    (forall d. Data d => d -> m d) -> NameAtomType -> m NameAtomType)
-> (forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> NameAtomType -> m NameAtomType)
-> (forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> NameAtomType -> m NameAtomType)
-> Data NameAtomType
NameAtomType -> DataType
NameAtomType -> Constr
(forall b. Data b => b -> b) -> NameAtomType -> NameAtomType
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> NameAtomType -> c NameAtomType
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c NameAtomType
forall a.
Typeable a
-> (forall (c :: Type -> Type).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: Type -> Type).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: Type -> Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: Type -> Type).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> NameAtomType -> u
forall u. (forall d. Data d => d -> u) -> NameAtomType -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> NameAtomType -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> NameAtomType -> r
forall (m :: Type -> Type).
Monad m =>
(forall d. Data d => d -> m d) -> NameAtomType -> m NameAtomType
forall (m :: Type -> Type).
MonadPlus m =>
(forall d. Data d => d -> m d) -> NameAtomType -> m NameAtomType
forall (c :: Type -> Type).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c NameAtomType
forall (c :: Type -> Type).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> NameAtomType -> c NameAtomType
forall (t :: Type -> Type) (c :: Type -> Type).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c NameAtomType)
forall (t :: Type -> Type -> Type) (c :: Type -> Type).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c NameAtomType)
$cPrefixAtom :: Constr
$cUnitAtom :: Constr
$tNameAtomType :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> NameAtomType -> m NameAtomType
$cgmapMo :: forall (m :: Type -> Type).
MonadPlus m =>
(forall d. Data d => d -> m d) -> NameAtomType -> m NameAtomType
gmapMp :: (forall d. Data d => d -> m d) -> NameAtomType -> m NameAtomType
$cgmapMp :: forall (m :: Type -> Type).
MonadPlus m =>
(forall d. Data d => d -> m d) -> NameAtomType -> m NameAtomType
gmapM :: (forall d. Data d => d -> m d) -> NameAtomType -> m NameAtomType
$cgmapM :: forall (m :: Type -> Type).
Monad m =>
(forall d. Data d => d -> m d) -> NameAtomType -> m NameAtomType
gmapQi :: Int -> (forall d. Data d => d -> u) -> NameAtomType -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> NameAtomType -> u
gmapQ :: (forall d. Data d => d -> u) -> NameAtomType -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> NameAtomType -> [u]
gmapQr :: (r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> NameAtomType -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> NameAtomType -> r
gmapQl :: (r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> NameAtomType -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> NameAtomType -> r
gmapT :: (forall b. Data b => b -> b) -> NameAtomType -> NameAtomType
$cgmapT :: (forall b. Data b => b -> b) -> NameAtomType -> NameAtomType
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c NameAtomType)
$cdataCast2 :: forall (t :: Type -> Type -> Type) (c :: Type -> Type).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c NameAtomType)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c NameAtomType)
$cdataCast1 :: forall (t :: Type -> Type) (c :: Type -> Type).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c NameAtomType)
dataTypeOf :: NameAtomType -> DataType
$cdataTypeOf :: NameAtomType -> DataType
toConstr :: NameAtomType -> Constr
$ctoConstr :: NameAtomType -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c NameAtomType
$cgunfold :: forall (c :: Type -> Type).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c NameAtomType
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> NameAtomType -> c NameAtomType
$cgfoldl :: forall (c :: Type -> Type).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> NameAtomType -> c NameAtomType
$cp1Data :: Typeable NameAtomType
Data, Typeable, (forall x. NameAtomType -> Rep NameAtomType x)
-> (forall x. Rep NameAtomType x -> NameAtomType)
-> Generic NameAtomType
forall x. Rep NameAtomType x -> NameAtomType
forall x. NameAtomType -> Rep NameAtomType x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep NameAtomType x -> NameAtomType
$cfrom :: forall x. NameAtomType -> Rep NameAtomType x
Generic)

instance NFData NameAtomType where -- instance is derived from Generic instance

-- | The name of a metric prefix.
type PrefixName = NameAtom 'PrefixAtom

-- | A metric prefix.
data Prefix = Prefix
              {
                -- | The name of a metric prefix.
                Prefix -> PrefixName
prefixName :: PrefixName,
                -- | The scale factor denoted by a metric prefix.
                Prefix -> Rational
scaleFactor :: Rational
              }
  deriving (Prefix -> Prefix -> Bool
(Prefix -> Prefix -> Bool)
-> (Prefix -> Prefix -> Bool) -> Eq Prefix
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Prefix -> Prefix -> Bool
$c/= :: Prefix -> Prefix -> Bool
== :: Prefix -> Prefix -> Bool
$c== :: Prefix -> Prefix -> Bool
Eq, Typeable Prefix
DataType
Constr
Typeable Prefix
-> (forall (c :: Type -> Type).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Prefix -> c Prefix)
-> (forall (c :: Type -> Type).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Prefix)
-> (Prefix -> Constr)
-> (Prefix -> DataType)
-> (forall (t :: Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Prefix))
-> (forall (t :: Type -> Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Prefix))
-> ((forall b. Data b => b -> b) -> Prefix -> Prefix)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Prefix -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Prefix -> r)
-> (forall u. (forall d. Data d => d -> u) -> Prefix -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> Prefix -> u)
-> (forall (m :: Type -> Type).
    Monad m =>
    (forall d. Data d => d -> m d) -> Prefix -> m Prefix)
-> (forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Prefix -> m Prefix)
-> (forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Prefix -> m Prefix)
-> Data Prefix
Prefix -> DataType
Prefix -> Constr
(forall b. Data b => b -> b) -> Prefix -> Prefix
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Prefix -> c Prefix
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Prefix
forall a.
Typeable a
-> (forall (c :: Type -> Type).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: Type -> Type).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: Type -> Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: Type -> Type).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Prefix -> u
forall u. (forall d. Data d => d -> u) -> Prefix -> [u]
forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Prefix -> r
forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Prefix -> r
forall (m :: Type -> Type).
Monad m =>
(forall d. Data d => d -> m d) -> Prefix -> m Prefix
forall (m :: Type -> Type).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Prefix -> m Prefix
forall (c :: Type -> Type).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Prefix
forall (c :: Type -> Type).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Prefix -> c Prefix
forall (t :: Type -> Type) (c :: Type -> Type).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Prefix)
forall (t :: Type -> Type -> Type) (c :: Type -> Type).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Prefix)
$cPrefix :: Constr
$tPrefix :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> Prefix -> m Prefix
$cgmapMo :: forall (m :: Type -> Type).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Prefix -> m Prefix
gmapMp :: (forall d. Data d => d -> m d) -> Prefix -> m Prefix
$cgmapMp :: forall (m :: Type -> Type).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Prefix -> m Prefix
gmapM :: (forall d. Data d => d -> m d) -> Prefix -> m Prefix
$cgmapM :: forall (m :: Type -> Type).
Monad m =>
(forall d. Data d => d -> m d) -> Prefix -> m Prefix
gmapQi :: Int -> (forall d. Data d => d -> u) -> Prefix -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Prefix -> u
gmapQ :: (forall d. Data d => d -> u) -> Prefix -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Prefix -> [u]
gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Prefix -> r
$cgmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Prefix -> r
gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Prefix -> r
$cgmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Prefix -> r
gmapT :: (forall b. Data b => b -> b) -> Prefix -> Prefix
$cgmapT :: (forall b. Data b => b -> b) -> Prefix -> Prefix
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Prefix)
$cdataCast2 :: forall (t :: Type -> Type -> Type) (c :: Type -> Type).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Prefix)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c Prefix)
$cdataCast1 :: forall (t :: Type -> Type) (c :: Type -> Type).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Prefix)
dataTypeOf :: Prefix -> DataType
$cdataTypeOf :: Prefix -> DataType
toConstr :: Prefix -> Constr
$ctoConstr :: Prefix -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Prefix
$cgunfold :: forall (c :: Type -> Type).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Prefix
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Prefix -> c Prefix
$cgfoldl :: forall (c :: Type -> Type).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Prefix -> c Prefix
$cp1Data :: Typeable Prefix
Data, Typeable, (forall x. Prefix -> Rep Prefix x)
-> (forall x. Rep Prefix x -> Prefix) -> Generic Prefix
forall x. Rep Prefix x -> Prefix
forall x. Prefix -> Rep Prefix x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Prefix x -> Prefix
$cfrom :: forall x. Prefix -> Rep Prefix x
Generic)

instance Ord Prefix where
  compare :: Prefix -> Prefix -> Ordering
compare = (Prefix -> Rational) -> Prefix -> Prefix -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing Prefix -> Rational
scaleFactor

instance NFData Prefix where -- instance is derived from Generic instance

instance HasInterchangeName Prefix where
  interchangeName :: Prefix -> InterchangeName
interchangeName = PrefixName -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName (PrefixName -> InterchangeName)
-> (Prefix -> PrefixName) -> Prefix -> InterchangeName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Prefix -> PrefixName
prefixName

-- | The name of the unit of dimensionless values.
nOne :: UnitName 'NonMetric
nOne :: UnitName 'NonMetric
nOne = UnitName 'NonMetric
One

nMeter :: UnitName 'Metric
nMeter :: UnitName 'Metric
nMeter = String -> String -> String -> UnitName 'Metric
ucumMetric String
"m" String
"m" String
"metre"

nGram :: UnitName 'Metric
nGram :: UnitName 'Metric
nGram = String -> String -> String -> UnitName 'Metric
ucumMetric String
"g" String
"g" String
"gram"

nKilogram :: UnitName 'NonMetric
nKilogram :: UnitName 'NonMetric
nKilogram = Prefix -> UnitName 'Metric -> UnitName 'NonMetric
applyPrefix Prefix
kilo UnitName 'Metric
nGram

nSecond :: UnitName 'Metric
nSecond :: UnitName 'Metric
nSecond = String -> String -> String -> UnitName 'Metric
ucumMetric String
"s" String
"s" String
"second"

nAmpere :: UnitName 'Metric
nAmpere :: UnitName 'Metric
nAmpere = String -> String -> String -> UnitName 'Metric
ucumMetric String
"A" String
"A" String
"Ampere"

nKelvin :: UnitName 'Metric
nKelvin :: UnitName 'Metric
nKelvin = String -> String -> String -> UnitName 'Metric
ucumMetric String
"K" String
"K" String
"Kelvin"

nMole :: UnitName 'Metric
nMole :: UnitName 'Metric
nMole = String -> String -> String -> UnitName 'Metric
ucumMetric String
"mol" String
"mol" String
"mole"

nCandela :: UnitName 'Metric
nCandela :: UnitName 'Metric
nCandela = String -> String -> String -> UnitName 'Metric
ucumMetric String
"cd" String
"cd" String
"candela"

-- | The name of the base unit associated with a specified dimension.
baseUnitName :: Dimension' -> UnitName 'NonMetric
baseUnitName :: Dimension' -> UnitName 'NonMetric
baseUnitName Dimension'
d = let powers :: [Int]
powers = Dimension' -> [Int]
asList (Dimension' -> [Int]) -> Dimension' -> [Int]
forall a b. (a -> b) -> a -> b
$ Dimension' -> Dimension'
forall a. HasDimension a => a -> Dimension'
dimension Dimension'
d
                  in UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName m
reduce (UnitName 'NonMetric -> UnitName 'NonMetric)
-> ([UnitName 'NonMetric] -> UnitName 'NonMetric)
-> [UnitName 'NonMetric]
-> UnitName 'NonMetric
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [UnitName 'NonMetric] -> UnitName 'NonMetric
forall (f :: Type -> Type).
Foldable f =>
f (UnitName 'NonMetric) -> UnitName 'NonMetric
product ([UnitName 'NonMetric] -> UnitName 'NonMetric)
-> [UnitName 'NonMetric] -> UnitName 'NonMetric
forall a b. (a -> b) -> a -> b
$ (UnitName 'NonMetric -> Int -> UnitName 'NonMetric)
-> [UnitName 'NonMetric] -> [Int] -> [UnitName 'NonMetric]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith UnitName 'NonMetric -> Int -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> Int -> UnitName 'NonMetric
(^) [UnitName 'NonMetric]
baseUnitNames [Int]
powers

baseUnitNames :: [UnitName 'NonMetric]
baseUnitNames :: [UnitName 'NonMetric]
baseUnitNames = [UnitName 'Metric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName 'NonMetric
weaken UnitName 'Metric
nMeter, UnitName 'NonMetric
nKilogram, UnitName 'Metric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName 'NonMetric
weaken UnitName 'Metric
nSecond, UnitName 'Metric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName 'NonMetric
weaken UnitName 'Metric
nAmpere, UnitName 'Metric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName 'NonMetric
weaken UnitName 'Metric
nKelvin, UnitName 'Metric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName 'NonMetric
weaken UnitName 'Metric
nMole, UnitName 'Metric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName 'NonMetric
weaken UnitName 'Metric
nCandela]

deca, hecto, kilo, mega, giga, tera, peta, exa, zetta, yotta :: Prefix
deca :: Prefix
deca  = String -> String -> String -> Rational -> Prefix
prefix String
"da" String
"da" String
"deca" Rational
1e1
hecto :: Prefix
hecto = String -> String -> String -> Rational -> Prefix
prefix String
"h" String
"h" String
"hecto"  Rational
1e2
kilo :: Prefix
kilo  = String -> String -> String -> Rational -> Prefix
prefix String
"k" String
"k" String
"kilo"   Rational
1e3
mega :: Prefix
mega  = String -> String -> String -> Rational -> Prefix
prefix String
"M" String
"M" String
"mega"   Rational
1e6
giga :: Prefix
giga  = String -> String -> String -> Rational -> Prefix
prefix String
"G" String
"G" String
"giga"   Rational
1e9
tera :: Prefix
tera  = String -> String -> String -> Rational -> Prefix
prefix String
"T" String
"T" String
"tera"   Rational
1e12
peta :: Prefix
peta  = String -> String -> String -> Rational -> Prefix
prefix String
"P" String
"P" String
"peta"   Rational
1e15
exa :: Prefix
exa   = String -> String -> String -> Rational -> Prefix
prefix String
"E" String
"E" String
"exa"    Rational
1e18
zetta :: Prefix
zetta = String -> String -> String -> Rational -> Prefix
prefix String
"Z" String
"Z" String
"zetta"  Rational
1e21
yotta :: Prefix
yotta = String -> String -> String -> Rational -> Prefix
prefix String
"Y" String
"Y" String
"yotta"  Rational
1e24
deci, centi, milli, micro, nano, pico, femto, atto, zepto, yocto :: Prefix
deci :: Prefix
deci  = String -> String -> String -> Rational -> Prefix
prefix String
"d" String
"d" String
"deci"   Rational
1e-1
centi :: Prefix
centi = String -> String -> String -> Rational -> Prefix
prefix String
"c" String
"c" String
"centi"  Rational
1e-2
milli :: Prefix
milli = String -> String -> String -> Rational -> Prefix
prefix String
"m" String
"m" String
"milli"  Rational
1e-3
micro :: Prefix
micro = String -> String -> String -> Rational -> Prefix
prefix String
"u" String
"μ" String
"micro"  Rational
1e-6
nano :: Prefix
nano  = String -> String -> String -> Rational -> Prefix
prefix String
"n" String
"n" String
"nano"   Rational
1e-9
pico :: Prefix
pico  = String -> String -> String -> Rational -> Prefix
prefix String
"p" String
"p" String
"pico"   Rational
1e-12
femto :: Prefix
femto = String -> String -> String -> Rational -> Prefix
prefix String
"f" String
"f" String
"femto"  Rational
1e-15
atto :: Prefix
atto  = String -> String -> String -> Rational -> Prefix
prefix String
"a" String
"a" String
"atto"   Rational
1e-18
zepto :: Prefix
zepto = String -> String -> String -> Rational -> Prefix
prefix String
"z" String
"z" String
"zepto"  Rational
1e-21
yocto :: Prefix
yocto = String -> String -> String -> Rational -> Prefix
prefix String
"y" String
"y" String
"yocto"  Rational
1e-24

-- | A list of all 'Prefix'es defined by the SI.
siPrefixes :: [Prefix]
siPrefixes :: [Prefix]
siPrefixes = [Prefix
yocto, Prefix
zepto, Prefix
atto, Prefix
femto, Prefix
pico, Prefix
nano, Prefix
micro, Prefix
milli, Prefix
centi, Prefix
deci, Prefix
deca, Prefix
hecto, Prefix
kilo, Prefix
mega, Prefix
giga, Prefix
tera, Prefix
peta, Prefix
exa, Prefix
zetta, Prefix
yotta]

-- | Forms a 'UnitName' from a 'Metric' name by applying a metric prefix.
applyPrefix :: Prefix -> UnitName 'Metric -> UnitName 'NonMetric
applyPrefix :: Prefix -> UnitName 'Metric -> UnitName 'NonMetric
applyPrefix = PrefixName -> UnitName 'Metric -> UnitName 'NonMetric
Prefixed (PrefixName -> UnitName 'Metric -> UnitName 'NonMetric)
-> (Prefix -> PrefixName)
-> Prefix
-> UnitName 'Metric
-> UnitName 'NonMetric
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Prefix -> PrefixName
prefixName

{-
We will reuse the operators and function names from the Prelude.
To prevent unpleasant surprises we give operators the same fixity
as the Prelude.
-}

infixr 8  ^
infixl 7  *, /

-- | Form a 'UnitName' by taking the product of two others.
(*) :: UnitName m1 -> UnitName m2 -> UnitName 'NonMetric
UnitName m1
a * :: UnitName m1 -> UnitName m2 -> UnitName 'NonMetric
* UnitName m2
b = UnitName 'NonMetric -> UnitName 'NonMetric -> UnitName 'NonMetric
Product (UnitName m1 -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName 'NonMetric
weaken UnitName m1
a) (UnitName m2 -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName 'NonMetric
weaken UnitName m2
b)

-- | Form a 'UnitName' by dividing one by another.
(/) :: UnitName m1 -> UnitName m2 -> UnitName 'NonMetric
UnitName m1
n1 / :: UnitName m1 -> UnitName m2 -> UnitName 'NonMetric
/ UnitName m2
n2 | UnitName m1 -> Bool
forall (m :: Metricality). UnitName m -> Bool
isAtomicOrProduct UnitName m1
n1 = UnitName 'NonMetric -> UnitName 'NonMetric -> UnitName 'NonMetric
Quotient (UnitName m1 -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName 'NonMetric
weaken UnitName m1
n1) (UnitName m2 -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName 'NonMetric
weaken UnitName m2
n2)
        | Bool
otherwise            = UnitName 'NonMetric -> UnitName 'NonMetric -> UnitName 'NonMetric
Quotient (UnitName m1 -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName 'NonMetric
grouped UnitName m1
n1) (UnitName m2 -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName 'NonMetric
weaken UnitName m2
n2)

-- | Form a 'UnitName' by raising a name to an integer power.
(^) :: UnitName m -> Int -> UnitName 'NonMetric
UnitName m
x ^ :: UnitName m -> Int -> UnitName 'NonMetric
^ Int
n | UnitName m -> Bool
forall (m :: Metricality). UnitName m -> Bool
isAtomic UnitName m
x = UnitName 'NonMetric -> Int -> UnitName 'NonMetric
Power (UnitName m -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName 'NonMetric
weaken UnitName m
x) Int
n
      | Bool
otherwise  = UnitName 'NonMetric -> Int -> UnitName 'NonMetric
Power (UnitName m -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName 'NonMetric
grouped UnitName m
x) Int
n

-- | Convert a 'UnitName' which may or may not be 'Metric' to one
-- which is certainly 'NonMetric'.
weaken :: UnitName m -> UnitName 'NonMetric
weaken :: UnitName m -> UnitName 'NonMetric
weaken n :: UnitName m
n@(MetricAtomic NameAtom ('UnitAtom 'Metric)
_) = UnitName 'Metric -> UnitName 'NonMetric
Weaken UnitName m
UnitName 'Metric
n -- we really only need this one case and a catchall, but the typechecker can't see it
weaken n :: UnitName m
n@UnitName m
One = UnitName m
UnitName 'NonMetric
n
weaken n :: UnitName m
n@(Atomic NameAtom ('UnitAtom 'NonMetric)
_) = UnitName m
UnitName 'NonMetric
n
weaken n :: UnitName m
n@(Prefixed PrefixName
_ UnitName 'Metric
_) = UnitName m
UnitName 'NonMetric
n
weaken n :: UnitName m
n@(Product UnitName 'NonMetric
_ UnitName 'NonMetric
_) = UnitName m
UnitName 'NonMetric
n
weaken n :: UnitName m
n@(Quotient UnitName 'NonMetric
_ UnitName 'NonMetric
_) = UnitName m
UnitName 'NonMetric
n
weaken n :: UnitName m
n@(Power UnitName 'NonMetric
_ Int
_) = UnitName m
UnitName 'NonMetric
n
weaken n :: UnitName m
n@(Grouped UnitName 'NonMetric
_) = UnitName m
UnitName 'NonMetric
n
weaken n :: UnitName m
n@(Weaken UnitName 'Metric
_) = UnitName m
UnitName 'NonMetric
n

-- | Attempt to convert a 'UnitName' which may or may not be 'Metric' to one
-- which is certainly 'Metric'.
strengthen :: UnitName m -> Maybe (UnitName 'Metric)
strengthen :: UnitName m -> Maybe (UnitName 'Metric)
strengthen n :: UnitName m
n@(MetricAtomic NameAtom ('UnitAtom 'Metric)
_) = UnitName m -> Maybe (UnitName m)
forall a. a -> Maybe a
Just UnitName m
n
strengthen (Weaken UnitName 'Metric
n) = UnitName 'Metric -> Maybe (UnitName 'Metric)
forall (m :: Metricality). UnitName m -> Maybe (UnitName 'Metric)
strengthen UnitName 'Metric
n
strengthen UnitName m
_ = Maybe (UnitName 'Metric)
forall a. Maybe a
Nothing

-- | Convert a 'UnitName' of one 'Metricality' into a name of another metricality by
-- strengthening or weakening if neccessary. Because it may not be possible to strengthen,
-- the result is returned in a 'Maybe' wrapper.
relax :: forall m1 m2.(Typeable m1, Typeable m2) => UnitName m1 -> Maybe (UnitName m2)
relax :: UnitName m1 -> Maybe (UnitName m2)
relax = TypeRep -> TypeRep -> UnitName m1 -> Maybe (UnitName m2)
go (Proxy m1 -> TypeRep
forall k (proxy :: k -> Type) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (Proxy m1
forall k (t :: k). Proxy t
Proxy :: Proxy m1)) (Proxy m2 -> TypeRep
forall k (proxy :: k -> Type) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (Proxy m2
forall k (t :: k). Proxy t
Proxy :: Proxy m2))
  where
    metric :: TypeRep
metric = Proxy 'Metric -> TypeRep
forall k (proxy :: k -> Type) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (Proxy 'Metric
forall k (t :: k). Proxy t
Proxy :: Proxy 'Metric)
    nonMetric :: TypeRep
nonMetric = Proxy 'NonMetric -> TypeRep
forall k (proxy :: k -> Type) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (Proxy 'NonMetric
forall k (t :: k). Proxy t
Proxy :: Proxy 'NonMetric)
    go :: TypeRep -> TypeRep -> UnitName m1 -> Maybe (UnitName m2)
    go :: TypeRep -> TypeRep -> UnitName m1 -> Maybe (UnitName m2)
go TypeRep
p1 TypeRep
p2 | TypeRep
p1 TypeRep -> TypeRep -> Bool
forall a. Eq a => a -> a -> Bool
== TypeRep
p2 = UnitName m1 -> Maybe (UnitName m2)
forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast
             | (TypeRep
p1 TypeRep -> TypeRep -> Bool
forall a. Eq a => a -> a -> Bool
== TypeRep
nonMetric) Bool -> Bool -> Bool
&& (TypeRep
p2 TypeRep -> TypeRep -> Bool
forall a. Eq a => a -> a -> Bool
== TypeRep
metric) = Maybe (Maybe (UnitName m2)) -> Maybe (UnitName m2)
forall (m :: Type -> Type) a. Monad m => m (m a) -> m a
join (Maybe (Maybe (UnitName m2)) -> Maybe (UnitName m2))
-> (UnitName m1 -> Maybe (Maybe (UnitName m2)))
-> UnitName m1
-> Maybe (UnitName m2)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UnitName 'Metric -> Maybe (UnitName m2))
-> Maybe (UnitName 'Metric) -> Maybe (Maybe (UnitName m2))
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap UnitName 'Metric -> Maybe (UnitName m2)
forall k (a :: k) (b :: k) (c :: k -> Type).
(Typeable a, Typeable b) =>
c a -> Maybe (c b)
gcast (Maybe (UnitName 'Metric) -> Maybe (Maybe (UnitName m2)))
-> (UnitName m1 -> Maybe (UnitName 'Metric))
-> UnitName m1
-> Maybe (Maybe (UnitName m2))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnitName m1 -> Maybe (UnitName 'Metric)
forall (m :: Metricality). UnitName m -> Maybe (UnitName 'Metric)
strengthen
             | (TypeRep
p1 TypeRep -> TypeRep -> Bool
forall a. Eq a => a -> a -> Bool
== TypeRep
metric) Bool -> Bool -> Bool
&& (TypeRep
p2 TypeRep -> TypeRep -> Bool
forall a. Eq a => a -> a -> Bool
== TypeRep
nonMetric) = UnitName 'NonMetric -> Maybe (UnitName m2)
forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast (UnitName 'NonMetric -> Maybe (UnitName m2))
-> (UnitName m1 -> UnitName 'NonMetric)
-> UnitName m1
-> Maybe (UnitName m2)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnitName m1 -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName 'NonMetric
weaken
             | Bool
otherwise = String -> UnitName m1 -> Maybe (UnitName m2)
forall a. HasCallStack => String -> a
error String
"Should be unreachable. TypeRep of an unexpected Metricality encountered."

-- | Constructs a 'UnitName' by applying a grouping operation to
-- another 'UnitName', which may be useful to express precedence.
grouped :: UnitName m -> UnitName 'NonMetric
grouped :: UnitName m -> UnitName 'NonMetric
grouped = UnitName 'NonMetric -> UnitName 'NonMetric
Grouped (UnitName 'NonMetric -> UnitName 'NonMetric)
-> (UnitName m -> UnitName 'NonMetric)
-> UnitName m
-> UnitName 'NonMetric
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnitName m -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName 'NonMetric
weaken

-- | Represents the name of an atomic unit or prefix.
data NameAtom (m :: NameAtomType)
  = NameAtom
  {
    NameAtom m -> InterchangeName
_interchangeName :: InterchangeName, -- ^ The interchange name of the unit.
    NameAtom m -> String
abbreviation_en :: String, -- ^ The abbreviated name of the unit in international English.
    NameAtom m -> String
name_en :: String -- ^ The full name of the unit in international English.
  }
  deriving (NameAtom m -> NameAtom m -> Bool
(NameAtom m -> NameAtom m -> Bool)
-> (NameAtom m -> NameAtom m -> Bool) -> Eq (NameAtom m)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (m :: NameAtomType). NameAtom m -> NameAtom m -> Bool
/= :: NameAtom m -> NameAtom m -> Bool
$c/= :: forall (m :: NameAtomType). NameAtom m -> NameAtom m -> Bool
== :: NameAtom m -> NameAtom m -> Bool
$c== :: forall (m :: NameAtomType). NameAtom m -> NameAtom m -> Bool
Eq, Eq (NameAtom m)
Eq (NameAtom m)
-> (NameAtom m -> NameAtom m -> Ordering)
-> (NameAtom m -> NameAtom m -> Bool)
-> (NameAtom m -> NameAtom m -> Bool)
-> (NameAtom m -> NameAtom m -> Bool)
-> (NameAtom m -> NameAtom m -> Bool)
-> (NameAtom m -> NameAtom m -> NameAtom m)
-> (NameAtom m -> NameAtom m -> NameAtom m)
-> Ord (NameAtom m)
NameAtom m -> NameAtom m -> Bool
NameAtom m -> NameAtom m -> Ordering
NameAtom m -> NameAtom m -> NameAtom m
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall (m :: NameAtomType). Eq (NameAtom m)
forall (m :: NameAtomType). NameAtom m -> NameAtom m -> Bool
forall (m :: NameAtomType). NameAtom m -> NameAtom m -> Ordering
forall (m :: NameAtomType). NameAtom m -> NameAtom m -> NameAtom m
min :: NameAtom m -> NameAtom m -> NameAtom m
$cmin :: forall (m :: NameAtomType). NameAtom m -> NameAtom m -> NameAtom m
max :: NameAtom m -> NameAtom m -> NameAtom m
$cmax :: forall (m :: NameAtomType). NameAtom m -> NameAtom m -> NameAtom m
>= :: NameAtom m -> NameAtom m -> Bool
$c>= :: forall (m :: NameAtomType). NameAtom m -> NameAtom m -> Bool
> :: NameAtom m -> NameAtom m -> Bool
$c> :: forall (m :: NameAtomType). NameAtom m -> NameAtom m -> Bool
<= :: NameAtom m -> NameAtom m -> Bool
$c<= :: forall (m :: NameAtomType). NameAtom m -> NameAtom m -> Bool
< :: NameAtom m -> NameAtom m -> Bool
$c< :: forall (m :: NameAtomType). NameAtom m -> NameAtom m -> Bool
compare :: NameAtom m -> NameAtom m -> Ordering
$ccompare :: forall (m :: NameAtomType). NameAtom m -> NameAtom m -> Ordering
$cp1Ord :: forall (m :: NameAtomType). Eq (NameAtom m)
Ord, Typeable (NameAtom m)
DataType
Constr
Typeable (NameAtom m)
-> (forall (c :: Type -> Type).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> NameAtom m -> c (NameAtom m))
-> (forall (c :: Type -> Type).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (NameAtom m))
-> (NameAtom m -> Constr)
-> (NameAtom m -> DataType)
-> (forall (t :: Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c (NameAtom m)))
-> (forall (t :: Type -> Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c (NameAtom m)))
-> ((forall b. Data b => b -> b) -> NameAtom m -> NameAtom m)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> NameAtom m -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> NameAtom m -> r)
-> (forall u. (forall d. Data d => d -> u) -> NameAtom m -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> NameAtom m -> u)
-> (forall (m :: Type -> Type).
    Monad m =>
    (forall d. Data d => d -> m d) -> NameAtom m -> m (NameAtom m))
-> (forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> NameAtom m -> m (NameAtom m))
-> (forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> NameAtom m -> m (NameAtom m))
-> Data (NameAtom m)
NameAtom m -> DataType
NameAtom m -> Constr
(forall b. Data b => b -> b) -> NameAtom m -> NameAtom m
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> NameAtom m -> c (NameAtom m)
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (NameAtom m)
forall a.
Typeable a
-> (forall (c :: Type -> Type).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: Type -> Type).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: Type -> Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: Type -> Type).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> NameAtom m -> u
forall u. (forall d. Data d => d -> u) -> NameAtom m -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> NameAtom m -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> NameAtom m -> r
forall (m :: NameAtomType). Typeable m => Typeable (NameAtom m)
forall (m :: NameAtomType). Typeable m => NameAtom m -> DataType
forall (m :: NameAtomType). Typeable m => NameAtom m -> Constr
forall (m :: NameAtomType).
Typeable m =>
(forall b. Data b => b -> b) -> NameAtom m -> NameAtom m
forall (m :: NameAtomType) u.
Typeable m =>
Int -> (forall d. Data d => d -> u) -> NameAtom m -> u
forall (m :: NameAtomType) u.
Typeable m =>
(forall d. Data d => d -> u) -> NameAtom m -> [u]
forall (m :: NameAtomType) r r'.
Typeable m =>
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> NameAtom m -> r
forall (m :: NameAtomType) r r'.
Typeable m =>
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> NameAtom m -> r
forall (m :: NameAtomType) (m :: Type -> Type).
(Typeable m, Monad m) =>
(forall d. Data d => d -> m d) -> NameAtom m -> m (NameAtom m)
forall (m :: NameAtomType) (m :: Type -> Type).
(Typeable m, MonadPlus m) =>
(forall d. Data d => d -> m d) -> NameAtom m -> m (NameAtom m)
forall (m :: NameAtomType) (c :: Type -> Type).
Typeable m =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (NameAtom m)
forall (m :: NameAtomType) (c :: Type -> Type).
Typeable m =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> NameAtom m -> c (NameAtom m)
forall (m :: NameAtomType) (t :: Type -> Type) (c :: Type -> Type).
(Typeable m, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (NameAtom m))
forall (m :: NameAtomType) (t :: Type -> Type -> Type)
       (c :: Type -> Type).
(Typeable m, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c (NameAtom m))
forall (m :: Type -> Type).
Monad m =>
(forall d. Data d => d -> m d) -> NameAtom m -> m (NameAtom m)
forall (m :: Type -> Type).
MonadPlus m =>
(forall d. Data d => d -> m d) -> NameAtom m -> m (NameAtom m)
forall (c :: Type -> Type).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (NameAtom m)
forall (c :: Type -> Type).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> NameAtom m -> c (NameAtom m)
forall (t :: Type -> Type) (c :: Type -> Type).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c (NameAtom m))
forall (t :: Type -> Type -> Type) (c :: Type -> Type).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c (NameAtom m))
$cNameAtom :: Constr
$tNameAtom :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> NameAtom m -> m (NameAtom m)
$cgmapMo :: forall (m :: NameAtomType) (m :: Type -> Type).
(Typeable m, MonadPlus m) =>
(forall d. Data d => d -> m d) -> NameAtom m -> m (NameAtom m)
gmapMp :: (forall d. Data d => d -> m d) -> NameAtom m -> m (NameAtom m)
$cgmapMp :: forall (m :: NameAtomType) (m :: Type -> Type).
(Typeable m, MonadPlus m) =>
(forall d. Data d => d -> m d) -> NameAtom m -> m (NameAtom m)
gmapM :: (forall d. Data d => d -> m d) -> NameAtom m -> m (NameAtom m)
$cgmapM :: forall (m :: NameAtomType) (m :: Type -> Type).
(Typeable m, Monad m) =>
(forall d. Data d => d -> m d) -> NameAtom m -> m (NameAtom m)
gmapQi :: Int -> (forall d. Data d => d -> u) -> NameAtom m -> u
$cgmapQi :: forall (m :: NameAtomType) u.
Typeable m =>
Int -> (forall d. Data d => d -> u) -> NameAtom m -> u
gmapQ :: (forall d. Data d => d -> u) -> NameAtom m -> [u]
$cgmapQ :: forall (m :: NameAtomType) u.
Typeable m =>
(forall d. Data d => d -> u) -> NameAtom m -> [u]
gmapQr :: (r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> NameAtom m -> r
$cgmapQr :: forall (m :: NameAtomType) r r'.
Typeable m =>
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> NameAtom m -> r
gmapQl :: (r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> NameAtom m -> r
$cgmapQl :: forall (m :: NameAtomType) r r'.
Typeable m =>
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> NameAtom m -> r
gmapT :: (forall b. Data b => b -> b) -> NameAtom m -> NameAtom m
$cgmapT :: forall (m :: NameAtomType).
Typeable m =>
(forall b. Data b => b -> b) -> NameAtom m -> NameAtom m
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c (NameAtom m))
$cdataCast2 :: forall (m :: NameAtomType) (t :: Type -> Type -> Type)
       (c :: Type -> Type).
(Typeable m, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c (NameAtom m))
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c (NameAtom m))
$cdataCast1 :: forall (m :: NameAtomType) (t :: Type -> Type) (c :: Type -> Type).
(Typeable m, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (NameAtom m))
dataTypeOf :: NameAtom m -> DataType
$cdataTypeOf :: forall (m :: NameAtomType). Typeable m => NameAtom m -> DataType
toConstr :: NameAtom m -> Constr
$ctoConstr :: forall (m :: NameAtomType). Typeable m => NameAtom m -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (NameAtom m)
$cgunfold :: forall (m :: NameAtomType) (c :: Type -> Type).
Typeable m =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (NameAtom m)
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> NameAtom m -> c (NameAtom m)
$cgfoldl :: forall (m :: NameAtomType) (c :: Type -> Type).
Typeable m =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> NameAtom m -> c (NameAtom m)
$cp1Data :: forall (m :: NameAtomType). Typeable m => Typeable (NameAtom m)
Data, Typeable, (forall x. NameAtom m -> Rep (NameAtom m) x)
-> (forall x. Rep (NameAtom m) x -> NameAtom m)
-> Generic (NameAtom m)
forall x. Rep (NameAtom m) x -> NameAtom m
forall x. NameAtom m -> Rep (NameAtom m) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (m :: NameAtomType) x. Rep (NameAtom m) x -> NameAtom m
forall (m :: NameAtomType) x. NameAtom m -> Rep (NameAtom m) x
$cto :: forall (m :: NameAtomType) x. Rep (NameAtom m) x -> NameAtom m
$cfrom :: forall (m :: NameAtomType) x. NameAtom m -> Rep (NameAtom m) x
Generic)

instance NFData (NameAtom m) where -- instance is derived from Generic instance

instance HasInterchangeName (NameAtom m) where
  interchangeName :: NameAtom m -> InterchangeName
interchangeName = NameAtom m -> InterchangeName
forall (m :: NameAtomType). NameAtom m -> InterchangeName
_interchangeName

instance HasInterchangeName (UnitName m) where
  interchangeName :: UnitName m -> InterchangeName
interchangeName UnitName m
One = InterchangeName :: String -> InterchangeNameAuthority -> Bool -> InterchangeName
InterchangeName { name :: String
name = String
"1", authority :: InterchangeNameAuthority
authority = InterchangeNameAuthority
UCUM, isAtomic :: Bool
I.isAtomic = Bool
True }
  interchangeName (MetricAtomic NameAtom ('UnitAtom 'Metric)
a) = NameAtom ('UnitAtom 'Metric) -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName NameAtom ('UnitAtom 'Metric)
a
  interchangeName (Atomic NameAtom ('UnitAtom 'NonMetric)
a) = NameAtom ('UnitAtom 'NonMetric) -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName NameAtom ('UnitAtom 'NonMetric)
a
  interchangeName (Prefixed PrefixName
p UnitName 'Metric
n) = let n' :: String
n' = (InterchangeName -> String
name (InterchangeName -> String)
-> (PrefixName -> InterchangeName) -> PrefixName -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrefixName -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName (PrefixName -> String) -> PrefixName -> String
forall a b. (a -> b) -> a -> b
$ PrefixName
p) String -> ShowS
forall a. [a] -> [a] -> [a]
++ (InterchangeName -> String
name (InterchangeName -> String)
-> (UnitName 'Metric -> InterchangeName)
-> UnitName 'Metric
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnitName 'Metric -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName (UnitName 'Metric -> String) -> UnitName 'Metric -> String
forall a b. (a -> b) -> a -> b
$ UnitName 'Metric
n)
                                       a' :: InterchangeNameAuthority
a' = InterchangeNameAuthority
-> InterchangeNameAuthority -> InterchangeNameAuthority
forall a. Ord a => a -> a -> a
max (InterchangeName -> InterchangeNameAuthority
authority (InterchangeName -> InterchangeNameAuthority)
-> (PrefixName -> InterchangeName)
-> PrefixName
-> InterchangeNameAuthority
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrefixName -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName (PrefixName -> InterchangeNameAuthority)
-> PrefixName -> InterchangeNameAuthority
forall a b. (a -> b) -> a -> b
$ PrefixName
p) (InterchangeName -> InterchangeNameAuthority
authority (InterchangeName -> InterchangeNameAuthority)
-> (UnitName 'Metric -> InterchangeName)
-> UnitName 'Metric
-> InterchangeNameAuthority
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnitName 'Metric -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName (UnitName 'Metric -> InterchangeNameAuthority)
-> UnitName 'Metric -> InterchangeNameAuthority
forall a b. (a -> b) -> a -> b
$ UnitName 'Metric
n)
                                    in InterchangeName :: String -> InterchangeNameAuthority -> Bool -> InterchangeName
InterchangeName { name :: String
name = String
n', authority :: InterchangeNameAuthority
authority = InterchangeNameAuthority
a', isAtomic :: Bool
I.isAtomic = Bool
False }
  interchangeName (Product UnitName 'NonMetric
n1 UnitName 'NonMetric
n2) = let n' :: String
n' = (InterchangeName -> String
name (InterchangeName -> String)
-> (UnitName 'NonMetric -> InterchangeName)
-> UnitName 'NonMetric
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnitName 'NonMetric -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName (UnitName 'NonMetric -> String) -> UnitName 'NonMetric -> String
forall a b. (a -> b) -> a -> b
$ UnitName 'NonMetric
n1) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"." String -> ShowS
forall a. [a] -> [a] -> [a]
++ (InterchangeName -> String
name (InterchangeName -> String)
-> (UnitName 'NonMetric -> InterchangeName)
-> UnitName 'NonMetric
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnitName 'NonMetric -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName (UnitName 'NonMetric -> String) -> UnitName 'NonMetric -> String
forall a b. (a -> b) -> a -> b
$ UnitName 'NonMetric
n2)
                                        a' :: InterchangeNameAuthority
a' = InterchangeNameAuthority
-> InterchangeNameAuthority -> InterchangeNameAuthority
forall a. Ord a => a -> a -> a
max (InterchangeName -> InterchangeNameAuthority
authority (InterchangeName -> InterchangeNameAuthority)
-> (UnitName 'NonMetric -> InterchangeName)
-> UnitName 'NonMetric
-> InterchangeNameAuthority
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnitName 'NonMetric -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName (UnitName 'NonMetric -> InterchangeNameAuthority)
-> UnitName 'NonMetric -> InterchangeNameAuthority
forall a b. (a -> b) -> a -> b
$ UnitName 'NonMetric
n1) (InterchangeName -> InterchangeNameAuthority
authority (InterchangeName -> InterchangeNameAuthority)
-> (UnitName 'NonMetric -> InterchangeName)
-> UnitName 'NonMetric
-> InterchangeNameAuthority
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnitName 'NonMetric -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName (UnitName 'NonMetric -> InterchangeNameAuthority)
-> UnitName 'NonMetric -> InterchangeNameAuthority
forall a b. (a -> b) -> a -> b
$ UnitName 'NonMetric
n2)
                                     in InterchangeName :: String -> InterchangeNameAuthority -> Bool -> InterchangeName
InterchangeName { name :: String
name = String
n', authority :: InterchangeNameAuthority
authority = InterchangeNameAuthority
a', isAtomic :: Bool
I.isAtomic = Bool
False }
  interchangeName (Quotient UnitName 'NonMetric
n1 UnitName 'NonMetric
n2) = let n' :: String
n' = (InterchangeName -> String
name (InterchangeName -> String)
-> (UnitName 'NonMetric -> InterchangeName)
-> UnitName 'NonMetric
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnitName 'NonMetric -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName (UnitName 'NonMetric -> String) -> UnitName 'NonMetric -> String
forall a b. (a -> b) -> a -> b
$ UnitName 'NonMetric
n1) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"/" String -> ShowS
forall a. [a] -> [a] -> [a]
++ (InterchangeName -> String
name (InterchangeName -> String)
-> (UnitName 'NonMetric -> InterchangeName)
-> UnitName 'NonMetric
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnitName 'NonMetric -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName (UnitName 'NonMetric -> String) -> UnitName 'NonMetric -> String
forall a b. (a -> b) -> a -> b
$ UnitName 'NonMetric
n2)
                                         a' :: InterchangeNameAuthority
a' = InterchangeNameAuthority
-> InterchangeNameAuthority -> InterchangeNameAuthority
forall a. Ord a => a -> a -> a
max (InterchangeName -> InterchangeNameAuthority
authority (InterchangeName -> InterchangeNameAuthority)
-> (UnitName 'NonMetric -> InterchangeName)
-> UnitName 'NonMetric
-> InterchangeNameAuthority
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnitName 'NonMetric -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName (UnitName 'NonMetric -> InterchangeNameAuthority)
-> UnitName 'NonMetric -> InterchangeNameAuthority
forall a b. (a -> b) -> a -> b
$ UnitName 'NonMetric
n1) (InterchangeName -> InterchangeNameAuthority
authority (InterchangeName -> InterchangeNameAuthority)
-> (UnitName 'NonMetric -> InterchangeName)
-> UnitName 'NonMetric
-> InterchangeNameAuthority
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnitName 'NonMetric -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName (UnitName 'NonMetric -> InterchangeNameAuthority)
-> UnitName 'NonMetric -> InterchangeNameAuthority
forall a b. (a -> b) -> a -> b
$ UnitName 'NonMetric
n2)
                                      in InterchangeName :: String -> InterchangeNameAuthority -> Bool -> InterchangeName
InterchangeName { name :: String
name = String
n', authority :: InterchangeNameAuthority
authority = InterchangeNameAuthority
a', isAtomic :: Bool
I.isAtomic = Bool
False }
  -- TODO #109: note in this case that the UCUM is changing their grammar to not accept exponents after
  -- as a result it will become necessary to distribute the exponentiation over the items in the base name
  -- prior to generating the interchange name
  interchangeName (Power UnitName 'NonMetric
n Int
x) = let n' :: String
n' = (InterchangeName -> String
name (InterchangeName -> String)
-> (UnitName 'NonMetric -> InterchangeName)
-> UnitName 'NonMetric
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnitName 'NonMetric -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName (UnitName 'NonMetric -> String) -> UnitName 'NonMetric -> String
forall a b. (a -> b) -> a -> b
$ UnitName 'NonMetric
n) String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
x
                                 in InterchangeName :: String -> InterchangeNameAuthority -> Bool -> InterchangeName
InterchangeName { name :: String
name = String
n', authority :: InterchangeNameAuthority
authority = InterchangeName -> InterchangeNameAuthority
authority (InterchangeName -> InterchangeNameAuthority)
-> (UnitName 'NonMetric -> InterchangeName)
-> UnitName 'NonMetric
-> InterchangeNameAuthority
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnitName 'NonMetric -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName (UnitName 'NonMetric -> InterchangeNameAuthority)
-> UnitName 'NonMetric -> InterchangeNameAuthority
forall a b. (a -> b) -> a -> b
$ UnitName 'NonMetric
n, isAtomic :: Bool
I.isAtomic = Bool
False }
  interchangeName (Grouped UnitName 'NonMetric
n) = let n' :: String
n' = String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ (InterchangeName -> String
name (InterchangeName -> String)
-> (UnitName 'NonMetric -> InterchangeName)
-> UnitName 'NonMetric
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnitName 'NonMetric -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName (UnitName 'NonMetric -> String) -> UnitName 'NonMetric -> String
forall a b. (a -> b) -> a -> b
$ UnitName 'NonMetric
n) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
                                 in InterchangeName :: String -> InterchangeNameAuthority -> Bool -> InterchangeName
InterchangeName { name :: String
name = String
n', authority :: InterchangeNameAuthority
authority = InterchangeName -> InterchangeNameAuthority
authority (InterchangeName -> InterchangeNameAuthority)
-> (UnitName 'NonMetric -> InterchangeName)
-> UnitName 'NonMetric
-> InterchangeNameAuthority
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnitName 'NonMetric -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName (UnitName 'NonMetric -> InterchangeNameAuthority)
-> UnitName 'NonMetric -> InterchangeNameAuthority
forall a b. (a -> b) -> a -> b
$ UnitName 'NonMetric
n, isAtomic :: Bool
I.isAtomic = Bool
False }
  interchangeName (Weaken UnitName 'Metric
n) = UnitName 'Metric -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName UnitName 'Metric
n

prefix :: String -> String -> String -> Rational -> Prefix
prefix :: String -> String -> String -> Rational -> Prefix
prefix String
i String
a String
f = PrefixName -> Rational -> Prefix
Prefix PrefixName
n
  where
    n :: PrefixName
n = InterchangeName -> String -> String -> PrefixName
forall (m :: NameAtomType).
InterchangeName -> String -> String -> NameAtom m
NameAtom (String -> InterchangeNameAuthority -> Bool -> InterchangeName
InterchangeName String
i InterchangeNameAuthority
UCUM Bool
True) String
a String
f

ucumMetric :: String -> String -> String -> UnitName 'Metric
ucumMetric :: String -> String -> String -> UnitName 'Metric
ucumMetric String
i String
a String
f = NameAtom ('UnitAtom 'Metric) -> UnitName 'Metric
MetricAtomic (NameAtom ('UnitAtom 'Metric) -> UnitName 'Metric)
-> NameAtom ('UnitAtom 'Metric) -> UnitName 'Metric
forall a b. (a -> b) -> a -> b
$ InterchangeName -> String -> String -> NameAtom ('UnitAtom 'Metric)
forall (m :: NameAtomType).
InterchangeName -> String -> String -> NameAtom m
NameAtom (String -> InterchangeNameAuthority -> Bool -> InterchangeName
InterchangeName String
i InterchangeNameAuthority
UCUM Bool
True) String
a String
f

ucum :: String -> String -> String -> UnitName 'NonMetric
ucum :: String -> String -> String -> UnitName 'NonMetric
ucum String
i String
a String
f = NameAtom ('UnitAtom 'NonMetric) -> UnitName 'NonMetric
Atomic (NameAtom ('UnitAtom 'NonMetric) -> UnitName 'NonMetric)
-> NameAtom ('UnitAtom 'NonMetric) -> UnitName 'NonMetric
forall a b. (a -> b) -> a -> b
$ InterchangeName
-> String -> String -> NameAtom ('UnitAtom 'NonMetric)
forall (m :: NameAtomType).
InterchangeName -> String -> String -> NameAtom m
NameAtom (String -> InterchangeNameAuthority -> Bool -> InterchangeName
InterchangeName String
i InterchangeNameAuthority
UCUM Bool
True) String
a String
f

dimensionalAtom :: String -> String -> String -> UnitName 'NonMetric
dimensionalAtom :: String -> String -> String -> UnitName 'NonMetric
dimensionalAtom String
i String
a String
f = NameAtom ('UnitAtom 'NonMetric) -> UnitName 'NonMetric
Atomic (NameAtom ('UnitAtom 'NonMetric) -> UnitName 'NonMetric)
-> NameAtom ('UnitAtom 'NonMetric) -> UnitName 'NonMetric
forall a b. (a -> b) -> a -> b
$ InterchangeName
-> String -> String -> NameAtom ('UnitAtom 'NonMetric)
forall (m :: NameAtomType).
InterchangeName -> String -> String -> NameAtom m
NameAtom (String -> InterchangeNameAuthority -> Bool -> InterchangeName
InterchangeName String
i InterchangeNameAuthority
DimensionalLibrary Bool
True) String
a String
f

-- | Constructs an atomic name for a custom unit.
atom :: String -- ^ Interchange name
     -> String -- ^ Abbreviated name in international English
     -> String -- ^ Full name in international English
     -> UnitName 'NonMetric
atom :: String -> String -> String -> UnitName 'NonMetric
atom String
i String
a String
f = NameAtom ('UnitAtom 'NonMetric) -> UnitName 'NonMetric
Atomic (NameAtom ('UnitAtom 'NonMetric) -> UnitName 'NonMetric)
-> NameAtom ('UnitAtom 'NonMetric) -> UnitName 'NonMetric
forall a b. (a -> b) -> a -> b
$ InterchangeName
-> String -> String -> NameAtom ('UnitAtom 'NonMetric)
forall (m :: NameAtomType).
InterchangeName -> String -> String -> NameAtom m
NameAtom (String -> InterchangeNameAuthority -> Bool -> InterchangeName
InterchangeName String
i InterchangeNameAuthority
Custom Bool
True) String
a String
f

-- | The type of a unit name transformation that may be associated with an operation that takes a single unit as input.
type UnitNameTransformer = (forall m.UnitName m -> UnitName 'NonMetric)

-- | The type of a unit name transformation that may be associated with an operation that takes two units as input.
type UnitNameTransformer2 = (forall m1 m2.UnitName m1 -> UnitName m2 -> UnitName 'NonMetric)

-- | Forms the product of a list of 'UnitName's.
--
-- If you wish to form a heterogenous product of 'Metric' and 'NonMetric' units
-- you should apply 'weaken' to the 'Metric' ones.
product :: Foldable f => f (UnitName 'NonMetric) -> UnitName 'NonMetric
product :: f (UnitName 'NonMetric) -> UnitName 'NonMetric
product = [UnitName 'NonMetric] -> UnitName 'NonMetric
go ([UnitName 'NonMetric] -> UnitName 'NonMetric)
-> (f (UnitName 'NonMetric) -> [UnitName 'NonMetric])
-> f (UnitName 'NonMetric)
-> UnitName 'NonMetric
forall b c a. (b -> c) -> (a -> b) -> a -> c
. f (UnitName 'NonMetric) -> [UnitName 'NonMetric]
forall (t :: Type -> Type) a. Foldable t => t a -> [a]
toList
  where
    -- This is not defined using a simple fold so that it does not complicate the product with
    -- valid but meaningless occurences of nOne.
    go :: [UnitName 'NonMetric] -> UnitName 'NonMetric
    go :: [UnitName 'NonMetric] -> UnitName 'NonMetric
go [] = UnitName 'NonMetric
nOne
    go [UnitName 'NonMetric
n] = UnitName 'NonMetric
n
    go (UnitName 'NonMetric
n : [UnitName 'NonMetric]
ns) = UnitName 'NonMetric
n UnitName 'NonMetric -> UnitName 'NonMetric -> UnitName 'NonMetric
forall (m1 :: Metricality) (m2 :: Metricality).
UnitName m1 -> UnitName m2 -> UnitName 'NonMetric
* [UnitName 'NonMetric] -> UnitName 'NonMetric
go [UnitName 'NonMetric]
ns