{-# OPTIONS_HADDOCK not-home #-}

{-# LANGUAGE AutoDeriveTypeable #-}
{-# 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 n :: UnitName m
n = case UnitName m
n of
    One -> ()
    MetricAtomic a :: NameAtom ('UnitAtom 'Metric)
a -> NameAtom ('UnitAtom 'Metric) -> ()
forall a. NFData a => a -> ()
rnf NameAtom ('UnitAtom 'Metric)
a
    Atomic a :: NameAtom ('UnitAtom 'NonMetric)
a -> NameAtom ('UnitAtom 'NonMetric) -> ()
forall a. NFData a => a -> ()
rnf NameAtom ('UnitAtom 'NonMetric)
a
    Prefixed p :: PrefixName
p n' :: UnitName 'Metric
n' -> PrefixName -> ()
forall a. NFData a => a -> ()
rnf PrefixName
p () -> () -> ()
forall a b. a -> b -> b
`seq` UnitName 'Metric -> ()
forall a. NFData a => a -> ()
rnf UnitName 'Metric
n'
    Product n1 :: UnitName 'NonMetric
n1 n2 :: UnitName 'NonMetric
n2 -> UnitName 'NonMetric -> ()
forall a. NFData a => a -> ()
rnf UnitName 'NonMetric
n1 () -> () -> ()
forall a b. a -> b -> b
`seq` UnitName 'NonMetric -> ()
forall a. NFData a => a -> ()
rnf UnitName 'NonMetric
n2
    Quotient n1 :: UnitName 'NonMetric
n1 n2 :: UnitName 'NonMetric
n2 -> UnitName 'NonMetric -> ()
forall a. NFData a => a -> ()
rnf UnitName 'NonMetric
n1 () -> () -> ()
forall a b. a -> b -> b
`seq` UnitName 'NonMetric -> ()
forall a. NFData a => a -> ()
rnf UnitName 'NonMetric
n2
    Power n' :: UnitName 'NonMetric
n' e :: Int
e -> UnitName 'NonMetric -> ()
forall a. NFData a => a -> ()
rnf UnitName 'NonMetric
n' () -> () -> ()
forall a b. a -> b -> b
`seq` Int -> ()
forall a. NFData a => a -> ()
rnf Int
e
    Grouped n' :: UnitName 'NonMetric
n' -> UnitName 'NonMetric -> ()
forall a. NFData a => a -> ()
rnf UnitName 'NonMetric
n'
    Weaken n' :: 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 One = "1"
  show (MetricAtomic a :: NameAtom ('UnitAtom 'Metric)
a) = NameAtom ('UnitAtom 'Metric) -> String
forall (m :: NameAtomType). NameAtom m -> String
abbreviation_en NameAtom ('UnitAtom 'Metric)
a
  show (Atomic a :: NameAtom ('UnitAtom 'NonMetric)
a) = NameAtom ('UnitAtom 'NonMetric) -> String
forall (m :: NameAtomType). NameAtom m -> String
abbreviation_en NameAtom ('UnitAtom 'NonMetric)
a
  show (Prefixed a :: PrefixName
a n :: 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 n1 :: UnitName 'NonMetric
n1 n2 :: UnitName 'NonMetric
n2) = UnitName 'NonMetric -> String
forall a. Show a => a -> String
show UnitName 'NonMetric
n1 String -> ShowS
forall a. [a] -> [a] -> [a]
++ "\xA0" String -> ShowS
forall a. [a] -> [a] -> [a]
++ UnitName 'NonMetric -> String
forall a. Show a => a -> String
show UnitName 'NonMetric
n2
  show (Quotient n1 :: UnitName 'NonMetric
n1 n2 :: UnitName 'NonMetric
n2) = UnitName 'NonMetric -> String
forall a. Show a => a -> String
show UnitName 'NonMetric
n1 String -> ShowS
forall a. [a] -> [a] -> [a]
++ "\xA0/\xA0" String -> ShowS
forall a. [a] -> [a] -> [a]
++ UnitName 'NonMetric -> String
forall a. Show a => a -> String
show UnitName 'NonMetric
n2
  show (Power x :: UnitName 'NonMetric
x n :: Int
n) = UnitName 'NonMetric -> String
forall a. Show a => a -> String
show UnitName 'NonMetric
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ "^" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
n
  show (Grouped n :: UnitName 'NonMetric
n) = "(" 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]
++ ")"
  show (Weaken n :: UnitName 'Metric
n) = UnitName 'Metric -> String
forall a. Show a => a -> String
show UnitName 'Metric
n

asAtomic :: UnitName m -> Maybe (NameAtom ('UnitAtom m))
asAtomic :: UnitName m -> Maybe (NameAtom ('UnitAtom m))
asAtomic (MetricAtomic a :: NameAtom ('UnitAtom 'Metric)
a) = NameAtom ('UnitAtom 'Metric)
-> Maybe (NameAtom ('UnitAtom 'Metric))
forall a. a -> Maybe a
Just NameAtom ('UnitAtom 'Metric)
a
asAtomic (Atomic a :: NameAtom ('UnitAtom 'NonMetric)
a) = NameAtom ('UnitAtom 'NonMetric)
-> Maybe (NameAtom ('UnitAtom 'NonMetric))
forall a. a -> Maybe a
Just NameAtom ('UnitAtom 'NonMetric)
a
asAtomic (Weaken n :: UnitName 'Metric
n) = NameAtom ('UnitAtom 'Metric) -> NameAtom ('UnitAtom m)
forall a b. Coercible a b => a -> b
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 _ = Maybe (NameAtom ('UnitAtom m))
forall a. Maybe a
Nothing

isAtomic :: UnitName m -> Bool
isAtomic :: UnitName m -> Bool
isAtomic One = Bool
True
isAtomic (MetricAtomic _) = Bool
True
isAtomic (Atomic _) = Bool
True
isAtomic (Prefixed _ _) = Bool
True
isAtomic (Grouped _) = Bool
True
isAtomic (Weaken n :: UnitName 'Metric
n) = UnitName 'Metric -> Bool
forall (m :: Metricality). UnitName m -> Bool
isAtomic UnitName 'Metric
n
isAtomic _ = Bool
False

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

-- reduce by algebraic simplifications

reduce :: UnitName m -> UnitName m
reduce :: UnitName m -> UnitName m
reduce One = UnitName m
UnitName 'NonMetric
One
reduce n :: UnitName m
n@(MetricAtomic _) = UnitName m
n
reduce n :: UnitName m
n@(Atomic _) = UnitName m
n
reduce n :: UnitName m
n@(Prefixed _ _) = UnitName m
n
reduce (Product n1 :: UnitName 'NonMetric
n1 n2 :: 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 n1 :: UnitName 'NonMetric
n1 n2 :: 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 n :: UnitName 'NonMetric
n x :: 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 n :: 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 n :: 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 One n :: UnitName 'NonMetric
n) = UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName m
reduce' UnitName 'NonMetric
n
reduce' (Product n :: UnitName 'NonMetric
n One) = UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName m
reduce' UnitName 'NonMetric
n
reduce' (Power (Power n :: UnitName 'NonMetric
n x1 :: Int
x1) x2 :: 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 n :: UnitName 'NonMetric
n x1 :: Int
x1)) x2 :: 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 _ 0) = UnitName m
UnitName 'NonMetric
One
reduce' (Power n :: UnitName 'NonMetric
n 1) = UnitName 'NonMetric -> UnitName 'NonMetric
forall (m :: Metricality). UnitName m -> UnitName m
reduce' UnitName 'NonMetric
n
reduce' (Grouped n :: 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 _)) = UnitName m
n
reduce' n :: 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
Constr
DataType
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 -> Constr
NameAtomType -> DataType
(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

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
Constr
DataType
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 -> Constr
Prefix -> DataType
(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 "m" "m" "metre"

nGram :: UnitName 'Metric
nGram :: UnitName 'Metric
nGram = String -> String -> String -> UnitName 'Metric
ucumMetric "g" "g" "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 "s" "s" "second"

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

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

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

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

-- | The name of the base unit associated with a specified dimension.

baseUnitName :: Dimension' -> UnitName 'NonMetric
baseUnitName :: Dimension' -> UnitName 'NonMetric
baseUnitName d :: 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]

deka, hecto, kilo, mega, giga, tera, peta, exa, zetta, yotta :: Prefix
deka :: Prefix
deka  = String -> String -> String -> Rational -> Prefix
prefix "da" "da" "deka" 1e1
hecto :: Prefix
hecto = String -> String -> String -> Rational -> Prefix
prefix "h" "h" "hecto"  1e2
kilo :: Prefix
kilo  = String -> String -> String -> Rational -> Prefix
prefix "k" "k" "kilo"   1e3
mega :: Prefix
mega  = String -> String -> String -> Rational -> Prefix
prefix "M" "M" "mega"   1e6
giga :: Prefix
giga  = String -> String -> String -> Rational -> Prefix
prefix "G" "G" "giga"   1e9
tera :: Prefix
tera  = String -> String -> String -> Rational -> Prefix
prefix "T" "T" "tera"   1e12
peta :: Prefix
peta  = String -> String -> String -> Rational -> Prefix
prefix "P" "P" "peta"   1e15
exa :: Prefix
exa   = String -> String -> String -> Rational -> Prefix
prefix "E" "E" "exa"    1e18
zetta :: Prefix
zetta = String -> String -> String -> Rational -> Prefix
prefix "Z" "Z" "zetta"  1e21
yotta :: Prefix
yotta = String -> String -> String -> Rational -> Prefix
prefix "Y" "Y" "yotta"  1e24
deci, centi, milli, micro, nano, pico, femto, atto, zepto, yocto :: Prefix
deci :: Prefix
deci  = String -> String -> String -> Rational -> Prefix
prefix "d" "d" "deci"   1e-1
centi :: Prefix
centi = String -> String -> String -> Rational -> Prefix
prefix "c" "c" "centi"  1e-2
milli :: Prefix
milli = String -> String -> String -> Rational -> Prefix
prefix "m" "m" "milli"  1e-3
micro :: Prefix
micro = String -> String -> String -> Rational -> Prefix
prefix "u" "μ" "micro"  1e-6
nano :: Prefix
nano  = String -> String -> String -> Rational -> Prefix
prefix "n" "n" "nano"   1e-9
pico :: Prefix
pico  = String -> String -> String -> Rational -> Prefix
prefix "p" "p" "pico"   1e-12
femto :: Prefix
femto = String -> String -> String -> Rational -> Prefix
prefix "f" "f" "femto"  1e-15
atto :: Prefix
atto  = String -> String -> String -> Rational -> Prefix
prefix "a" "a" "atto"   1e-18
zepto :: Prefix
zepto = String -> String -> String -> Rational -> Prefix
prefix "z" "z" "zepto"  1e-21
yocto :: Prefix
yocto = String -> String -> String -> Rational -> Prefix
prefix "y" "y" "yocto"  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
deka, 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
a :: UnitName m1
a * :: UnitName m1 -> UnitName m2 -> UnitName 'NonMetric
* b :: 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
n1 :: UnitName m1
n1 / :: UnitName m1 -> UnitName m2 -> UnitName 'NonMetric
/ n2 :: 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
x :: UnitName m
x ^ :: UnitName m -> Int -> UnitName 'NonMetric
^ n :: 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 _) = 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 _) = UnitName m
UnitName 'NonMetric
n
weaken n :: UnitName m
n@(Prefixed _ _) = UnitName m
UnitName 'NonMetric
n
weaken n :: UnitName m
n@(Product _ _) = UnitName m
UnitName 'NonMetric
n
weaken n :: UnitName m
n@(Quotient _ _) = UnitName m
UnitName 'NonMetric
n
weaken n :: UnitName m
n@(Power _ _) = UnitName m
UnitName 'NonMetric
n
weaken n :: UnitName m
n@(Grouped _) = UnitName m
UnitName 'NonMetric
n
weaken n :: UnitName m
n@(Weaken _) = 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 _) = UnitName m -> Maybe (UnitName m)
forall a. a -> Maybe a
Just UnitName m
n
strengthen (Weaken n :: UnitName 'Metric
n) = UnitName 'Metric -> Maybe (UnitName 'Metric)
forall (m :: Metricality). UnitName m -> Maybe (UnitName 'Metric)
strengthen UnitName 'Metric
n
strengthen _ = 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 p1 :: TypeRep
p1 p2 :: 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 "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)
Constr
DataType
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 -> Constr
NameAtom m -> DataType
(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 -> Constr
forall (m :: NameAtomType). Typeable m => NameAtom m -> DataType
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 One = InterchangeName :: String -> InterchangeNameAuthority -> Bool -> InterchangeName
InterchangeName { name :: String
name = "1", authority :: InterchangeNameAuthority
authority = InterchangeNameAuthority
UCUM, isAtomic :: Bool
I.isAtomic = Bool
True }
  interchangeName (MetricAtomic a :: NameAtom ('UnitAtom 'Metric)
a) = NameAtom ('UnitAtom 'Metric) -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName NameAtom ('UnitAtom 'Metric)
a
  interchangeName (Atomic a :: NameAtom ('UnitAtom 'NonMetric)
a) = NameAtom ('UnitAtom 'NonMetric) -> InterchangeName
forall a. HasInterchangeName a => a -> InterchangeName
interchangeName NameAtom ('UnitAtom 'NonMetric)
a
  interchangeName (Prefixed p :: PrefixName
p n :: 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 n1 :: UnitName 'NonMetric
n1 n2 :: 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 -> 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 n1 :: UnitName 'NonMetric
n1 n2 :: 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 -> 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 n :: UnitName 'NonMetric
n x :: 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 n :: UnitName 'NonMetric
n) = let n' :: String
n' = "(" 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]
++ ")"
                                 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 n :: 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 i :: String
i a :: String
a f :: 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 i :: String
i a :: String
a f :: 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 i :: String
i a :: String
a f :: 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 i :: String
i a :: String
a f :: 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 i :: String
i a :: String
a f :: 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 [n :: UnitName 'NonMetric
n] = UnitName 'NonMetric
n
    go (n :: UnitName 'NonMetric
n : ns :: [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