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

    -- | Returns 'True' if the 'UnitName' is atomic.
    isAtomic :: UnitName m -> Bool
    isAtomic :: forall (m :: Metricality). 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 :: forall (m :: Metricality). 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 :: forall (m :: Metricality). 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 m -> UnitName m
    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 m -> UnitName m
    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 m -> UnitName m
    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 m -> UnitName m
    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 m -> UnitName m
    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' :: forall (m :: Metricality). UnitName m -> UnitName m
    reduce' (Product UnitName 'NonMetric
    One UnitName 'NonMetric
    n) = UnitName m -> UnitName m
    forall (m :: Metricality). UnitName m -> UnitName m
    reduce' UnitName m
    UnitName 'NonMetric
    n
    reduce' (Product UnitName 'NonMetric
    n UnitName 'NonMetric
    One) = UnitName m -> UnitName m
    forall (m :: Metricality). UnitName m -> UnitName m
    reduce' UnitName m
    UnitName 'NonMetric
    n
    reduce' (Power (Power UnitName 'NonMetric
    n Int
    x1) Int
    x2) = UnitName m -> UnitName m
    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 m -> UnitName m
    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 m -> UnitName m
    forall (m :: Metricality). UnitName m -> UnitName m
    reduce' UnitName m
    UnitName 'NonMetric
    n
    reduce' (Grouped UnitName 'NonMetric
    n) = UnitName m -> UnitName m
    forall (m :: Metricality). UnitName m -> UnitName m
    reduce' UnitName m
    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
    $c== :: NameAtomType -> NameAtomType -> Bool
    == :: NameAtomType -> NameAtomType -> Bool
    $c/= :: NameAtomType -> NameAtomType -> Bool
    /= :: 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
    $ccompare :: NameAtomType -> NameAtomType -> Ordering
    compare :: NameAtomType -> NameAtomType -> Ordering
    $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
    >= :: NameAtomType -> NameAtomType -> Bool
    $cmax :: NameAtomType -> NameAtomType -> NameAtomType
    max :: NameAtomType -> NameAtomType -> NameAtomType
    $cmin :: NameAtomType -> NameAtomType -> NameAtomType
    min :: NameAtomType -> NameAtomType -> NameAtomType
    Ord, Typeable NameAtomType
    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 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)
    $cgfoldl :: forall (c :: Type -> Type).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> NameAtomType -> c NameAtomType
    gfoldl :: forall (c :: Type -> Type).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> NameAtomType -> 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
    gunfold :: forall (c :: Type -> Type).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c NameAtomType
    $ctoConstr :: NameAtomType -> Constr
    toConstr :: NameAtomType -> Constr
    $cdataTypeOf :: NameAtomType -> DataType
    dataTypeOf :: NameAtomType -> DataType
    $cdataCast1 :: forall (t :: Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c NameAtomType)
    dataCast1 :: forall (t :: Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d. Data d => c (t d)) -> 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)
    dataCast2 :: forall (t :: Type -> Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c NameAtomType)
    $cgmapT :: (forall b. Data b => b -> b) -> NameAtomType -> NameAtomType
    gmapT :: (forall b. Data b => b -> b) -> NameAtomType -> NameAtomType
    $cgmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> NameAtomType -> r
    gmapQl :: forall r r'.
    (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
    gmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> NameAtomType -> r
    $cgmapQ :: forall u. (forall d. Data d => d -> u) -> NameAtomType -> [u]
    gmapQ :: forall u. (forall d. Data d => d -> u) -> NameAtomType -> [u]
    $cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> NameAtomType -> u
    gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> NameAtomType -> u
    $cgmapM :: forall (m :: Type -> Type).
    Monad m =>
    (forall d. Data d => d -> m d) -> NameAtomType -> m NameAtomType
    gmapM :: forall (m :: Type -> Type).
    Monad m =>
    (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
    gmapMp :: forall (m :: Type -> Type).
    MonadPlus m =>
    (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
    gmapMo :: forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> NameAtomType -> m 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
    $cfrom :: forall x. NameAtomType -> Rep NameAtomType x
    from :: forall x. NameAtomType -> Rep NameAtomType x
    $cto :: forall x. Rep NameAtomType x -> NameAtomType
    to :: forall x. Rep NameAtomType x -> NameAtomType
    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
    $c== :: Prefix -> Prefix -> Bool
    == :: Prefix -> Prefix -> Bool
    $c/= :: Prefix -> Prefix -> Bool
    /= :: Prefix -> Prefix -> Bool
    Eq, Typeable Prefix
    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 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)
    $cgfoldl :: forall (c :: Type -> Type).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Prefix -> c Prefix
    gfoldl :: forall (c :: Type -> Type).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Prefix -> 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
    gunfold :: forall (c :: Type -> Type).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Prefix
    $ctoConstr :: Prefix -> Constr
    toConstr :: Prefix -> Constr
    $cdataTypeOf :: Prefix -> DataType
    dataTypeOf :: Prefix -> DataType
    $cdataCast1 :: forall (t :: Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Prefix)
    dataCast1 :: forall (t :: Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d. Data d => c (t d)) -> 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)
    dataCast2 :: forall (t :: Type -> Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Prefix)
    $cgmapT :: (forall b. Data b => b -> b) -> Prefix -> Prefix
    gmapT :: (forall b. Data b => b -> b) -> Prefix -> Prefix
    $cgmapQl :: forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Prefix -> r
    gmapQl :: forall r r'.
    (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
    gmapQr :: forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Prefix -> r
    $cgmapQ :: forall u. (forall d. Data d => d -> u) -> Prefix -> [u]
    gmapQ :: forall u. (forall d. Data d => d -> u) -> Prefix -> [u]
    $cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Prefix -> u
    gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Prefix -> u
    $cgmapM :: forall (m :: Type -> Type).
    Monad m =>
    (forall d. Data d => d -> m d) -> Prefix -> m Prefix
    gmapM :: forall (m :: Type -> Type).
    Monad m =>
    (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
    gmapMp :: forall (m :: Type -> Type).
    MonadPlus m =>
    (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
    gmapMo :: forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Prefix -> m 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
    $cfrom :: forall x. Prefix -> Rep Prefix x
    from :: forall x. Prefix -> Rep Prefix x
    $cto :: forall x. Rep Prefix x -> Prefix
    to :: forall x. Rep Prefix x -> Prefix
    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 * :: forall (m1 :: Metricality) (m2 :: Metricality).
    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 / :: forall (m1 :: Metricality) (m2 :: Metricality).
    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 ^ :: forall (m :: Metricality). 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 :: forall (m :: Metricality). 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 :: forall (m :: Metricality). UnitName m -> Maybe (UnitName 'Metric)
    strengthen n :: UnitName m
    n@(MetricAtomic NameAtom ('UnitAtom 'Metric)
    _) = UnitName 'Metric -> Maybe (UnitName 'Metric)
    forall a. a -> Maybe a
    Just UnitName m
    UnitName 'Metric
    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 :: forall (m1 :: Metricality) (m2 :: Metricality).
    (Typeable m1, Typeable m2) =>
    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 a b. (a -> b) -> Maybe a -> Maybe b
    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 :: forall (m :: Metricality). 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
      {
        forall (m :: NameAtomType). NameAtom m -> InterchangeName
    _interchangeName :: InterchangeName, -- ^ The interchange name of the unit.
        forall (m :: NameAtomType). NameAtom m -> String
    abbreviation_en :: String, -- ^ The abbreviated name of the unit in international English.
        forall (m :: NameAtomType). 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
    $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
    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
    $ccompare :: forall (m :: NameAtomType). NameAtom m -> NameAtom m -> Ordering
    compare :: NameAtom m -> NameAtom m -> Ordering
    $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
    >= :: NameAtom m -> NameAtom m -> Bool
    $cmax :: forall (m :: NameAtomType). NameAtom m -> NameAtom m -> NameAtom m
    max :: NameAtom m -> NameAtom m -> NameAtom m
    $cmin :: forall (m :: NameAtomType). NameAtom m -> NameAtom m -> NameAtom m
    min :: NameAtom m -> NameAtom m -> NameAtom m
    Ord, Typeable (NameAtom m)
    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 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))
    $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)
    gfoldl :: 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)
    $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)
    gunfold :: forall (c :: Type -> Type).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (NameAtom m)
    $ctoConstr :: forall (m :: NameAtomType). Typeable m => NameAtom m -> Constr
    toConstr :: NameAtom m -> Constr
    $cdataTypeOf :: forall (m :: NameAtomType). Typeable m => NameAtom m -> DataType
    dataTypeOf :: NameAtom m -> DataType
    $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))
    dataCast1 :: forall (t :: Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d. Data d => c (t d)) -> 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))
    dataCast2 :: 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))
    $cgmapT :: forall (m :: NameAtomType).
    Typeable m =>
    (forall b. Data b => b -> b) -> NameAtom m -> NameAtom m
    gmapT :: (forall b. Data b => b -> b) -> NameAtom m -> NameAtom m
    $cgmapQl :: forall (m :: NameAtomType) r r'.
    Typeable m =>
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> NameAtom m -> r
    gmapQl :: forall r r'.
    (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
    gmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> NameAtom m -> r
    $cgmapQ :: forall (m :: NameAtomType) u.
    Typeable m =>
    (forall d. Data d => d -> u) -> NameAtom m -> [u]
    gmapQ :: forall u. (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
    gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> NameAtom m -> u
    $cgmapM :: forall (m :: NameAtomType) (m :: Type -> Type).
    (Typeable m, Monad m) =>
    (forall d. Data d => d -> m d) -> NameAtom m -> m (NameAtom m)
    gmapM :: forall (m :: Type -> Type).
    Monad m =>
    (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)
    gmapMp :: forall (m :: Type -> Type).
    MonadPlus m =>
    (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)
    gmapMo :: forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> NameAtom m -> m (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
    $cfrom :: forall (m :: NameAtomType) x. NameAtom m -> Rep (NameAtom m) x
    from :: forall x. NameAtom m -> Rep (NameAtom m) x
    $cto :: forall (m :: NameAtomType) x. Rep (NameAtom m) x -> NameAtom m
    to :: forall x. Rep (NameAtom m) x -> NameAtom m
    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 { 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 { 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 { 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 { 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 { 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 { 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 :: forall (f :: Type -> Type).
    Foldable f =>
    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 a. f a -> [a]
    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