packages feed

dimensional 1.1 → 1.2

raw patch · 30 files changed

+5199/−5181 lines, 30 filesdep ~basesetup-changedPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base

API changes (from Hackage documentation)

- Numeric.Units.Dimensional: }
- Numeric.Units.Dimensional.Dimensions.TermLevel: instance Data.Semigroup.Semigroup Numeric.Units.Dimensional.Dimensions.TermLevel.Dimension'
- Numeric.Units.Dimensional.Dynamic: instance Data.Semigroup.Semigroup Numeric.Units.Dimensional.Dynamic.AnyUnit
- Numeric.Units.Dimensional.Dynamic: instance GHC.Num.Num a => Data.Semigroup.Semigroup (Numeric.Units.Dimensional.Dynamic.AnyQuantity a)
- Numeric.Units.Dimensional.Dynamic: instance GHC.Num.Num a => Data.Semigroup.Semigroup (Numeric.Units.Dimensional.Dynamic.DynQuantity a)
- Numeric.Units.Dimensional.FixedPoint: }
+ Numeric.Units.Dimensional: type family NRoot (d :: Dimension) (x :: TypeInt)
+ Numeric.Units.Dimensional.Coercion: data family Dimensional v :: Dimension -> Type -> Type
+ Numeric.Units.Dimensional.Dimensions: AnyDimension :: DynamicDimension
+ Numeric.Units.Dimensional.Dimensions: Dim' :: !Int -> !Int -> !Int -> !Int -> !Int -> !Int -> !Int -> Dimension'
+ Numeric.Units.Dimensional.Dimensions: NoDimension :: DynamicDimension
+ Numeric.Units.Dimensional.Dimensions: SomeDimension :: Dimension' -> DynamicDimension
+ Numeric.Units.Dimensional.Dimensions: asList :: Dimension' -> [Int]
+ Numeric.Units.Dimensional.Dimensions: class HasDynamicDimension a => HasDimension a
+ Numeric.Units.Dimensional.Dimensions: class HasDynamicDimension a
+ Numeric.Units.Dimensional.Dimensions: dOne :: Dimension'
+ Numeric.Units.Dimensional.Dimensions: data Dimension'
+ Numeric.Units.Dimensional.Dimensions: data DynamicDimension
+ Numeric.Units.Dimensional.Dimensions: dimension :: HasDimension a => a -> Dimension'
+ Numeric.Units.Dimensional.Dimensions: dynamicDimension :: (HasDynamicDimension a, HasDimension a) => a -> DynamicDimension
+ Numeric.Units.Dimensional.Dimensions: hasSomeDimension :: HasDynamicDimension a => a -> Bool
+ Numeric.Units.Dimensional.Dimensions: isCompatibleWith :: HasDynamicDimension a => a -> Dimension' -> Bool
+ Numeric.Units.Dimensional.Dimensions: matchDimensions :: DynamicDimension -> DynamicDimension -> DynamicDimension
+ Numeric.Units.Dimensional.Dimensions.TermLevel: instance GHC.Base.Semigroup Numeric.Units.Dimensional.Dimensions.TermLevel.Dimension'
+ Numeric.Units.Dimensional.Dimensions.TypeLevel: infixl 7 /
+ Numeric.Units.Dimensional.Dimensions.TypeLevel: infixr 8 ^
+ Numeric.Units.Dimensional.Dimensions.TypeLevel: type family NRoot (d :: Dimension) (x :: TypeInt)
+ Numeric.Units.Dimensional.Dynamic: instance GHC.Base.Semigroup Numeric.Units.Dimensional.Dynamic.AnyUnit
+ Numeric.Units.Dimensional.Dynamic: instance GHC.Num.Num a => GHC.Base.Semigroup (Numeric.Units.Dimensional.Dynamic.AnyQuantity a)
+ Numeric.Units.Dimensional.Dynamic: instance GHC.Num.Num a => GHC.Base.Semigroup (Numeric.Units.Dimensional.Dynamic.DynQuantity a)
+ Numeric.Units.Dimensional.FixedPoint: infixr 8 ^
+ Numeric.Units.Dimensional.FixedPoint: type family NRoot (d :: Dimension) (x :: TypeInt)
+ Numeric.Units.Dimensional.Prelude: (!!) :: () => [a] -> Int -> a
+ Numeric.Units.Dimensional.Prelude: ($!) :: () => (a -> b) -> a -> b
+ Numeric.Units.Dimensional.Prelude: ($) :: () => (a -> b) -> a -> b
+ Numeric.Units.Dimensional.Prelude: (&&) :: Bool -> Bool -> Bool
+ Numeric.Units.Dimensional.Prelude: (*) :: (KnownVariant v1, KnownVariant v2, KnownVariant (v1 * v2), Num a) => Dimensional v1 d1 a -> Dimensional v2 d2 a -> Dimensional (v1 * v2) (d1 * d2) a
+ Numeric.Units.Dimensional.Prelude: (**) :: Floating a => Dimensionless a -> Dimensionless a -> Dimensionless a
+ Numeric.Units.Dimensional.Prelude: (*>) :: Applicative f => f a -> f b -> f b
+ Numeric.Units.Dimensional.Prelude: (*~) :: Num a => a -> Unit m d a -> Quantity d a
+ Numeric.Units.Dimensional.Prelude: (*~~) :: (Functor f, Num a) => f a -> Unit m d a -> f (Quantity d a)
+ Numeric.Units.Dimensional.Prelude: (+) :: Num a => Quantity d a -> Quantity d a -> Quantity d a
+ Numeric.Units.Dimensional.Prelude: (++) :: () => [a] -> [a] -> [a]
+ Numeric.Units.Dimensional.Prelude: (-) :: Num a => Quantity d a -> Quantity d a -> Quantity d a
+ Numeric.Units.Dimensional.Prelude: (.) :: Category cat => cat b c -> cat a b -> cat a c
+ Numeric.Units.Dimensional.Prelude: (/) :: (KnownVariant v1, KnownVariant v2, KnownVariant (v1 / v2), Fractional a) => Dimensional v1 d1 a -> Dimensional v2 d2 a -> Dimensional (v1 / v2) (d1 / d2) a
+ Numeric.Units.Dimensional.Prelude: (/=) :: Eq a => a -> a -> Bool
+ Numeric.Units.Dimensional.Prelude: (/~) :: Fractional a => Quantity d a -> Unit m d a -> a
+ Numeric.Units.Dimensional.Prelude: (/~~) :: forall f m d a. (Functor f, Fractional a) => f (Quantity d a) -> Unit m d a -> f a
+ Numeric.Units.Dimensional.Prelude: (<$) :: Functor f => a -> f b -> f a
+ Numeric.Units.Dimensional.Prelude: (<$>) :: Functor f => (a -> b) -> f a -> f b
+ Numeric.Units.Dimensional.Prelude: (<) :: Ord a => a -> a -> Bool
+ Numeric.Units.Dimensional.Prelude: (<*) :: Applicative f => f a -> f b -> f a
+ Numeric.Units.Dimensional.Prelude: (<*>) :: Applicative f => f (a -> b) -> f a -> f b
+ Numeric.Units.Dimensional.Prelude: (<=) :: Ord a => a -> a -> Bool
+ Numeric.Units.Dimensional.Prelude: (<>) :: Semigroup a => a -> a -> a
+ Numeric.Units.Dimensional.Prelude: (=<<) :: Monad m => (a -> m b) -> m a -> m b
+ Numeric.Units.Dimensional.Prelude: (==) :: Eq a => a -> a -> Bool
+ Numeric.Units.Dimensional.Prelude: (>) :: Ord a => a -> a -> Bool
+ Numeric.Units.Dimensional.Prelude: (>=) :: Ord a => a -> a -> Bool
+ Numeric.Units.Dimensional.Prelude: (>>) :: Monad m => m a -> m b -> m b
+ Numeric.Units.Dimensional.Prelude: (>>=) :: Monad m => m a -> (a -> m b) -> m b
+ Numeric.Units.Dimensional.Prelude: (^) :: (Fractional a, KnownTypeInt i, KnownVariant v, KnownVariant (Weaken v)) => Dimensional v d1 a -> Proxy i -> Dimensional (Weaken v) (d1 ^ i) a
+ Numeric.Units.Dimensional.Prelude: (^/) :: (KnownTypeInt n, Floating a) => Quantity d a -> Proxy n -> Quantity (NRoot d n) a
+ Numeric.Units.Dimensional.Prelude: (^^) :: (Fractional a, Integral b) => a -> b -> a
+ Numeric.Units.Dimensional.Prelude: (||) :: Bool -> Bool -> Bool
+ Numeric.Units.Dimensional.Prelude: -- parameterized by its <a>Dimension</a> and representation.
+ Numeric.Units.Dimensional.Prelude: -- | A dimensional value, either a <a>Quantity</a> or a <a>Unit</a>,
+ Numeric.Units.Dimensional.Prelude: Dim :: TypeInt -> TypeInt -> TypeInt -> TypeInt -> TypeInt -> TypeInt -> TypeInt -> Dimension
+ Numeric.Units.Dimensional.Prelude: Dim' :: !Int -> !Int -> !Int -> !Int -> !Int -> !Int -> !Int -> Dimension'
+ Numeric.Units.Dimensional.Prelude: EQ :: Ordering
+ Numeric.Units.Dimensional.Prelude: False :: Bool
+ Numeric.Units.Dimensional.Prelude: GT :: Ordering
+ Numeric.Units.Dimensional.Prelude: Just :: a -> Maybe a
+ Numeric.Units.Dimensional.Prelude: LT :: Ordering
+ Numeric.Units.Dimensional.Prelude: Left :: a -> Either a b
+ Numeric.Units.Dimensional.Prelude: Metric :: Metricality
+ Numeric.Units.Dimensional.Prelude: NonMetric :: Metricality
+ Numeric.Units.Dimensional.Prelude: Nothing :: Maybe a
+ Numeric.Units.Dimensional.Prelude: Right :: b -> Either a b
+ Numeric.Units.Dimensional.Prelude: True :: Bool
+ Numeric.Units.Dimensional.Prelude: _0 :: Num a => Quantity d a
+ Numeric.Units.Dimensional.Prelude: _1 :: Num a => Dimensionless a
+ Numeric.Units.Dimensional.Prelude: _2 :: Num a => Dimensionless a
+ Numeric.Units.Dimensional.Prelude: _3 :: Num a => Dimensionless a
+ Numeric.Units.Dimensional.Prelude: _4 :: Num a => Dimensionless a
+ Numeric.Units.Dimensional.Prelude: _5 :: Num a => Dimensionless a
+ Numeric.Units.Dimensional.Prelude: _6 :: Num a => Dimensionless a
+ Numeric.Units.Dimensional.Prelude: _7 :: Num a => Dimensionless a
+ Numeric.Units.Dimensional.Prelude: _8 :: Num a => Dimensionless a
+ Numeric.Units.Dimensional.Prelude: _9 :: Num a => Dimensionless a
+ Numeric.Units.Dimensional.Prelude: abs :: Num a => Quantity d a -> Quantity d a
+ Numeric.Units.Dimensional.Prelude: acos :: Floating a => Dimensionless a -> Dimensionless a
+ Numeric.Units.Dimensional.Prelude: acosh :: Floating a => Dimensionless a -> Dimensionless a
+ Numeric.Units.Dimensional.Prelude: all :: Foldable t => (a -> Bool) -> t a -> Bool
+ Numeric.Units.Dimensional.Prelude: and :: Foldable t => t Bool -> Bool
+ Numeric.Units.Dimensional.Prelude: any :: Foldable t => (a -> Bool) -> t a -> Bool
+ Numeric.Units.Dimensional.Prelude: appendFile :: FilePath -> String -> IO ()
+ Numeric.Units.Dimensional.Prelude: asLens :: Fractional a => Unit m d a -> forall f. Functor f => (a -> f a) -> Quantity d a -> f (Quantity d a)
+ Numeric.Units.Dimensional.Prelude: asTypeOf :: () => a -> a -> a
+ Numeric.Units.Dimensional.Prelude: asin :: Floating a => Dimensionless a -> Dimensionless a
+ Numeric.Units.Dimensional.Prelude: asinh :: Floating a => Dimensionless a -> Dimensionless a
+ Numeric.Units.Dimensional.Prelude: atan :: Floating a => Dimensionless a -> Dimensionless a
+ Numeric.Units.Dimensional.Prelude: atan2 :: RealFloat a => Quantity d a -> Quantity d a -> Dimensionless a
+ Numeric.Units.Dimensional.Prelude: atanh :: Floating a => Dimensionless a -> Dimensionless a
+ Numeric.Units.Dimensional.Prelude: break :: () => (a -> Bool) -> [a] -> ([a], [a])
+ Numeric.Units.Dimensional.Prelude: cbrt :: Floating a => Quantity d a -> Quantity (Cbrt d) a
+ Numeric.Units.Dimensional.Prelude: ceiling :: (RealFrac a, Integral b) => a -> b
+ Numeric.Units.Dimensional.Prelude: changeRep :: (KnownVariant v, Real a, Fractional b) => Dimensional v d a -> Dimensional v d b
+ Numeric.Units.Dimensional.Prelude: changeRepApproximate :: (KnownVariant v, Floating b) => Dimensional v d ExactPi -> Dimensional v d b
+ Numeric.Units.Dimensional.Prelude: class Functor f => Applicative (f :: Type -> Type)
+ Numeric.Units.Dimensional.Prelude: class Bounded a
+ Numeric.Units.Dimensional.Prelude: class Category (cat :: k -> k -> Type)
+ Numeric.Units.Dimensional.Prelude: class Enum a
+ Numeric.Units.Dimensional.Prelude: class Eq a
+ Numeric.Units.Dimensional.Prelude: class Fractional a => Floating a
+ Numeric.Units.Dimensional.Prelude: class Foldable (t :: Type -> Type)
+ Numeric.Units.Dimensional.Prelude: class Num a => Fractional a
+ Numeric.Units.Dimensional.Prelude: class Functor (f :: Type -> Type)
+ Numeric.Units.Dimensional.Prelude: class HasDynamicDimension a => HasDimension a
+ Numeric.Units.Dimensional.Prelude: class (Real a, Enum a) => Integral a
+ Numeric.Units.Dimensional.Prelude: class KnownVariant (v :: Variant) where {
+ Numeric.Units.Dimensional.Prelude: class Applicative m => Monad (m :: Type -> Type)
+ Numeric.Units.Dimensional.Prelude: class Semigroup a => Monoid a
+ Numeric.Units.Dimensional.Prelude: class Num a
+ Numeric.Units.Dimensional.Prelude: class Eq a => Ord a
+ Numeric.Units.Dimensional.Prelude: class Read a
+ Numeric.Units.Dimensional.Prelude: class (Num a, Ord a) => Real a
+ Numeric.Units.Dimensional.Prelude: class (RealFrac a, Floating a) => RealFloat a
+ Numeric.Units.Dimensional.Prelude: class (Real a, Fractional a) => RealFrac a
+ Numeric.Units.Dimensional.Prelude: class Semigroup a
+ Numeric.Units.Dimensional.Prelude: class Show a
+ Numeric.Units.Dimensional.Prelude: class (Functor t, Foldable t) => Traversable (t :: Type -> Type)
+ Numeric.Units.Dimensional.Prelude: compare :: Ord a => a -> a -> Ordering
+ Numeric.Units.Dimensional.Prelude: concat :: Foldable t => t [a] -> [a]
+ Numeric.Units.Dimensional.Prelude: concatMap :: Foldable t => (a -> [b]) -> t a -> [b]
+ Numeric.Units.Dimensional.Prelude: const :: () => a -> b -> a
+ Numeric.Units.Dimensional.Prelude: cos :: Floating a => Dimensionless a -> Dimensionless a
+ Numeric.Units.Dimensional.Prelude: cosh :: Floating a => Dimensionless a -> Dimensionless a
+ Numeric.Units.Dimensional.Prelude: curry :: () => ((a, b) -> c) -> a -> b -> c
+ Numeric.Units.Dimensional.Prelude: cycle :: () => [a] -> [a]
+ Numeric.Units.Dimensional.Prelude: data Bool
+ Numeric.Units.Dimensional.Prelude: data Char
+ Numeric.Units.Dimensional.Prelude: data Dimension
+ Numeric.Units.Dimensional.Prelude: data Dimension'
+ Numeric.Units.Dimensional.Prelude: data Double
+ Numeric.Units.Dimensional.Prelude: data Either a b
+ Numeric.Units.Dimensional.Prelude: data Float
+ Numeric.Units.Dimensional.Prelude: data IO a
+ Numeric.Units.Dimensional.Prelude: data Int
+ Numeric.Units.Dimensional.Prelude: data Integer
+ Numeric.Units.Dimensional.Prelude: data Maybe a
+ Numeric.Units.Dimensional.Prelude: data Metricality
+ Numeric.Units.Dimensional.Prelude: data Ordering
+ Numeric.Units.Dimensional.Prelude: data Word
+ Numeric.Units.Dimensional.Prelude: data family Dimensional v :: Dimension -> Type -> Type;
+ Numeric.Units.Dimensional.Prelude: decodeFloat :: RealFloat a => a -> (Integer, Int)
+ Numeric.Units.Dimensional.Prelude: dimension :: HasDimension a => a -> Dimension'
+ Numeric.Units.Dimensional.Prelude: dimensionlessLength :: (Num a, Foldable f) => f b -> Dimensionless a
+ Numeric.Units.Dimensional.Prelude: div :: Integral a => a -> a -> a
+ Numeric.Units.Dimensional.Prelude: divMod :: Integral a => a -> a -> (a, a)
+ Numeric.Units.Dimensional.Prelude: drop :: () => Int -> [a] -> [a]
+ Numeric.Units.Dimensional.Prelude: dropWhile :: () => (a -> Bool) -> [a] -> [a]
+ Numeric.Units.Dimensional.Prelude: either :: () => (a -> c) -> (b -> c) -> Either a b -> c
+ Numeric.Units.Dimensional.Prelude: elem :: (Foldable t, Eq a) => a -> t a -> Bool
+ Numeric.Units.Dimensional.Prelude: encodeFloat :: RealFloat a => Integer -> Int -> a
+ Numeric.Units.Dimensional.Prelude: enumFrom :: Enum a => a -> [a]
+ Numeric.Units.Dimensional.Prelude: enumFromThen :: Enum a => a -> a -> [a]
+ Numeric.Units.Dimensional.Prelude: enumFromThenTo :: Enum a => a -> a -> a -> [a]
+ Numeric.Units.Dimensional.Prelude: enumFromTo :: Enum a => a -> a -> [a]
+ Numeric.Units.Dimensional.Prelude: error :: HasCallStack => [Char] -> a
+ Numeric.Units.Dimensional.Prelude: errorWithoutStackTrace :: () => [Char] -> a
+ Numeric.Units.Dimensional.Prelude: even :: Integral a => a -> Bool
+ Numeric.Units.Dimensional.Prelude: exactValue :: Unit m d a -> ExactPi
+ Numeric.Units.Dimensional.Prelude: exactify :: Unit m d a -> Unit m d ExactPi
+ Numeric.Units.Dimensional.Prelude: exp :: Floating a => Dimensionless a -> Dimensionless a
+ Numeric.Units.Dimensional.Prelude: exponent :: RealFloat a => a -> Int
+ Numeric.Units.Dimensional.Prelude: fail :: Monad m => String -> m a
+ Numeric.Units.Dimensional.Prelude: filter :: () => (a -> Bool) -> [a] -> [a]
+ Numeric.Units.Dimensional.Prelude: flip :: () => (a -> b -> c) -> b -> a -> c
+ Numeric.Units.Dimensional.Prelude: floatDigits :: RealFloat a => a -> Int
+ Numeric.Units.Dimensional.Prelude: floatRadix :: RealFloat a => a -> Integer
+ Numeric.Units.Dimensional.Prelude: floatRange :: RealFloat a => a -> (Int, Int)
+ Numeric.Units.Dimensional.Prelude: floor :: (RealFrac a, Integral b) => a -> b
+ Numeric.Units.Dimensional.Prelude: fmap :: Functor f => (a -> b) -> f a -> f b
+ Numeric.Units.Dimensional.Prelude: foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m
+ Numeric.Units.Dimensional.Prelude: foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b
+ Numeric.Units.Dimensional.Prelude: foldl1 :: Foldable t => (a -> a -> a) -> t a -> a
+ Numeric.Units.Dimensional.Prelude: foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
+ Numeric.Units.Dimensional.Prelude: foldr1 :: Foldable t => (a -> a -> a) -> t a -> a
+ Numeric.Units.Dimensional.Prelude: fromEnum :: Enum a => a -> Int
+ Numeric.Units.Dimensional.Prelude: fromInteger :: Num a => Integer -> a
+ Numeric.Units.Dimensional.Prelude: fromIntegral :: (Integral a, Num b) => a -> b
+ Numeric.Units.Dimensional.Prelude: fromRational :: Fractional a => Rational -> a
+ Numeric.Units.Dimensional.Prelude: fst :: () => (a, b) -> a
+ Numeric.Units.Dimensional.Prelude: gcd :: Integral a => a -> a -> a
+ Numeric.Units.Dimensional.Prelude: getChar :: IO Char
+ Numeric.Units.Dimensional.Prelude: getContents :: IO String
+ Numeric.Units.Dimensional.Prelude: getLine :: IO String
+ Numeric.Units.Dimensional.Prelude: head :: () => [a] -> a
+ Numeric.Units.Dimensional.Prelude: id :: Category cat => cat a a
+ Numeric.Units.Dimensional.Prelude: infix 4 `notElem`
+ Numeric.Units.Dimensional.Prelude: infixl 1 >>
+ Numeric.Units.Dimensional.Prelude: infixl 4 <$>
+ Numeric.Units.Dimensional.Prelude: infixl 6 -
+ Numeric.Units.Dimensional.Prelude: infixl 7 `mod`
+ Numeric.Units.Dimensional.Prelude: infixl 9 !!
+ Numeric.Units.Dimensional.Prelude: infixr 0 $!
+ Numeric.Units.Dimensional.Prelude: infixr 1 =<<
+ Numeric.Units.Dimensional.Prelude: infixr 2 ||
+ Numeric.Units.Dimensional.Prelude: infixr 3 &&
+ Numeric.Units.Dimensional.Prelude: infixr 5 ++
+ Numeric.Units.Dimensional.Prelude: infixr 6 <>
+ Numeric.Units.Dimensional.Prelude: infixr 8 ^^
+ Numeric.Units.Dimensional.Prelude: infixr 9 .
+ Numeric.Units.Dimensional.Prelude: init :: () => [a] -> [a]
+ Numeric.Units.Dimensional.Prelude: interact :: (String -> String) -> IO ()
+ Numeric.Units.Dimensional.Prelude: ioError :: () => IOError -> IO a
+ Numeric.Units.Dimensional.Prelude: isDenormalized :: RealFloat a => a -> Bool
+ Numeric.Units.Dimensional.Prelude: isIEEE :: RealFloat a => a -> Bool
+ Numeric.Units.Dimensional.Prelude: isInfinite :: RealFloat a => a -> Bool
+ Numeric.Units.Dimensional.Prelude: isNaN :: RealFloat a => a -> Bool
+ Numeric.Units.Dimensional.Prelude: isNegativeZero :: RealFloat a => a -> Bool
+ Numeric.Units.Dimensional.Prelude: iterate :: () => (a -> a) -> a -> [a]
+ Numeric.Units.Dimensional.Prelude: last :: () => [a] -> a
+ Numeric.Units.Dimensional.Prelude: lcm :: Integral a => a -> a -> a
+ Numeric.Units.Dimensional.Prelude: length :: Foldable t => t a -> Int
+ Numeric.Units.Dimensional.Prelude: lex :: ReadS String
+ Numeric.Units.Dimensional.Prelude: lines :: String -> [String]
+ Numeric.Units.Dimensional.Prelude: log :: Floating a => Dimensionless a -> Dimensionless a
+ Numeric.Units.Dimensional.Prelude: logBase :: Floating a => Dimensionless a -> Dimensionless a -> Dimensionless a
+ Numeric.Units.Dimensional.Prelude: lookup :: Eq a => a -> [(a, b)] -> Maybe b
+ Numeric.Units.Dimensional.Prelude: map :: () => (a -> b) -> [a] -> [b]
+ Numeric.Units.Dimensional.Prelude: mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)
+ Numeric.Units.Dimensional.Prelude: mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()
+ Numeric.Units.Dimensional.Prelude: mappend :: Monoid a => a -> a -> a
+ Numeric.Units.Dimensional.Prelude: max :: Ord a => a -> a -> a
+ Numeric.Units.Dimensional.Prelude: maxBound :: Bounded a => a
+ Numeric.Units.Dimensional.Prelude: maximum :: (Foldable t, Ord a) => t a -> a
+ Numeric.Units.Dimensional.Prelude: maybe :: () => b -> (a -> b) -> Maybe a -> b
+ Numeric.Units.Dimensional.Prelude: mconcat :: Monoid a => [a] -> a
+ Numeric.Units.Dimensional.Prelude: mean :: (Fractional a, Foldable f) => f (Quantity d a) -> Quantity d a
+ Numeric.Units.Dimensional.Prelude: mempty :: Monoid a => a
+ Numeric.Units.Dimensional.Prelude: min :: Ord a => a -> a -> a
+ Numeric.Units.Dimensional.Prelude: minBound :: Bounded a => a
+ Numeric.Units.Dimensional.Prelude: minimum :: (Foldable t, Ord a) => t a -> a
+ Numeric.Units.Dimensional.Prelude: mkUnitQ :: Fractional a => UnitName m -> Rational -> Unit m1 d a -> Unit m d a
+ Numeric.Units.Dimensional.Prelude: mkUnitR :: Floating a => UnitName m -> ExactPi -> Unit m1 d a -> Unit m d a
+ Numeric.Units.Dimensional.Prelude: mkUnitZ :: Num a => UnitName m -> Integer -> Unit m1 d a -> Unit m d a
+ Numeric.Units.Dimensional.Prelude: mod :: Integral a => a -> a -> a
+ Numeric.Units.Dimensional.Prelude: nFromTo :: (Fractional a, Integral b) => Quantity d a -> Quantity d a -> b -> [Quantity d a]
+ Numeric.Units.Dimensional.Prelude: name :: Unit m d a -> UnitName m
+ Numeric.Units.Dimensional.Prelude: neg1 :: Proxy Neg1
+ Numeric.Units.Dimensional.Prelude: neg2 :: Proxy Neg2
+ Numeric.Units.Dimensional.Prelude: neg3 :: Proxy Neg3
+ Numeric.Units.Dimensional.Prelude: neg4 :: Proxy Neg4
+ Numeric.Units.Dimensional.Prelude: neg5 :: Proxy Neg5
+ Numeric.Units.Dimensional.Prelude: negate :: Num a => Quantity d a -> Quantity d a
+ Numeric.Units.Dimensional.Prelude: not :: Bool -> Bool
+ Numeric.Units.Dimensional.Prelude: notElem :: (Foldable t, Eq a) => a -> t a -> Bool
+ Numeric.Units.Dimensional.Prelude: nroot :: (KnownTypeInt n, Floating a) => Proxy n -> Quantity d a -> Quantity (NRoot d n) a
+ Numeric.Units.Dimensional.Prelude: null :: Foldable t => t a -> Bool
+ Numeric.Units.Dimensional.Prelude: odd :: Integral a => a -> Bool
+ Numeric.Units.Dimensional.Prelude: one :: Num a => Unit 'NonMetric DOne a
+ Numeric.Units.Dimensional.Prelude: or :: Foldable t => t Bool -> Bool
+ Numeric.Units.Dimensional.Prelude: otherwise :: Bool
+ Numeric.Units.Dimensional.Prelude: pi :: Floating a => Dimensionless a
+ Numeric.Units.Dimensional.Prelude: pos1 :: Proxy Pos1
+ Numeric.Units.Dimensional.Prelude: pos2 :: Proxy Pos2
+ Numeric.Units.Dimensional.Prelude: pos3 :: Proxy Pos3
+ Numeric.Units.Dimensional.Prelude: pos4 :: Proxy Pos4
+ Numeric.Units.Dimensional.Prelude: pos5 :: Proxy Pos5
+ Numeric.Units.Dimensional.Prelude: pred :: Enum a => a -> a
+ Numeric.Units.Dimensional.Prelude: print :: Show a => a -> IO ()
+ Numeric.Units.Dimensional.Prelude: product :: (Num a, Foldable f) => f (Dimensionless a) -> Dimensionless a
+ Numeric.Units.Dimensional.Prelude: properFraction :: (RealFrac a, Integral b) => a -> (b, a)
+ Numeric.Units.Dimensional.Prelude: pure :: Applicative f => a -> f a
+ Numeric.Units.Dimensional.Prelude: putChar :: Char -> IO ()
+ Numeric.Units.Dimensional.Prelude: putStr :: String -> IO ()
+ Numeric.Units.Dimensional.Prelude: putStrLn :: String -> IO ()
+ Numeric.Units.Dimensional.Prelude: quot :: Integral a => a -> a -> a
+ Numeric.Units.Dimensional.Prelude: quotRem :: Integral a => a -> a -> (a, a)
+ Numeric.Units.Dimensional.Prelude: read :: Read a => String -> a
+ Numeric.Units.Dimensional.Prelude: readFile :: FilePath -> IO String
+ Numeric.Units.Dimensional.Prelude: readIO :: Read a => String -> IO a
+ Numeric.Units.Dimensional.Prelude: readList :: Read a => ReadS [a]
+ Numeric.Units.Dimensional.Prelude: readLn :: Read a => IO a
+ Numeric.Units.Dimensional.Prelude: readParen :: () => Bool -> ReadS a -> ReadS a
+ Numeric.Units.Dimensional.Prelude: reads :: Read a => ReadS a
+ Numeric.Units.Dimensional.Prelude: readsPrec :: Read a => Int -> ReadS a
+ Numeric.Units.Dimensional.Prelude: realToFrac :: (Real a, Fractional b) => a -> b
+ Numeric.Units.Dimensional.Prelude: recip :: Fractional a => Quantity d a -> Quantity (Recip d) a
+ Numeric.Units.Dimensional.Prelude: rem :: Integral a => a -> a -> a
+ Numeric.Units.Dimensional.Prelude: repeat :: () => a -> [a]
+ Numeric.Units.Dimensional.Prelude: replicate :: () => Int -> a -> [a]
+ Numeric.Units.Dimensional.Prelude: return :: Monad m => a -> m a
+ Numeric.Units.Dimensional.Prelude: reverse :: () => [a] -> [a]
+ Numeric.Units.Dimensional.Prelude: round :: (RealFrac a, Integral b) => a -> b
+ Numeric.Units.Dimensional.Prelude: scaleFloat :: RealFloat a => Int -> a -> a
+ Numeric.Units.Dimensional.Prelude: scanl :: () => (b -> a -> b) -> b -> [a] -> [b]
+ Numeric.Units.Dimensional.Prelude: scanl1 :: () => (a -> a -> a) -> [a] -> [a]
+ Numeric.Units.Dimensional.Prelude: scanr :: () => (a -> b -> b) -> b -> [a] -> [b]
+ Numeric.Units.Dimensional.Prelude: scanr1 :: () => (a -> a -> a) -> [a] -> [a]
+ Numeric.Units.Dimensional.Prelude: seq :: () => a -> b -> b
+ Numeric.Units.Dimensional.Prelude: sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)
+ Numeric.Units.Dimensional.Prelude: sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)
+ Numeric.Units.Dimensional.Prelude: sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()
+ Numeric.Units.Dimensional.Prelude: show :: Show a => a -> String
+ Numeric.Units.Dimensional.Prelude: showChar :: Char -> ShowS
+ Numeric.Units.Dimensional.Prelude: showIn :: (Show a, Fractional a) => Unit m d a -> Quantity d a -> String
+ Numeric.Units.Dimensional.Prelude: showList :: Show a => [a] -> ShowS
+ Numeric.Units.Dimensional.Prelude: showParen :: Bool -> ShowS -> ShowS
+ Numeric.Units.Dimensional.Prelude: showString :: String -> ShowS
+ Numeric.Units.Dimensional.Prelude: shows :: Show a => a -> ShowS
+ Numeric.Units.Dimensional.Prelude: showsPrec :: Show a => Int -> a -> ShowS
+ Numeric.Units.Dimensional.Prelude: siUnit :: forall d a. (KnownDimension d, Num a) => Unit 'NonMetric d a
+ Numeric.Units.Dimensional.Prelude: significand :: RealFloat a => a -> a
+ Numeric.Units.Dimensional.Prelude: signum :: Num a => Quantity d a -> Dimensionless a
+ Numeric.Units.Dimensional.Prelude: sin :: Floating a => Dimensionless a -> Dimensionless a
+ Numeric.Units.Dimensional.Prelude: sinh :: Floating a => Dimensionless a -> Dimensionless a
+ Numeric.Units.Dimensional.Prelude: snd :: () => (a, b) -> b
+ Numeric.Units.Dimensional.Prelude: span :: () => (a -> Bool) -> [a] -> ([a], [a])
+ Numeric.Units.Dimensional.Prelude: splitAt :: () => Int -> [a] -> ([a], [a])
+ Numeric.Units.Dimensional.Prelude: sqrt :: Floating a => Quantity d a -> Quantity (Sqrt d) a
+ Numeric.Units.Dimensional.Prelude: strengthen :: Unit m d a -> Maybe (Unit 'Metric d a)
+ Numeric.Units.Dimensional.Prelude: subtract :: Num a => a -> a -> a
+ Numeric.Units.Dimensional.Prelude: succ :: Enum a => a -> a
+ Numeric.Units.Dimensional.Prelude: sum :: (Num a, Foldable f) => f (Quantity d a) -> Quantity d a
+ Numeric.Units.Dimensional.Prelude: tail :: () => [a] -> [a]
+ Numeric.Units.Dimensional.Prelude: take :: () => Int -> [a] -> [a]
+ Numeric.Units.Dimensional.Prelude: takeWhile :: () => (a -> Bool) -> [a] -> [a]
+ Numeric.Units.Dimensional.Prelude: tan :: Floating a => Dimensionless a -> Dimensionless a
+ Numeric.Units.Dimensional.Prelude: tanh :: Floating a => Dimensionless a -> Dimensionless a
+ Numeric.Units.Dimensional.Prelude: tau :: Floating a => Dimensionless a
+ Numeric.Units.Dimensional.Prelude: toEnum :: Enum a => Int -> a
+ Numeric.Units.Dimensional.Prelude: toInteger :: Integral a => a -> Integer
+ Numeric.Units.Dimensional.Prelude: toRational :: Real a => a -> Rational
+ Numeric.Units.Dimensional.Prelude: traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)
+ Numeric.Units.Dimensional.Prelude: truncate :: (RealFrac a, Integral b) => a -> b
+ Numeric.Units.Dimensional.Prelude: type AmountOfSubstance = Quantity DAmountOfSubstance
+ Numeric.Units.Dimensional.Prelude: type Cbrt d = NRoot d 'Pos3
+ Numeric.Units.Dimensional.Prelude: type DAmountOfSubstance = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero
+ Numeric.Units.Dimensional.Prelude: type DElectricCurrent = 'Dim 'Zero 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Prelude: type DLength = 'Dim 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Prelude: type DLuminousIntensity = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1
+ Numeric.Units.Dimensional.Prelude: type DMass = 'Dim 'Zero 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Prelude: type DOne = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Prelude: type DThermodynamicTemperature = 'Dim 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero 'Zero
+ Numeric.Units.Dimensional.Prelude: type DTime = 'Dim 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Prelude: type Dimensionless = Quantity DOne
+ Numeric.Units.Dimensional.Prelude: type ElectricCurrent = Quantity DElectricCurrent
+ Numeric.Units.Dimensional.Prelude: type FilePath = String
+ Numeric.Units.Dimensional.Prelude: type IOError = IOException
+ Numeric.Units.Dimensional.Prelude: type KnownDimension (d :: Dimension) = HasDimension (Proxy d)
+ Numeric.Units.Dimensional.Prelude: type Length = Quantity DLength
+ Numeric.Units.Dimensional.Prelude: type LuminousIntensity = Quantity DLuminousIntensity
+ Numeric.Units.Dimensional.Prelude: type Mass = Quantity DMass
+ Numeric.Units.Dimensional.Prelude: type Quantity = SQuantity One
+ Numeric.Units.Dimensional.Prelude: type Rational = Ratio Integer
+ Numeric.Units.Dimensional.Prelude: type ReadS a = String -> [(a, String)]
+ Numeric.Units.Dimensional.Prelude: type Recip (d :: Dimension) = DOne / d
+ Numeric.Units.Dimensional.Prelude: type ShowS = String -> String
+ Numeric.Units.Dimensional.Prelude: type Sqrt d = NRoot d 'Pos2
+ Numeric.Units.Dimensional.Prelude: type String = [Char]
+ Numeric.Units.Dimensional.Prelude: type ThermodynamicTemperature = Quantity DThermodynamicTemperature
+ Numeric.Units.Dimensional.Prelude: type Time = Quantity DTime
+ Numeric.Units.Dimensional.Prelude: type Unit (m :: Metricality) = Dimensional ( 'DUnit m)
+ Numeric.Units.Dimensional.Prelude: type family (a :: Dimension) * (b :: Dimension)
+ Numeric.Units.Dimensional.Prelude: uncurry :: () => (a -> b -> c) -> (a, b) -> c
+ Numeric.Units.Dimensional.Prelude: undefined :: HasCallStack => a
+ Numeric.Units.Dimensional.Prelude: unlines :: [String] -> String
+ Numeric.Units.Dimensional.Prelude: until :: () => (a -> Bool) -> (a -> a) -> a -> a
+ Numeric.Units.Dimensional.Prelude: unwords :: [String] -> String
+ Numeric.Units.Dimensional.Prelude: unzip :: () => [(a, b)] -> ([a], [b])
+ Numeric.Units.Dimensional.Prelude: unzip3 :: () => [(a, b, c)] -> ([a], [b], [c])
+ Numeric.Units.Dimensional.Prelude: userError :: String -> IOError
+ Numeric.Units.Dimensional.Prelude: weaken :: Unit m d a -> Unit 'NonMetric d a
+ Numeric.Units.Dimensional.Prelude: words :: String -> [String]
+ Numeric.Units.Dimensional.Prelude: writeFile :: FilePath -> String -> IO ()
+ Numeric.Units.Dimensional.Prelude: zero :: Proxy Zero
+ Numeric.Units.Dimensional.Prelude: zip :: () => [a] -> [b] -> [(a, b)]
+ Numeric.Units.Dimensional.Prelude: zip3 :: () => [a] -> [b] -> [c] -> [(a, b, c)]
+ Numeric.Units.Dimensional.Prelude: zipWith :: () => (a -> b -> c) -> [a] -> [b] -> [c]
+ Numeric.Units.Dimensional.Prelude: zipWith3 :: () => (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
+ Numeric.Units.Dimensional.Prelude: }
+ Numeric.Units.Dimensional.Variants: infixl 7 *
+ Numeric.Units.Dimensional.Variants: type family Weaken (v :: Variant) :: Variant
- Numeric.Units.Dimensional: (*~) :: (Num a) => a -> Unit m d a -> Quantity d a
+ Numeric.Units.Dimensional: (*~) :: Num a => a -> Unit m d a -> Quantity d a
- Numeric.Units.Dimensional: _1 :: (Num a) => Dimensionless a
+ Numeric.Units.Dimensional: _1 :: Num a => Dimensionless a
- Numeric.Units.Dimensional: _2 :: (Num a) => Dimensionless a
+ Numeric.Units.Dimensional: _2 :: Num a => Dimensionless a
- Numeric.Units.Dimensional: _3 :: (Num a) => Dimensionless a
+ Numeric.Units.Dimensional: _3 :: Num a => Dimensionless a
- Numeric.Units.Dimensional: _4 :: (Num a) => Dimensionless a
+ Numeric.Units.Dimensional: _4 :: Num a => Dimensionless a
- Numeric.Units.Dimensional: _5 :: (Num a) => Dimensionless a
+ Numeric.Units.Dimensional: _5 :: Num a => Dimensionless a
- Numeric.Units.Dimensional: _6 :: (Num a) => Dimensionless a
+ Numeric.Units.Dimensional: _6 :: Num a => Dimensionless a
- Numeric.Units.Dimensional: _7 :: (Num a) => Dimensionless a
+ Numeric.Units.Dimensional: _7 :: Num a => Dimensionless a
- Numeric.Units.Dimensional: _8 :: (Num a) => Dimensionless a
+ Numeric.Units.Dimensional: _8 :: Num a => Dimensionless a
- Numeric.Units.Dimensional: _9 :: (Num a) => Dimensionless a
+ Numeric.Units.Dimensional: _9 :: Num a => Dimensionless a
- Numeric.Units.Dimensional: asLens :: (Fractional a) => Unit m d a -> (forall f. Functor f => (a -> f a) -> Quantity d a -> f (Quantity d a))
+ Numeric.Units.Dimensional: asLens :: Fractional a => Unit m d a -> forall f. Functor f => (a -> f a) -> Quantity d a -> f (Quantity d a)
- Numeric.Units.Dimensional: atan2 :: (RealFloat a) => Quantity d a -> Quantity d a -> Dimensionless a
+ Numeric.Units.Dimensional: atan2 :: RealFloat a => Quantity d a -> Quantity d a -> Dimensionless a
- Numeric.Units.Dimensional: class KnownVariant (v :: Variant) where {
+ Numeric.Units.Dimensional: class KnownVariant (v :: Variant)
- Numeric.Units.Dimensional: data family Dimensional v :: Dimension -> * -> *;
+ Numeric.Units.Dimensional: data family Dimensional v :: Dimension -> Type -> Type
- Numeric.Units.Dimensional: recip :: (Fractional a) => Quantity d a -> Quantity (Recip d) a
+ Numeric.Units.Dimensional: recip :: Fractional a => Quantity d a -> Quantity (Recip d) a
- Numeric.Units.Dimensional: type DAmountOfSubstance = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero
+ Numeric.Units.Dimensional: type DAmountOfSubstance = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero
- Numeric.Units.Dimensional: type DElectricCurrent = 'Dim 'Zero 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional: type DElectricCurrent = 'Dim 'Zero 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional: type DLength = 'Dim 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional: type DLength = 'Dim 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional: type DLuminousIntensity = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1
+ Numeric.Units.Dimensional: type DLuminousIntensity = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1
- Numeric.Units.Dimensional: type DThermodynamicTemperature = 'Dim 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero 'Zero
+ Numeric.Units.Dimensional: type DThermodynamicTemperature = 'Dim 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero 'Zero
- Numeric.Units.Dimensional.Coercion: coerce :: Coercible * a b => a -> b
+ Numeric.Units.Dimensional.Coercion: coerce :: Coercible a b => a -> b
- Numeric.Units.Dimensional.Dimensions.TermLevel: dynamicDimension :: (HasDynamicDimension a, (HasDimension a)) => a -> DynamicDimension
+ Numeric.Units.Dimensional.Dimensions.TermLevel: dynamicDimension :: (HasDynamicDimension a, HasDimension a) => a -> DynamicDimension
- Numeric.Units.Dimensional.Dimensions.TermLevel: hasSomeDimension :: (HasDynamicDimension a) => a -> Bool
+ Numeric.Units.Dimensional.Dimensions.TermLevel: hasSomeDimension :: HasDynamicDimension a => a -> Bool
- Numeric.Units.Dimensional.Dimensions.TermLevel: isCompatibleWith :: (HasDynamicDimension a) => a -> Dimension' -> Bool
+ Numeric.Units.Dimensional.Dimensions.TermLevel: isCompatibleWith :: HasDynamicDimension a => a -> Dimension' -> Bool
- Numeric.Units.Dimensional.Dimensions.TypeLevel: type DAmountOfSubstance = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero
+ Numeric.Units.Dimensional.Dimensions.TypeLevel: type DAmountOfSubstance = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero
- Numeric.Units.Dimensional.Dimensions.TypeLevel: type DElectricCurrent = 'Dim 'Zero 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Dimensions.TypeLevel: type DElectricCurrent = 'Dim 'Zero 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Dimensions.TypeLevel: type DLength = 'Dim 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Dimensions.TypeLevel: type DLength = 'Dim 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Dimensions.TypeLevel: type DLuminousIntensity = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1
+ Numeric.Units.Dimensional.Dimensions.TypeLevel: type DLuminousIntensity = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1
- Numeric.Units.Dimensional.Dimensions.TypeLevel: type DThermodynamicTemperature = 'Dim 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero 'Zero
+ Numeric.Units.Dimensional.Dimensions.TypeLevel: type DThermodynamicTemperature = 'Dim 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero 'Zero
- Numeric.Units.Dimensional.Dynamic: (^) :: (Integral a) => AnyUnit -> a -> AnyUnit
+ Numeric.Units.Dimensional.Dynamic: (^) :: Integral a => AnyUnit -> a -> AnyUnit
- Numeric.Units.Dimensional.Dynamic: class Demotable (q :: * -> *)
+ Numeric.Units.Dimensional.Dynamic: class Demotable (q :: Type -> Type)
- Numeric.Units.Dimensional.Dynamic: class Promotable (q :: * -> *)
+ Numeric.Units.Dimensional.Dynamic: class Promotable (q :: Type -> Type)
- Numeric.Units.Dimensional.Dynamic: demoteUnit :: forall m d a. (KnownDimension d) => Unit m d a -> AnyUnit
+ Numeric.Units.Dimensional.Dynamic: demoteUnit :: forall m d a. KnownDimension d => Unit m d a -> AnyUnit
- Numeric.Units.Dimensional.Dynamic: demoteUnit' :: (KnownDimension d) => Unit m d ExactPi -> AnyUnit
+ Numeric.Units.Dimensional.Dynamic: demoteUnit' :: KnownDimension d => Unit m d ExactPi -> AnyUnit
- Numeric.Units.Dimensional.Dynamic: dynamicDimension :: (HasDynamicDimension a, (HasDimension a)) => a -> DynamicDimension
+ Numeric.Units.Dimensional.Dynamic: dynamicDimension :: (HasDynamicDimension a, HasDimension a) => a -> DynamicDimension
- Numeric.Units.Dimensional.Dynamic: polydimensionalZero :: (Num a) => DynQuantity a
+ Numeric.Units.Dimensional.Dynamic: polydimensionalZero :: Num a => DynQuantity a
- Numeric.Units.Dimensional.Dynamic: promoteUnit :: forall d. (KnownDimension d) => AnyUnit -> Maybe (Unit 'NonMetric d ExactPi)
+ Numeric.Units.Dimensional.Dynamic: promoteUnit :: forall d. KnownDimension d => AnyUnit -> Maybe (Unit 'NonMetric d ExactPi)
- Numeric.Units.Dimensional.FixedPoint: (+) :: (Num a) => SQuantity s d a -> SQuantity s d a -> SQuantity s d a
+ Numeric.Units.Dimensional.FixedPoint: (+) :: Num a => SQuantity s d a -> SQuantity s d a -> SQuantity s d a
- Numeric.Units.Dimensional.FixedPoint: (-) :: (Num a) => SQuantity s d a -> SQuantity s d a -> SQuantity s d a
+ Numeric.Units.Dimensional.FixedPoint: (-) :: Num a => SQuantity s d a -> SQuantity s d a -> SQuantity s d a
- Numeric.Units.Dimensional.FixedPoint: abs :: (Num a) => SQuantity s d a -> SQuantity s d a
+ Numeric.Units.Dimensional.FixedPoint: abs :: Num a => SQuantity s d a -> SQuantity s d a
- Numeric.Units.Dimensional.FixedPoint: class KnownVariant (v :: Variant) where {
+ Numeric.Units.Dimensional.FixedPoint: class KnownVariant (v :: Variant)
- Numeric.Units.Dimensional.FixedPoint: data family Dimensional v :: Dimension -> * -> *;
+ Numeric.Units.Dimensional.FixedPoint: data family Dimensional v :: Dimension -> Type -> Type
- Numeric.Units.Dimensional.FixedPoint: epsilon :: (Integral a) => SQuantity s d a
+ Numeric.Units.Dimensional.FixedPoint: epsilon :: Integral a => SQuantity s d a
- Numeric.Units.Dimensional.FixedPoint: negate :: (Num a) => SQuantity s d a -> SQuantity s d a
+ Numeric.Units.Dimensional.FixedPoint: negate :: Num a => SQuantity s d a -> SQuantity s d a
- Numeric.Units.Dimensional.FixedPoint: type DAmountOfSubstance = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero
+ Numeric.Units.Dimensional.FixedPoint: type DAmountOfSubstance = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero
- Numeric.Units.Dimensional.FixedPoint: type DElectricCurrent = 'Dim 'Zero 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.FixedPoint: type DElectricCurrent = 'Dim 'Zero 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.FixedPoint: type DLength = 'Dim 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.FixedPoint: type DLength = 'Dim 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.FixedPoint: type DLuminousIntensity = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1
+ Numeric.Units.Dimensional.FixedPoint: type DLuminousIntensity = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1
- Numeric.Units.Dimensional.FixedPoint: type DThermodynamicTemperature = 'Dim 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero 'Zero
+ Numeric.Units.Dimensional.FixedPoint: type DThermodynamicTemperature = 'Dim 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero 'Zero
- Numeric.Units.Dimensional.NonSI: acre :: (Fractional a) => Unit 'NonMetric DArea a
+ Numeric.Units.Dimensional.NonSI: acre :: Fractional a => Unit 'NonMetric DArea a
- Numeric.Units.Dimensional.NonSI: angstrom :: (Fractional a) => Unit 'NonMetric DLength a
+ Numeric.Units.Dimensional.NonSI: angstrom :: Fractional a => Unit 'NonMetric DLength a
- Numeric.Units.Dimensional.NonSI: atmosphere :: (Num a) => Unit 'NonMetric DPressure a
+ Numeric.Units.Dimensional.NonSI: atmosphere :: Num a => Unit 'NonMetric DPressure a
- Numeric.Units.Dimensional.NonSI: bar :: (Num a) => Unit 'Metric DPressure a
+ Numeric.Units.Dimensional.NonSI: bar :: Num a => Unit 'Metric DPressure a
- Numeric.Units.Dimensional.NonSI: degreeFahrenheit :: (Fractional a) => Unit 'NonMetric DThermodynamicTemperature a
+ Numeric.Units.Dimensional.NonSI: degreeFahrenheit :: Fractional a => Unit 'NonMetric DThermodynamicTemperature a
- Numeric.Units.Dimensional.NonSI: degreeRankine :: (Fractional a) => Unit 'NonMetric DThermodynamicTemperature a
+ Numeric.Units.Dimensional.NonSI: degreeRankine :: Fractional a => Unit 'NonMetric DThermodynamicTemperature a
- Numeric.Units.Dimensional.NonSI: gauss :: (Fractional a) => Unit 'NonMetric DMagneticFluxDensity a
+ Numeric.Units.Dimensional.NonSI: gauss :: Fractional a => Unit 'NonMetric DMagneticFluxDensity a
- Numeric.Units.Dimensional.NonSI: imperialCup :: (Fractional a) => Unit 'NonMetric DVolume a
+ Numeric.Units.Dimensional.NonSI: imperialCup :: Fractional a => Unit 'NonMetric DVolume a
- Numeric.Units.Dimensional.NonSI: imperialFluidOunce :: (Fractional a) => Unit 'NonMetric DVolume a
+ Numeric.Units.Dimensional.NonSI: imperialFluidOunce :: Fractional a => Unit 'NonMetric DVolume a
- Numeric.Units.Dimensional.NonSI: imperialGallon :: (Fractional a) => Unit 'NonMetric DVolume a
+ Numeric.Units.Dimensional.NonSI: imperialGallon :: Fractional a => Unit 'NonMetric DVolume a
- Numeric.Units.Dimensional.NonSI: imperialGill :: (Fractional a) => Unit 'NonMetric DVolume a
+ Numeric.Units.Dimensional.NonSI: imperialGill :: Fractional a => Unit 'NonMetric DVolume a
- Numeric.Units.Dimensional.NonSI: imperialPint :: (Fractional a) => Unit 'NonMetric DVolume a
+ Numeric.Units.Dimensional.NonSI: imperialPint :: Fractional a => Unit 'NonMetric DVolume a
- Numeric.Units.Dimensional.NonSI: imperialQuart :: (Fractional a) => Unit 'NonMetric DVolume a
+ Numeric.Units.Dimensional.NonSI: imperialQuart :: Fractional a => Unit 'NonMetric DVolume a
- Numeric.Units.Dimensional.NonSI: inHg :: (Fractional a) => Unit 'NonMetric DPressure a
+ Numeric.Units.Dimensional.NonSI: inHg :: Fractional a => Unit 'NonMetric DPressure a
- Numeric.Units.Dimensional.NonSI: inHg_NIST :: (Fractional a) => Unit 'NonMetric DPressure a
+ Numeric.Units.Dimensional.NonSI: inHg_NIST :: Fractional a => Unit 'NonMetric DPressure a
- Numeric.Units.Dimensional.NonSI: inHg_UCUM :: (Fractional a) => Unit 'NonMetric DPressure a
+ Numeric.Units.Dimensional.NonSI: inHg_UCUM :: Fractional a => Unit 'NonMetric DPressure a
- Numeric.Units.Dimensional.NonSI: knot :: (Fractional a) => Unit 'NonMetric DVelocity a
+ Numeric.Units.Dimensional.NonSI: knot :: Fractional a => Unit 'NonMetric DVelocity a
- Numeric.Units.Dimensional.NonSI: mile :: (Fractional a) => Unit 'NonMetric DLength a
+ Numeric.Units.Dimensional.NonSI: mile :: Fractional a => Unit 'NonMetric DLength a
- Numeric.Units.Dimensional.NonSI: mmHg :: (Fractional a) => Unit 'NonMetric DPressure a
+ Numeric.Units.Dimensional.NonSI: mmHg :: Fractional a => Unit 'NonMetric DPressure a
- Numeric.Units.Dimensional.NonSI: nauticalMile :: (Num a) => Unit 'NonMetric DLength a
+ Numeric.Units.Dimensional.NonSI: nauticalMile :: Num a => Unit 'NonMetric DLength a
- Numeric.Units.Dimensional.NonSI: rad :: (Fractional a) => Unit 'Metric DAbsorbedDose a
+ Numeric.Units.Dimensional.NonSI: rad :: Fractional a => Unit 'Metric DAbsorbedDose a
- Numeric.Units.Dimensional.NonSI: revolution :: (Floating a) => Unit 'NonMetric DOne a
+ Numeric.Units.Dimensional.NonSI: revolution :: Floating a => Unit 'NonMetric DOne a
- Numeric.Units.Dimensional.NonSI: solid :: (Floating a) => Unit 'NonMetric DOne a
+ Numeric.Units.Dimensional.NonSI: solid :: Floating a => Unit 'NonMetric DOne a
- Numeric.Units.Dimensional.NonSI: stokes :: (Fractional a) => Unit 'Metric DKinematicViscosity a
+ Numeric.Units.Dimensional.NonSI: stokes :: Fractional a => Unit 'Metric DKinematicViscosity a
- Numeric.Units.Dimensional.NonSI: teaspoon :: (Fractional a) => Unit 'NonMetric DVolume a
+ Numeric.Units.Dimensional.NonSI: teaspoon :: Fractional a => Unit 'NonMetric DVolume a
- Numeric.Units.Dimensional.NonSI: technicalAtmosphere :: (Fractional a) => Unit 'NonMetric DPressure a
+ Numeric.Units.Dimensional.NonSI: technicalAtmosphere :: Fractional a => Unit 'NonMetric DPressure a
- Numeric.Units.Dimensional.NonSI: torr :: (Fractional a) => Unit 'NonMetric DPressure a
+ Numeric.Units.Dimensional.NonSI: torr :: Fractional a => Unit 'NonMetric DPressure a
- Numeric.Units.Dimensional.NonSI: usCup :: (Fractional a) => Unit 'NonMetric DVolume a
+ Numeric.Units.Dimensional.NonSI: usCup :: Fractional a => Unit 'NonMetric DVolume a
- Numeric.Units.Dimensional.NonSI: usFluidOunce :: (Fractional a) => Unit 'NonMetric DVolume a
+ Numeric.Units.Dimensional.NonSI: usFluidOunce :: Fractional a => Unit 'NonMetric DVolume a
- Numeric.Units.Dimensional.NonSI: usGallon :: (Fractional a) => Unit 'NonMetric DVolume a
+ Numeric.Units.Dimensional.NonSI: usGallon :: Fractional a => Unit 'NonMetric DVolume a
- Numeric.Units.Dimensional.NonSI: usGill :: (Fractional a) => Unit 'NonMetric DVolume a
+ Numeric.Units.Dimensional.NonSI: usGill :: Fractional a => Unit 'NonMetric DVolume a
- Numeric.Units.Dimensional.NonSI: usPint :: (Fractional a) => Unit 'NonMetric DVolume a
+ Numeric.Units.Dimensional.NonSI: usPint :: Fractional a => Unit 'NonMetric DVolume a
- Numeric.Units.Dimensional.NonSI: usQuart :: (Fractional a) => Unit 'NonMetric DVolume a
+ Numeric.Units.Dimensional.NonSI: usQuart :: Fractional a => Unit 'NonMetric DVolume a
- Numeric.Units.Dimensional.NonSI: usSurveyAcre :: (Fractional a) => Unit 'NonMetric DArea a
+ Numeric.Units.Dimensional.NonSI: usSurveyAcre :: Fractional a => Unit 'NonMetric DArea a
- Numeric.Units.Dimensional.NonSI: usSurveyMile :: (Fractional a) => Unit 'NonMetric DLength a
+ Numeric.Units.Dimensional.NonSI: usSurveyMile :: Fractional a => Unit 'NonMetric DLength a
- Numeric.Units.Dimensional.NonSI: usSurveyYard :: (Fractional a) => Unit 'NonMetric DLength a
+ Numeric.Units.Dimensional.NonSI: usSurveyYard :: Fractional a => Unit 'NonMetric DLength a
- Numeric.Units.Dimensional.NonSI: yard :: (Fractional a) => Unit 'NonMetric DLength a
+ Numeric.Units.Dimensional.NonSI: yard :: Fractional a => Unit 'NonMetric DLength a
- Numeric.Units.Dimensional.Quantities: type DAbsorbedDose = 'Dim 'Pos2 'Zero 'Neg2 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DAbsorbedDose = 'Dim 'Pos2 'Zero 'Neg2 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DAbsorbedDoseRate = 'Dim 'Pos2 'Zero 'Neg3 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DAbsorbedDoseRate = 'Dim 'Pos2 'Zero 'Neg3 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DAcceleration = 'Dim 'Pos1 'Zero 'Neg2 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DAcceleration = 'Dim 'Pos1 'Zero 'Neg2 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DAmountOfSubstanceConcentration = 'Dim 'Neg3 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero
+ Numeric.Units.Dimensional.Quantities: type DAmountOfSubstanceConcentration = 'Dim 'Neg3 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero
- Numeric.Units.Dimensional.Quantities: type DAngularAcceleration = 'Dim 'Zero 'Zero 'Neg2 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DAngularAcceleration = 'Dim 'Zero 'Zero 'Neg2 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DAngularMomentum = 'Dim 'Pos2 'Pos1 'Neg1 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DAngularMomentum = 'Dim 'Pos2 'Pos1 'Neg1 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DCapacitance = 'Dim 'Neg2 'Neg1 'Pos4 'Pos2 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DCapacitance = 'Dim 'Neg2 'Neg1 'Pos4 'Pos2 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DCatalyticActivity = 'Dim 'Zero 'Zero 'Neg1 'Zero 'Zero 'Pos1 'Zero
+ Numeric.Units.Dimensional.Quantities: type DCatalyticActivity = 'Dim 'Zero 'Zero 'Neg1 'Zero 'Zero 'Pos1 'Zero
- Numeric.Units.Dimensional.Quantities: type DCurrentDensity = 'Dim 'Neg2 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DCurrentDensity = 'Dim 'Neg2 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DDynamicViscosity = 'Dim 'Neg1 'Pos1 'Neg1 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DDynamicViscosity = 'Dim 'Neg1 'Pos1 'Neg1 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DElectricCharge = 'Dim 'Zero 'Zero 'Pos1 'Pos1 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DElectricCharge = 'Dim 'Zero 'Zero 'Pos1 'Pos1 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DElectricChargeDensity = 'Dim 'Neg3 'Zero 'Pos1 'Pos1 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DElectricChargeDensity = 'Dim 'Neg3 'Zero 'Pos1 'Pos1 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DElectricConductance = 'Dim 'Neg2 'Neg1 'Pos3 'Pos2 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DElectricConductance = 'Dim 'Neg2 'Neg1 'Pos3 'Pos2 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DElectricFieldStrength = 'Dim 'Pos1 'Pos1 'Neg3 'Neg1 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DElectricFieldStrength = 'Dim 'Pos1 'Pos1 'Neg3 'Neg1 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DElectricFluxDensity = 'Dim 'Neg2 'Zero 'Pos1 'Pos1 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DElectricFluxDensity = 'Dim 'Neg2 'Zero 'Pos1 'Pos1 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DElectricPotential = 'Dim 'Pos2 'Pos1 'Neg3 'Neg1 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DElectricPotential = 'Dim 'Pos2 'Pos1 'Neg3 'Neg1 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DElectricResistance = 'Dim 'Pos2 'Pos1 'Neg3 'Neg2 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DElectricResistance = 'Dim 'Pos2 'Pos1 'Neg3 'Neg2 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DEnergy = 'Dim 'Pos2 'Pos1 'Neg2 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DEnergy = 'Dim 'Pos2 'Pos1 'Neg2 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DExposure = 'Dim 'Zero 'Neg1 'Pos1 'Pos1 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DExposure = 'Dim 'Zero 'Neg1 'Pos1 'Pos1 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DFirstMassMoment = 'Dim 'Pos1 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DFirstMassMoment = 'Dim 'Pos1 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DForce = 'Dim 'Pos1 'Pos1 'Neg2 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DForce = 'Dim 'Pos1 'Pos1 'Neg2 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DFrequency = 'Dim 'Zero 'Zero 'Neg1 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DFrequency = 'Dim 'Zero 'Zero 'Neg1 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DGravitationalParameter = 'Dim 'Pos3 'Zero 'Neg2 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DGravitationalParameter = 'Dim 'Pos3 'Zero 'Neg2 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DHeatCapacity = 'Dim 'Pos2 'Pos1 'Neg2 'Zero 'Neg1 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DHeatCapacity = 'Dim 'Pos2 'Pos1 'Neg2 'Zero 'Neg1 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DHeatFluxDensity = 'Dim 'Zero 'Pos1 'Neg3 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DHeatFluxDensity = 'Dim 'Zero 'Pos1 'Neg3 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DHeatTransferCoefficient = 'Dim 'Zero 'Pos1 'Neg3 'Zero 'Neg1 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DHeatTransferCoefficient = 'Dim 'Zero 'Pos1 'Neg3 'Zero 'Neg1 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DIlluminance = 'Dim 'Neg2 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1
+ Numeric.Units.Dimensional.Quantities: type DIlluminance = 'Dim 'Neg2 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1
- Numeric.Units.Dimensional.Quantities: type DImpulse = 'Dim 'Pos1 'Pos1 'Neg1 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DImpulse = 'Dim 'Pos1 'Pos1 'Neg1 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DInductance = 'Dim 'Pos2 'Pos1 'Neg2 'Neg2 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DInductance = 'Dim 'Pos2 'Pos1 'Neg2 'Neg2 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DKinematicViscosity = 'Dim 'Pos2 'Zero 'Neg1 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DKinematicViscosity = 'Dim 'Pos2 'Zero 'Neg1 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DLuminance = 'Dim 'Neg2 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1
+ Numeric.Units.Dimensional.Quantities: type DLuminance = 'Dim 'Neg2 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1
- Numeric.Units.Dimensional.Quantities: type DMagneticFieldStrength = 'Dim 'Neg1 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DMagneticFieldStrength = 'Dim 'Neg1 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DMagneticFlux = 'Dim 'Pos2 'Pos1 'Neg2 'Neg1 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DMagneticFlux = 'Dim 'Pos2 'Pos1 'Neg2 'Neg1 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DMagneticFluxDensity = 'Dim 'Zero 'Pos1 'Neg2 'Neg1 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DMagneticFluxDensity = 'Dim 'Zero 'Pos1 'Neg2 'Neg1 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DMassDensity = 'Dim 'Neg3 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DMassDensity = 'Dim 'Neg3 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DMassFlow = 'Dim 'Zero 'Pos1 'Neg1 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DMassFlow = 'Dim 'Zero 'Pos1 'Neg1 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DMolarEnergy = 'Dim 'Pos2 'Pos1 'Neg2 'Zero 'Zero 'Neg1 'Zero
+ Numeric.Units.Dimensional.Quantities: type DMolarEnergy = 'Dim 'Pos2 'Pos1 'Neg2 'Zero 'Zero 'Neg1 'Zero
- Numeric.Units.Dimensional.Quantities: type DMolarEntropy = 'Dim 'Pos2 'Pos1 'Neg2 'Zero 'Neg1 'Neg1 'Zero
+ Numeric.Units.Dimensional.Quantities: type DMolarEntropy = 'Dim 'Pos2 'Pos1 'Neg2 'Zero 'Neg1 'Neg1 'Zero
- Numeric.Units.Dimensional.Quantities: type DMomentOfInertia = 'Dim 'Pos2 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DMomentOfInertia = 'Dim 'Pos2 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DPermeability = 'Dim 'Pos1 'Pos1 'Neg2 'Neg2 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DPermeability = 'Dim 'Pos1 'Pos1 'Neg2 'Neg2 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DPermittivity = 'Dim 'Neg3 'Neg1 'Pos4 'Pos2 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DPermittivity = 'Dim 'Neg3 'Neg1 'Pos4 'Pos2 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DPower = 'Dim 'Pos2 'Pos1 'Neg3 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DPower = 'Dim 'Pos2 'Pos1 'Neg3 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DPressure = 'Dim 'Neg1 'Pos1 'Neg2 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DPressure = 'Dim 'Neg1 'Pos1 'Neg2 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DSpecificHeatCapacity = 'Dim 'Pos2 'Zero 'Neg2 'Zero 'Neg1 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DSpecificHeatCapacity = 'Dim 'Pos2 'Zero 'Neg2 'Zero 'Neg1 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DSpecificVolume = 'Dim 'Pos3 'Neg1 'Zero 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DSpecificVolume = 'Dim 'Pos3 'Neg1 'Zero 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DSurfaceTension = 'Dim 'Zero 'Pos1 'Neg2 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DSurfaceTension = 'Dim 'Zero 'Pos1 'Neg2 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DThermalConductance = 'Dim 'Pos2 'Pos1 'Neg3 'Zero 'Neg1 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DThermalConductance = 'Dim 'Pos2 'Pos1 'Neg3 'Zero 'Neg1 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DThermalConductivity = 'Dim 'Pos1 'Pos1 'Neg3 'Zero 'Neg1 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DThermalConductivity = 'Dim 'Pos1 'Pos1 'Neg3 'Zero 'Neg1 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DThermalInsulance = 'Dim 'Zero 'Neg1 'Pos3 'Zero 'Pos1 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DThermalInsulance = 'Dim 'Zero 'Neg1 'Pos3 'Zero 'Pos1 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DThermalResistance = 'Dim 'Neg2 'Neg1 'Pos3 'Zero 'Pos1 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DThermalResistance = 'Dim 'Neg2 'Neg1 'Pos3 'Zero 'Pos1 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DThermalResistivity = 'Dim 'Neg1 'Neg1 'Pos3 'Zero 'Pos1 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DThermalResistivity = 'Dim 'Neg1 'Neg1 'Pos3 'Zero 'Pos1 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DVelocity = 'Dim 'Pos1 'Zero 'Neg1 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DVelocity = 'Dim 'Pos1 'Zero 'Neg1 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DVolume = 'Dim 'Pos3 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DVolume = 'Dim 'Pos3 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DVolumeFlow = 'Dim 'Pos3 'Zero 'Neg1 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DVolumeFlow = 'Dim 'Pos3 'Zero 'Neg1 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.Quantities: type DWaveNumber = 'Dim 'Neg1 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
+ Numeric.Units.Dimensional.Quantities: type DWaveNumber = 'Dim 'Neg1 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
- Numeric.Units.Dimensional.SIUnits: applyPrefix :: (Fractional a) => Prefix -> Unit 'Metric d a -> Unit 'NonMetric d a
+ Numeric.Units.Dimensional.SIUnits: applyPrefix :: Fractional a => Prefix -> Unit 'Metric d a -> Unit 'NonMetric d a

Files

CHANGELOG.md view
@@ -1,3 +1,7 @@+1.2 (2018-11)+-------------+* Add `NoStarIsType` extension and import `Data.Kind.Type` for [GHC 8.6 compitbility](https://github.com/ghc-proposals/ghc-proposals/blob/05721788de9ab6538def68c3c2c9dec50c9f24a8/proposals/0020-no-type-in-type.rst). Abandon compatibility with GHC < 8.+ 1.1 (2018-03) ------------- * Added `Semigroup` instances for [GHC 8.4 compatibility](https://ghc.haskell.org/trac/ghc/wiki/Migration/8.4#SemigroupMonoidsuperclasses).
LICENSE view
@@ -1,31 +1,31 @@-Copyright (c) 2006-2018, Bjorn Buckwalter.-All rights reserved.--Redistribution and use in source and binary forms, with or without-modification, are permitted provided that the following conditions-are met:--  * Redistributions of source code must retain the above copyright-    notice, this list of conditions and the following disclaimer.--  * Redistributions in binary form must reproduce the above-    copyright notice, this list of conditions and the following-    disclaimer in the documentation and/or other materials provided-    with the distribution.--  * Neither the name of the copyright holder(s) nor the names of-    contributors may be used to endorse or promote products derived-    from this software without specific prior written permission.--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS-FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE-COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN-ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE-POSSIBILITY OF SUCH DAMAGE.+Copyright (c) 2006-2018, Bjorn Buckwalter.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above
+    copyright notice, this list of conditions and the following
+    disclaimer in the documentation and/or other materials provided
+    with the distribution.
+
+  * Neither the name of the copyright holder(s) nor the names of
+    contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
Setup.lhs view
@@ -1,3 +1,3 @@-#!/usr/bin/env runhaskell-> import Distribution.Simple+#!/usr/bin/env runhaskell
+> import Distribution.Simple
 > main = defaultMain
benchmarks/Main.hs view
@@ -1,19 +1,19 @@-{-# LANGUAGE NoImplicitPrelude #-}--module Main where--import Criterion.Main-import Numeric.Units.Dimensional.Prelude-import qualified Prelude as P--main :: IO ()-main = defaultMain [-         bench "RawArithmetic" $ nf rawArithmetic 1000-       , bench "Arithmetic" $ nf arithmetic 1000-       ]--rawArithmetic :: Int -> [Double]-rawArithmetic n = fmap (P./ 3.7) $ [1.0 .. fromIntegral n]--arithmetic :: Int -> [Density Double]-arithmetic n = fmap (/ (3.7 *~ cubic meter)) $ [1.0 .. fromIntegral n] *~~ kilo gram+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Main where
+
+import Criterion.Main
+import Numeric.Units.Dimensional.Prelude
+import qualified Prelude as P
+
+main :: IO ()
+main = defaultMain [
+         bench "RawArithmetic" $ nf rawArithmetic 1000
+       , bench "Arithmetic" $ nf arithmetic 1000
+       ]
+
+rawArithmetic :: Int -> [Double]
+rawArithmetic n = fmap (P./ 3.7) $ [1.0 .. fromIntegral n]
+
+arithmetic :: Int -> [Density Double]
+arithmetic n = fmap (/ (3.7 *~ cubic meter)) $ [1.0 .. fromIntegral n] *~~ kilo gram
dimensional.cabal view
@@ -1,5 +1,5 @@ name:                dimensional-version:             1.1+version:             1.2 license:             BSD3 license-file:        LICENSE copyright:           Bjorn Buckwalter 2006-2018@@ -12,7 +12,7 @@ synopsis:            Statically checked physical dimensions,                      using Type Families and Data Kinds. cabal-version:       >= 1.10-tested-with:         GHC == 7.8.4, GHC == 7.10.1, GHC == 7.10.2, GHC == 7.10.3, GHC == 8.0.1, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.1+tested-with:         GHC == 8.0.1, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.1 build-type:          Simple  description:@@ -30,7 +30,7 @@     rather than functional dependencies. This enables a number of features, including     improved support for unit names and quantities with statically-unknown dimensions. -    Requires GHC 7.8 or later.+    Requires GHC 8.0 or later.  extra-source-files:  README.md,                      CHANGELOG.md,@@ -52,6 +52,8 @@   hs-source-dirs:      src   default-language:    Haskell2010   default-extensions:  NoImplicitPrelude+  if impl(ghc >= 8.6)+    default-extensions: NoStarIsType   ghc-options:         -Wall   exposed-modules:     Numeric.Units.Dimensional,                        Numeric.Units.Dimensional.Coercion,@@ -78,6 +80,8 @@   hs-source-dirs:      tests   default-language:    Haskell2010   default-extensions:  NoImplicitPrelude+  if impl(ghc >= 8.6)+    default-extensions: NoStarIsType   other-modules:       Numeric.Units.DimensionalSpec                        Numeric.Units.Dimensional.DynamicSpec                        Numeric.Units.Dimensional.QuantitiesSpec@@ -86,6 +90,7 @@                        hspec,                        QuickCheck,                        base+  build-tool-depends: hspec-discover:hspec-discover == 2.*  test-suite doctests   type:                exitcode-stdio-1.0
examples/GM.lhs view
@@ -1,94 +1,94 @@--= GM calculation =--Several representation can be used to describe a satellite's orbit. Two-of the most popular are the cartesian state vector (position and-velocity vectors) and the keplerian elements. Conversion between the two-representations is fairly straight-forward but requires an assumption-to be made about the universal gravitational constant 'G' and the mass-'M' of the body the satellite is orbiting. In practice they are often-combined into a parameter "mu = GM" where the magnitude of 'mu' is-empirically better known that the magnitudes of 'G' and 'M' individually.--*The problem:* Given two representations of the same satellite orbit -- one-using the cartesian state vector and using keplerian elements, both at the-same epoch -- determine the value of 'mu' used to convert between the two.-{{{--> {-# LANGUAGE NegativeLiterals #-}-> module GM where--> import Numeric.Units.Dimensional.Prelude-> import qualified Prelude--}}}-The state vector describing the orbit at epoch.-{{{--> x     =   4383.9449203752        *~ kilo meter-> y     = -41940.917505092       *~ kilo meter-> z     =     22.790255916589      *~ kilo meter-> x_dot =      3.0575666627812     *~ (kilo meter / second)-> y_dot =      0.32047068607303    *~ (kilo meter / second)-> z_dot =      0.00084729371755294 *~ (kilo meter / second)--}}}-From the state vector we calculate the distance from the reference frame center at epoch and the velocity squared at epoch.-{{{--> r = sqrt (x ^ pos2 + y ^ pos2 + z ^ pos2)-> v = sqrt (x_dot ^ pos2 + y_dot ^ pos2 + z_dot ^ pos2)--}}}-The kinetic energy per unit mass at epoch is a function of the velocity.-{{{--> e_kin :: EnergyPerUnitMass Double-> e_kin = v ^ pos2 / _2--}}}-The only keplerian element we need for this calculation is the semi-major axis.-{{{--> semi_major_axis = 42165.221455 *~ kilo meter--}}}-The expression for 'mu' is obtained by solving the following equation system:--    e_pot = - mu / r,--    e_tot = - mu / 2a,--    e_tot = e_pot + e_kin,--which gives:--    mu = e_kin / (1 / r - 1 / 2a).--{{{--> mu = e_kin / (_1 / r - _1 / (_2 * semi_major_axis))--}}}-Wrap up with a main function showing the value of 'mu' in desired units.-{{{--> main = putStrLn $ "The value used for GM was " ++ show mu--}}}-Loading this module in 'ghci' and running 'main' produces the following output.-{{{-   ___         ___ _-  / _ \ /\  /\/ __(_)- / /_\// /_/ / /  | |      GHC Interactive, version 6.6.1, for Haskell 98.-/ /_\\/ __  / /___| |      http://www.haskell.org/ghc/-\____/\/ /_/\____/|_|      Type :? for help.--Loading package base ... linking ... done.-[1 of 1] Compiling GM               ( GM.lhs, interpreted )-Ok, modules loaded: GM.-*GM> main-Loading package dimensional-0.5 ... linking ... done.-The value used for GM was 3.986004400008003e14 m^3 s^-2-*GM>-}}}+
+= GM calculation =
+
+Several representation can be used to describe a satellite's orbit. Two
+of the most popular are the cartesian state vector (position and
+velocity vectors) and the keplerian elements. Conversion between the two
+representations is fairly straight-forward but requires an assumption
+to be made about the universal gravitational constant 'G' and the mass
+'M' of the body the satellite is orbiting. In practice they are often
+combined into a parameter "mu = GM" where the magnitude of 'mu' is
+empirically better known that the magnitudes of 'G' and 'M' individually.
+
+*The problem:* Given two representations of the same satellite orbit -- one
+using the cartesian state vector and using keplerian elements, both at the
+same epoch -- determine the value of 'mu' used to convert between the two.
+{{{
+
+> {-# LANGUAGE NegativeLiterals #-}
+> module GM where
+
+> import Numeric.Units.Dimensional.Prelude
+> import qualified Prelude
+
+}}}
+The state vector describing the orbit at epoch.
+{{{
+
+> x     =   4383.9449203752        *~ kilo meter
+> y     = -41940.917505092       *~ kilo meter
+> z     =     22.790255916589      *~ kilo meter
+> x_dot =      3.0575666627812     *~ (kilo meter / second)
+> y_dot =      0.32047068607303    *~ (kilo meter / second)
+> z_dot =      0.00084729371755294 *~ (kilo meter / second)
+
+}}}
+From the state vector we calculate the distance from the reference frame center at epoch and the velocity squared at epoch.
+{{{
+
+> r = sqrt (x ^ pos2 + y ^ pos2 + z ^ pos2)
+> v = sqrt (x_dot ^ pos2 + y_dot ^ pos2 + z_dot ^ pos2)
+
+}}}
+The kinetic energy per unit mass at epoch is a function of the velocity.
+{{{
+
+> e_kin :: EnergyPerUnitMass Double
+> e_kin = v ^ pos2 / _2
+
+}}}
+The only keplerian element we need for this calculation is the semi-major axis.
+{{{
+
+> semi_major_axis = 42165.221455 *~ kilo meter
+
+}}}
+The expression for 'mu' is obtained by solving the following equation system:
+
+    e_pot = - mu / r,
+
+    e_tot = - mu / 2a,
+
+    e_tot = e_pot + e_kin,
+
+which gives:
+
+    mu = e_kin / (1 / r - 1 / 2a).
+
+{{{
+
+> mu = e_kin / (_1 / r - _1 / (_2 * semi_major_axis))
+
+}}}
+Wrap up with a main function showing the value of 'mu' in desired units.
+{{{
+
+> main = putStrLn $ "The value used for GM was " ++ show mu
+
+}}}
+Loading this module in 'ghci' and running 'main' produces the following output.
+{{{
+   ___         ___ _
+  / _ \ /\  /\/ __(_)
+ / /_\// /_/ / /  | |      GHC Interactive, version 6.6.1, for Haskell 98.
+/ /_\\/ __  / /___| |      http://www.haskell.org/ghc/
+\____/\/ /_/\____/|_|      Type :? for help.
+
+Loading package base ... linking ... done.
+[1 of 1] Compiling GM               ( GM.lhs, interpreted )
+Ok, modules loaded: GM.
+*GM> main
+Loading package dimensional-0.5 ... linking ... done.
+The value used for GM was 3.986004400008003e14 m^3 s^-2
+*GM>
+}}}
examples/ReadmeExample.hs view
@@ -1,33 +1,33 @@-{-# LANGUAGE NoImplicitPrelude #-}--module ReadmeExample where--import Numeric.Units.Dimensional.Prelude-import Numeric.Units.Dimensional.NonSI (mile)--leg :: Length Double-leg = 1 *~ mile -- *~ combines a raw number and a unit to form a quantity--speeds :: [Velocity Double]-speeds = [60, 50, 40, 30] *~~ (kilo meter / hour)-  -- *~~ does the same thing for a whole Functor at once-  -- Parentheses are required around unit expressions that are comingled with *~, /~, *~~, or /~~ operations--timeOfJourney :: Time Double-timeOfJourney = sum $ fmap (leg /) speeds-  -- We can use dimensional versions of ordinary functions like / and sum to combine quantities--averageSpeed :: Velocity Double-averageSpeed = _4 * leg / timeOfJourney-  -- _4 is an alias for the dimensionless number 4--wholeSeconds :: Integer-wholeSeconds = ceiling $ timeOfJourney /~ second-  -- /~ lets us recover a raw number from a quantity and a unit in which it should be expressed--main :: IO ()-main = do-         putStrLn $ "Length of journey is: " ++ showIn minute timeOfJourney-         putStrLn $ "Average speed is: " ++ showIn (mile / hour) averageSpeed-         putStrLn $ "If we don't want to be explicit about units, the show instance uses the SI basis: " ++ show averageSpeed-         putStrLn $ "The journey requires " ++ show wholeSeconds ++ " seconds, rounded up to the nearest second."+{-# LANGUAGE NoImplicitPrelude #-}
+
+module ReadmeExample where
+
+import Numeric.Units.Dimensional.Prelude
+import Numeric.Units.Dimensional.NonSI (mile)
+
+leg :: Length Double
+leg = 1 *~ mile -- *~ combines a raw number and a unit to form a quantity
+
+speeds :: [Velocity Double]
+speeds = [60, 50, 40, 30] *~~ (kilo meter / hour)
+  -- *~~ does the same thing for a whole Functor at once
+  -- Parentheses are required around unit expressions that are comingled with *~, /~, *~~, or /~~ operations
+
+timeOfJourney :: Time Double
+timeOfJourney = sum $ fmap (leg /) speeds
+  -- We can use dimensional versions of ordinary functions like / and sum to combine quantities
+
+averageSpeed :: Velocity Double
+averageSpeed = _4 * leg / timeOfJourney
+  -- _4 is an alias for the dimensionless number 4
+
+wholeSeconds :: Integer
+wholeSeconds = ceiling $ timeOfJourney /~ second
+  -- /~ lets us recover a raw number from a quantity and a unit in which it should be expressed
+
+main :: IO ()
+main = do
+         putStrLn $ "Length of journey is: " ++ showIn minute timeOfJourney
+         putStrLn $ "Average speed is: " ++ showIn (mile / hour) averageSpeed
+         putStrLn $ "If we don't want to be explicit about units, the show instance uses the SI basis: " ++ show averageSpeed
+         putStrLn $ "The journey requires " ++ show wholeSeconds ++ " seconds, rounded up to the nearest second."
src/Numeric/Units/Dimensional.hs view
@@ -1,788 +1,788 @@-{-# OPTIONS_HADDOCK show-extensions #-}--{-# LANGUAGE AutoDeriveTypeable #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE RoleAnnotations #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}---{- |-   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter-   License    : BSD3--   Maintainer : bjorn@buckwalter.se-   Stability  : Stable-   Portability: GHC only--= Summary--In this module we provide data types for performing arithmetic with-physical quantities and units. Information about the physical-dimensions of the quantities/units is embedded in their types and-the validity of operations is verified by the type checker at compile-time. The boxing and unboxing of numerical values as quantities is-done by multiplication and division of units, of which an incomplete-set is provided.--We limit ourselves to \"Newtonian\" physics. We do not attempt to-accommodate relativistic physics in which e.g. addition of length-and time would be valid.--As far as possible and/or practical the conventions and guidelines-of NIST's "Guide for the Use of the International System of Units-(SI)" <#note1 [1]> are followed. Occasionally we will reference specific-sections from the guide and deviations will be explained.--== Disclaimer--Merely an engineer, the author doubtlessly uses a language and-notation that makes mathematicians and physicist cringe. He does-not mind constructive criticism (or pull requests).--The sets of functions and units defined herein are incomplete and-reflect only the author's needs to date. Again, patches are welcome.--= Usage--== Preliminaries--This module requires GHC 7.8 or later. We utilize Data Kinds, TypeNats,-Closed Type Families, etc. Clients of the module are generally not-required to use these extensions.--Clients probably will want to use the NegativeLiterals extension.--== Examples--We have defined operators and units that allow us to define and-work with physical quantities. A physical quantity is defined by-multiplying a number with a unit (the type signature is optional).--> v :: Velocity Prelude.Double-> v = 90 *~ (kilo meter / hour)--It follows naturally that the numerical value of a quantity is-obtained by division by a unit.--> numval :: Prelude.Double-> numval = v /~ (meter / second)--The notion of a quantity as the product of a numerical value and a-unit is supported by 7.1 "Value and numerical value of a quantity" of-<#note1 [1]>. While the above syntax is fairly natural it is unfortunate that-it must violate a number of the guidelines in <#note1 [1]>, in particular 9.3-"Spelling unit names with prefixes", 9.4 "Spelling unit names obtained-by multiplication", 9.5 "Spelling unit names obtained by division".--As a more elaborate example of how to use the module we define a-function for calculating the escape velocity of a celestial body-<#note2 [2]>.--> escapeVelocity :: (Floating a) => Mass a -> Length a -> Velocity a-> escapeVelocity m r = sqrt (two * g * m / r)->   where->       two = 2 *~ one->       g = 6.6720e-11 *~ (newton * meter ^ pos2 / kilo gram ^ pos2)--For completeness we should also show an example of the error messages-we will get from GHC when performing invalid arithmetic. In the-best case GHC will be able to use the type synonyms we have defined-in its error messages.--> let x = 1 *~ meter + 1 *~ second->-> Couldn't match type 'Numeric.NumType.DK.Integers.Zero->                with 'Numeric.NumType.DK.Integers.Pos1-> Expected type: Unit 'Metric DLength a->   Actual type: Unit 'Metric DTime a-> In the second argument of `(*~)', namely `second'-> In the second argument of `(+)', namely `1 *~ second'--In other cases the error messages aren't very friendly.--> let x = 1 *~ meter / (1 *~ second) + 1 *~ kilo gram->-> Couldn't match type 'Numeric.NumType.DK.Integers.Zero->                with 'Numeric.NumType.DK.Integers.Neg1-> Expected type: Quantity DMass a->   Actual type: Dimensional->                  ('DQuantity V.* 'DQuantity) (DLength / DTime) a-> In the first argument of `(+)', namely `1 *~ meter / (1 *~ second)'-> In the expression: 1 *~ meter / (1 *~ second) + 1 *~ kilo gram-> In an equation for `x':->       x = 1 *~ meter / (1 *~ second) + 1 *~ kilo gram--It is the author's experience that the usefulness of the compiler-error messages is more often than not limited to pinpointing the-location of errors.--= Notes--== Future work--While there is an insane amount of units in use around the world-it is reasonable to provide those in relatively widespread use. Units outside-of SI will most likely be added on an as-needed basis.--Additional physics models could be implemented. See <#note3 [3]> for ideas.--== Related work--Henning Thielemann numeric prelude has a physical units library,-however, checking of dimensions is dynamic rather than static.-Aaron Denney has created a toy example of statically checked-physical dimensions covering only length and time. HaskellWiki-has pointers <#note4 [4]> to these.--Also see Samuel Hoffstaetter's blog post <#note5 [5]> which uses techniques-similar to this library.--Libraries with similar functionality exist for other programming-languages and may serve as inspiration. The author has found the-Java library JScience <#note6 [6]> and the Fortress programming language <#note7 [7]>-particularly noteworthy.--== References--1. #note1# http://physics.nist.gov/Pubs/SP811/-2. #note2# http://en.wikipedia.org/wiki/Escape_velocity-3. #note3# http://jscience.org/api/org/jscience/physics/models/package-summary.html-4. #note4# http://www.haskell.org/haskellwiki/Physical_units-5. #note5# http://liftm.wordpress.com/2007/06/03/scientificdimension-type-arithmetic-and-physical-units-in-haskell/-6. #note6# http://jscience.org/-7. #note7# http://research.sun.com/projects/plrg/fortress.pdf---}--module Numeric.Units.Dimensional-  (-    -- * Types-    -- $types-    Dimensional,-    Unit, Quantity,-    Metricality(..),-    -- * Physical Dimensions-    -- $dimensions-    Dimension (Dim),-    -- ** Dimension Arithmetic-    -- $dimension-arithmetic-    type (*), type (/), type (^), NRoot, Sqrt, Cbrt, Recip,-    -- ** Term Level Representation of Dimensions-    -- $dimension-terms-    Dimension' (Dim'), HasDimension(..), KnownDimension,-    -- * Dimensional Arithmetic-    (*~), (/~),-    (^), (^/), (**), (*), (/), (+), (-),-    negate, abs, signum, recip, nroot, sqrt, cbrt,-    -- ** Transcendental Functions-    exp, log, logBase, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh, atan2,-    -- ** Operations on Collections-    -- $collections-    (*~~), (/~~), sum, mean, product, dimensionlessLength, nFromTo,-    -- * Dimension Synonyms-    -- $dimension-synonyms-    DOne, DLength, DMass, DTime, DElectricCurrent, DThermodynamicTemperature, DAmountOfSubstance, DLuminousIntensity,-    -- * Quantity Synonyms-    -- $quantity-synonyms-    Dimensionless, Length, Mass, Time, ElectricCurrent, ThermodynamicTemperature, AmountOfSubstance, LuminousIntensity,-    -- * Constants-    -- $constants-    _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, pi, tau,-    -- * Constructing Units-    siUnit, one, mkUnitR, mkUnitQ, mkUnitZ,-    -- * Unit Metadata-    name, exactValue, weaken, strengthen, exactify,-    -- * Pretty Printing-    showIn,-    -- * On 'Functor', and Conversion Between Number Representations-    -- $functor-    KnownVariant(dmap), changeRep, changeRepApproximate,-    -- * Lenses-    -- $lenses-    asLens-  )-  where--import Prelude-  ( Eq(..), Num, Fractional, Floating, Real, RealFloat, Functor, fmap-  , (.), flip, (++), fromIntegral, fromInteger, fromRational, error, max, succ-  , Int, Integer, Integral, ($), uncurry, realToFrac, otherwise-  )-import qualified Prelude-import Numeric.NumType.DK.Integers-  ( pos2, pos3-  , KnownTypeInt, toNum-  )-import Data.Data-import Data.ExactPi-import Data.Foldable (Foldable(foldr))-import Data.Maybe-import Data.Ratio-import Numeric.Units.Dimensional.Dimensions-import Numeric.Units.Dimensional.Internal-import Numeric.Units.Dimensional.UnitNames hiding ((*), (/), (^), weaken, strengthen, product)-import qualified Numeric.Units.Dimensional.UnitNames.Internal as Name-import Numeric.Units.Dimensional.Variants hiding (type (*), type (/))-import qualified Numeric.Units.Dimensional.Variants as V---- Provide a version of length which is compatible with base-4.8's version.--- Where 4.8 is available we use that version as it may have performance advantages.--- Where it is not available we implement it in terms of foldl'.-#if MIN_VERSION_base(4,8,0)-import Data.Foldable (Foldable(length))-#else-import Data.Foldable (Foldable(foldl'))--length :: Foldable t => t a -> Int-length = foldl' (\c _ -> c Prelude.+ 1) 0-#endif---- $setup--- >>> :set -XFlexibleInstances--- >>> :set -XNoImplicitPrelude--- >>> import Test.QuickCheck.Arbitrary--- >>> import Numeric.Units.Dimensional.Prelude--- >>> import Numeric.Units.Dimensional.Float--- >>> import Numeric.Units.Dimensional.NonSI--- >>> instance Arbitrary a => Arbitrary (Quantity d a) where arbitrary = fmap Quantity arbitrary--{--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  *, /-infixl 6  +, ----{- $types-Our primary objective is to define a data type that can be used to-represent (while still differentiating between) units and quantities.-There are two reasons for consolidating units and quantities in one-data type. The first being to allow code reuse as they are largely-subject to the same operations. The second being that it allows-reuse of operators (and functions) between the two without resorting-to occasionally cumbersome type classes.--The relationship between (the value of) a 'Quantity', its numerical-value and its 'Unit' is described in 7.1 "Value and numerical value-of a quantity" of <#note1 [1]>. In short a 'Quantity' is the product of a-number and a 'Unit'. We define the '*~' operator as a convenient-way to declare quantities as such a product.---}---- | Extracts the 'UnitName' of a 'Unit'.-name :: Unit m d a -> UnitName m-name (Unit n _ _) = n---- | Extracts the exact value of a 'Unit', expressed in terms of the SI coherent derived unit (see 'siUnit') of the same 'Dimension'.------ Note that the actual value may in some cases be approximate, for example if the unit is defined by experiment.-exactValue :: Unit m d a -> ExactPi-exactValue (Unit _ e _) = e---- | Discards potentially unwanted type level information about a 'Unit'.-weaken :: Unit m d a -> Unit 'NonMetric d a-weaken (Unit n e v) = Unit (Name.weaken n) e v---- | Attempts to convert a 'Unit' which may or may not be 'Metric' to one--- which is certainly 'Metric'.-strengthen :: Unit m d a -> Maybe (Unit 'Metric d a)-strengthen (Unit n e v) | Just n' <- Name.strengthen n = Just $ Unit n' e v-                        | otherwise                    = Nothing---- | Forms the exact version of a 'Unit'.-exactify :: Unit m d a -> Unit m d ExactPi-exactify (Unit n e _) = Unit n e e---- | Forms a 'Quantity' by multipliying a number and a unit.-(*~) :: (Num a) => a -> Unit m d a -> Quantity d a-x *~ (Unit _ _ y) = Quantity (x Prelude.* y)---- | Divides a 'Quantity' by a 'Unit' of the same physical dimension, obtaining the--- numerical value of the quantity expressed in that unit.-(/~) :: Fractional a => Quantity d a -> Unit m d a -> a-(Quantity x) /~ (Unit _ _ y) = (x Prelude./ y)--{--We give '*~' and '/~' the same fixity as '*' and '/' defined below.-Note that this necessitates the use of parenthesis when composing-units using '*' and '/', e.g. "1 *~ (meter / second)".--}--infixl 7  *~, /~--{- $dimensions-The phantom type variable d encompasses the physical dimension of-a 'Dimensional'. As detailed in <#note5 [5]> there are seven base dimensions,-which can be combined in integer powers to a given physical dimension.-We represent physical dimensions as the powers of the seven base-dimensions that make up the given dimension. The powers are represented-using NumTypes. For convenience we collect all seven base dimensions-in a data kind 'Dimension'.--We could have chosen to provide type variables for the seven base-dimensions in 'Dimensional' instead of creating a new data kind-'Dimension'. However, that would have made any type signatures involving-'Dimensional' very cumbersome.  By encompassing the physical dimension-in a single type variable we can "hide" the cumbersome type arithmetic-behind convenient type classes as will be seen later.---}--{- $dimension-synonyms-Using our 'Dimension' data kind we define some type synonyms for convenience.-We start with the base dimensions, others can be found in "Numeric.Units.Dimensional.Quantities".---}--{- $quantity-synonyms-Using the above type synonyms we can define type synonyms for-quantities of particular physical dimensions.--Again we limit ourselves to the base dimensions, others can be found in "Numeric.Units.Dimensional.Quantities".---}--type Dimensionless            = Quantity DOne-type Length                   = Quantity DLength-type Mass                     = Quantity DMass-type Time                     = Quantity DTime-type ElectricCurrent          = Quantity DElectricCurrent-type ThermodynamicTemperature = Quantity DThermodynamicTemperature-type AmountOfSubstance        = Quantity DAmountOfSubstance-type LuminousIntensity        = Quantity DLuminousIntensity--{- $dimension-arithmetic-When performing arithmetic on units and quantities the arithmetics-must be applied to both the numerical values of the Dimensionals-but also to their physical dimensions. The type level arithmetic-on physical dimensions is governed by closed type families expressed-as type operators.--We could provide the 'Mul' and 'Div' classes with full functional-dependencies but that would be of limited utility as there is no-limited use for "backwards" type inference. Efforts are underway to-develop a type-checker plugin that does enable these scenarios, e.g.-for linear algebra.---}--{--= Arithmetic on units and quantities =--Thanks to the arithmetic on physical dimensions having been sorted-out separately a lot of the arithmetic on Dimensionals is straight-forward. In particular the type signatures are much simplified.--Multiplication, division and powers apply to both units and quantities.--}---- | Multiplies two 'Quantity's or two 'Unit's.------ The intimidating type signature captures the similarity between these operations--- and ensures that composite 'Unit's are 'NonMetric'.-(*) :: (KnownVariant v1, KnownVariant v2, KnownVariant (v1 V.* v2), Num a) => Dimensional v1 d1 a -> Dimensional v2 d2 a -> Dimensional (v1 V.* v2) (d1 * d2) a-(*) = liftD2 (Prelude.*) (Prelude.*) (Name.*)---- | Divides one 'Quantity' by another or one 'Unit' by another.------ The intimidating type signature captures the similarity between these operations--- and ensures that composite 'Unit's are 'NotPrefixable'.-(/) :: (KnownVariant v1, KnownVariant v2, KnownVariant (v1 V./ v2), Fractional a) => Dimensional v1 d1 a -> Dimensional v2 d2 a -> Dimensional (v1 V./ v2) (d1 / d2) a-(/) = liftD2 (Prelude./) (Prelude./) (Name./)---- | Forms the reciprocal of a 'Quantity', which has the reciprocal dimension.------ >>> recip $ 47 *~ hertz--- 2.127659574468085e-2 s-recip :: (Fractional a) => Quantity d a -> Quantity (Recip d) a-recip = liftQ Prelude.recip---- | Raises a 'Quantity' or 'Unit' to an integer power.------ Because the power chosen impacts the 'Dimension' of the result, it is necessary to supply a type-level representation--- of the exponent in the form of a 'Proxy' to some 'TypeInt'. Convenience values 'pos1', 'pos2', 'neg1', ...--- are supplied by the "Numeric.NumType.DK.Integers" module. The most commonly used ones are--- also reexported by "Numeric.Units.Dimensional.Prelude".------ The intimidating type signature captures the similarity between these operations--- and ensures that composite 'Unit's are 'NotPrefixable'.-(^) :: (Fractional a, KnownTypeInt i, KnownVariant v, KnownVariant (Weaken v))-    => Dimensional v d1 a -> Proxy i -> Dimensional (Weaken v) (d1 ^ i) a-x ^ n = let n' = (toNum n) :: Int-         in liftD (Prelude.^^ n') (Prelude.^^ n') (Name.^ n') x--{--A special case is that dimensionless quantities are not restricted-to integer exponents. This is accommodated by the '**' operator-defined later.---= Quantity operations =--Some additional operations obviously only make sense for quantities.-Of these, negation, addition and subtraction are particularly simple-as they are done in a single physical dimension.--}---- | Negates the value of a 'Quantity'.-negate :: Num a => Quantity d a -> Quantity d a-negate = liftQ Prelude.negate---- | Adds two 'Quantity's.-(+) :: Num a => Quantity d a -> Quantity d a -> Quantity d a-(+) = liftQ2 (Prelude.+)---- | Subtracts one 'Quantity' from another.-(-) :: Num a => Quantity d a -> Quantity d a -> Quantity d a-(-) = liftQ2 (Prelude.-)---- | Takes the absolute value of a 'Quantity'.-abs :: Num a => Quantity d a -> Quantity d a-abs = liftQ Prelude.abs---- | Takes the sign of a 'Quantity'. The functions 'abs' and 'signum'--- satisy the law that:------ > abs x * signum x == x------ The sign is either @negate _1@ (negative), @_0@ (zero),--- or @_1@ (positive).-signum :: Num a => Quantity d a -> Dimensionless a-signum = liftQ Prelude.signum--{--Roots of arbitrary (integral) degree. Appears to occasionally be useful-for units as well as quantities.--}---- | Computes the nth root of a 'Quantity' using 'Prelude.**'.------ The 'NRoot' type family will prevent application of this operator where the result would have a fractional dimension or where n is zero.------ Because the root chosen impacts the 'Dimension' of the result, it is necessary to supply a type-level representation--- of the root in the form of a 'Proxy' to some 'TypeInt'. Convenience values 'pos1', 'pos2', 'neg1', ...--- are supplied by the "Numeric.NumType.DK.Integers" module. The most commonly used ones are--- also reexported by "Numeric.Units.Dimensional.Prelude".------ n must not be zero. Negative roots are defined such that @nroot (Proxy :: Proxy (Negate n)) x == nroot (Proxy :: Proxy n) (recip x)@.------ Also available in operator form, see '^/'.-nroot :: (KnownTypeInt n, Floating a)-      => Proxy n -> Quantity d a -> Quantity (NRoot d n) a-nroot n = let n' = 1 Prelude./ toNum n-           in liftQ (Prelude.** n')--{--We provide short-hands for the square and cube roots.--}---- | Computes the square root of a 'Quantity' using 'Prelude.**'.------ The 'NRoot' type family will prevent application where the supplied quantity does not have a square dimension.------ prop> (x :: Area Double) >= _0 ==> sqrt x == nroot pos2 x-sqrt :: Floating a => Quantity d a -> Quantity (Sqrt d) a-sqrt = nroot pos2---- | Computes the cube root of a 'Quantity' using 'Prelude.**'.------ The 'NRoot' type family will prevent application where the supplied quantity does not have a cubic dimension.------ prop> (x :: Volume Double) >= _0 ==> cbrt x == nroot pos3 x-cbrt :: Floating a => Quantity d a -> Quantity (Cbrt d) a-cbrt = nroot pos3--{--We also provide an operator alternative to nroot for those that-prefer such.--}---- | Computes the nth root of a 'Quantity' using 'Prelude.**'.------ The 'NRoot' type family will prevent application of this operator where the result would have a fractional dimension or where n is zero.------ Because the root chosen impacts the 'Dimension' of the result, it is necessary to supply a type-level representation--- of the root in the form of a 'Proxy' to some 'TypeInt'. Convenience values 'pos1', 'pos2', 'neg1', ...--- are supplied by the "Numeric.NumType.DK.Integers" module. The most commonly used ones are--- also reexported by "Numeric.Units.Dimensional.Prelude".------ Also available in prefix form, see 'nroot'.-(^/) :: (KnownTypeInt n, Floating a)-     => Quantity d a -> Proxy n -> Quantity (NRoot d n) a-(^/) = flip nroot--{- $collections-Here we define operators and functions to make working with homogenuous-lists of dimensionals more convenient.--We define two convenience operators for applying units to all-elements of a functor (e.g. a list).--}---- | Applies '*~' to all values in a functor.-(*~~) :: (Functor f, Num a) => f a -> Unit m d a -> f (Quantity d a)-xs *~~ u = fmap (*~ u) xs---- | Applies '/~' to all values in a functor.-(/~~) :: forall f m d a.(Functor f, Fractional a) => f (Quantity d a) -> Unit m d a -> f a-xs /~~ u = fmap (/~ u) xs--infixl 7  *~~, /~~---- | The sum of all elements in a foldable structure.------ >>> sum ([] :: [Mass Double])--- 0.0 kg------ >>> sum [12.4 *~ meter, 1 *~ foot]--- 12.7048 m-sum :: (Num a, Foldable f) => f (Quantity d a) -> Quantity d a-sum = foldr (+) _0---- | The product of all elements in a foldable structure.------ >>> product ([] :: [Dimensionless Double])--- 1.0------ >>> product [pi, _4, 0.36 *~ one]--- 4.523893421169302-product :: (Num a, Foldable f) => f (Dimensionless a) -> Dimensionless a-product = foldr (*) _1---- | The arithmetic mean of all elements in a foldable structure.------ >>> mean [pi, _7]--- 5.070796326794897-mean :: (Fractional a, Foldable f) => f (Quantity d a) -> Quantity d a-mean = uncurry (/) . foldr accumulate (_0, _0)-  where-    accumulate val (accum, count) = (accum + val, count + _1)---- | The length of the foldable data structure as a 'Dimensionless'.--- This can be useful for purposes of e.g. calculating averages.------ >>> dimensionlessLength ["foo", "bar"]--- 2-dimensionlessLength :: (Num a, Foldable f) => f b -> Dimensionless a-dimensionlessLength x = (fromIntegral $ length x) *~ one---- | Returns a list of quantities between given bounds.------ prop> n <= 0 ==> nFromTo (x :: Mass Double) (y :: Mass Double) n == [x, y]------ prop> (x :: Length Double) <= (y :: Length Double) ==> all (\z -> x <= z && z <= y) (nFromTo x y n)------ >>> nFromTo _0 _3 2--- [0.0,1.0,2.0,3.0]------ >>> nFromTo _1 _0 7--- [1.0,0.875,0.75,0.625,0.5,0.375,0.25,0.125,0.0]------ >>> nFromTo _0 _1 (-5)--- [0.0,1.0]-nFromTo :: (Fractional a, Integral b) => Quantity d a -- ^ The initial value.-                                      -> Quantity d a -- ^ The final value.-                                      -> b -- ^ The number of intermediate values. If less than one, no intermediate values will result.-                                      -> [Quantity d a]-nFromTo xi xf n = fmap f [0..n'] ++ [xf]-  where-    n' = max 0 n-    f i = xi + realToFrac (i % succ n') *~ one * (xf - xi)--{--We continue by defining elementary functions on 'Dimensionless'-that may be obviously useful.--}--exp, log, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh-  :: Floating a => Dimensionless a -> Dimensionless a-exp   = fmap Prelude.exp-log   = fmap Prelude.log-sin   = fmap Prelude.sin-cos   = fmap Prelude.cos-tan   = fmap Prelude.tan-asin  = fmap Prelude.asin-acos  = fmap Prelude.acos-atan  = fmap Prelude.atan-sinh  = fmap Prelude.sinh-cosh  = fmap Prelude.cosh-tanh  = fmap Prelude.tanh-asinh = fmap Prelude.asinh-acosh = fmap Prelude.acosh-atanh = fmap Prelude.atanh---- | Raises a dimensionless quantity to a dimensionless power.-(**) :: Floating a => Dimensionless a -> Dimensionless a -> Dimensionless a-(**) = liftQ2 (Prelude.**)---- | Takes the logarithm of the second argument in the base of the first.------ >>> logBase _2 _8--- 3.0-logBase :: Floating a => Dimensionless a -> Dimensionless a -> Dimensionless a-logBase = liftQ2 Prelude.logBase---- | The standard two argument arctangent function.--- Since it interprets its two arguments in comparison with one another, the input may have any dimension.------ >>> atan2 _0 _1--- 0.0------ >>> atan2 _1 _0--- 1.5707963267948966------ >>> atan2 _0 (negate _1)--- 3.141592653589793------ >>> atan2 (negate _1) _0--- -1.5707963267948966-atan2 :: (RealFloat a) => Quantity d a -> Quantity d a -> Dimensionless a-atan2 = liftQ2 Prelude.atan2--{--The only unit we will define in this module is 'one'.--}---- | The unit 'one' has dimension 'DOne' and is the base unit of dimensionless values.------ As detailed in 7.10 "Values of quantities expressed simply as numbers:--- the unit one, symbol 1" of <#note1 [1]> the unit one generally does not--- appear in expressions. However, for us it is necessary to use 'one'--- as we would any other unit to perform the "boxing" of dimensionless values.-one :: Num a => Unit 'NonMetric DOne a-one = Unit nOne 1 1--{- $constants-For convenience we define some constants for small integer values-that often show up in formulae. We also throw in 'pi' and 'tau' for-good measure.---}---- | The constant for zero is polymorphic, allowing it to express zero 'Length' or--- 'Numeric.Units.Dimensional.Quantities.Capacitance' or 'Numeric.Units.Dimensional.Quantities.Velocity' etc,--- in addition to the 'Dimensionless' value zero.-_0 :: Num a => Quantity d a-_0 = Quantity 0--_1, _2, _3, _4, _5, _6, _7, _8, _9 :: (Num a) => Dimensionless a-_1 = 1 *~ one-_2 = 2 *~ one-_3 = 3 *~ one-_4 = 4 *~ one-_5 = 5 *~ one-_6 = 6 *~ one-_7 = 7 *~ one-_8 = 8 *~ one-_9 = 9 *~ one--pi :: Floating a => Dimensionless a-pi = Prelude.pi *~ one---- | Twice 'pi'.------ For background on 'tau' see http://tauday.com/tau-manifesto (but also--- feel free to review http://www.thepimanifesto.com).-tau :: Floating a => Dimensionless a-tau = _2 * pi--{- $functor-We intentionally decline to provide a 'Functor' instance for 'Dimensional' because its use breaks the-abstraction of physical dimensions.--If you feel your work requires this instance, it is provided as an orphan in "Numeric.Units.Dimensional.Functor".---}---- | Convenient conversion between numerical types while retaining dimensional information.------ >>> let x = (37 :: Rational) *~ poundMass--- >>> changeRep x :: Mass Double--- 16.78291769 kg-changeRep :: (KnownVariant v, Real a, Fractional b) => Dimensional v d a -> Dimensional v d b-changeRep = dmap realToFrac---- | Convenient conversion from exactly represented values while retaining dimensional information.-changeRepApproximate :: (KnownVariant v, Floating b) => Dimensional v d ExactPi -> Dimensional v d b-changeRepApproximate = dmap approximateValue--{- $lenses-These functions are compatible with the lens library.---}---- | Converts a 'Unit' into a lens from 'Quantity's to values.-asLens :: (Fractional a) => Unit m d a-                         -> (forall f.Functor f => (a -> f a)-                                                -> Quantity d a-                                                -> f (Quantity d a))-asLens u f q = fmap (\v' -> v' *~ u) (f (q /~ u))--{- $dimension-terms-To facilitate parsing and pretty-printing functions that may wish to operate on term-level representations of dimension,-we provide a means for converting from type-level dimensions to term-level dimensions.---}---- | Forms a new atomic 'Unit' by specifying its 'UnitName' and its definition as a multiple of another 'Unit'.------ Use this variant when the scale factor of the resulting unit is irrational or 'Approximate'. See 'mkUnitQ' for when it is rational--- and 'mkUnitZ' for when it is an integer.------ Note that supplying zero as a definining quantity is invalid, as the library relies--- upon units forming a group under multiplication.------ Supplying negative defining quantities is allowed and handled gracefully, but is discouraged--- on the grounds that it may be unexpected by other readers.-mkUnitR :: Floating a => UnitName m -> ExactPi -> Unit m1 d a -> Unit m d a-mkUnitR n s (Unit _ e _) | isExactZero s = error "Supplying zero as a conversion factor is not valid."-                         | otherwise     = Unit n e' x'-  where-    e' = s Prelude.* e-    x' = approximateValue e'---- | Forms a new atomic 'Unit' by specifying its 'UnitName' and its definition as a multiple of another 'Unit'.------ Use this variant when the scale factor of the resulting unit is rational. See 'mkUnitZ' for when it is an integer--- and 'mkUnitR' for the general case.------ For more information see 'mkUnitR'.-mkUnitQ :: Fractional a => UnitName m -> Rational -> Unit m1 d a -> Unit m d a-mkUnitQ n s (Unit _ e x) | s == 0    = error "Supplying zero as a conversion factor is not valid."-                         | Just x'' <- toExactRational e' = Unit n e' (fromRational x'')-                         | otherwise = Unit n e' x'-  where-    e' = fromRational s Prelude.* e-    x' = fromRational s Prelude.* x---- | Forms a new atomic 'Unit' by specifying its 'UnitName' and its definition as a multiple of another 'Unit'.------ Use this variant when the scale factor of the resulting unit is an integer. See 'mkUnitQ' for when it is rational--- and 'mkUnitR' for the general case.------ For more information see 'mkUnitR'.-mkUnitZ :: Num a => UnitName m -> Integer -> Unit m1 d a -> Unit m d a-mkUnitZ n s (Unit _ e x) | s == 0    = error "Supplying zero as a conversion factor is not valid."-                         | Just x'' <- toExactInteger e' = Unit n e' (fromInteger x'')-                         | otherwise = Unit n e' x'-  where-    e' = fromInteger s Prelude.* e-    x' = fromInteger s Prelude.* x+{-# OPTIONS_HADDOCK show-extensions #-}
+
+{-# LANGUAGE AutoDeriveTypeable #-}
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE PatternGuards #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RoleAnnotations #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+
+
+{- |
+   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+= Summary
+
+In this module we provide data types for performing arithmetic with
+physical quantities and units. Information about the physical
+dimensions of the quantities/units is embedded in their types and
+the validity of operations is verified by the type checker at compile
+time. The boxing and unboxing of numerical values as quantities is
+done by multiplication and division of units, of which an incomplete
+set is provided.
+
+We limit ourselves to \"Newtonian\" physics. We do not attempt to
+accommodate relativistic physics in which e.g. addition of length
+and time would be valid.
+
+As far as possible and/or practical the conventions and guidelines
+of NIST's "Guide for the Use of the International System of Units
+(SI)" <#note1 [1]> are followed. Occasionally we will reference specific
+sections from the guide and deviations will be explained.
+
+== Disclaimer
+
+Merely an engineer, the author doubtlessly uses a language and
+notation that makes mathematicians and physicist cringe. He does
+not mind constructive criticism (or pull requests).
+
+The sets of functions and units defined herein are incomplete and
+reflect only the author's needs to date. Again, patches are welcome.
+
+= Usage
+
+== Preliminaries
+
+This module requires GHC 7.8 or later. We utilize Data Kinds, TypeNats,
+Closed Type Families, etc. Clients of the module are generally not
+required to use these extensions.
+
+Clients probably will want to use the NegativeLiterals extension.
+
+== Examples
+
+We have defined operators and units that allow us to define and
+work with physical quantities. A physical quantity is defined by
+multiplying a number with a unit (the type signature is optional).
+
+> v :: Velocity Prelude.Double
+> v = 90 *~ (kilo meter / hour)
+
+It follows naturally that the numerical value of a quantity is
+obtained by division by a unit.
+
+> numval :: Prelude.Double
+> numval = v /~ (meter / second)
+
+The notion of a quantity as the product of a numerical value and a
+unit is supported by 7.1 "Value and numerical value of a quantity" of
+<#note1 [1]>. While the above syntax is fairly natural it is unfortunate that
+it must violate a number of the guidelines in <#note1 [1]>, in particular 9.3
+"Spelling unit names with prefixes", 9.4 "Spelling unit names obtained
+by multiplication", 9.5 "Spelling unit names obtained by division".
+
+As a more elaborate example of how to use the module we define a
+function for calculating the escape velocity of a celestial body
+<#note2 [2]>.
+
+> escapeVelocity :: (Floating a) => Mass a -> Length a -> Velocity a
+> escapeVelocity m r = sqrt (two * g * m / r)
+>   where
+>       two = 2 *~ one
+>       g = 6.6720e-11 *~ (newton * meter ^ pos2 / kilo gram ^ pos2)
+
+For completeness we should also show an example of the error messages
+we will get from GHC when performing invalid arithmetic. In the
+best case GHC will be able to use the type synonyms we have defined
+in its error messages.
+
+> let x = 1 *~ meter + 1 *~ second
+>
+> Couldn't match type 'Numeric.NumType.DK.Integers.Zero
+>                with 'Numeric.NumType.DK.Integers.Pos1
+> Expected type: Unit 'Metric DLength a
+>   Actual type: Unit 'Metric DTime a
+> In the second argument of `(*~)', namely `second'
+> In the second argument of `(+)', namely `1 *~ second'
+
+In other cases the error messages aren't very friendly.
+
+> let x = 1 *~ meter / (1 *~ second) + 1 *~ kilo gram
+>
+> Couldn't match type 'Numeric.NumType.DK.Integers.Zero
+>                with 'Numeric.NumType.DK.Integers.Neg1
+> Expected type: Quantity DMass a
+>   Actual type: Dimensional
+>                  ('DQuantity V.* 'DQuantity) (DLength / DTime) a
+> In the first argument of `(+)', namely `1 *~ meter / (1 *~ second)'
+> In the expression: 1 *~ meter / (1 *~ second) + 1 *~ kilo gram
+> In an equation for `x':
+>       x = 1 *~ meter / (1 *~ second) + 1 *~ kilo gram
+
+It is the author's experience that the usefulness of the compiler
+error messages is more often than not limited to pinpointing the
+location of errors.
+
+= Notes
+
+== Future work
+
+While there is an insane amount of units in use around the world
+it is reasonable to provide those in relatively widespread use. Units outside
+of SI will most likely be added on an as-needed basis.
+
+Additional physics models could be implemented. See <#note3 [3]> for ideas.
+
+== Related work
+
+Henning Thielemann numeric prelude has a physical units library,
+however, checking of dimensions is dynamic rather than static.
+Aaron Denney has created a toy example of statically checked
+physical dimensions covering only length and time. HaskellWiki
+has pointers <#note4 [4]> to these.
+
+Also see Samuel Hoffstaetter's blog post <#note5 [5]> which uses techniques
+similar to this library.
+
+Libraries with similar functionality exist for other programming
+languages and may serve as inspiration. The author has found the
+Java library JScience <#note6 [6]> and the Fortress programming language <#note7 [7]>
+particularly noteworthy.
+
+== References
+
+1. #note1# http://physics.nist.gov/Pubs/SP811/
+2. #note2# http://en.wikipedia.org/wiki/Escape_velocity
+3. #note3# http://jscience.org/api/org/jscience/physics/models/package-summary.html
+4. #note4# http://www.haskell.org/haskellwiki/Physical_units
+5. #note5# http://liftm.wordpress.com/2007/06/03/scientificdimension-type-arithmetic-and-physical-units-in-haskell/
+6. #note6# http://jscience.org/
+7. #note7# http://research.sun.com/projects/plrg/fortress.pdf
+
+-}
+
+module Numeric.Units.Dimensional
+  (
+    -- * Types
+    -- $types
+    Dimensional,
+    Unit, Quantity,
+    Metricality(..),
+    -- * Physical Dimensions
+    -- $dimensions
+    Dimension (Dim),
+    -- ** Dimension Arithmetic
+    -- $dimension-arithmetic
+    type (*), type (/), type (^), NRoot, Sqrt, Cbrt, Recip,
+    -- ** Term Level Representation of Dimensions
+    -- $dimension-terms
+    Dimension' (Dim'), HasDimension(..), KnownDimension,
+    -- * Dimensional Arithmetic
+    (*~), (/~),
+    (^), (^/), (**), (*), (/), (+), (-),
+    negate, abs, signum, recip, nroot, sqrt, cbrt,
+    -- ** Transcendental Functions
+    exp, log, logBase, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh, atan2,
+    -- ** Operations on Collections
+    -- $collections
+    (*~~), (/~~), sum, mean, product, dimensionlessLength, nFromTo,
+    -- * Dimension Synonyms
+    -- $dimension-synonyms
+    DOne, DLength, DMass, DTime, DElectricCurrent, DThermodynamicTemperature, DAmountOfSubstance, DLuminousIntensity,
+    -- * Quantity Synonyms
+    -- $quantity-synonyms
+    Dimensionless, Length, Mass, Time, ElectricCurrent, ThermodynamicTemperature, AmountOfSubstance, LuminousIntensity,
+    -- * Constants
+    -- $constants
+    _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, pi, tau,
+    -- * Constructing Units
+    siUnit, one, mkUnitR, mkUnitQ, mkUnitZ,
+    -- * Unit Metadata
+    name, exactValue, weaken, strengthen, exactify,
+    -- * Pretty Printing
+    showIn,
+    -- * On 'Functor', and Conversion Between Number Representations
+    -- $functor
+    KnownVariant(dmap), changeRep, changeRepApproximate,
+    -- * Lenses
+    -- $lenses
+    asLens
+  )
+  where
+
+import Prelude
+  ( Eq(..), Num, Fractional, Floating, Real, RealFloat, Functor, fmap
+  , (.), flip, (++), fromIntegral, fromInteger, fromRational, error, max, succ
+  , Int, Integer, Integral, ($), uncurry, realToFrac, otherwise
+  )
+import qualified Prelude
+import Numeric.NumType.DK.Integers
+  ( pos2, pos3
+  , KnownTypeInt, toNum
+  )
+import Data.Data
+import Data.ExactPi
+import Data.Foldable (Foldable(foldr))
+import Data.Maybe
+import Data.Ratio
+import Numeric.Units.Dimensional.Dimensions
+import Numeric.Units.Dimensional.Internal
+import Numeric.Units.Dimensional.UnitNames hiding ((*), (/), (^), weaken, strengthen, product)
+import qualified Numeric.Units.Dimensional.UnitNames.Internal as Name
+import Numeric.Units.Dimensional.Variants hiding (type (*), type (/))
+import qualified Numeric.Units.Dimensional.Variants as V
+
+-- Provide a version of length which is compatible with base-4.8's version.
+-- Where 4.8 is available we use that version as it may have performance advantages.
+-- Where it is not available we implement it in terms of foldl'.
+#if MIN_VERSION_base(4,8,0)
+import Data.Foldable (Foldable(length))
+#else
+import Data.Foldable (Foldable(foldl'))
+
+length :: Foldable t => t a -> Int
+length = foldl' (\c _ -> c Prelude.+ 1) 0
+#endif
+
+-- $setup
+-- >>> :set -XFlexibleInstances
+-- >>> :set -XNoImplicitPrelude
+-- >>> import Test.QuickCheck.Arbitrary
+-- >>> import Numeric.Units.Dimensional.Prelude
+-- >>> import Numeric.Units.Dimensional.Float
+-- >>> import Numeric.Units.Dimensional.NonSI
+-- >>> instance Arbitrary a => Arbitrary (Quantity d a) where arbitrary = fmap Quantity arbitrary
+
+{-
+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  *, /
+infixl 6  +, -
+
+
+{- $types
+Our primary objective is to define a data type that can be used to
+represent (while still differentiating between) units and quantities.
+There are two reasons for consolidating units and quantities in one
+data type. The first being to allow code reuse as they are largely
+subject to the same operations. The second being that it allows
+reuse of operators (and functions) between the two without resorting
+to occasionally cumbersome type classes.
+
+The relationship between (the value of) a 'Quantity', its numerical
+value and its 'Unit' is described in 7.1 "Value and numerical value
+of a quantity" of <#note1 [1]>. In short a 'Quantity' is the product of a
+number and a 'Unit'. We define the '*~' operator as a convenient
+way to declare quantities as such a product.
+
+-}
+
+-- | Extracts the 'UnitName' of a 'Unit'.
+name :: Unit m d a -> UnitName m
+name (Unit n _ _) = n
+
+-- | Extracts the exact value of a 'Unit', expressed in terms of the SI coherent derived unit (see 'siUnit') of the same 'Dimension'.
+--
+-- Note that the actual value may in some cases be approximate, for example if the unit is defined by experiment.
+exactValue :: Unit m d a -> ExactPi
+exactValue (Unit _ e _) = e
+
+-- | Discards potentially unwanted type level information about a 'Unit'.
+weaken :: Unit m d a -> Unit 'NonMetric d a
+weaken (Unit n e v) = Unit (Name.weaken n) e v
+
+-- | Attempts to convert a 'Unit' which may or may not be 'Metric' to one
+-- which is certainly 'Metric'.
+strengthen :: Unit m d a -> Maybe (Unit 'Metric d a)
+strengthen (Unit n e v) | Just n' <- Name.strengthen n = Just $ Unit n' e v
+                        | otherwise                    = Nothing
+
+-- | Forms the exact version of a 'Unit'.
+exactify :: Unit m d a -> Unit m d ExactPi
+exactify (Unit n e _) = Unit n e e
+
+-- | Forms a 'Quantity' by multipliying a number and a unit.
+(*~) :: (Num a) => a -> Unit m d a -> Quantity d a
+x *~ (Unit _ _ y) = Quantity (x Prelude.* y)
+
+-- | Divides a 'Quantity' by a 'Unit' of the same physical dimension, obtaining the
+-- numerical value of the quantity expressed in that unit.
+(/~) :: Fractional a => Quantity d a -> Unit m d a -> a
+(Quantity x) /~ (Unit _ _ y) = (x Prelude./ y)
+
+{-
+We give '*~' and '/~' the same fixity as '*' and '/' defined below.
+Note that this necessitates the use of parenthesis when composing
+units using '*' and '/', e.g. "1 *~ (meter / second)".
+-}
+
+infixl 7  *~, /~
+
+{- $dimensions
+The phantom type variable d encompasses the physical dimension of
+a 'Dimensional'. As detailed in <#note5 [5]> there are seven base dimensions,
+which can be combined in integer powers to a given physical dimension.
+We represent physical dimensions as the powers of the seven base
+dimensions that make up the given dimension. The powers are represented
+using NumTypes. For convenience we collect all seven base dimensions
+in a data kind 'Dimension'.
+
+We could have chosen to provide type variables for the seven base
+dimensions in 'Dimensional' instead of creating a new data kind
+'Dimension'. However, that would have made any type signatures involving
+'Dimensional' very cumbersome.  By encompassing the physical dimension
+in a single type variable we can "hide" the cumbersome type arithmetic
+behind convenient type classes as will be seen later.
+
+-}
+
+{- $dimension-synonyms
+Using our 'Dimension' data kind we define some type synonyms for convenience.
+We start with the base dimensions, others can be found in "Numeric.Units.Dimensional.Quantities".
+
+-}
+
+{- $quantity-synonyms
+Using the above type synonyms we can define type synonyms for
+quantities of particular physical dimensions.
+
+Again we limit ourselves to the base dimensions, others can be found in "Numeric.Units.Dimensional.Quantities".
+
+-}
+
+type Dimensionless            = Quantity DOne
+type Length                   = Quantity DLength
+type Mass                     = Quantity DMass
+type Time                     = Quantity DTime
+type ElectricCurrent          = Quantity DElectricCurrent
+type ThermodynamicTemperature = Quantity DThermodynamicTemperature
+type AmountOfSubstance        = Quantity DAmountOfSubstance
+type LuminousIntensity        = Quantity DLuminousIntensity
+
+{- $dimension-arithmetic
+When performing arithmetic on units and quantities the arithmetics
+must be applied to both the numerical values of the Dimensionals
+but also to their physical dimensions. The type level arithmetic
+on physical dimensions is governed by closed type families expressed
+as type operators.
+
+We could provide the 'Mul' and 'Div' classes with full functional
+dependencies but that would be of limited utility as there is no
+limited use for "backwards" type inference. Efforts are underway to
+develop a type-checker plugin that does enable these scenarios, e.g.
+for linear algebra.
+
+-}
+
+{-
+= Arithmetic on units and quantities =
+
+Thanks to the arithmetic on physical dimensions having been sorted
+out separately a lot of the arithmetic on Dimensionals is straight
+forward. In particular the type signatures are much simplified.
+
+Multiplication, division and powers apply to both units and quantities.
+-}
+
+-- | Multiplies two 'Quantity's or two 'Unit's.
+--
+-- The intimidating type signature captures the similarity between these operations
+-- and ensures that composite 'Unit's are 'NonMetric'.
+(*) :: (KnownVariant v1, KnownVariant v2, KnownVariant (v1 V.* v2), Num a) => Dimensional v1 d1 a -> Dimensional v2 d2 a -> Dimensional (v1 V.* v2) (d1 * d2) a
+(*) = liftD2 (Prelude.*) (Prelude.*) (Name.*)
+
+-- | Divides one 'Quantity' by another or one 'Unit' by another.
+--
+-- The intimidating type signature captures the similarity between these operations
+-- and ensures that composite 'Unit's are 'NotPrefixable'.
+(/) :: (KnownVariant v1, KnownVariant v2, KnownVariant (v1 V./ v2), Fractional a) => Dimensional v1 d1 a -> Dimensional v2 d2 a -> Dimensional (v1 V./ v2) (d1 / d2) a
+(/) = liftD2 (Prelude./) (Prelude./) (Name./)
+
+-- | Forms the reciprocal of a 'Quantity', which has the reciprocal dimension.
+--
+-- >>> recip $ 47 *~ hertz
+-- 2.127659574468085e-2 s
+recip :: (Fractional a) => Quantity d a -> Quantity (Recip d) a
+recip = liftQ Prelude.recip
+
+-- | Raises a 'Quantity' or 'Unit' to an integer power.
+--
+-- Because the power chosen impacts the 'Dimension' of the result, it is necessary to supply a type-level representation
+-- of the exponent in the form of a 'Proxy' to some 'TypeInt'. Convenience values 'pos1', 'pos2', 'neg1', ...
+-- are supplied by the "Numeric.NumType.DK.Integers" module. The most commonly used ones are
+-- also reexported by "Numeric.Units.Dimensional.Prelude".
+--
+-- The intimidating type signature captures the similarity between these operations
+-- and ensures that composite 'Unit's are 'NotPrefixable'.
+(^) :: (Fractional a, KnownTypeInt i, KnownVariant v, KnownVariant (Weaken v))
+    => Dimensional v d1 a -> Proxy i -> Dimensional (Weaken v) (d1 ^ i) a
+x ^ n = let n' = (toNum n) :: Int
+         in liftD (Prelude.^^ n') (Prelude.^^ n') (Name.^ n') x
+
+{-
+A special case is that dimensionless quantities are not restricted
+to integer exponents. This is accommodated by the '**' operator
+defined later.
+
+
+= Quantity operations =
+
+Some additional operations obviously only make sense for quantities.
+Of these, negation, addition and subtraction are particularly simple
+as they are done in a single physical dimension.
+-}
+
+-- | Negates the value of a 'Quantity'.
+negate :: Num a => Quantity d a -> Quantity d a
+negate = liftQ Prelude.negate
+
+-- | Adds two 'Quantity's.
+(+) :: Num a => Quantity d a -> Quantity d a -> Quantity d a
+(+) = liftQ2 (Prelude.+)
+
+-- | Subtracts one 'Quantity' from another.
+(-) :: Num a => Quantity d a -> Quantity d a -> Quantity d a
+(-) = liftQ2 (Prelude.-)
+
+-- | Takes the absolute value of a 'Quantity'.
+abs :: Num a => Quantity d a -> Quantity d a
+abs = liftQ Prelude.abs
+
+-- | Takes the sign of a 'Quantity'. The functions 'abs' and 'signum'
+-- satisy the law that:
+--
+-- > abs x * signum x == x
+--
+-- The sign is either @negate _1@ (negative), @_0@ (zero),
+-- or @_1@ (positive).
+signum :: Num a => Quantity d a -> Dimensionless a
+signum = liftQ Prelude.signum
+
+{-
+Roots of arbitrary (integral) degree. Appears to occasionally be useful
+for units as well as quantities.
+-}
+
+-- | Computes the nth root of a 'Quantity' using 'Prelude.**'.
+--
+-- The 'NRoot' type family will prevent application of this operator where the result would have a fractional dimension or where n is zero.
+--
+-- Because the root chosen impacts the 'Dimension' of the result, it is necessary to supply a type-level representation
+-- of the root in the form of a 'Proxy' to some 'TypeInt'. Convenience values 'pos1', 'pos2', 'neg1', ...
+-- are supplied by the "Numeric.NumType.DK.Integers" module. The most commonly used ones are
+-- also reexported by "Numeric.Units.Dimensional.Prelude".
+--
+-- n must not be zero. Negative roots are defined such that @nroot (Proxy :: Proxy (Negate n)) x == nroot (Proxy :: Proxy n) (recip x)@.
+--
+-- Also available in operator form, see '^/'.
+nroot :: (KnownTypeInt n, Floating a)
+      => Proxy n -> Quantity d a -> Quantity (NRoot d n) a
+nroot n = let n' = 1 Prelude./ toNum n
+           in liftQ (Prelude.** n')
+
+{-
+We provide short-hands for the square and cube roots.
+-}
+
+-- | Computes the square root of a 'Quantity' using 'Prelude.**'.
+--
+-- The 'NRoot' type family will prevent application where the supplied quantity does not have a square dimension.
+--
+-- prop> (x :: Area Double) >= _0 ==> sqrt x == nroot pos2 x
+sqrt :: Floating a => Quantity d a -> Quantity (Sqrt d) a
+sqrt = nroot pos2
+
+-- | Computes the cube root of a 'Quantity' using 'Prelude.**'.
+--
+-- The 'NRoot' type family will prevent application where the supplied quantity does not have a cubic dimension.
+--
+-- prop> (x :: Volume Double) >= _0 ==> cbrt x == nroot pos3 x
+cbrt :: Floating a => Quantity d a -> Quantity (Cbrt d) a
+cbrt = nroot pos3
+
+{-
+We also provide an operator alternative to nroot for those that
+prefer such.
+-}
+
+-- | Computes the nth root of a 'Quantity' using 'Prelude.**'.
+--
+-- The 'NRoot' type family will prevent application of this operator where the result would have a fractional dimension or where n is zero.
+--
+-- Because the root chosen impacts the 'Dimension' of the result, it is necessary to supply a type-level representation
+-- of the root in the form of a 'Proxy' to some 'TypeInt'. Convenience values 'pos1', 'pos2', 'neg1', ...
+-- are supplied by the "Numeric.NumType.DK.Integers" module. The most commonly used ones are
+-- also reexported by "Numeric.Units.Dimensional.Prelude".
+--
+-- Also available in prefix form, see 'nroot'.
+(^/) :: (KnownTypeInt n, Floating a)
+     => Quantity d a -> Proxy n -> Quantity (NRoot d n) a
+(^/) = flip nroot
+
+{- $collections
+Here we define operators and functions to make working with homogenuous
+lists of dimensionals more convenient.
+
+We define two convenience operators for applying units to all
+elements of a functor (e.g. a list).
+-}
+
+-- | Applies '*~' to all values in a functor.
+(*~~) :: (Functor f, Num a) => f a -> Unit m d a -> f (Quantity d a)
+xs *~~ u = fmap (*~ u) xs
+
+-- | Applies '/~' to all values in a functor.
+(/~~) :: forall f m d a.(Functor f, Fractional a) => f (Quantity d a) -> Unit m d a -> f a
+xs /~~ u = fmap (/~ u) xs
+
+infixl 7  *~~, /~~
+
+-- | The sum of all elements in a foldable structure.
+--
+-- >>> sum ([] :: [Mass Double])
+-- 0.0 kg
+--
+-- >>> sum [12.4 *~ meter, 1 *~ foot]
+-- 12.7048 m
+sum :: (Num a, Foldable f) => f (Quantity d a) -> Quantity d a
+sum = foldr (+) _0
+
+-- | The product of all elements in a foldable structure.
+--
+-- >>> product ([] :: [Dimensionless Double])
+-- 1.0
+--
+-- >>> product [pi, _4, 0.36 *~ one]
+-- 4.523893421169302
+product :: (Num a, Foldable f) => f (Dimensionless a) -> Dimensionless a
+product = foldr (*) _1
+
+-- | The arithmetic mean of all elements in a foldable structure.
+--
+-- >>> mean [pi, _7]
+-- 5.070796326794897
+mean :: (Fractional a, Foldable f) => f (Quantity d a) -> Quantity d a
+mean = uncurry (/) . foldr accumulate (_0, _0)
+  where
+    accumulate val (accum, count) = (accum + val, count + _1)
+
+-- | The length of the foldable data structure as a 'Dimensionless'.
+-- This can be useful for purposes of e.g. calculating averages.
+--
+-- >>> dimensionlessLength ["foo", "bar"]
+-- 2
+dimensionlessLength :: (Num a, Foldable f) => f b -> Dimensionless a
+dimensionlessLength x = (fromIntegral $ length x) *~ one
+
+-- | Returns a list of quantities between given bounds.
+--
+-- prop> n <= 0 ==> nFromTo (x :: Mass Double) (y :: Mass Double) n == [x, y]
+--
+-- prop> (x :: Length Double) <= (y :: Length Double) ==> all (\z -> x <= z && z <= y) (nFromTo x y n)
+--
+-- >>> nFromTo _0 _3 2
+-- [0.0,1.0,2.0,3.0]
+--
+-- >>> nFromTo _1 _0 7
+-- [1.0,0.875,0.75,0.625,0.5,0.375,0.25,0.125,0.0]
+--
+-- >>> nFromTo _0 _1 (-5)
+-- [0.0,1.0]
+nFromTo :: (Fractional a, Integral b) => Quantity d a -- ^ The initial value.
+                                      -> Quantity d a -- ^ The final value.
+                                      -> b -- ^ The number of intermediate values. If less than one, no intermediate values will result.
+                                      -> [Quantity d a]
+nFromTo xi xf n = fmap f [0..n'] ++ [xf]
+  where
+    n' = max 0 n
+    f i = xi + realToFrac (i % succ n') *~ one * (xf - xi)
+
+{-
+We continue by defining elementary functions on 'Dimensionless'
+that may be obviously useful.
+-}
+
+exp, log, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh
+  :: Floating a => Dimensionless a -> Dimensionless a
+exp   = fmap Prelude.exp
+log   = fmap Prelude.log
+sin   = fmap Prelude.sin
+cos   = fmap Prelude.cos
+tan   = fmap Prelude.tan
+asin  = fmap Prelude.asin
+acos  = fmap Prelude.acos
+atan  = fmap Prelude.atan
+sinh  = fmap Prelude.sinh
+cosh  = fmap Prelude.cosh
+tanh  = fmap Prelude.tanh
+asinh = fmap Prelude.asinh
+acosh = fmap Prelude.acosh
+atanh = fmap Prelude.atanh
+
+-- | Raises a dimensionless quantity to a dimensionless power.
+(**) :: Floating a => Dimensionless a -> Dimensionless a -> Dimensionless a
+(**) = liftQ2 (Prelude.**)
+
+-- | Takes the logarithm of the second argument in the base of the first.
+--
+-- >>> logBase _2 _8
+-- 3.0
+logBase :: Floating a => Dimensionless a -> Dimensionless a -> Dimensionless a
+logBase = liftQ2 Prelude.logBase
+
+-- | The standard two argument arctangent function.
+-- Since it interprets its two arguments in comparison with one another, the input may have any dimension.
+--
+-- >>> atan2 _0 _1
+-- 0.0
+--
+-- >>> atan2 _1 _0
+-- 1.5707963267948966
+--
+-- >>> atan2 _0 (negate _1)
+-- 3.141592653589793
+--
+-- >>> atan2 (negate _1) _0
+-- -1.5707963267948966
+atan2 :: (RealFloat a) => Quantity d a -> Quantity d a -> Dimensionless a
+atan2 = liftQ2 Prelude.atan2
+
+{-
+The only unit we will define in this module is 'one'.
+-}
+
+-- | The unit 'one' has dimension 'DOne' and is the base unit of dimensionless values.
+--
+-- As detailed in 7.10 "Values of quantities expressed simply as numbers:
+-- the unit one, symbol 1" of <#note1 [1]> the unit one generally does not
+-- appear in expressions. However, for us it is necessary to use 'one'
+-- as we would any other unit to perform the "boxing" of dimensionless values.
+one :: Num a => Unit 'NonMetric DOne a
+one = Unit nOne 1 1
+
+{- $constants
+For convenience we define some constants for small integer values
+that often show up in formulae. We also throw in 'pi' and 'tau' for
+good measure.
+
+-}
+
+-- | The constant for zero is polymorphic, allowing it to express zero 'Length' or
+-- 'Numeric.Units.Dimensional.Quantities.Capacitance' or 'Numeric.Units.Dimensional.Quantities.Velocity' etc,
+-- in addition to the 'Dimensionless' value zero.
+_0 :: Num a => Quantity d a
+_0 = Quantity 0
+
+_1, _2, _3, _4, _5, _6, _7, _8, _9 :: (Num a) => Dimensionless a
+_1 = 1 *~ one
+_2 = 2 *~ one
+_3 = 3 *~ one
+_4 = 4 *~ one
+_5 = 5 *~ one
+_6 = 6 *~ one
+_7 = 7 *~ one
+_8 = 8 *~ one
+_9 = 9 *~ one
+
+pi :: Floating a => Dimensionless a
+pi = Prelude.pi *~ one
+
+-- | Twice 'pi'.
+--
+-- For background on 'tau' see http://tauday.com/tau-manifesto (but also
+-- feel free to review http://www.thepimanifesto.com).
+tau :: Floating a => Dimensionless a
+tau = _2 * pi
+
+{- $functor
+We intentionally decline to provide a 'Functor' instance for 'Dimensional' because its use breaks the
+abstraction of physical dimensions.
+
+If you feel your work requires this instance, it is provided as an orphan in "Numeric.Units.Dimensional.Functor".
+
+-}
+
+-- | Convenient conversion between numerical types while retaining dimensional information.
+--
+-- >>> let x = (37 :: Rational) *~ poundMass
+-- >>> changeRep x :: Mass Double
+-- 16.78291769 kg
+changeRep :: (KnownVariant v, Real a, Fractional b) => Dimensional v d a -> Dimensional v d b
+changeRep = dmap realToFrac
+
+-- | Convenient conversion from exactly represented values while retaining dimensional information.
+changeRepApproximate :: (KnownVariant v, Floating b) => Dimensional v d ExactPi -> Dimensional v d b
+changeRepApproximate = dmap approximateValue
+
+{- $lenses
+These functions are compatible with the lens library.
+
+-}
+
+-- | Converts a 'Unit' into a lens from 'Quantity's to values.
+asLens :: (Fractional a) => Unit m d a
+                         -> (forall f.Functor f => (a -> f a)
+                                                -> Quantity d a
+                                                -> f (Quantity d a))
+asLens u f q = fmap (\v' -> v' *~ u) (f (q /~ u))
+
+{- $dimension-terms
+To facilitate parsing and pretty-printing functions that may wish to operate on term-level representations of dimension,
+we provide a means for converting from type-level dimensions to term-level dimensions.
+
+-}
+
+-- | Forms a new atomic 'Unit' by specifying its 'UnitName' and its definition as a multiple of another 'Unit'.
+--
+-- Use this variant when the scale factor of the resulting unit is irrational or 'Approximate'. See 'mkUnitQ' for when it is rational
+-- and 'mkUnitZ' for when it is an integer.
+--
+-- Note that supplying zero as a definining quantity is invalid, as the library relies
+-- upon units forming a group under multiplication.
+--
+-- Supplying negative defining quantities is allowed and handled gracefully, but is discouraged
+-- on the grounds that it may be unexpected by other readers.
+mkUnitR :: Floating a => UnitName m -> ExactPi -> Unit m1 d a -> Unit m d a
+mkUnitR n s (Unit _ e _) | isExactZero s = error "Supplying zero as a conversion factor is not valid."
+                         | otherwise     = Unit n e' x'
+  where
+    e' = s Prelude.* e
+    x' = approximateValue e'
+
+-- | Forms a new atomic 'Unit' by specifying its 'UnitName' and its definition as a multiple of another 'Unit'.
+--
+-- Use this variant when the scale factor of the resulting unit is rational. See 'mkUnitZ' for when it is an integer
+-- and 'mkUnitR' for the general case.
+--
+-- For more information see 'mkUnitR'.
+mkUnitQ :: Fractional a => UnitName m -> Rational -> Unit m1 d a -> Unit m d a
+mkUnitQ n s (Unit _ e x) | s == 0    = error "Supplying zero as a conversion factor is not valid."
+                         | Just x'' <- toExactRational e' = Unit n e' (fromRational x'')
+                         | otherwise = Unit n e' x'
+  where
+    e' = fromRational s Prelude.* e
+    x' = fromRational s Prelude.* x
+
+-- | Forms a new atomic 'Unit' by specifying its 'UnitName' and its definition as a multiple of another 'Unit'.
+--
+-- Use this variant when the scale factor of the resulting unit is an integer. See 'mkUnitQ' for when it is rational
+-- and 'mkUnitR' for the general case.
+--
+-- For more information see 'mkUnitR'.
+mkUnitZ :: Num a => UnitName m -> Integer -> Unit m1 d a -> Unit m d a
+mkUnitZ n s (Unit _ e x) | s == 0    = error "Supplying zero as a conversion factor is not valid."
+                         | Just x'' <- toExactInteger e' = Unit n e' (fromInteger x'')
+                         | otherwise = Unit n e' x'
+  where
+    e' = fromInteger s Prelude.* e
+    x' = fromInteger s Prelude.* x
src/Numeric/Units/Dimensional/Coercion.hs view
@@ -1,35 +1,35 @@-{- |-    Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter-    License    : BSD3--    Maintainer : bjorn@buckwalter.se-    Stability  : Experimental-    Portability: GHC only?--Re-exports the raw 'Quantity' constructor from the Numeric.Units.Dimensional.Internal module, along with 'Data.Coerce.coerce',-for convenience in converting between raw representations and dimensional values.--Note that use of these constructs requires the user to verify the dimensional safety of the conversion,-because the coercion doesn't explicitly mention the unit of the representation. Note also that the-'Quantity' constructor constructs a 'Numeric.Units.Dimensional.SQuantity' which may have a scale factor-other than 'Data.ExactPi.TypeLevel.One'.--Note that the haddock documentation doesn't mention the 'Quantity' constructor because it is a part of the-'Dimensional' associated data family, but it is exported by this module.---}--module Numeric.Units.Dimensional.Coercion-(-  coerce, Dimensional(Quantity), unQuantity-)-where--import Data.Coerce (coerce)-import Numeric.Units.Dimensional.Internal (SQuantity, Dimensional(Quantity))---- | Unwraps a possibly-scaled `SQuantity`, yielding its underlying representation.------ This is a type-restricted version of `coerce`.-unQuantity :: SQuantity s d a -> a-unQuantity = coerce+{- |
+    Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter
+    License    : BSD3
+
+    Maintainer : bjorn@buckwalter.se
+    Stability  : Experimental
+    Portability: GHC only?
+
+Re-exports the raw 'Quantity' constructor from the Numeric.Units.Dimensional.Internal module, along with 'Data.Coerce.coerce',
+for convenience in converting between raw representations and dimensional values.
+
+Note that use of these constructs requires the user to verify the dimensional safety of the conversion,
+because the coercion doesn't explicitly mention the unit of the representation. Note also that the
+'Quantity' constructor constructs a 'Numeric.Units.Dimensional.SQuantity' which may have a scale factor
+other than 'Data.ExactPi.TypeLevel.One'.
+
+Note that the haddock documentation doesn't mention the 'Quantity' constructor because it is a part of the
+'Dimensional' associated data family, but it is exported by this module.
+
+-}
+
+module Numeric.Units.Dimensional.Coercion
+(
+  coerce, Dimensional(Quantity), unQuantity
+)
+where
+
+import Data.Coerce (coerce)
+import Numeric.Units.Dimensional.Internal (SQuantity, Dimensional(Quantity))
+
+-- | Unwraps a possibly-scaled `SQuantity`, yielding its underlying representation.
+--
+-- This is a type-restricted version of `coerce`.
+unQuantity :: SQuantity s d a -> a
+unQuantity = coerce
src/Numeric/Units/Dimensional/Dimensions.hs view
@@ -1,25 +1,25 @@-{- |-   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter-   License    : BSD3--   Maintainer : bjorn@buckwalter.se-   Stability  : Stable-   Portability: GHC only--Provides both term-level and type-level representations for physical dimensions in-a single import for convenience.--Presuming that users intend to work primarily with type level dimensions, this module hides-arithmetic operators over term level dimensions and aliases for the base term-level dimensions-to avoid namespace pollution. These features are available directly from-"Numeric.Units.Dimensional.Dimensions.TermLevel" if desired.--}-module Numeric.Units.Dimensional.Dimensions-(-  module Numeric.Units.Dimensional.Dimensions.TermLevel,-  module Numeric.Units.Dimensional.Dimensions.TypeLevel-)-where--import Numeric.Units.Dimensional.Dimensions.TermLevel hiding ((*), (/), (^), recip, nroot, sqrt, cbrt, dLength, dMass, dTime, dElectricCurrent, dThermodynamicTemperature, dAmountOfSubstance, dLuminousIntensity)-import Numeric.Units.Dimensional.Dimensions.TypeLevel+{- |
+   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+Provides both term-level and type-level representations for physical dimensions in
+a single import for convenience.
+
+Presuming that users intend to work primarily with type level dimensions, this module hides
+arithmetic operators over term level dimensions and aliases for the base term-level dimensions
+to avoid namespace pollution. These features are available directly from
+"Numeric.Units.Dimensional.Dimensions.TermLevel" if desired.
+-}
+module Numeric.Units.Dimensional.Dimensions
+(
+  module Numeric.Units.Dimensional.Dimensions.TermLevel,
+  module Numeric.Units.Dimensional.Dimensions.TypeLevel
+)
+where
+
+import Numeric.Units.Dimensional.Dimensions.TermLevel hiding ((*), (/), (^), recip, nroot, sqrt, cbrt, dLength, dMass, dTime, dElectricCurrent, dThermodynamicTemperature, dAmountOfSubstance, dLuminousIntensity)
+import Numeric.Units.Dimensional.Dimensions.TypeLevel
src/Numeric/Units/Dimensional/Dimensions/TermLevel.hs view
@@ -1,192 +1,192 @@-{-# OPTIONS_HADDOCK not-home, show-extensions #-}--{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--{- |-   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter-   License    : BSD3--   Maintainer : bjorn@buckwalter.se-   Stability  : Stable-   Portability: GHC only--This module defines physical dimensions expressed in terms of-the SI base dimensions, including arithmetic.---}-module Numeric.Units.Dimensional.Dimensions.TermLevel-(-  -- * Type-  Dimension'(..),-  -- * Access to Dimension of Dimensional Values-  HasDimension(..), HasDynamicDimension(..), DynamicDimension(..),-  -- * Dimension Arithmetic-  (*), (/), (^), recip, nroot, sqrt, cbrt,-  -- * Synonyms for Base Dimensions-  dOne,-  dLength, dMass, dTime, dElectricCurrent, dThermodynamicTemperature, dAmountOfSubstance, dLuminousIntensity,-  -- * Deconstruction-  asList,-  -- * Examining Dynamic Dimensions-  matchDimensions, isCompatibleWith, hasSomeDimension-)-where--import Control.DeepSeq-import Data.Data-import Data.Semigroup (Semigroup(..))-import Data.Monoid (Monoid(..))-import GHC.Generics-import Prelude (id, all, fst, snd, fmap, otherwise, divMod, ($), (+), (-), (.), (&&), Int, Show, Eq(..), Ord(..), Maybe(..), Bool(..))-import qualified Prelude as P---- $setup--- >>> import Prelude (negate)--- >>> import Control.Applicative--- >>> import Test.QuickCheck.Arbitrary--- >>> instance Arbitrary Dimension' where arbitrary = Dim' <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary---- | A physical dimension, encoded as 7 integers, representing a factorization of the dimension into the--- 7 SI base dimensions. By convention they are stored in the same order as--- in the 'Numeric.Units.Dimensional.Dimensions.TypeLevel.Dimension' data kind.-data Dimension' = Dim' !Int !Int !Int !Int !Int !Int !Int-  deriving (Show, Eq, Ord, Data, Generic, Typeable)--instance NFData Dimension' where-  rnf !_ = () -- The Dimension' constructor is already fully strict.--instance Semigroup Dimension' where-  (<>) = (*)---- | The monoid of dimensions under multiplication.-instance Monoid Dimension' where-  mempty = dOne-  mappend = (Data.Semigroup.<>)---- | The dimension of a dynamic value, which may not have any dimension at all.-data DynamicDimension = NoDimension -- ^ The value has no valid dimension.-                      | SomeDimension Dimension' -- ^ The value has the given dimension.-                      | AnyDimension -- ^ The value may be interpreted as having any dimension.-  deriving (Eq, Ord, Show, Data, Generic, Typeable)--instance NFData DynamicDimension where---- | Dimensional values, or those that are only possibly dimensional, inhabit this class,--- which allows access to a term-level representation of their dimension.-class HasDynamicDimension a where-  -- | Gets the 'DynamicDimension of a dynamic dimensional value, which may be 'NoDimension' if it does not represent-  -- a dimensional value of any 'Dimension'.-  ---  -- A default implementation is available for types that are also in the `HasDimension` typeclass.-  dynamicDimension :: a -> DynamicDimension-  default dynamicDimension :: (HasDimension a) => a -> DynamicDimension-  dynamicDimension = SomeDimension . dimension---- | Dimensional values inhabit this class, which allows access to a term-level representation of their dimension.-class HasDynamicDimension a => HasDimension a where-  -- | Obtains a term-level representation of a value's dimension.-  dimension :: a -> Dimension'--instance HasDynamicDimension DynamicDimension where-  dynamicDimension = id--instance HasDynamicDimension Dimension' where--instance HasDimension Dimension' where-  dimension = id---- | Combines two 'DynamicDimension's, determining the 'DynamicDimension' of a quantity that must--- match both inputs.------ This is the lattice meet operation for 'DynamicDimension'.-matchDimensions :: DynamicDimension -> DynamicDimension -> DynamicDimension-matchDimensions AnyDimension        AnyDimension                   = AnyDimension-matchDimensions d@(SomeDimension _) AnyDimension                   = d-matchDimensions AnyDimension        d@(SomeDimension _)            = d-matchDimensions (SomeDimension d1)  (SomeDimension d2) | d1 == d2  = SomeDimension d1-matchDimensions _                   _                              = NoDimension---- | Determines if a value that has a 'DynamicDimension' is compatible with a specified 'Dimension''.-isCompatibleWith :: (HasDynamicDimension a) => a -> Dimension' -> Bool-isCompatibleWith = f . dynamicDimension-  where-    f AnyDimension       _             = True-    f (SomeDimension d1) d2 | d1 == d2 = True-    f _                  _             = False---- | Determines if a value that has a 'DynamicDimension' in fact has any valid dimension at all.-hasSomeDimension :: (HasDynamicDimension a) => a -> Bool-hasSomeDimension = (/= NoDimension) . dynamicDimension---- | The dimension of dimensionless values.-dOne :: Dimension'-dOne = Dim' 0 0 0 0 0 0 0--dLength, dMass, dTime, dElectricCurrent, dThermodynamicTemperature, dAmountOfSubstance, dLuminousIntensity :: Dimension'-dLength                   = Dim' 1 0 0 0 0 0 0-dMass                     = Dim' 0 1 0 0 0 0 0-dTime                     = Dim' 0 0 1 0 0 0 0-dElectricCurrent          = Dim' 0 0 0 1 0 0 0-dThermodynamicTemperature = Dim' 0 0 0 0 1 0 0-dAmountOfSubstance        = Dim' 0 0 0 0 0 1 0-dLuminousIntensity        = Dim' 0 0 0 0 0 0 1--{--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  *, /---- | Forms the product of two dimensions.-(*) :: Dimension' -> Dimension' -> Dimension'-(Dim' l m t i th n j) * (Dim' l' m' t' i' th' n' j') = Dim' (l + l') (m + m') (t + t') (i + i') (th + th') (n + n') (j + j')---- | Forms the quotient of two dimensions.-(/) :: Dimension' -> Dimension' -> Dimension'-(Dim' l m t i th n j) / (Dim' l' m' t' i' th' n' j') = Dim' (l - l') (m - m') (t - t') (i - i') (th - th') (n - n') (j - j')---- | Raises a dimension to an integer power.-(^) :: Dimension' -> Int -> Dimension'-(Dim' l m t i th n j) ^ x = Dim' (x P.* l) (x P.* m) (x P.* t) (x P.* i) (x P.* th) (x P.* n) (x P.* j)---- | Forms the reciprocal of a dimension.-recip :: Dimension' -> Dimension'-recip = (dOne /)---- | Takes the nth root of a dimension, if it exists.------ n must not be zero.------ prop> nroot (negate n) d == nroot n (recip d)-nroot :: Int -> Dimension' -> Maybe Dimension'-nroot n d | n /= 0 && all ((== 0) . snd) ds = fromList . fmap fst $ ds-          | otherwise                      = Nothing-  where-    ds = fmap (`divMod` n) . asList $ d---- | Takes the square root of a dimension, if it exists.------ prop> sqrt d == nroot 2 d-sqrt :: Dimension' -> Maybe Dimension'-sqrt = nroot 2---- | Takes the cube root of a dimension, if it exists.------ prop> cbrt d == nroot 3 d-cbrt :: Dimension' -> Maybe Dimension'-cbrt = nroot 3---- | Converts a dimension to a list of 7 integers, representing the exponent associated with each--- of the 7 SI base dimensions in the standard order.-asList :: Dimension' -> [Int]-asList (Dim' l m t i th n j) = [l, m, t, i, th, n, j]--fromList :: [Int] -> Maybe Dimension'-fromList [l, m, t, i, th, n, j] = Just $ Dim' l m t i th n j-fromList _ = Nothing+{-# OPTIONS_HADDOCK not-home, show-extensions #-}
+
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE DefaultSignatures #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric #-}
+
+{- |
+   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+This module defines physical dimensions expressed in terms of
+the SI base dimensions, including arithmetic.
+
+-}
+module Numeric.Units.Dimensional.Dimensions.TermLevel
+(
+  -- * Type
+  Dimension'(..),
+  -- * Access to Dimension of Dimensional Values
+  HasDimension(..), HasDynamicDimension(..), DynamicDimension(..),
+  -- * Dimension Arithmetic
+  (*), (/), (^), recip, nroot, sqrt, cbrt,
+  -- * Synonyms for Base Dimensions
+  dOne,
+  dLength, dMass, dTime, dElectricCurrent, dThermodynamicTemperature, dAmountOfSubstance, dLuminousIntensity,
+  -- * Deconstruction
+  asList,
+  -- * Examining Dynamic Dimensions
+  matchDimensions, isCompatibleWith, hasSomeDimension
+)
+where
+
+import Control.DeepSeq
+import Data.Data
+import Data.Semigroup (Semigroup(..))
+import Data.Monoid (Monoid(..))
+import GHC.Generics
+import Prelude (id, all, fst, snd, fmap, otherwise, divMod, ($), (+), (-), (.), (&&), Int, Show, Eq(..), Ord(..), Maybe(..), Bool(..))
+import qualified Prelude as P
+
+-- $setup
+-- >>> import Prelude (negate)
+-- >>> import Control.Applicative
+-- >>> import Test.QuickCheck.Arbitrary
+-- >>> instance Arbitrary Dimension' where arbitrary = Dim' <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
+
+-- | A physical dimension, encoded as 7 integers, representing a factorization of the dimension into the
+-- 7 SI base dimensions. By convention they are stored in the same order as
+-- in the 'Numeric.Units.Dimensional.Dimensions.TypeLevel.Dimension' data kind.
+data Dimension' = Dim' !Int !Int !Int !Int !Int !Int !Int
+  deriving (Show, Eq, Ord, Data, Generic, Typeable)
+
+instance NFData Dimension' where
+  rnf !_ = () -- The Dimension' constructor is already fully strict.
+
+instance Semigroup Dimension' where
+  (<>) = (*)
+
+-- | The monoid of dimensions under multiplication.
+instance Monoid Dimension' where
+  mempty = dOne
+  mappend = (Data.Semigroup.<>)
+
+-- | The dimension of a dynamic value, which may not have any dimension at all.
+data DynamicDimension = NoDimension -- ^ The value has no valid dimension.
+                      | SomeDimension Dimension' -- ^ The value has the given dimension.
+                      | AnyDimension -- ^ The value may be interpreted as having any dimension.
+  deriving (Eq, Ord, Show, Data, Generic, Typeable)
+
+instance NFData DynamicDimension where
+
+-- | Dimensional values, or those that are only possibly dimensional, inhabit this class,
+-- which allows access to a term-level representation of their dimension.
+class HasDynamicDimension a where
+  -- | Gets the 'DynamicDimension of a dynamic dimensional value, which may be 'NoDimension' if it does not represent
+  -- a dimensional value of any 'Dimension'.
+  --
+  -- A default implementation is available for types that are also in the `HasDimension` typeclass.
+  dynamicDimension :: a -> DynamicDimension
+  default dynamicDimension :: (HasDimension a) => a -> DynamicDimension
+  dynamicDimension = SomeDimension . dimension
+
+-- | Dimensional values inhabit this class, which allows access to a term-level representation of their dimension.
+class HasDynamicDimension a => HasDimension a where
+  -- | Obtains a term-level representation of a value's dimension.
+  dimension :: a -> Dimension'
+
+instance HasDynamicDimension DynamicDimension where
+  dynamicDimension = id
+
+instance HasDynamicDimension Dimension' where
+
+instance HasDimension Dimension' where
+  dimension = id
+
+-- | Combines two 'DynamicDimension's, determining the 'DynamicDimension' of a quantity that must
+-- match both inputs.
+--
+-- This is the lattice meet operation for 'DynamicDimension'.
+matchDimensions :: DynamicDimension -> DynamicDimension -> DynamicDimension
+matchDimensions AnyDimension        AnyDimension                   = AnyDimension
+matchDimensions d@(SomeDimension _) AnyDimension                   = d
+matchDimensions AnyDimension        d@(SomeDimension _)            = d
+matchDimensions (SomeDimension d1)  (SomeDimension d2) | d1 == d2  = SomeDimension d1
+matchDimensions _                   _                              = NoDimension
+
+-- | Determines if a value that has a 'DynamicDimension' is compatible with a specified 'Dimension''.
+isCompatibleWith :: (HasDynamicDimension a) => a -> Dimension' -> Bool
+isCompatibleWith = f . dynamicDimension
+  where
+    f AnyDimension       _             = True
+    f (SomeDimension d1) d2 | d1 == d2 = True
+    f _                  _             = False
+
+-- | Determines if a value that has a 'DynamicDimension' in fact has any valid dimension at all.
+hasSomeDimension :: (HasDynamicDimension a) => a -> Bool
+hasSomeDimension = (/= NoDimension) . dynamicDimension
+
+-- | The dimension of dimensionless values.
+dOne :: Dimension'
+dOne = Dim' 0 0 0 0 0 0 0
+
+dLength, dMass, dTime, dElectricCurrent, dThermodynamicTemperature, dAmountOfSubstance, dLuminousIntensity :: Dimension'
+dLength                   = Dim' 1 0 0 0 0 0 0
+dMass                     = Dim' 0 1 0 0 0 0 0
+dTime                     = Dim' 0 0 1 0 0 0 0
+dElectricCurrent          = Dim' 0 0 0 1 0 0 0
+dThermodynamicTemperature = Dim' 0 0 0 0 1 0 0
+dAmountOfSubstance        = Dim' 0 0 0 0 0 1 0
+dLuminousIntensity        = Dim' 0 0 0 0 0 0 1
+
+{-
+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  *, /
+
+-- | Forms the product of two dimensions.
+(*) :: Dimension' -> Dimension' -> Dimension'
+(Dim' l m t i th n j) * (Dim' l' m' t' i' th' n' j') = Dim' (l + l') (m + m') (t + t') (i + i') (th + th') (n + n') (j + j')
+
+-- | Forms the quotient of two dimensions.
+(/) :: Dimension' -> Dimension' -> Dimension'
+(Dim' l m t i th n j) / (Dim' l' m' t' i' th' n' j') = Dim' (l - l') (m - m') (t - t') (i - i') (th - th') (n - n') (j - j')
+
+-- | Raises a dimension to an integer power.
+(^) :: Dimension' -> Int -> Dimension'
+(Dim' l m t i th n j) ^ x = Dim' (x P.* l) (x P.* m) (x P.* t) (x P.* i) (x P.* th) (x P.* n) (x P.* j)
+
+-- | Forms the reciprocal of a dimension.
+recip :: Dimension' -> Dimension'
+recip = (dOne /)
+
+-- | Takes the nth root of a dimension, if it exists.
+--
+-- n must not be zero.
+--
+-- prop> nroot (negate n) d == nroot n (recip d)
+nroot :: Int -> Dimension' -> Maybe Dimension'
+nroot n d | n /= 0 && all ((== 0) . snd) ds = fromList . fmap fst $ ds
+          | otherwise                      = Nothing
+  where
+    ds = fmap (`divMod` n) . asList $ d
+
+-- | Takes the square root of a dimension, if it exists.
+--
+-- prop> sqrt d == nroot 2 d
+sqrt :: Dimension' -> Maybe Dimension'
+sqrt = nroot 2
+
+-- | Takes the cube root of a dimension, if it exists.
+--
+-- prop> cbrt d == nroot 3 d
+cbrt :: Dimension' -> Maybe Dimension'
+cbrt = nroot 3
+
+-- | Converts a dimension to a list of 7 integers, representing the exponent associated with each
+-- of the 7 SI base dimensions in the standard order.
+asList :: Dimension' -> [Int]
+asList (Dim' l m t i th n j) = [l, m, t, i, th, n, j]
+
+fromList :: [Int] -> Maybe Dimension'
+fromList [l, m, t, i, th, n, j] = Just $ Dim' l m t i th n j
+fromList _ = Nothing
src/Numeric/Units/Dimensional/Dimensions/TypeLevel.hs view
@@ -1,160 +1,160 @@-{-# OPTIONS_HADDOCK not-home, show-extensions #-}--{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}--{- |-   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter-   License    : BSD3--   Maintainer : bjorn@buckwalter.se-   Stability  : Stable-   Portability: GHC only--This module defines type-level physical dimensions expressed in terms of-the SI base dimensions using 'Numeric.NumType.DK.NumType' for type-level integers.--Type-level arithmetic, synonyms for the base dimensions, and conversion to the term-level are included.--}-module Numeric.Units.Dimensional.Dimensions.TypeLevel-(-  -- * Kind of Type-Level Dimensions-  type Dimension(..),-  -- * Dimension Arithmetic-  type (*), type (/), type (^), type Recip, type NRoot, type Sqrt, type Cbrt,-  -- * Synonyms for Base Dimensions-  DOne,-  DLength, DMass, DTime, DElectricCurrent, DThermodynamicTemperature, DAmountOfSubstance, DLuminousIntensity,-  -- * Conversion to Term Level-  type KnownDimension-)-where--import Data.Proxy-import Numeric.NumType.DK.Integers-  ( TypeInt (Zero, Pos1, Pos2, Pos3), type (+), type (-)-  , KnownTypeInt, toNum-  )-import qualified Numeric.NumType.DK.Integers as N-import Numeric.Units.Dimensional.Dimensions.TermLevel---- | Represents a physical dimension in the basis of the 7 SI base dimensions,--- where the respective dimensions are represented by type variables--- using the following convention:------  * l: Length---  * m: Mass---  * t: Time---  * i: Electric current---  * th: Thermodynamic temperature---  * n: Amount of substance---  * j: Luminous intensity------ For the equivalent term-level representation, see 'Dimension''-data Dimension = Dim TypeInt TypeInt TypeInt TypeInt TypeInt TypeInt TypeInt---- | The type-level dimension of dimensionless values.-type DOne                      = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero-type DLength                   = 'Dim 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero-type DMass                     = 'Dim 'Zero 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero-type DTime                     = 'Dim 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero 'Zero-type DElectricCurrent          = 'Dim 'Zero 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero-type DThermodynamicTemperature = 'Dim 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero 'Zero-type DAmountOfSubstance        = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero-type DLuminousIntensity        = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1--{--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  *, /---- | Multiplication of dimensions corresponds to adding of the base--- dimensions' exponents.-type family (a::Dimension) * (b::Dimension) where-  DOne * d = d-  d * DOne = d-  ('Dim l  m  t  i  th  n  j) * ('Dim l' m' t' i' th' n' j')-    = 'Dim (l + l') (m + m') (t + t') (i + i') (th + th') (n + n') (j + j')---- | Division of dimensions corresponds to subtraction of the base--- dimensions' exponents.-type family (a::Dimension) / (d::Dimension) where-  d / DOne = d-  d / d = DOne-  ('Dim l  m  t  i  th  n  j) / ('Dim l' m' t' i' th' n' j')-    = 'Dim (l - l') (m - m') (t - t') (i - i') (th - th') (n - n') (j - j')---- | The reciprocal of a dimension is defined as the result of dividing 'DOne' by it,--- or of negating each of the base dimensions' exponents.-type Recip (d :: Dimension) = DOne / d---- | Powers of dimensions corresponds to multiplication of the base--- dimensions' exponents by the exponent.------ We limit ourselves to integer powers of Dimensionals as fractional--- powers make little physical sense.-type family (d::Dimension) ^ (x::TypeInt) where-  DOne ^ x = DOne-  d ^ 'Zero = DOne-  d ^ 'Pos1 = d-  ('Dim l  m  t  i  th  n  j) ^ x-    = 'Dim (l N.* x) (m N.* x) (t N.* x) (i N.* x) (th N.* x) (n N.* x) (j N.* x)---- | Roots of dimensions corresponds to division of the base dimensions'--- exponents by the order of the root.-type family NRoot (d::Dimension) (x::TypeInt) where-  NRoot DOne x = DOne-  NRoot d 'Pos1 = d-  NRoot ('Dim l  m  t  i  th  n  j) x-    = 'Dim (l N./ x) (m N./ x) (t N./ x) (i N./ x) (th N./ x) (n N./ x) (j N./ x)---- | Square root is a special case of 'NRoot' with order 2.-type Sqrt d = NRoot d 'Pos2---- | Cube root is a special case of 'NRoot' with order 3.-type Cbrt d = NRoot d 'Pos3---- | A KnownDimension is one for which we can construct a term-level representation.--- Each validly constructed type of kind 'Dimension' has a 'KnownDimension' instance.------ While 'KnownDimension' is a constraint synonym, the presence of @'KnownDimension' d@ in---  a context allows use of @'dimension' :: 'Proxy' d -> 'Dimension''@.-type KnownDimension (d :: Dimension) = HasDimension (Proxy d)--instance ( KnownTypeInt l-         , KnownTypeInt m-         , KnownTypeInt t-         , KnownTypeInt i-         , KnownTypeInt th-         , KnownTypeInt n-         , KnownTypeInt j-         ) => HasDynamicDimension (Proxy ('Dim l m t i th n j))-  where--instance ( KnownTypeInt l-         , KnownTypeInt m-         , KnownTypeInt t-         , KnownTypeInt i-         , KnownTypeInt th-         , KnownTypeInt n-         , KnownTypeInt j-         ) => HasDimension (Proxy ('Dim l m t i th n j))-  where-    dimension _ = Dim'-                (toNum (Proxy :: Proxy l))-                (toNum (Proxy :: Proxy m))-                (toNum (Proxy :: Proxy t))-                (toNum (Proxy :: Proxy i))-                (toNum (Proxy :: Proxy th))-                (toNum (Proxy :: Proxy n))-                (toNum (Proxy :: Proxy j))+{-# OPTIONS_HADDOCK not-home, show-extensions #-}
+
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+
+{- |
+   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+This module defines type-level physical dimensions expressed in terms of
+the SI base dimensions using 'Numeric.NumType.DK.NumType' for type-level integers.
+
+Type-level arithmetic, synonyms for the base dimensions, and conversion to the term-level are included.
+-}
+module Numeric.Units.Dimensional.Dimensions.TypeLevel
+(
+  -- * Kind of Type-Level Dimensions
+  type Dimension(..),
+  -- * Dimension Arithmetic
+  type (*), type (/), type (^), type Recip, type NRoot, type Sqrt, type Cbrt,
+  -- * Synonyms for Base Dimensions
+  DOne,
+  DLength, DMass, DTime, DElectricCurrent, DThermodynamicTemperature, DAmountOfSubstance, DLuminousIntensity,
+  -- * Conversion to Term Level
+  type KnownDimension
+)
+where
+
+import Data.Proxy
+import Numeric.NumType.DK.Integers
+  ( TypeInt (Zero, Pos1, Pos2, Pos3), type (+), type (-)
+  , KnownTypeInt, toNum
+  )
+import qualified Numeric.NumType.DK.Integers as N
+import Numeric.Units.Dimensional.Dimensions.TermLevel
+
+-- | Represents a physical dimension in the basis of the 7 SI base dimensions,
+-- where the respective dimensions are represented by type variables
+-- using the following convention:
+--
+--  * l: Length
+--  * m: Mass
+--  * t: Time
+--  * i: Electric current
+--  * th: Thermodynamic temperature
+--  * n: Amount of substance
+--  * j: Luminous intensity
+--
+-- For the equivalent term-level representation, see 'Dimension''
+data Dimension = Dim TypeInt TypeInt TypeInt TypeInt TypeInt TypeInt TypeInt
+
+-- | The type-level dimension of dimensionless values.
+type DOne                      = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
+type DLength                   = 'Dim 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
+type DMass                     = 'Dim 'Zero 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero
+type DTime                     = 'Dim 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero 'Zero
+type DElectricCurrent          = 'Dim 'Zero 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero
+type DThermodynamicTemperature = 'Dim 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero 'Zero
+type DAmountOfSubstance        = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero
+type DLuminousIntensity        = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1
+
+{-
+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  *, /
+
+-- | Multiplication of dimensions corresponds to adding of the base
+-- dimensions' exponents.
+type family (a::Dimension) * (b::Dimension) where
+  DOne * d = d
+  d * DOne = d
+  ('Dim l  m  t  i  th  n  j) * ('Dim l' m' t' i' th' n' j')
+    = 'Dim (l + l') (m + m') (t + t') (i + i') (th + th') (n + n') (j + j')
+
+-- | Division of dimensions corresponds to subtraction of the base
+-- dimensions' exponents.
+type family (a::Dimension) / (d::Dimension) where
+  d / DOne = d
+  d / d = DOne
+  ('Dim l  m  t  i  th  n  j) / ('Dim l' m' t' i' th' n' j')
+    = 'Dim (l - l') (m - m') (t - t') (i - i') (th - th') (n - n') (j - j')
+
+-- | The reciprocal of a dimension is defined as the result of dividing 'DOne' by it,
+-- or of negating each of the base dimensions' exponents.
+type Recip (d :: Dimension) = DOne / d
+
+-- | Powers of dimensions corresponds to multiplication of the base
+-- dimensions' exponents by the exponent.
+--
+-- We limit ourselves to integer powers of Dimensionals as fractional
+-- powers make little physical sense.
+type family (d::Dimension) ^ (x::TypeInt) where
+  DOne ^ x = DOne
+  d ^ 'Zero = DOne
+  d ^ 'Pos1 = d
+  ('Dim l  m  t  i  th  n  j) ^ x
+    = 'Dim (l N.* x) (m N.* x) (t N.* x) (i N.* x) (th N.* x) (n N.* x) (j N.* x)
+
+-- | Roots of dimensions corresponds to division of the base dimensions'
+-- exponents by the order of the root.
+type family NRoot (d::Dimension) (x::TypeInt) where
+  NRoot DOne x = DOne
+  NRoot d 'Pos1 = d
+  NRoot ('Dim l  m  t  i  th  n  j) x
+    = 'Dim (l N./ x) (m N./ x) (t N./ x) (i N./ x) (th N./ x) (n N./ x) (j N./ x)
+
+-- | Square root is a special case of 'NRoot' with order 2.
+type Sqrt d = NRoot d 'Pos2
+
+-- | Cube root is a special case of 'NRoot' with order 3.
+type Cbrt d = NRoot d 'Pos3
+
+-- | A KnownDimension is one for which we can construct a term-level representation.
+-- Each validly constructed type of kind 'Dimension' has a 'KnownDimension' instance.
+--
+-- While 'KnownDimension' is a constraint synonym, the presence of @'KnownDimension' d@ in
+--  a context allows use of @'dimension' :: 'Proxy' d -> 'Dimension''@.
+type KnownDimension (d :: Dimension) = HasDimension (Proxy d)
+
+instance ( KnownTypeInt l
+         , KnownTypeInt m
+         , KnownTypeInt t
+         , KnownTypeInt i
+         , KnownTypeInt th
+         , KnownTypeInt n
+         , KnownTypeInt j
+         ) => HasDynamicDimension (Proxy ('Dim l m t i th n j))
+  where
+
+instance ( KnownTypeInt l
+         , KnownTypeInt m
+         , KnownTypeInt t
+         , KnownTypeInt i
+         , KnownTypeInt th
+         , KnownTypeInt n
+         , KnownTypeInt j
+         ) => HasDimension (Proxy ('Dim l m t i th n j))
+  where
+    dimension _ = Dim'
+                (toNum (Proxy :: Proxy l))
+                (toNum (Proxy :: Proxy m))
+                (toNum (Proxy :: Proxy t))
+                (toNum (Proxy :: Proxy i))
+                (toNum (Proxy :: Proxy th))
+                (toNum (Proxy :: Proxy n))
+                (toNum (Proxy :: Proxy j))
src/Numeric/Units/Dimensional/Dynamic.hs view
@@ -1,351 +1,352 @@-{- |-    Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter-    License    : BSD3--    Maintainer : bjorn@buckwalter.se-    Stability  : Stable-    Portability: GHC only?--Defines types for manipulation of units and quantities without phantom types for their dimensions.--}--{-# LANGUAGE DataKinds #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE ScopedTypeVariables #-}--module Numeric.Units.Dimensional.Dynamic-(-  -- * Dynamic Quantities-  AnyQuantity-, DynQuantity-, Demotable-, Promotable-, HasDynamicDimension(..), DynamicDimension(..)-, promoteQuantity, demoteQuantity-, (*~), (/~), invalidQuantity, polydimensionalZero-  -- * Dynamic Units-, AnyUnit-, demoteUnit, promoteUnit, demoteUnit'-, siUnit, anyUnitName-  -- ** Arithmetic on Dynamic Units-, (*), (/), (^), recip, applyPrefix-) where--import Control.DeepSeq-import Control.Monad-import Data.Data-import Data.ExactPi-import Data.Semigroup (Semigroup(..))-import Data.Monoid (Monoid(..))-import GHC.Generics-import Prelude (Eq(..), Num, Fractional, Floating, Show(..), Bool(..), Maybe(..), (.), ($), (++), (&&), id, otherwise, error)-import qualified Prelude as P-import Numeric.Units.Dimensional hiding ((*~), (/~), (*), (/), (^), recip, nroot, siUnit)-import qualified Numeric.Units.Dimensional as Dim-import Numeric.Units.Dimensional.Coercion-import Numeric.Units.Dimensional.UnitNames (UnitName, baseUnitName)-import qualified Numeric.Units.Dimensional.UnitNames.InterchangeNames as I-import qualified Numeric.Units.Dimensional.UnitNames as N-import Numeric.Units.Dimensional.Dimensions.TermLevel (HasDynamicDimension(..), DynamicDimension(..), matchDimensions, isCompatibleWith)-import qualified Numeric.Units.Dimensional.Dimensions.TermLevel as D---- | The class of types that can be used to model 'Quantity's that are certain to have a value with--- some dimension.-class Demotable (q :: * -> *) where-  demotableOut :: q a -> AnyQuantity a---- | The class of types that can be used to model 'Quantity's whose 'Dimension's are--- only known dynamically.-class Promotable (q :: * -> *) where-  promotableIn :: AnyQuantity a -> q a-  promotableOut :: q a -> DynQuantity a---- | Forgets information about a 'Quantity' or 'AnyQuantity', yielding an 'AnyQuantity' or a 'DynQuantity'.-demoteQuantity :: (Demotable q, Promotable d) => q a -> d a-demoteQuantity = promotableIn . demotableOut---- | Converts a dynamic quantity such as an 'AnyQuantity' or a 'DynQuantity' into a--- 'Quantity', or to 'Nothing' if the dynamic quantity cannot be represented in the--- narrower result type.-promoteQuantity :: forall a d q.(Promotable q, KnownDimension d) => q a -> Maybe (Quantity d a)-promoteQuantity = promoteQ . promotableOut-  where-    dim' = dimension (Proxy :: Proxy d)-    promoteQ (DynQuantity d v) | d `isCompatibleWith` dim' = Just . Quantity $ v-                               | otherwise                 = Nothing--instance (KnownDimension d) => Demotable (Quantity d) where-  demotableOut q@(Quantity x) = AnyQuantity (dimension q) x---- | A 'Quantity' whose 'Dimension' is only known dynamically.-data AnyQuantity a = AnyQuantity !Dimension' !a-  deriving (Eq, Data, Generic, Generic1, Typeable)--instance (Show a) => Show (AnyQuantity a) where-  show (AnyQuantity d a) | d == D.dOne = show a-                         | otherwise   = (show a) ++ " " ++ (show . baseUnitName $ d)--instance HasDynamicDimension (AnyQuantity a) where--instance HasDimension (AnyQuantity a) where-  dimension (AnyQuantity d _) = d--instance NFData a => NFData (AnyQuantity a) -- instance is derived from Generic instance--instance Promotable AnyQuantity where-  promotableIn = id-  promotableOut (AnyQuantity d a) = DynQuantity (SomeDimension d) a--instance Demotable AnyQuantity where-  demotableOut = id---- | 'AnyQuantity's form a 'Semigroup' under multiplication, but not under addition because--- they may not be added together if their dimensions do not match.-instance Num a => Semigroup (AnyQuantity a) where-  (AnyQuantity d1 a1) <> (AnyQuantity d2 a2) = AnyQuantity (d1 D.* d2) (a1 P.* a2)---- | 'AnyQuantity's form a 'Monoid' under multiplication, but not under addition because--- they may not be added together if their dimensions do not match.-instance Num a => Monoid (AnyQuantity a) where-  mempty = demoteQuantity (1 Dim.*~ one)-  mappend = (Data.Semigroup.<>)---- | Possibly a 'Quantity' whose 'Dimension' is only known dynamically.------ By modeling the absence of a value, this type differs from 'AnyQuantity' in that it may--- not be a 'Quantity' of any 'Dimension' whatsoever, but in exchange it gains instances--- for the common numeric classes. It's therefore useful for manipulating, and not merely storing,--- quantities of unknown dimension.------ This type also contains a 'polydimensionalZero', representing zero value of any dimension.------ Note that the 'Eq' instance for 'DynQuantity' equates all representations of an invalid value,--- and also does not equate polydimensional zero with zero of any specific dimension.-data DynQuantity a = DynQuantity !DynamicDimension a -- we can't have strictness annotation on a as it is sometimes undefined-  deriving (Data, Generic, Generic1, Typeable)--instance Eq a => Eq (DynQuantity a) where-  (DynQuantity NoDimension _) == (DynQuantity NoDimension _) = True -- all invalid quantities are equal-  (DynQuantity NoDimension _) == _                           = False -- invalid quanties are not equal to any other quantity-  _                           == (DynQuantity NoDimension _) = False-  (DynQuantity d1 v1)         == (DynQuantity d2 v2)         = d1 == d2 && v1 == v2--instance NFData a => NFData (DynQuantity a) -- instance is derived from Generic instance--instance Show a => Show (DynQuantity a) where-  show (DynQuantity NoDimension _) = "invalidQuantity"-  show (DynQuantity AnyDimension v) = show v-  show (DynQuantity (SomeDimension d) v) = show $ AnyQuantity d v--instance Promotable DynQuantity where-  promotableIn (AnyQuantity d a) = DynQuantity (SomeDimension d) a-  promotableOut = id--instance HasDynamicDimension (DynQuantity a) where-  dynamicDimension (DynQuantity d _) = d--instance Num a => Num (DynQuantity a) where-  x + y = liftDQ2 matchDimensions (P.+) x y-  x - y = liftDQ2 matchDimensions (P.-) x y-  x * y = liftDQ2 (valid2 (D.*)) (P.*) x y-  negate = liftDQ id P.negate-  abs = liftDQ id P.abs-  signum = liftDQ (constant D.dOne) P.signum-  fromInteger = demoteQuantity . (Dim.*~ one) . P.fromInteger--instance Fractional a => Fractional (DynQuantity a) where-  x / y = liftDQ2 (valid2 (D./)) (P./) x y-  recip = liftDQ (valid D.recip) P.recip-  fromRational = demoteQuantity . (Dim.*~ one) . P.fromRational--instance Floating a => Floating (DynQuantity a) where-  pi = demoteQuantity pi-  exp = liftDimensionless P.exp-  log = liftDimensionless P.log-  sqrt = liftDQ (whenValid $ D.nroot 2) P.sqrt-  (**) = liftDQ2 (matchDimensions3 $ SomeDimension D.dOne) (P.**)-  logBase = liftDQ2 (matchDimensions3 $ SomeDimension D.dOne) P.logBase-  sin = liftDimensionless P.sin-  cos = liftDimensionless P.cos-  tan = liftDimensionless P.tan-  asin = liftDimensionless P.asin-  acos = liftDimensionless P.acos-  atan = liftDimensionless P.atan-  sinh = liftDimensionless P.sinh-  cosh = liftDimensionless P.cosh-  tanh = liftDimensionless P.tanh-  asinh = liftDimensionless P.asinh-  acosh = liftDimensionless P.acosh-  atanh = liftDimensionless P.atanh---- | 'DynQuantity's form a 'Semigroup' under multiplication, but not under addition because--- they may not be added together if their dimensions do not match.-instance Num a => Semigroup (DynQuantity a) where-    (<>) = (P.*)---- | 'DynQuantity's form a 'Monoid' under multiplication, but not under addition because--- they may not be added together if their dimensions do not match.-instance Num a => Monoid (DynQuantity a) where-  mempty = demoteQuantity (1 Dim.*~ one)-  mappend = (Data.Semigroup.<>)---- | A 'DynQuantity' which does not correspond to a value of any dimension.-invalidQuantity :: DynQuantity a-invalidQuantity = DynQuantity NoDimension $ error "Attempt to evaluate the value of an invalid quantity."---- | A 'DynQuantity' which corresponds to zero value of any dimension.------ When combined through arithmetic with other 'DynQuantity's, inference is performed. For example,--- adding a length to polydimensional zero produces that length. Adding two polydimensional zeros produces another.--- Taking the sine of a polydimensional zero interprets it as a dimensionless zero and produces a dimensionless result.------ Note that division by 'polydimensionalZero' produces a polydimensional result, which may be an error or some representation--- of infinity, as determined by the underlying arithmetic type. This behavior was chosen for consistency with the behavior of division--- by zero 'DynQuantity's of a specific dimension.-polydimensionalZero :: (Num a) => DynQuantity a-polydimensionalZero = DynQuantity AnyDimension 0---- Lifts a function which is only valid on dimensionless quantities into a function on DynQuantitys.-liftDimensionless :: (a -> a) -> DynQuantity a -> DynQuantity a-liftDimensionless f = liftDQ (matchDimensions $ SomeDimension D.dOne) f---- Lifts a function on values into a function on DynQuantitys.-liftDQ :: (DynamicDimension -> DynamicDimension) -- ^ How the function operates on dimensions.-       -> (a -> a) -- ^ How the function operates on values.-       -> DynQuantity a -> DynQuantity a-liftDQ fd fv (DynQuantity d v) = case fd d of-                                   NoDimension -> invalidQuantity-                                   d' -> DynQuantity d' $ fv v---- Lifts a function on values into a function on DynQuantitys.------ This works by treating polydimensional zeros as dimensionless zeros. If that is not the desired behavior,--- handle polydimensional zeros first and then call this function.-liftDQ2 :: (DynamicDimension -> DynamicDimension -> DynamicDimension)-        -> (a -> a -> a)-        -> DynQuantity a -> DynQuantity a -> DynQuantity a-liftDQ2 fd fv (DynQuantity d1 v1) (DynQuantity d2 v2) = case fd d1 d2 of-                                                          NoDimension -> invalidQuantity-                                                          d' -> DynQuantity d' $ fv v1 v2---- Transforms a dynamic dimension in a way which is always valid-valid :: (Dimension' -> Dimension') -> DynamicDimension -> DynamicDimension-valid _ AnyDimension      = AnyDimension-valid f (SomeDimension d) = SomeDimension (f d)-valid _ NoDimension       = NoDimension--whenValid :: (Dimension' -> Maybe Dimension') -> DynamicDimension -> DynamicDimension-whenValid _ AnyDimension = AnyDimension-whenValid f (SomeDimension d) | Just d' <- f d = SomeDimension d'-whenValid _ _ = NoDimension--constant :: Dimension' -> DynamicDimension -> DynamicDimension-constant d AnyDimension = SomeDimension d-constant d (SomeDimension _) = SomeDimension d-constant _ _ = NoDimension---- Transforms two dynamic dimensions in a way which is always valid-valid2 :: (Dimension' -> Dimension' -> Dimension') -> DynamicDimension -> DynamicDimension -> DynamicDimension-valid2 _ AnyDimension       (SomeDimension _)  = AnyDimension-valid2 _ (SomeDimension _)  AnyDimension       = AnyDimension-valid2 _ AnyDimension       AnyDimension       = AnyDimension-valid2 f (SomeDimension d1) (SomeDimension d2) = SomeDimension (f d1 d2)-valid2 _ _                  _                  = NoDimension--matchDimensions3 :: DynamicDimension -> DynamicDimension -> DynamicDimension -> DynamicDimension-matchDimensions3 x y z = matchDimensions x (matchDimensions y z)---- | A 'Unit' whose 'Dimension' is only known dynamically.-data AnyUnit = AnyUnit Dimension' (UnitName 'NonMetric) ExactPi-  deriving (Generic, Typeable)--instance Show AnyUnit where-  show (AnyUnit _ n e) = (show n) ++ " =def= " ++ (show e) ++ " of the SI base unit"--instance HasDynamicDimension AnyUnit where--instance HasDimension AnyUnit where-  dimension (AnyUnit d _ _) = d--instance I.HasInterchangeName AnyUnit where-  interchangeName (AnyUnit _ n _) = I.interchangeName n---- | 'AnyUnit's form a 'Semigroup' under multiplication.-instance Semigroup AnyUnit where-  (<>) = (Numeric.Units.Dimensional.Dynamic.*)---- | 'AnyUnit's form a 'Monoid' under multiplication.-instance Monoid AnyUnit where-  mempty = demoteUnit' one-  mappend = (Data.Semigroup.<>)--anyUnitName :: AnyUnit -> UnitName 'NonMetric-anyUnitName (AnyUnit _ n _) = n---- | The dynamic SI coherent unit of a given dimension.-siUnit :: Dimension' -> AnyUnit-siUnit d = AnyUnit d (baseUnitName d) 1---- | Converts a 'Unit' of statically known 'Dimension' into an 'AnyUnit'.-demoteUnit :: forall m d a.(KnownDimension d) => Unit m d a -> AnyUnit-demoteUnit u = AnyUnit dim (name $ weaken u) (exactValue u)-  where-    dim = dimension (Proxy :: Proxy d)---- | Converts a 'Unit' of statically known 'Dimension' into an 'AnyUnit'.------ This is the same as the more general 'demoteUnit' but is useful in certain circumstances to avoid--- needlessly introducing an ambiguous type variable.-demoteUnit' :: (KnownDimension d) => Unit m d ExactPi -> AnyUnit-demoteUnit' = demoteUnit---- | Converts an 'AnyUnit' into a 'Unit' of statically known 'Dimension', or 'Nothing' if the dimension does not match.------ The result is represented in 'ExactPi', conversion to other representations is possible using 'changeRepApproximate'.------ The result is always tagged as 'NonMetric', conversion to a 'Metric' unit can be attempted using 'strengthen'.-promoteUnit :: forall d.(KnownDimension d) => AnyUnit -> Maybe (Unit 'NonMetric d ExactPi)-promoteUnit (AnyUnit dim n e) | dim == dim' = Just $ mkUnitR n e Dim.siUnit-                              | otherwise   = Nothing-  where-    dim' = dimension (Proxy :: Proxy d)---- | Forms the reciprocal of a dynamic unit.-recip :: AnyUnit -> AnyUnit-recip (AnyUnit d n e) = AnyUnit (D.recip d) (N.nOne N./ n) (P.recip e)---- | Forms the product of two dynamic units.-(*) :: AnyUnit -> AnyUnit -> AnyUnit-(AnyUnit d1 n1 e1) * (AnyUnit d2 n2 e2) = AnyUnit (d1 D.* d2) (n1 N.* n2) (e1 P.* e2)---- | Forms the quotient of two dynamic units.-(/) :: AnyUnit -> AnyUnit -> AnyUnit-(AnyUnit d1 n1 e1) / (AnyUnit d2 n2 e2) = AnyUnit (d1 D./ d2) (n1 N./ n2) (e1 P./ e2)---- | Raises a dynamic unit to an integer power.-(^) :: (P.Integral a) => AnyUnit -> a -> AnyUnit-(AnyUnit d n e) ^ x = AnyUnit (d D.^ P.fromIntegral x) (n N.^ P.fromIntegral x) (e P.^^ x)---- | Applies a prefix to a dynamic unit.--- Returns 'Nothing' if the 'Unit' was 'NonMetric' and thus could not accept a prefix.-applyPrefix :: N.Prefix -> AnyUnit -> Maybe AnyUnit-applyPrefix p (AnyUnit d n e) = do-                                  n' <- N.strengthen n-                                  let n'' = N.applyPrefix p n'-                                  let e' = (P.fromRational $ N.scaleFactor p) P.* e-                                  return $ AnyUnit d n'' e'---- | Forms a dynamic quantity by multipliying a number and a dynamic unit.-(*~) :: (Floating a, Promotable q) => a -> AnyUnit -> q a-x *~ (AnyUnit d _ e) = promotableIn $ AnyQuantity d (x P.* approximateValue e)---- | Divides a dynamic quantity by a dynamic unit, obtaining the numerical value of the quantity--- expressed in that unit if they are of the same physical dimension, or 'Nothing' otherwise.-(/~) :: (Floating a, Promotable q) => q a -> AnyUnit -> Maybe a-x /~ (AnyUnit d _ e) = case promotableOut x of-                         DynQuantity d' x' | d' `isCompatibleWith` d -> Just $ x' P./ approximateValue e-                                           | otherwise -> Nothing+{- |
+    Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter
+    License    : BSD3
+
+    Maintainer : bjorn@buckwalter.se
+    Stability  : Stable
+    Portability: GHC only?
+
+Defines types for manipulation of units and quantities without phantom types for their dimensions.
+-}
+
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module Numeric.Units.Dimensional.Dynamic
+(
+  -- * Dynamic Quantities
+  AnyQuantity
+, DynQuantity
+, Demotable
+, Promotable
+, HasDynamicDimension(..), DynamicDimension(..)
+, promoteQuantity, demoteQuantity
+, (*~), (/~), invalidQuantity, polydimensionalZero
+  -- * Dynamic Units
+, AnyUnit
+, demoteUnit, promoteUnit, demoteUnit'
+, siUnit, anyUnitName
+  -- ** Arithmetic on Dynamic Units
+, (*), (/), (^), recip, applyPrefix
+) where
+
+import Control.DeepSeq
+import Control.Monad
+import Data.Data
+import Data.ExactPi
+import Data.Kind
+import Data.Semigroup (Semigroup(..))
+import Data.Monoid (Monoid(..))
+import GHC.Generics
+import Prelude (Eq(..), Num, Fractional, Floating, Show(..), Bool(..), Maybe(..), (.), ($), (++), (&&), id, otherwise, error)
+import qualified Prelude as P
+import Numeric.Units.Dimensional hiding ((*~), (/~), (*), (/), (^), recip, nroot, siUnit)
+import qualified Numeric.Units.Dimensional as Dim
+import Numeric.Units.Dimensional.Coercion
+import Numeric.Units.Dimensional.UnitNames (UnitName, baseUnitName)
+import qualified Numeric.Units.Dimensional.UnitNames.InterchangeNames as I
+import qualified Numeric.Units.Dimensional.UnitNames as N
+import Numeric.Units.Dimensional.Dimensions.TermLevel (HasDynamicDimension(..), DynamicDimension(..), matchDimensions, isCompatibleWith)
+import qualified Numeric.Units.Dimensional.Dimensions.TermLevel as D
+
+-- | The class of types that can be used to model 'Quantity's that are certain to have a value with
+-- some dimension.
+class Demotable (q :: Type -> Type) where
+  demotableOut :: q a -> AnyQuantity a
+
+-- | The class of types that can be used to model 'Quantity's whose 'Dimension's are
+-- only known dynamically.
+class Promotable (q :: Type -> Type) where
+  promotableIn :: AnyQuantity a -> q a
+  promotableOut :: q a -> DynQuantity a
+
+-- | Forgets information about a 'Quantity' or 'AnyQuantity', yielding an 'AnyQuantity' or a 'DynQuantity'.
+demoteQuantity :: (Demotable q, Promotable d) => q a -> d a
+demoteQuantity = promotableIn . demotableOut
+
+-- | Converts a dynamic quantity such as an 'AnyQuantity' or a 'DynQuantity' into a
+-- 'Quantity', or to 'Nothing' if the dynamic quantity cannot be represented in the
+-- narrower result type.
+promoteQuantity :: forall a d q.(Promotable q, KnownDimension d) => q a -> Maybe (Quantity d a)
+promoteQuantity = promoteQ . promotableOut
+  where
+    dim' = dimension (Proxy :: Proxy d)
+    promoteQ (DynQuantity d v) | d `isCompatibleWith` dim' = Just . Quantity $ v
+                               | otherwise                 = Nothing
+
+instance (KnownDimension d) => Demotable (Quantity d) where
+  demotableOut q@(Quantity x) = AnyQuantity (dimension q) x
+
+-- | A 'Quantity' whose 'Dimension' is only known dynamically.
+data AnyQuantity a = AnyQuantity !Dimension' !a
+  deriving (Eq, Data, Generic, Generic1, Typeable)
+
+instance (Show a) => Show (AnyQuantity a) where
+  show (AnyQuantity d a) | d == D.dOne = show a
+                         | otherwise   = (show a) ++ " " ++ (show . baseUnitName $ d)
+
+instance HasDynamicDimension (AnyQuantity a) where
+
+instance HasDimension (AnyQuantity a) where
+  dimension (AnyQuantity d _) = d
+
+instance NFData a => NFData (AnyQuantity a) -- instance is derived from Generic instance
+
+instance Promotable AnyQuantity where
+  promotableIn = id
+  promotableOut (AnyQuantity d a) = DynQuantity (SomeDimension d) a
+
+instance Demotable AnyQuantity where
+  demotableOut = id
+
+-- | 'AnyQuantity's form a 'Semigroup' under multiplication, but not under addition because
+-- they may not be added together if their dimensions do not match.
+instance Num a => Semigroup (AnyQuantity a) where
+  (AnyQuantity d1 a1) <> (AnyQuantity d2 a2) = AnyQuantity (d1 D.* d2) (a1 P.* a2)
+
+-- | 'AnyQuantity's form a 'Monoid' under multiplication, but not under addition because
+-- they may not be added together if their dimensions do not match.
+instance Num a => Monoid (AnyQuantity a) where
+  mempty = demoteQuantity (1 Dim.*~ one)
+  mappend = (Data.Semigroup.<>)
+
+-- | Possibly a 'Quantity' whose 'Dimension' is only known dynamically.
+--
+-- By modeling the absence of a value, this type differs from 'AnyQuantity' in that it may
+-- not be a 'Quantity' of any 'Dimension' whatsoever, but in exchange it gains instances
+-- for the common numeric classes. It's therefore useful for manipulating, and not merely storing,
+-- quantities of unknown dimension.
+--
+-- This type also contains a 'polydimensionalZero', representing zero value of any dimension.
+--
+-- Note that the 'Eq' instance for 'DynQuantity' equates all representations of an invalid value,
+-- and also does not equate polydimensional zero with zero of any specific dimension.
+data DynQuantity a = DynQuantity !DynamicDimension a -- we can't have strictness annotation on a as it is sometimes undefined
+  deriving (Data, Generic, Generic1, Typeable)
+
+instance Eq a => Eq (DynQuantity a) where
+  (DynQuantity NoDimension _) == (DynQuantity NoDimension _) = True -- all invalid quantities are equal
+  (DynQuantity NoDimension _) == _                           = False -- invalid quanties are not equal to any other quantity
+  _                           == (DynQuantity NoDimension _) = False
+  (DynQuantity d1 v1)         == (DynQuantity d2 v2)         = d1 == d2 && v1 == v2
+
+instance NFData a => NFData (DynQuantity a) -- instance is derived from Generic instance
+
+instance Show a => Show (DynQuantity a) where
+  show (DynQuantity NoDimension _) = "invalidQuantity"
+  show (DynQuantity AnyDimension v) = show v
+  show (DynQuantity (SomeDimension d) v) = show $ AnyQuantity d v
+
+instance Promotable DynQuantity where
+  promotableIn (AnyQuantity d a) = DynQuantity (SomeDimension d) a
+  promotableOut = id
+
+instance HasDynamicDimension (DynQuantity a) where
+  dynamicDimension (DynQuantity d _) = d
+
+instance Num a => Num (DynQuantity a) where
+  x + y = liftDQ2 matchDimensions (P.+) x y
+  x - y = liftDQ2 matchDimensions (P.-) x y
+  x * y = liftDQ2 (valid2 (D.*)) (P.*) x y
+  negate = liftDQ id P.negate
+  abs = liftDQ id P.abs
+  signum = liftDQ (constant D.dOne) P.signum
+  fromInteger = demoteQuantity . (Dim.*~ one) . P.fromInteger
+
+instance Fractional a => Fractional (DynQuantity a) where
+  x / y = liftDQ2 (valid2 (D./)) (P./) x y
+  recip = liftDQ (valid D.recip) P.recip
+  fromRational = demoteQuantity . (Dim.*~ one) . P.fromRational
+
+instance Floating a => Floating (DynQuantity a) where
+  pi = demoteQuantity pi
+  exp = liftDimensionless P.exp
+  log = liftDimensionless P.log
+  sqrt = liftDQ (whenValid $ D.nroot 2) P.sqrt
+  (**) = liftDQ2 (matchDimensions3 $ SomeDimension D.dOne) (P.**)
+  logBase = liftDQ2 (matchDimensions3 $ SomeDimension D.dOne) P.logBase
+  sin = liftDimensionless P.sin
+  cos = liftDimensionless P.cos
+  tan = liftDimensionless P.tan
+  asin = liftDimensionless P.asin
+  acos = liftDimensionless P.acos
+  atan = liftDimensionless P.atan
+  sinh = liftDimensionless P.sinh
+  cosh = liftDimensionless P.cosh
+  tanh = liftDimensionless P.tanh
+  asinh = liftDimensionless P.asinh
+  acosh = liftDimensionless P.acosh
+  atanh = liftDimensionless P.atanh
+
+-- | 'DynQuantity's form a 'Semigroup' under multiplication, but not under addition because
+-- they may not be added together if their dimensions do not match.
+instance Num a => Semigroup (DynQuantity a) where
+    (<>) = (P.*)
+
+-- | 'DynQuantity's form a 'Monoid' under multiplication, but not under addition because
+-- they may not be added together if their dimensions do not match.
+instance Num a => Monoid (DynQuantity a) where
+  mempty = demoteQuantity (1 Dim.*~ one)
+  mappend = (Data.Semigroup.<>)
+
+-- | A 'DynQuantity' which does not correspond to a value of any dimension.
+invalidQuantity :: DynQuantity a
+invalidQuantity = DynQuantity NoDimension $ error "Attempt to evaluate the value of an invalid quantity."
+
+-- | A 'DynQuantity' which corresponds to zero value of any dimension.
+--
+-- When combined through arithmetic with other 'DynQuantity's, inference is performed. For example,
+-- adding a length to polydimensional zero produces that length. Adding two polydimensional zeros produces another.
+-- Taking the sine of a polydimensional zero interprets it as a dimensionless zero and produces a dimensionless result.
+--
+-- Note that division by 'polydimensionalZero' produces a polydimensional result, which may be an error or some representation
+-- of infinity, as determined by the underlying arithmetic type. This behavior was chosen for consistency with the behavior of division
+-- by zero 'DynQuantity's of a specific dimension.
+polydimensionalZero :: (Num a) => DynQuantity a
+polydimensionalZero = DynQuantity AnyDimension 0
+
+-- Lifts a function which is only valid on dimensionless quantities into a function on DynQuantitys.
+liftDimensionless :: (a -> a) -> DynQuantity a -> DynQuantity a
+liftDimensionless f = liftDQ (matchDimensions $ SomeDimension D.dOne) f
+
+-- Lifts a function on values into a function on DynQuantitys.
+liftDQ :: (DynamicDimension -> DynamicDimension) -- ^ How the function operates on dimensions.
+       -> (a -> a) -- ^ How the function operates on values.
+       -> DynQuantity a -> DynQuantity a
+liftDQ fd fv (DynQuantity d v) = case fd d of
+                                   NoDimension -> invalidQuantity
+                                   d' -> DynQuantity d' $ fv v
+
+-- Lifts a function on values into a function on DynQuantitys.
+--
+-- This works by treating polydimensional zeros as dimensionless zeros. If that is not the desired behavior,
+-- handle polydimensional zeros first and then call this function.
+liftDQ2 :: (DynamicDimension -> DynamicDimension -> DynamicDimension)
+        -> (a -> a -> a)
+        -> DynQuantity a -> DynQuantity a -> DynQuantity a
+liftDQ2 fd fv (DynQuantity d1 v1) (DynQuantity d2 v2) = case fd d1 d2 of
+                                                          NoDimension -> invalidQuantity
+                                                          d' -> DynQuantity d' $ fv v1 v2
+
+-- Transforms a dynamic dimension in a way which is always valid
+valid :: (Dimension' -> Dimension') -> DynamicDimension -> DynamicDimension
+valid _ AnyDimension      = AnyDimension
+valid f (SomeDimension d) = SomeDimension (f d)
+valid _ NoDimension       = NoDimension
+
+whenValid :: (Dimension' -> Maybe Dimension') -> DynamicDimension -> DynamicDimension
+whenValid _ AnyDimension = AnyDimension
+whenValid f (SomeDimension d) | Just d' <- f d = SomeDimension d'
+whenValid _ _ = NoDimension
+
+constant :: Dimension' -> DynamicDimension -> DynamicDimension
+constant d AnyDimension = SomeDimension d
+constant d (SomeDimension _) = SomeDimension d
+constant _ _ = NoDimension
+
+-- Transforms two dynamic dimensions in a way which is always valid
+valid2 :: (Dimension' -> Dimension' -> Dimension') -> DynamicDimension -> DynamicDimension -> DynamicDimension
+valid2 _ AnyDimension       (SomeDimension _)  = AnyDimension
+valid2 _ (SomeDimension _)  AnyDimension       = AnyDimension
+valid2 _ AnyDimension       AnyDimension       = AnyDimension
+valid2 f (SomeDimension d1) (SomeDimension d2) = SomeDimension (f d1 d2)
+valid2 _ _                  _                  = NoDimension
+
+matchDimensions3 :: DynamicDimension -> DynamicDimension -> DynamicDimension -> DynamicDimension
+matchDimensions3 x y z = matchDimensions x (matchDimensions y z)
+
+-- | A 'Unit' whose 'Dimension' is only known dynamically.
+data AnyUnit = AnyUnit Dimension' (UnitName 'NonMetric) ExactPi
+  deriving (Generic, Typeable)
+
+instance Show AnyUnit where
+  show (AnyUnit _ n e) = (show n) ++ " =def= " ++ (show e) ++ " of the SI base unit"
+
+instance HasDynamicDimension AnyUnit where
+
+instance HasDimension AnyUnit where
+  dimension (AnyUnit d _ _) = d
+
+instance I.HasInterchangeName AnyUnit where
+  interchangeName (AnyUnit _ n _) = I.interchangeName n
+
+-- | 'AnyUnit's form a 'Semigroup' under multiplication.
+instance Semigroup AnyUnit where
+  (<>) = (Numeric.Units.Dimensional.Dynamic.*)
+
+-- | 'AnyUnit's form a 'Monoid' under multiplication.
+instance Monoid AnyUnit where
+  mempty = demoteUnit' one
+  mappend = (Data.Semigroup.<>)
+
+anyUnitName :: AnyUnit -> UnitName 'NonMetric
+anyUnitName (AnyUnit _ n _) = n
+
+-- | The dynamic SI coherent unit of a given dimension.
+siUnit :: Dimension' -> AnyUnit
+siUnit d = AnyUnit d (baseUnitName d) 1
+
+-- | Converts a 'Unit' of statically known 'Dimension' into an 'AnyUnit'.
+demoteUnit :: forall m d a.(KnownDimension d) => Unit m d a -> AnyUnit
+demoteUnit u = AnyUnit dim (name $ weaken u) (exactValue u)
+  where
+    dim = dimension (Proxy :: Proxy d)
+
+-- | Converts a 'Unit' of statically known 'Dimension' into an 'AnyUnit'.
+--
+-- This is the same as the more general 'demoteUnit' but is useful in certain circumstances to avoid
+-- needlessly introducing an ambiguous type variable.
+demoteUnit' :: (KnownDimension d) => Unit m d ExactPi -> AnyUnit
+demoteUnit' = demoteUnit
+
+-- | Converts an 'AnyUnit' into a 'Unit' of statically known 'Dimension', or 'Nothing' if the dimension does not match.
+--
+-- The result is represented in 'ExactPi', conversion to other representations is possible using 'changeRepApproximate'.
+--
+-- The result is always tagged as 'NonMetric', conversion to a 'Metric' unit can be attempted using 'strengthen'.
+promoteUnit :: forall d.(KnownDimension d) => AnyUnit -> Maybe (Unit 'NonMetric d ExactPi)
+promoteUnit (AnyUnit dim n e) | dim == dim' = Just $ mkUnitR n e Dim.siUnit
+                              | otherwise   = Nothing
+  where
+    dim' = dimension (Proxy :: Proxy d)
+
+-- | Forms the reciprocal of a dynamic unit.
+recip :: AnyUnit -> AnyUnit
+recip (AnyUnit d n e) = AnyUnit (D.recip d) (N.nOne N./ n) (P.recip e)
+
+-- | Forms the product of two dynamic units.
+(*) :: AnyUnit -> AnyUnit -> AnyUnit
+(AnyUnit d1 n1 e1) * (AnyUnit d2 n2 e2) = AnyUnit (d1 D.* d2) (n1 N.* n2) (e1 P.* e2)
+
+-- | Forms the quotient of two dynamic units.
+(/) :: AnyUnit -> AnyUnit -> AnyUnit
+(AnyUnit d1 n1 e1) / (AnyUnit d2 n2 e2) = AnyUnit (d1 D./ d2) (n1 N./ n2) (e1 P./ e2)
+
+-- | Raises a dynamic unit to an integer power.
+(^) :: (P.Integral a) => AnyUnit -> a -> AnyUnit
+(AnyUnit d n e) ^ x = AnyUnit (d D.^ P.fromIntegral x) (n N.^ P.fromIntegral x) (e P.^^ x)
+
+-- | Applies a prefix to a dynamic unit.
+-- Returns 'Nothing' if the 'Unit' was 'NonMetric' and thus could not accept a prefix.
+applyPrefix :: N.Prefix -> AnyUnit -> Maybe AnyUnit
+applyPrefix p (AnyUnit d n e) = do
+                                  n' <- N.strengthen n
+                                  let n'' = N.applyPrefix p n'
+                                  let e' = (P.fromRational $ N.scaleFactor p) P.* e
+                                  return $ AnyUnit d n'' e'
+
+-- | Forms a dynamic quantity by multipliying a number and a dynamic unit.
+(*~) :: (Floating a, Promotable q) => a -> AnyUnit -> q a
+x *~ (AnyUnit d _ e) = promotableIn $ AnyQuantity d (x P.* approximateValue e)
+
+-- | Divides a dynamic quantity by a dynamic unit, obtaining the numerical value of the quantity
+-- expressed in that unit if they are of the same physical dimension, or 'Nothing' otherwise.
+(/~) :: (Floating a, Promotable q) => q a -> AnyUnit -> Maybe a
+x /~ (AnyUnit d _ e) = case promotableOut x of
+                         DynQuantity d' x' | d' `isCompatibleWith` d -> Just $ x' P./ approximateValue e
+                                           | otherwise -> Nothing
src/Numeric/Units/Dimensional/FixedPoint.hs view
@@ -1,373 +1,373 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeOperators #-}--{- |-    Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter-    License    : BSD3--    Maintainer : bjorn@buckwalter.se-    Stability  : Experimental-    Portability: GHC only?--Defines types for manipulation of quantities with fixed point representations.--}-module Numeric.Units.Dimensional.FixedPoint-(-  -- * Types-  -- $types-  Dimensional,-  Unit, Quantity, SQuantity,-  Metricality(..),-  -- * Physical Dimensions-  Dimension (Dim),-  -- ** Dimension Arithmetic-  type (*), type (/), type (^), NRoot, Recip,-  -- ** Term Level Representation of Dimensions-  Dimension' (Dim'), HasDimension(..), KnownDimension,-  -- * Dimensional Arithmetic-  (*~), (/~),-  (*), (/), (+), (-),-  negate, abs,-  -- ** Transcendental Functions-  -- *** Via 'Double'-  expD, logD, sinD, cosD, tanD, asinD, acosD, atanD, sinhD, coshD, tanhD, asinhD, acoshD, atanhD, atan2D,-  -- *** Via arbitary 'Floating' type-  expVia, logVia, sinVia, cosVia, tanVia, asinVia, acosVia, atanVia, sinhVia, coshVia, tanhVia, asinhVia, acoshVia, atanhVia, atan2Via,-  -- ** Operations on Collections-  (*~~), (/~~), sum, mean, -- dimensionlessLength, nFromTo,-  -- ** Conversion Between Representations-  rescale, rescaleFinite, rescaleD, rescaleVia, KnownVariant(dmap), changeRep, changeRepRound, changeRepApproximate,-  -- * Dimension Synonyms-  DOne, DLength, DMass, DTime, DElectricCurrent, DThermodynamicTemperature, DAmountOfSubstance, DLuminousIntensity,-  -- * Quantity Synonyms-  Dimensionless, Length, Mass, Time, ElectricCurrent, ThermodynamicTemperature, AmountOfSubstance, LuminousIntensity,-  -- * Constants-  _0, epsilon,-  -- $possibly-imprecise-constants-  _1, _2, _3, _4, _5, _6, _7, _8, _9, pi, tau,-  -- * Constructing Units-  siUnit, one, mkUnitR, mkUnitQ, mkUnitZ,-  -- * Unit Metadata-  name, exactValue, weaken, strengthen, exactify,-  -- * Commonly Used Type Synonyms-  -- $synonyms-  type Q, type QScale, type Angle8, type Angle16, type Angle32-)-where--import Data.Bits-import Data.ExactPi-import qualified Data.ExactPi.TypeLevel as E-import Data.Int-import Data.Proxy-import qualified Data.Foldable as F-import Data.Ratio-import qualified GHC.TypeLits as N-import Numeric.Units.Dimensional.Coercion-import Numeric.Units.Dimensional.Internal-import Numeric.Units.Dimensional.Prelude hiding ((*~), (/~), (+), (-), recip, negate, abs, (*~~), (/~~), sum, mean, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, pi, tau, changeRep)-import Numeric.Units.Dimensional.Variants hiding (type (*), type (/))-import qualified Numeric.Units.Dimensional.UnitNames as Name-import qualified Prelude as P--{- $types--We provide access to the same 'Dimensional', 'Unit', and 'Quantity' types as are exposed by "Numeric.Units.Dimensional", but additionally-offer the 'SQuantity' type to represent scaled quantities. Fixed-point quantities are quantities backed by integers, it is frequently-necessary to scale those integers into a range appropriate for the physical problem at hand.---}--{---Arithmetic Operators and Functions--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 6  +, ----- | Adds two possibly scaled 'SQuantity's, preserving any scale factor.------ Use in conjunction with 'changeRepRound' to combine quantities with differing scale factors.-(+) :: (Num a) => SQuantity s d a -> SQuantity s d a -> SQuantity s d a-(+) = liftQ2 (P.+)---- | Subtracts one possibly scaled 'SQuantity' from another, preserving any scale factor.------ Use in conjunction with 'changeRepRound' to combine quantities with differing scale factors.-(-) :: (Num a) => SQuantity s d a -> SQuantity s d a -> SQuantity s d a-(-) = liftQ2 (P.-)---- | Takes the absolute value of a possibly scaled 'SQuantity', preserving any scale factor.-abs :: (Num a) => SQuantity s d a -> SQuantity s d a-abs = liftQ (P.abs)---- | Negates the value of a possibly scaled 'SQuantity', preserving any scale factor.-negate :: (Num a) => SQuantity s d a -> SQuantity s d a-negate = liftQ (P.negate)--infixl 7  *~~, /~~---- | Applies '*~' to all values in a functor.-(*~~) :: (Functor f, RealFrac a, Integral b, E.MinCtxt s a) => f a -> Unit m d a -> f (SQuantity s d b)-xs *~~ u = fmap (*~ u) xs---- | Applies '/~' to all values in a functor.-(/~~) :: (Functor f, Real a, Fractional b,  E.MinCtxt s b) => f (SQuantity s d a) -> Unit m d b -> f b-xs /~~ u = fmap (/~ u) xs---- | The sum of all elements in a list.-sum :: (Num a, F.Foldable f) => f (SQuantity s d a) -> SQuantity s d a-sum = F.foldr (+) _0---- | The arithmetic mean of all elements in a list.-mean :: (Fractional a, F.Foldable f) => f (SQuantity s d a) -> SQuantity s d a-mean = reduce . F.foldr accumulate (_0, 0 :: Int)-  where-    reduce (s, n) = dmap (P./ fromIntegral n) s-    accumulate val (accum, count) = (accum + val, count P.+ 1)--expD, logD, sinD, cosD, tanD, asinD, acosD, atanD, sinhD, coshD, tanhD, asinhD, acoshD, atanhD-  :: (Integral a, Integral b, E.MinCtxt s1 Double, E.MinCtxt s2 Double) => SQuantity s1 DOne a -> SQuantity s2 DOne b-expD = expVia (Proxy :: Proxy P.Double)-logD = logVia (Proxy :: Proxy P.Double)-sinD = sinVia (Proxy :: Proxy P.Double)-cosD = cosVia (Proxy :: Proxy P.Double)-tanD = tanVia (Proxy :: Proxy P.Double)-asinD = asinVia (Proxy :: Proxy P.Double)-acosD = acosVia (Proxy :: Proxy P.Double)-atanD = atanVia (Proxy :: Proxy P.Double)-sinhD = sinhVia (Proxy :: Proxy P.Double)-coshD = coshVia (Proxy :: Proxy P.Double)-tanhD = tanhVia (Proxy :: Proxy P.Double)-asinhD = asinhVia (Proxy :: Proxy P.Double)-acoshD = acoshVia (Proxy :: Proxy P.Double)-atanhD = atanhVia (Proxy :: Proxy P.Double)---- | The standard two argument arctangent function.--- Since it interprets its two arguments in comparison with one another, the input may have any dimension.-atan2D :: (Integral a, Integral b, E.MinCtxt s1 Double, E.MinCtxt s2 Double, E.MinCtxt s3 Double) => SQuantity s1 DOne a -> SQuantity s2 DOne a -> SQuantity s3 DOne b-atan2D = atan2Via (Proxy :: Proxy P.Double)--expVia, logVia, sinVia, cosVia, tanVia, asinVia, acosVia, atanVia, sinhVia, coshVia, tanhVia, asinhVia, acoshVia, atanhVia-  :: (Integral a, RealFrac b, Floating b, Integral c, E.MinCtxt s1 b, E.MinCtxt s2 b) => Proxy b -> SQuantity s1 DOne a -> SQuantity s2 DOne c-expVia = liftDimensionlessVia P.exp-logVia = liftDimensionlessVia P.log-sinVia = liftDimensionlessPeriodicVia (2 P.* P.pi) P.sin-cosVia = liftDimensionlessPeriodicVia (2 P.* P.pi) P.cos-tanVia = liftDimensionlessPeriodicVia P.pi P.tan-asinVia = liftDimensionlessVia P.asin-acosVia = liftDimensionlessVia P.acos-atanVia = liftDimensionlessVia P.atan-sinhVia = liftDimensionlessPeriodicVia (2 P.* P.pi) P.sinh-coshVia = liftDimensionlessPeriodicVia (2 P.* P.pi) P.cosh-tanhVia = liftDimensionlessPeriodicVia P.pi P.tanh-asinhVia = liftDimensionlessVia P.asinh-acoshVia = liftDimensionlessVia P.acosh-atanhVia = liftDimensionlessVia P.atanh---- | The standard two argument arctangent function.--- Since it interprets its two arguments in comparison with one another, the input may have any dimension.-atan2Via :: forall s1 s2 s3 a b c d.(Integral a, RealFloat b, Integral c, E.MinCtxt s1 b, E.MinCtxt s2 b, E.MinCtxt s3 b, KnownDimension d) => Proxy b -> SQuantity s1 d a -> SQuantity s2 d a -> SQuantity s3 DOne c-atan2Via _ y x = (*~ siUnit) $ (P.atan2 :: b -> b -> b) (y /~ siUnit) (x /~ siUnit)---- | Lift a function on dimensionless values of a specified intermediate type to operate on possibly scaled dimensionless.-liftDimensionlessVia :: forall s1 s2 a b c.(Real a, RealFrac b, Integral c, E.MinCtxt s1 b, E.MinCtxt s2 b) => (b -> b) -> Proxy b -> SQuantity s1 DOne a -> SQuantity s2 DOne c-liftDimensionlessVia f _ = (*~ siUnit) . (f :: b -> b) . (/~ siUnit)---- | Lift a periodic function on dimensionless values of a specified intermediate type to operate on possibly scaled dimensionless.------ If the scale factor of the input type is an exact integer divisor of the function's period, the argument--- will be clamped via an integer `mod` operation prior to applying the function to avoid errors introduced by a floating point modulus.-liftDimensionlessPeriodicVia :: forall s1 s2 a b c.(Integral a, RealFrac b, Floating b, Integral c, E.MinCtxt s1 b, E.MinCtxt s2 b) => ExactPi -> (forall d.Floating d => d -> d) -> Proxy b -> SQuantity s1 DOne a -> SQuantity s2 DOne c-liftDimensionlessPeriodicVia p f proxy | Just p'' <- p', p'' /= 0 = (liftDimensionlessVia f proxy) . dmap (`mod` p'')-                                       | otherwise = liftDimensionlessVia f proxy-  where-    p' :: Maybe a-    p' = fmap fromInteger . toExactInteger . P.recip . (P./ p) . E.exactPiVal $ (Proxy :: Proxy s1)--{--We give '*~' and '/~' the same fixity as '*' and '/' defined below.-Note that this necessitates the use of parenthesis when composing-units using '*' and '/', e.g. "1 *~ (meter / second)".--}--infixl 7  *~, /~---- | Forms a possibly scaled 'SQuantity' by multipliying a number and a unit.-(*~) :: forall s m d a b.(RealFrac a, Integral b, E.MinCtxt s a) => a -> Unit m d a -> SQuantity s d b-x *~ (Unit _ _ y) = Quantity . round $ (x P.* y P./ s)-  where-    s = E.injMin (Proxy :: Proxy s)---- | Divides a possibly scaled 'SQuantity' by a 'Unit' of the same physical dimension, obtaining the--- numerical value of the quantity expressed in that unit.-(/~) :: forall s m d a b.(Real a, Fractional b,  E.MinCtxt s b) => SQuantity s d a -> Unit m d b -> b-(Quantity x) /~ (Unit _ _ y) = ((realToFrac x) P.* s P./ y)-  where-    s = E.injMin (Proxy :: Proxy s)--{---Rescaling Operations---}---- | Rescales a fixed point quantity, accomodating changes both in its scale factor and its representation type.------ Note that this uses an arbitrary precision representation of 'pi', which may be quite slow.-rescale :: forall a b d s1 s2.(Integral a, Integral b, E.KnownExactPi s1, E.KnownExactPi s2) => SQuantity s1 d a -> SQuantity s2 d b-rescale | Just s' <- toExactInteger s           = viaInteger (P.* s')-        | Just s' <- toExactInteger (P.recip s) = viaInteger (`P.quot` s')-        | Just q  <- toExactRational s          = viaInteger $ timesRational q-        | otherwise                             = viaInteger $ \x -> fixedPoint (fmap (($ x) . timesRational) (rationalApproximations s))-  where-    s = (s1' P./ s2')-    s1' = E.exactPiVal (Proxy :: Proxy s1)-    s2' = E.exactPiVal (Proxy :: Proxy s2)-    timesRational :: Rational -> Integer -> Integer-    timesRational q = (`P.quot` denominator q) . (P.* numerator q)---- | Rescales a fixed point quantity, accomodating changes both in its scale factor and its representation type.------ Expected to outperform `rescale` when a `FiniteBits` context is available for the source and destination representation types.-rescaleFinite :: (Integral a, FiniteBits a, Integral b, FiniteBits b, E.KnownExactPi s1, E.KnownExactPi s2) => SQuantity s1 d a -> SQuantity s2 d b-rescaleFinite = rescale -- It should be possible to do this more quickly, since we have a priori knowledge of how well we need to approximate the result---- | Approximately rescales a fixed point quantity, accomodating changes both in its scale factor and its representation type.------ Uses approximate arithmetic by way of an intermediate `Floating` type, to which a proxy must be supplied.-rescaleVia :: forall a b c d s1 s2.(Integral a, RealFrac b, Floating b, Integral c, E.KnownExactPi s1, E.KnownExactPi s2) => Proxy b -> SQuantity s1 d a -> SQuantity s2 d c-rescaleVia _ = viaIntermediate (P.* s)-  where-    s = approximateValue (s1' P./ s2') :: b-    s1' = E.exactPiVal $ (Proxy :: Proxy s1)-    s2' = E.exactPiVal $ (Proxy :: Proxy s2)---- | Approximately rescales a fixed point quantity, accomodating changes both in its scale factor and its representation type.------ Uses approximate arithmetic by way of an intermediate `Double` representation.-rescaleD :: (Integral a, Integral b, E.KnownExactPi s1, E.KnownExactPi s2) => SQuantity s1 d a -> SQuantity s2 d b-rescaleD = rescaleVia (Proxy :: Proxy Double)---- Note that this does not respect scaling factors at all.-viaInteger :: (Integral a, Integral b) => (P.Integer -> P.Integer) -> SQuantity s1 d a -> SQuantity s2 d b-viaInteger f = Quantity . fromInteger . f . fromIntegral . unQuantity---- Note that this does not respect scaling factors at all.-viaIntermediate :: (Integral a, RealFrac b, Integral c) => (b -> b) -> SQuantity s1 d a -> SQuantity s2 d c-viaIntermediate f = Quantity . round . f . fromIntegral . unQuantity--fixedPoint :: (Eq a) => [a] -> a-fixedPoint []                     = error "Fixed point of empty list."-fixedPoint [x]                    = x-fixedPoint (x1:x2:xs) | x1 == x2  = x1-                      | otherwise = fixedPoint (x2:xs)--{---Changes of Representation---}---- | Convenient conversion between numerical types while retaining dimensional information.-changeRep :: forall v1 v2 d a b.-            (KnownVariant v1, KnownVariant v2,-             CompatibleVariants v1 v2,-             E.MinCtxt (ScaleFactor v1 E./ ScaleFactor v2) b,-             Real a, Fractional b)-          => Dimensional v1 d a -> Dimensional v2 d b-changeRep = liftD (P.* s) ((P.* s') . realToFrac) Name.weaken-  where-    p :: Proxy (ScaleFactor v1 E./ ScaleFactor v2)-    p = Proxy-    s = E.exactPiVal p-    s' = E.injMin p---- | Convenient conversion to types with `Integral` representations using `round`.-changeRepRound :: forall v1 v2 d a b.-                 (KnownVariant v1, KnownVariant v2,-                  CompatibleVariants v1 v2,-                  E.MinCtxt (ScaleFactor v1 E./ ScaleFactor v2) a,-                  RealFrac a, Integral b)-               => Dimensional v1 d a -> Dimensional v2 d b-changeRepRound = liftD (P.* s) (round . (P.* s')) Name.weaken-  where-    p :: Proxy (ScaleFactor v1 E./ ScaleFactor v2)-    p = Proxy-    s = E.exactPiVal p-    s' = E.injMin p--{---Useful Constant Values---}--{- $possibly-imprecise-constants--Note that, other than '_0' and 'epsilon', these constants may not be exactly representable with certain scale factors.---}---- | The constant for zero is polymorphic, allowing--- it to express zero 'Length' or 'Capacitance' or 'Velocity' etc, in addition--- to the 'Dimensionless' value zero.-_0 :: Num a => SQuantity s d a-_0 = Quantity 0--_1, _2, _3, _4, _5, _6, _7, _8, _9 :: (Integral a, E.KnownExactPi s) => SQuantity s DOne a-_1 = rescale (epsilon :: SQuantity E.One DOne Integer)-_2 = rescale (epsilon :: SQuantity (E.ExactNatural 2) DOne Integer)-_3 = rescale (epsilon :: SQuantity (E.ExactNatural 3) DOne Integer)-_4 = rescale (epsilon :: SQuantity (E.ExactNatural 4) DOne Integer)-_5 = rescale (epsilon :: SQuantity (E.ExactNatural 5) DOne Integer)-_6 = rescale (epsilon :: SQuantity (E.ExactNatural 6) DOne Integer)-_7 = rescale (epsilon :: SQuantity (E.ExactNatural 7) DOne Integer)-_8 = rescale (epsilon :: SQuantity (E.ExactNatural 8) DOne Integer)-_9 = rescale (epsilon :: SQuantity (E.ExactNatural 9) DOne Integer)--pi :: (Integral a, E.KnownExactPi s) => SQuantity s DOne a-pi = rescale (epsilon :: SQuantity E.Pi DOne Integer)---- | Twice 'pi'.------ For background on 'tau' see http://tauday.com/tau-manifesto (but also--- feel free to review http://www.thepimanifesto.com).-tau :: (Integral a, E.KnownExactPi s) => SQuantity s DOne a-tau = rescale (epsilon :: SQuantity (E.ExactNatural 2 E.* E.Pi) DOne Integer)---- | The least positive representable value in a given fixed-point scaled quantity type.-epsilon :: (Integral a) => SQuantity s d a-epsilon = Quantity 1--{- $synonyms--These type synonyms for commonly used fixed-point types are provided for convenience.---}---- | A binary scale factor.-type QScale n = (E.One E./ (E.ExactNatural (2 N.^ n)))---- | A dimensionless number with `n` fractional bits, using a representation of type `a`.-type Q n a = SQuantity (QScale n) DOne a---- | A single-turn angle represented as a signed 8-bit integer.-type Angle8  = SQuantity (E.Pi E.* (QScale 7))  DPlaneAngle Int8---- | A single-turn angle represented as a signed 16-bit integer.-type Angle16 = SQuantity (E.Pi E.* (QScale 15)) DPlaneAngle Int16---- | A single-turn angle represented as a signed 32-bit integer.-type Angle32 = SQuantity (E.Pi E.* (QScale 31)) DPlaneAngle Int32+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeOperators #-}
+
+{- |
+    Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter
+    License    : BSD3
+
+    Maintainer : bjorn@buckwalter.se
+    Stability  : Experimental
+    Portability: GHC only?
+
+Defines types for manipulation of quantities with fixed point representations.
+-}
+module Numeric.Units.Dimensional.FixedPoint
+(
+  -- * Types
+  -- $types
+  Dimensional,
+  Unit, Quantity, SQuantity,
+  Metricality(..),
+  -- * Physical Dimensions
+  Dimension (Dim),
+  -- ** Dimension Arithmetic
+  type (*), type (/), type (^), NRoot, Recip,
+  -- ** Term Level Representation of Dimensions
+  Dimension' (Dim'), HasDimension(..), KnownDimension,
+  -- * Dimensional Arithmetic
+  (*~), (/~),
+  (*), (/), (+), (-),
+  negate, abs,
+  -- ** Transcendental Functions
+  -- *** Via 'Double'
+  expD, logD, sinD, cosD, tanD, asinD, acosD, atanD, sinhD, coshD, tanhD, asinhD, acoshD, atanhD, atan2D,
+  -- *** Via arbitary 'Floating' type
+  expVia, logVia, sinVia, cosVia, tanVia, asinVia, acosVia, atanVia, sinhVia, coshVia, tanhVia, asinhVia, acoshVia, atanhVia, atan2Via,
+  -- ** Operations on Collections
+  (*~~), (/~~), sum, mean, -- dimensionlessLength, nFromTo,
+  -- ** Conversion Between Representations
+  rescale, rescaleFinite, rescaleD, rescaleVia, KnownVariant(dmap), changeRep, changeRepRound, changeRepApproximate,
+  -- * Dimension Synonyms
+  DOne, DLength, DMass, DTime, DElectricCurrent, DThermodynamicTemperature, DAmountOfSubstance, DLuminousIntensity,
+  -- * Quantity Synonyms
+  Dimensionless, Length, Mass, Time, ElectricCurrent, ThermodynamicTemperature, AmountOfSubstance, LuminousIntensity,
+  -- * Constants
+  _0, epsilon,
+  -- $possibly-imprecise-constants
+  _1, _2, _3, _4, _5, _6, _7, _8, _9, pi, tau,
+  -- * Constructing Units
+  siUnit, one, mkUnitR, mkUnitQ, mkUnitZ,
+  -- * Unit Metadata
+  name, exactValue, weaken, strengthen, exactify,
+  -- * Commonly Used Type Synonyms
+  -- $synonyms
+  type Q, type QScale, type Angle8, type Angle16, type Angle32
+)
+where
+
+import Data.Bits
+import Data.ExactPi
+import qualified Data.ExactPi.TypeLevel as E
+import Data.Int
+import Data.Proxy
+import qualified Data.Foldable as F
+import Data.Ratio
+import qualified GHC.TypeLits as N
+import Numeric.Units.Dimensional.Coercion
+import Numeric.Units.Dimensional.Internal
+import Numeric.Units.Dimensional.Prelude hiding ((*~), (/~), (+), (-), recip, negate, abs, (*~~), (/~~), sum, mean, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, pi, tau, changeRep)
+import Numeric.Units.Dimensional.Variants hiding (type (*), type (/))
+import qualified Numeric.Units.Dimensional.UnitNames as Name
+import qualified Prelude as P
+
+{- $types
+
+We provide access to the same 'Dimensional', 'Unit', and 'Quantity' types as are exposed by "Numeric.Units.Dimensional", but additionally
+offer the 'SQuantity' type to represent scaled quantities. Fixed-point quantities are quantities backed by integers, it is frequently
+necessary to scale those integers into a range appropriate for the physical problem at hand.
+
+-}
+
+{-
+
+Arithmetic Operators and Functions
+
+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 6  +, -
+
+-- | Adds two possibly scaled 'SQuantity's, preserving any scale factor.
+--
+-- Use in conjunction with 'changeRepRound' to combine quantities with differing scale factors.
+(+) :: (Num a) => SQuantity s d a -> SQuantity s d a -> SQuantity s d a
+(+) = liftQ2 (P.+)
+
+-- | Subtracts one possibly scaled 'SQuantity' from another, preserving any scale factor.
+--
+-- Use in conjunction with 'changeRepRound' to combine quantities with differing scale factors.
+(-) :: (Num a) => SQuantity s d a -> SQuantity s d a -> SQuantity s d a
+(-) = liftQ2 (P.-)
+
+-- | Takes the absolute value of a possibly scaled 'SQuantity', preserving any scale factor.
+abs :: (Num a) => SQuantity s d a -> SQuantity s d a
+abs = liftQ (P.abs)
+
+-- | Negates the value of a possibly scaled 'SQuantity', preserving any scale factor.
+negate :: (Num a) => SQuantity s d a -> SQuantity s d a
+negate = liftQ (P.negate)
+
+infixl 7  *~~, /~~
+
+-- | Applies '*~' to all values in a functor.
+(*~~) :: (Functor f, RealFrac a, Integral b, E.MinCtxt s a) => f a -> Unit m d a -> f (SQuantity s d b)
+xs *~~ u = fmap (*~ u) xs
+
+-- | Applies '/~' to all values in a functor.
+(/~~) :: (Functor f, Real a, Fractional b,  E.MinCtxt s b) => f (SQuantity s d a) -> Unit m d b -> f b
+xs /~~ u = fmap (/~ u) xs
+
+-- | The sum of all elements in a list.
+sum :: (Num a, F.Foldable f) => f (SQuantity s d a) -> SQuantity s d a
+sum = F.foldr (+) _0
+
+-- | The arithmetic mean of all elements in a list.
+mean :: (Fractional a, F.Foldable f) => f (SQuantity s d a) -> SQuantity s d a
+mean = reduce . F.foldr accumulate (_0, 0 :: Int)
+  where
+    reduce (s, n) = dmap (P./ fromIntegral n) s
+    accumulate val (accum, count) = (accum + val, count P.+ 1)
+
+expD, logD, sinD, cosD, tanD, asinD, acosD, atanD, sinhD, coshD, tanhD, asinhD, acoshD, atanhD
+  :: (Integral a, Integral b, E.MinCtxt s1 Double, E.MinCtxt s2 Double) => SQuantity s1 DOne a -> SQuantity s2 DOne b
+expD = expVia (Proxy :: Proxy P.Double)
+logD = logVia (Proxy :: Proxy P.Double)
+sinD = sinVia (Proxy :: Proxy P.Double)
+cosD = cosVia (Proxy :: Proxy P.Double)
+tanD = tanVia (Proxy :: Proxy P.Double)
+asinD = asinVia (Proxy :: Proxy P.Double)
+acosD = acosVia (Proxy :: Proxy P.Double)
+atanD = atanVia (Proxy :: Proxy P.Double)
+sinhD = sinhVia (Proxy :: Proxy P.Double)
+coshD = coshVia (Proxy :: Proxy P.Double)
+tanhD = tanhVia (Proxy :: Proxy P.Double)
+asinhD = asinhVia (Proxy :: Proxy P.Double)
+acoshD = acoshVia (Proxy :: Proxy P.Double)
+atanhD = atanhVia (Proxy :: Proxy P.Double)
+
+-- | The standard two argument arctangent function.
+-- Since it interprets its two arguments in comparison with one another, the input may have any dimension.
+atan2D :: (Integral a, Integral b, E.MinCtxt s1 Double, E.MinCtxt s2 Double, E.MinCtxt s3 Double) => SQuantity s1 DOne a -> SQuantity s2 DOne a -> SQuantity s3 DOne b
+atan2D = atan2Via (Proxy :: Proxy P.Double)
+
+expVia, logVia, sinVia, cosVia, tanVia, asinVia, acosVia, atanVia, sinhVia, coshVia, tanhVia, asinhVia, acoshVia, atanhVia
+  :: (Integral a, RealFrac b, Floating b, Integral c, E.MinCtxt s1 b, E.MinCtxt s2 b) => Proxy b -> SQuantity s1 DOne a -> SQuantity s2 DOne c
+expVia = liftDimensionlessVia P.exp
+logVia = liftDimensionlessVia P.log
+sinVia = liftDimensionlessPeriodicVia (2 P.* P.pi) P.sin
+cosVia = liftDimensionlessPeriodicVia (2 P.* P.pi) P.cos
+tanVia = liftDimensionlessPeriodicVia P.pi P.tan
+asinVia = liftDimensionlessVia P.asin
+acosVia = liftDimensionlessVia P.acos
+atanVia = liftDimensionlessVia P.atan
+sinhVia = liftDimensionlessPeriodicVia (2 P.* P.pi) P.sinh
+coshVia = liftDimensionlessPeriodicVia (2 P.* P.pi) P.cosh
+tanhVia = liftDimensionlessPeriodicVia P.pi P.tanh
+asinhVia = liftDimensionlessVia P.asinh
+acoshVia = liftDimensionlessVia P.acosh
+atanhVia = liftDimensionlessVia P.atanh
+
+-- | The standard two argument arctangent function.
+-- Since it interprets its two arguments in comparison with one another, the input may have any dimension.
+atan2Via :: forall s1 s2 s3 a b c d.(Integral a, RealFloat b, Integral c, E.MinCtxt s1 b, E.MinCtxt s2 b, E.MinCtxt s3 b, KnownDimension d) => Proxy b -> SQuantity s1 d a -> SQuantity s2 d a -> SQuantity s3 DOne c
+atan2Via _ y x = (*~ siUnit) $ (P.atan2 :: b -> b -> b) (y /~ siUnit) (x /~ siUnit)
+
+-- | Lift a function on dimensionless values of a specified intermediate type to operate on possibly scaled dimensionless.
+liftDimensionlessVia :: forall s1 s2 a b c.(Real a, RealFrac b, Integral c, E.MinCtxt s1 b, E.MinCtxt s2 b) => (b -> b) -> Proxy b -> SQuantity s1 DOne a -> SQuantity s2 DOne c
+liftDimensionlessVia f _ = (*~ siUnit) . (f :: b -> b) . (/~ siUnit)
+
+-- | Lift a periodic function on dimensionless values of a specified intermediate type to operate on possibly scaled dimensionless.
+--
+-- If the scale factor of the input type is an exact integer divisor of the function's period, the argument
+-- will be clamped via an integer `mod` operation prior to applying the function to avoid errors introduced by a floating point modulus.
+liftDimensionlessPeriodicVia :: forall s1 s2 a b c.(Integral a, RealFrac b, Floating b, Integral c, E.MinCtxt s1 b, E.MinCtxt s2 b) => ExactPi -> (forall d.Floating d => d -> d) -> Proxy b -> SQuantity s1 DOne a -> SQuantity s2 DOne c
+liftDimensionlessPeriodicVia p f proxy | Just p'' <- p', p'' /= 0 = (liftDimensionlessVia f proxy) . dmap (`mod` p'')
+                                       | otherwise = liftDimensionlessVia f proxy
+  where
+    p' :: Maybe a
+    p' = fmap fromInteger . toExactInteger . P.recip . (P./ p) . E.exactPiVal $ (Proxy :: Proxy s1)
+
+{-
+We give '*~' and '/~' the same fixity as '*' and '/' defined below.
+Note that this necessitates the use of parenthesis when composing
+units using '*' and '/', e.g. "1 *~ (meter / second)".
+-}
+
+infixl 7  *~, /~
+
+-- | Forms a possibly scaled 'SQuantity' by multipliying a number and a unit.
+(*~) :: forall s m d a b.(RealFrac a, Integral b, E.MinCtxt s a) => a -> Unit m d a -> SQuantity s d b
+x *~ (Unit _ _ y) = Quantity . round $ (x P.* y P./ s)
+  where
+    s = E.injMin (Proxy :: Proxy s)
+
+-- | Divides a possibly scaled 'SQuantity' by a 'Unit' of the same physical dimension, obtaining the
+-- numerical value of the quantity expressed in that unit.
+(/~) :: forall s m d a b.(Real a, Fractional b,  E.MinCtxt s b) => SQuantity s d a -> Unit m d b -> b
+(Quantity x) /~ (Unit _ _ y) = ((realToFrac x) P.* s P./ y)
+  where
+    s = E.injMin (Proxy :: Proxy s)
+
+{-
+
+Rescaling Operations
+
+-}
+
+-- | Rescales a fixed point quantity, accomodating changes both in its scale factor and its representation type.
+--
+-- Note that this uses an arbitrary precision representation of 'pi', which may be quite slow.
+rescale :: forall a b d s1 s2.(Integral a, Integral b, E.KnownExactPi s1, E.KnownExactPi s2) => SQuantity s1 d a -> SQuantity s2 d b
+rescale | Just s' <- toExactInteger s           = viaInteger (P.* s')
+        | Just s' <- toExactInteger (P.recip s) = viaInteger (`P.quot` s')
+        | Just q  <- toExactRational s          = viaInteger $ timesRational q
+        | otherwise                             = viaInteger $ \x -> fixedPoint (fmap (($ x) . timesRational) (rationalApproximations s))
+  where
+    s = (s1' P./ s2')
+    s1' = E.exactPiVal (Proxy :: Proxy s1)
+    s2' = E.exactPiVal (Proxy :: Proxy s2)
+    timesRational :: Rational -> Integer -> Integer
+    timesRational q = (`P.quot` denominator q) . (P.* numerator q)
+
+-- | Rescales a fixed point quantity, accomodating changes both in its scale factor and its representation type.
+--
+-- Expected to outperform `rescale` when a `FiniteBits` context is available for the source and destination representation types.
+rescaleFinite :: (Integral a, FiniteBits a, Integral b, FiniteBits b, E.KnownExactPi s1, E.KnownExactPi s2) => SQuantity s1 d a -> SQuantity s2 d b
+rescaleFinite = rescale -- It should be possible to do this more quickly, since we have a priori knowledge of how well we need to approximate the result
+
+-- | Approximately rescales a fixed point quantity, accomodating changes both in its scale factor and its representation type.
+--
+-- Uses approximate arithmetic by way of an intermediate `Floating` type, to which a proxy must be supplied.
+rescaleVia :: forall a b c d s1 s2.(Integral a, RealFrac b, Floating b, Integral c, E.KnownExactPi s1, E.KnownExactPi s2) => Proxy b -> SQuantity s1 d a -> SQuantity s2 d c
+rescaleVia _ = viaIntermediate (P.* s)
+  where
+    s = approximateValue (s1' P./ s2') :: b
+    s1' = E.exactPiVal $ (Proxy :: Proxy s1)
+    s2' = E.exactPiVal $ (Proxy :: Proxy s2)
+
+-- | Approximately rescales a fixed point quantity, accomodating changes both in its scale factor and its representation type.
+--
+-- Uses approximate arithmetic by way of an intermediate `Double` representation.
+rescaleD :: (Integral a, Integral b, E.KnownExactPi s1, E.KnownExactPi s2) => SQuantity s1 d a -> SQuantity s2 d b
+rescaleD = rescaleVia (Proxy :: Proxy Double)
+
+-- Note that this does not respect scaling factors at all.
+viaInteger :: (Integral a, Integral b) => (P.Integer -> P.Integer) -> SQuantity s1 d a -> SQuantity s2 d b
+viaInteger f = Quantity . fromInteger . f . fromIntegral . unQuantity
+
+-- Note that this does not respect scaling factors at all.
+viaIntermediate :: (Integral a, RealFrac b, Integral c) => (b -> b) -> SQuantity s1 d a -> SQuantity s2 d c
+viaIntermediate f = Quantity . round . f . fromIntegral . unQuantity
+
+fixedPoint :: (Eq a) => [a] -> a
+fixedPoint []                     = error "Fixed point of empty list."
+fixedPoint [x]                    = x
+fixedPoint (x1:x2:xs) | x1 == x2  = x1
+                      | otherwise = fixedPoint (x2:xs)
+
+{-
+
+Changes of Representation
+
+-}
+
+-- | Convenient conversion between numerical types while retaining dimensional information.
+changeRep :: forall v1 v2 d a b.
+            (KnownVariant v1, KnownVariant v2,
+             CompatibleVariants v1 v2,
+             E.MinCtxt (ScaleFactor v1 E./ ScaleFactor v2) b,
+             Real a, Fractional b)
+          => Dimensional v1 d a -> Dimensional v2 d b
+changeRep = liftD (P.* s) ((P.* s') . realToFrac) Name.weaken
+  where
+    p :: Proxy (ScaleFactor v1 E./ ScaleFactor v2)
+    p = Proxy
+    s = E.exactPiVal p
+    s' = E.injMin p
+
+-- | Convenient conversion to types with `Integral` representations using `round`.
+changeRepRound :: forall v1 v2 d a b.
+                 (KnownVariant v1, KnownVariant v2,
+                  CompatibleVariants v1 v2,
+                  E.MinCtxt (ScaleFactor v1 E./ ScaleFactor v2) a,
+                  RealFrac a, Integral b)
+               => Dimensional v1 d a -> Dimensional v2 d b
+changeRepRound = liftD (P.* s) (round . (P.* s')) Name.weaken
+  where
+    p :: Proxy (ScaleFactor v1 E./ ScaleFactor v2)
+    p = Proxy
+    s = E.exactPiVal p
+    s' = E.injMin p
+
+{-
+
+Useful Constant Values
+
+-}
+
+{- $possibly-imprecise-constants
+
+Note that, other than '_0' and 'epsilon', these constants may not be exactly representable with certain scale factors.
+
+-}
+
+-- | The constant for zero is polymorphic, allowing
+-- it to express zero 'Length' or 'Capacitance' or 'Velocity' etc, in addition
+-- to the 'Dimensionless' value zero.
+_0 :: Num a => SQuantity s d a
+_0 = Quantity 0
+
+_1, _2, _3, _4, _5, _6, _7, _8, _9 :: (Integral a, E.KnownExactPi s) => SQuantity s DOne a
+_1 = rescale (epsilon :: SQuantity E.One DOne Integer)
+_2 = rescale (epsilon :: SQuantity (E.ExactNatural 2) DOne Integer)
+_3 = rescale (epsilon :: SQuantity (E.ExactNatural 3) DOne Integer)
+_4 = rescale (epsilon :: SQuantity (E.ExactNatural 4) DOne Integer)
+_5 = rescale (epsilon :: SQuantity (E.ExactNatural 5) DOne Integer)
+_6 = rescale (epsilon :: SQuantity (E.ExactNatural 6) DOne Integer)
+_7 = rescale (epsilon :: SQuantity (E.ExactNatural 7) DOne Integer)
+_8 = rescale (epsilon :: SQuantity (E.ExactNatural 8) DOne Integer)
+_9 = rescale (epsilon :: SQuantity (E.ExactNatural 9) DOne Integer)
+
+pi :: (Integral a, E.KnownExactPi s) => SQuantity s DOne a
+pi = rescale (epsilon :: SQuantity E.Pi DOne Integer)
+
+-- | Twice 'pi'.
+--
+-- For background on 'tau' see http://tauday.com/tau-manifesto (but also
+-- feel free to review http://www.thepimanifesto.com).
+tau :: (Integral a, E.KnownExactPi s) => SQuantity s DOne a
+tau = rescale (epsilon :: SQuantity (E.ExactNatural 2 E.* E.Pi) DOne Integer)
+
+-- | The least positive representable value in a given fixed-point scaled quantity type.
+epsilon :: (Integral a) => SQuantity s d a
+epsilon = Quantity 1
+
+{- $synonyms
+
+These type synonyms for commonly used fixed-point types are provided for convenience.
+
+-}
+
+-- | A binary scale factor.
+type QScale n = (E.One E./ (E.ExactNatural (2 N.^ n)))
+
+-- | A dimensionless number with `n` fractional bits, using a representation of type `a`.
+type Q n a = SQuantity (QScale n) DOne a
+
+-- | A single-turn angle represented as a signed 8-bit integer.
+type Angle8  = SQuantity (E.Pi E.* (QScale 7))  DPlaneAngle Int8
+
+-- | A single-turn angle represented as a signed 16-bit integer.
+type Angle16 = SQuantity (E.Pi E.* (QScale 15)) DPlaneAngle Int16
+
+-- | A single-turn angle represented as a signed 32-bit integer.
+type Angle32 = SQuantity (E.Pi E.* (QScale 31)) DPlaneAngle Int32
src/Numeric/Units/Dimensional/Float.hs view
@@ -1,178 +1,178 @@-{- |-    Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter-    License    : BSD3--    Maintainer : bjorn@buckwalter.se-    Stability  : Stable--Defines convenience functions for inspecting and manipulating quantities with 'RealFloat'-floating-point representations.--The dimensionally-typed versions of functions from Patrick Perry's @ieee754@ package-copy that package's API as closely as possible, by permission. In turn they are based on-the @tango@ math library for the D language.---}--{-# LANGUAGE ScopedTypeVariables #-}--module Numeric.Units.Dimensional.Float-(-  -- * Lifted Predicates from 'RealFloat'-  isDenormalized, isInfinite, isNaN, isNegativeZero-  -- * Convenience Functions-, isFiniteNumber, scaleFloat-  -- * Lifted Functions from "Numeric.IEEE"-  -- ** Values-, infinity, minNormal, maxFinite, epsilon, nan-  -- ** Arithmetic-, predIEEE, succIEEE, bisectIEEE, copySign-  -- ** NaN with Payload-, nanWithPayload, nanPayload, F.maxNaNPayload-  -- ** Comparisons-, identicalIEEE, minNum, maxNum, minNaN, maxNaN-)-where--import Control.Applicative-import Data.Word (Word64)-import Prelude (RealFloat)-import qualified Prelude as P-import Numeric.IEEE (IEEE)-import qualified Numeric.IEEE as F-import Numeric.Units.Dimensional.Internal (liftQ, liftQ2)-import Numeric.Units.Dimensional.Prelude hiding (RealFloat(..))-import Numeric.Units.Dimensional.Coercion---- $setup--- >>> :set -XExtendedDefaultRules--- >>> :set -XNegativeLiterals---- | 'True' if the representation of the argument is too small to be represented in normalized format.-isDenormalized :: RealFloat a => Quantity d a -> Bool-isDenormalized = P.isDenormalized . unQuantity---- | 'True' if the representation of the argument is a number and is not infinite.------ >>> isFiniteNumber (_1 / _0)--- False------ >>> isFiniteNumber (_0 / _0)--- False------ >>> isFiniteNumber (_3 / _2)--- True-isFiniteNumber :: RealFloat a => Quantity d a -> Bool-isFiniteNumber = not . liftA2 (||) isNaN isInfinite---- | 'True' if the representation of the argument is an IEEE infinity or negative infinity.------ >>> isInfinite (_1 / _0)--- True------ >>> isInfinite (42 *~ micro farad)--- False-isInfinite :: RealFloat a => Quantity d a -> Bool-isInfinite = P.isInfinite . unQuantity---- | 'True' if the representation of the argument is an IEEE "not-a-number" (NaN) value.------ >>> isNaN _3--- False------ >>> isNaN (_1 / _0)--- False------ >>> isNaN (asin _4)--- True-isNaN :: RealFloat a => Quantity d a -> Bool-isNaN = P.isNaN . unQuantity---- | 'True' if the representation of the argument is an IEEE negative zero.------ >>> isNegativeZero _0--- False------ >>> isNegativeZero $ (-1e-200 *~ one) * (1e-200 *~ one)--- True-isNegativeZero :: RealFloat a => Quantity d a -> Bool-isNegativeZero = P.isNegativeZero . unQuantity---- | Multiplies a floating-point quantity by an integer power of the radix of the representation type.------ Use 'P.floatRadix' to determine the radix.------ >>> let x = 3 *~ meter--- >>> scaleFloat 3 x--- 24.0 m-scaleFloat :: RealFloat a => Int -> Quantity d a -> Quantity d a-scaleFloat x = Quantity . P.scaleFloat x . unQuantity---- | An infinite floating-point quantity.-infinity :: IEEE a => Quantity d a-infinity = Quantity $ F.infinity---- | The smallest representable positive quantity whose representation is normalized.-minNormal :: IEEE a => Quantity d a-minNormal = Quantity $ F.minNormal---- | The largest representable finite floating-point quantity.-maxFinite :: IEEE a => Quantity d a-maxFinite = Quantity $ F.maxFinite---- | The smallest positive value @x@ such that @_1 + x@ is representable.-epsilon :: IEEE a => Dimensionless a-epsilon = Quantity $ F.epsilon---- | @copySign x y@ returns the quantity @x@ with its sign changed to match that of @y@.-copySign :: IEEE a => Quantity d a -> Quantity d a -> Quantity d a-copySign = liftQ2 F.copySign---- | Return 'True' if two floating-point quantities are /exactly/ (bitwise) equal.-identicalIEEE :: IEEE a => Quantity d a -> Quantity d a -> Bool-identicalIEEE (Quantity x) (Quantity y) = F.identicalIEEE x y---- | Return the next largest representable floating-point quantity (@Infinity@ and @NaN@ are unchanged).-succIEEE :: IEEE a => Quantity d a -> Quantity d a-succIEEE = liftQ F.succIEEE---- | Return the next smallest representable floating-point quantity (@Infinity@ and @NaN@ are unchanged).-predIEEE :: IEEE a => Quantity d a -> Quantity d a-predIEEE = liftQ F.predIEEE---- | Given two floating-point quantities with the same sign, return the quantity whose representation is halfway--- between their representations on the IEEE number line. If the signs of the values differ or either is @NaN@,--- the value is undefined.-bisectIEEE :: IEEE a => Quantity d a -> Quantity d a -> Quantity d a-bisectIEEE (Quantity x) (Quantity y) = Quantity $ F.bisectIEEE x y---- | Default @NaN@ quantity.-nan :: IEEE a => Quantity d a-nan = Quantity $ F.nan---- | Quiet @NaN@ quantity with a positive integer payload.--- Payload must be less than 'maxNaNPayload' of the representation type.------ Beware that while some platforms allow using 0 as a payload, this behavior is not portable.-nanWithPayload :: IEEE a => Word64 -> Quantity d a-nanWithPayload = Quantity . F.nanWithPayload---- | The payload stored in a @NaN@ quantity. Undefined if the argument is not @NaN@.-nanPayload :: IEEE a => Quantity d a -> Word64-nanPayload = F.nanPayload . unQuantity---- | Return the minimum of two quantities; if one value is @NaN@, return the other. Prefer the first if both values are @NaN@.-minNum :: RealFloat a => Quantity d a -> Quantity d a -> Quantity d a-minNum = liftQ2 F.minNum---- | Return the maximum of two quantities; if one value is @NaN@, return the other. Prefer the first if both values are @NaN@.-maxNum :: RealFloat a => Quantity d a -> Quantity d a -> Quantity d a-maxNum = liftQ2 F.maxNum---- | Return the minimum of two quantities; if one value is @NaN@, return it. Prefer the first if both values are @NaN@.-minNaN :: RealFloat a => Quantity d a -> Quantity d a -> Quantity d a-minNaN = liftQ2 F.minNaN---- | Return the maximum of two quantities; if one value is @NaN@, return it. Prefer the first if both values are @NaN@.-maxNaN :: RealFloat a => Quantity d a -> Quantity d a -> Quantity d a-maxNaN = liftQ2 F.maxNaN+{- |
+    Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter
+    License    : BSD3
+
+    Maintainer : bjorn@buckwalter.se
+    Stability  : Stable
+
+Defines convenience functions for inspecting and manipulating quantities with 'RealFloat'
+floating-point representations.
+
+The dimensionally-typed versions of functions from Patrick Perry's @ieee754@ package
+copy that package's API as closely as possible, by permission. In turn they are based on
+the @tango@ math library for the D language.
+
+-}
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module Numeric.Units.Dimensional.Float
+(
+  -- * Lifted Predicates from 'RealFloat'
+  isDenormalized, isInfinite, isNaN, isNegativeZero
+  -- * Convenience Functions
+, isFiniteNumber, scaleFloat
+  -- * Lifted Functions from "Numeric.IEEE"
+  -- ** Values
+, infinity, minNormal, maxFinite, epsilon, nan
+  -- ** Arithmetic
+, predIEEE, succIEEE, bisectIEEE, copySign
+  -- ** NaN with Payload
+, nanWithPayload, nanPayload, F.maxNaNPayload
+  -- ** Comparisons
+, identicalIEEE, minNum, maxNum, minNaN, maxNaN
+)
+where
+
+import Control.Applicative
+import Data.Word (Word64)
+import Prelude (RealFloat)
+import qualified Prelude as P
+import Numeric.IEEE (IEEE)
+import qualified Numeric.IEEE as F
+import Numeric.Units.Dimensional.Internal (liftQ, liftQ2)
+import Numeric.Units.Dimensional.Prelude hiding (RealFloat(..))
+import Numeric.Units.Dimensional.Coercion
+
+-- $setup
+-- >>> :set -XExtendedDefaultRules
+-- >>> :set -XNegativeLiterals
+
+-- | 'True' if the representation of the argument is too small to be represented in normalized format.
+isDenormalized :: RealFloat a => Quantity d a -> Bool
+isDenormalized = P.isDenormalized . unQuantity
+
+-- | 'True' if the representation of the argument is a number and is not infinite.
+--
+-- >>> isFiniteNumber (_1 / _0)
+-- False
+--
+-- >>> isFiniteNumber (_0 / _0)
+-- False
+--
+-- >>> isFiniteNumber (_3 / _2)
+-- True
+isFiniteNumber :: RealFloat a => Quantity d a -> Bool
+isFiniteNumber = not . liftA2 (||) isNaN isInfinite
+
+-- | 'True' if the representation of the argument is an IEEE infinity or negative infinity.
+--
+-- >>> isInfinite (_1 / _0)
+-- True
+--
+-- >>> isInfinite (42 *~ micro farad)
+-- False
+isInfinite :: RealFloat a => Quantity d a -> Bool
+isInfinite = P.isInfinite . unQuantity
+
+-- | 'True' if the representation of the argument is an IEEE "not-a-number" (NaN) value.
+--
+-- >>> isNaN _3
+-- False
+--
+-- >>> isNaN (_1 / _0)
+-- False
+--
+-- >>> isNaN (asin _4)
+-- True
+isNaN :: RealFloat a => Quantity d a -> Bool
+isNaN = P.isNaN . unQuantity
+
+-- | 'True' if the representation of the argument is an IEEE negative zero.
+--
+-- >>> isNegativeZero _0
+-- False
+--
+-- >>> isNegativeZero $ (-1e-200 *~ one) * (1e-200 *~ one)
+-- True
+isNegativeZero :: RealFloat a => Quantity d a -> Bool
+isNegativeZero = P.isNegativeZero . unQuantity
+
+-- | Multiplies a floating-point quantity by an integer power of the radix of the representation type.
+--
+-- Use 'P.floatRadix' to determine the radix.
+--
+-- >>> let x = 3 *~ meter
+-- >>> scaleFloat 3 x
+-- 24.0 m
+scaleFloat :: RealFloat a => Int -> Quantity d a -> Quantity d a
+scaleFloat x = Quantity . P.scaleFloat x . unQuantity
+
+-- | An infinite floating-point quantity.
+infinity :: IEEE a => Quantity d a
+infinity = Quantity $ F.infinity
+
+-- | The smallest representable positive quantity whose representation is normalized.
+minNormal :: IEEE a => Quantity d a
+minNormal = Quantity $ F.minNormal
+
+-- | The largest representable finite floating-point quantity.
+maxFinite :: IEEE a => Quantity d a
+maxFinite = Quantity $ F.maxFinite
+
+-- | The smallest positive value @x@ such that @_1 + x@ is representable.
+epsilon :: IEEE a => Dimensionless a
+epsilon = Quantity $ F.epsilon
+
+-- | @copySign x y@ returns the quantity @x@ with its sign changed to match that of @y@.
+copySign :: IEEE a => Quantity d a -> Quantity d a -> Quantity d a
+copySign = liftQ2 F.copySign
+
+-- | Return 'True' if two floating-point quantities are /exactly/ (bitwise) equal.
+identicalIEEE :: IEEE a => Quantity d a -> Quantity d a -> Bool
+identicalIEEE (Quantity x) (Quantity y) = F.identicalIEEE x y
+
+-- | Return the next largest representable floating-point quantity (@Infinity@ and @NaN@ are unchanged).
+succIEEE :: IEEE a => Quantity d a -> Quantity d a
+succIEEE = liftQ F.succIEEE
+
+-- | Return the next smallest representable floating-point quantity (@Infinity@ and @NaN@ are unchanged).
+predIEEE :: IEEE a => Quantity d a -> Quantity d a
+predIEEE = liftQ F.predIEEE
+
+-- | Given two floating-point quantities with the same sign, return the quantity whose representation is halfway
+-- between their representations on the IEEE number line. If the signs of the values differ or either is @NaN@,
+-- the value is undefined.
+bisectIEEE :: IEEE a => Quantity d a -> Quantity d a -> Quantity d a
+bisectIEEE (Quantity x) (Quantity y) = Quantity $ F.bisectIEEE x y
+
+-- | Default @NaN@ quantity.
+nan :: IEEE a => Quantity d a
+nan = Quantity $ F.nan
+
+-- | Quiet @NaN@ quantity with a positive integer payload.
+-- Payload must be less than 'maxNaNPayload' of the representation type.
+--
+-- Beware that while some platforms allow using 0 as a payload, this behavior is not portable.
+nanWithPayload :: IEEE a => Word64 -> Quantity d a
+nanWithPayload = Quantity . F.nanWithPayload
+
+-- | The payload stored in a @NaN@ quantity. Undefined if the argument is not @NaN@.
+nanPayload :: IEEE a => Quantity d a -> Word64
+nanPayload = F.nanPayload . unQuantity
+
+-- | Return the minimum of two quantities; if one value is @NaN@, return the other. Prefer the first if both values are @NaN@.
+minNum :: RealFloat a => Quantity d a -> Quantity d a -> Quantity d a
+minNum = liftQ2 F.minNum
+
+-- | Return the maximum of two quantities; if one value is @NaN@, return the other. Prefer the first if both values are @NaN@.
+maxNum :: RealFloat a => Quantity d a -> Quantity d a -> Quantity d a
+maxNum = liftQ2 F.maxNum
+
+-- | Return the minimum of two quantities; if one value is @NaN@, return it. Prefer the first if both values are @NaN@.
+minNaN :: RealFloat a => Quantity d a -> Quantity d a -> Quantity d a
+minNaN = liftQ2 F.minNaN
+
+-- | Return the maximum of two quantities; if one value is @NaN@, return it. Prefer the first if both values are @NaN@.
+maxNaN :: RealFloat a => Quantity d a -> Quantity d a -> Quantity d a
+maxNaN = liftQ2 F.maxNaN
src/Numeric/Units/Dimensional/Functor.hs view
@@ -1,41 +1,41 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-{-# OPTIONS_HADDOCK show-extensions #-}--{-# LANGUAGE CPP #-}-#if MIN_VERSION_base(4,8,0)--- OverlappingInstances was deprecated by GHC 7.10 in favor of OVERLAPPING pragmas.-#else-{-# LANGUAGE OverlappingInstances #-}-{-# OPTIONS_GHC -fno-warn-unrecognised-pragmas #-}-#endif--{- |-   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter-   License    : BSD3--   Maintainer : bjorn@buckwalter.se-   Stability  : Stable-   Portability: GHC only--Provides a 'Functor' instance for 'Dimensional'.--Note that this instance is dubious, because it allows you to break the dimensional abstraction. See 'dmap' for more information.--Note that, while this instance overlaps with that given for 'Dimensionless', it is confluent with that instance.--Note that this is an orphan instance.--}-module Numeric.Units.Dimensional.Functor where--import Numeric.Units.Dimensional-import Prelude---- | A 'Functor' instance for 'Dimensional'.------ Note that this instance is dubious, because it allows you to break the dimensional abstraction. See 'dmap' for more information.------ Note that, while this instance overlaps with that given for 'Dimensionless', it is confluent with that instance.------ Note that this is an orphan instance.-instance {-# OVERLAPPING #-} (KnownVariant v) => Functor (Dimensional v d) where-  fmap = dmap+{-# OPTIONS_GHC -fno-warn-orphans #-}
+{-# OPTIONS_HADDOCK show-extensions #-}
+
+{-# LANGUAGE CPP #-}
+#if MIN_VERSION_base(4,8,0)
+-- OverlappingInstances was deprecated by GHC 7.10 in favor of OVERLAPPING pragmas.
+#else
+{-# LANGUAGE OverlappingInstances #-}
+{-# OPTIONS_GHC -fno-warn-unrecognised-pragmas #-}
+#endif
+
+{- |
+   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+Provides a 'Functor' instance for 'Dimensional'.
+
+Note that this instance is dubious, because it allows you to break the dimensional abstraction. See 'dmap' for more information.
+
+Note that, while this instance overlaps with that given for 'Dimensionless', it is confluent with that instance.
+
+Note that this is an orphan instance.
+-}
+module Numeric.Units.Dimensional.Functor where
+
+import Numeric.Units.Dimensional
+import Prelude
+
+-- | A 'Functor' instance for 'Dimensional'.
+--
+-- Note that this instance is dubious, because it allows you to break the dimensional abstraction. See 'dmap' for more information.
+--
+-- Note that, while this instance overlaps with that given for 'Dimensionless', it is confluent with that instance.
+--
+-- Note that this is an orphan instance.
+instance {-# OVERLAPPING #-} (KnownVariant v) => Functor (Dimensional v d) where
+  fmap = dmap
src/Numeric/Units/Dimensional/Internal.hs view
@@ -1,274 +1,275 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE MultiParamTypeClasses #-} -- for Vector instances only-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TypeSynonymInstances #-}--module Numeric.Units.Dimensional.Internal-(-  KnownVariant(..),-  Dimensional(..),-  type Unit, type Quantity, type SQuantity,-  siUnit, showIn,-  liftD, liftD2,-  liftQ, liftQ2-)-where--import Control.Applicative-import Control.DeepSeq-import Control.Monad (liftM)-import Data.AEq (AEq)-import Data.Coerce (coerce)-import Data.Data-import Data.ExactPi-#if MIN_VERSION_base(4,9,0)-import Data.Functor.Classes (Eq1(..), Ord1(..))-#endif-import qualified Data.ExactPi.TypeLevel as E-import Data.Monoid (Monoid(..))-import Data.Semigroup (Semigroup(..))-import Foreign.Ptr (Ptr, castPtr)-import Foreign.Storable (Storable(..))-import GHC.Generics-import Numeric.Units.Dimensional.Dimensions-import Numeric.Units.Dimensional.Variants-import Numeric.Units.Dimensional.UnitNames hiding ((*), (/), (^), weaken, strengthen)-import qualified Numeric.Units.Dimensional.UnitNames.Internal as Name-import Numeric.Units.Dimensional.UnitNames.InterchangeNames (HasInterchangeName(..))-import qualified Data.Vector.Generic.Mutable as M-import qualified Data.Vector.Generic as G-import qualified Data.Vector.Unboxed.Base as U-import Prelude-  ( Show, Eq(..), Ord, Bounded(..), Num, Fractional, Functor, Real(..)-  , String, Maybe(..), Double-  , (.), ($), (++), (+), (/)-  , show, otherwise, undefined, error, fmap, realToFrac-  )-import qualified Prelude as P---- $setup--- >>> :set -XNoImplicitPrelude--- >>> import Numeric.Units.Dimensional.Prelude---- | A unit of measurement.-type Unit (m :: Metricality) = Dimensional ('DUnit m)---- | A dimensional quantity.-type Quantity = SQuantity E.One---- | A dimensional quantity, stored as an 'ExactPi'' multiple of its value in its dimension's SI coherent unit.------ The name is an abbreviation for scaled quantity.-type SQuantity s = Dimensional ('DQuantity s)---- | A KnownVariant is one whose term-level 'Dimensional' values we can represent with an associated data family instance--- and manipulate with certain functions, not all of which are exported from the package.------ Each validly constructed type of kind 'Variant' has a 'KnownVariant' instance.-class KnownVariant (v :: Variant) where-  -- | A dimensional value, either a 'Quantity' or a 'Unit', parameterized by its 'Dimension' and representation.-  data Dimensional v :: Dimension -> * -> *-  -- | A scale factor by which the numerical value of this dimensional value is implicitly multiplied.-  type ScaleFactor v :: E.ExactPi'-  extractValue :: Dimensional v d a -> (a, Maybe ExactPi)-  extractName :: Dimensional v d a -> Maybe (UnitName 'NonMetric)-  injectValue :: (Maybe (UnitName 'NonMetric)) -> (a, Maybe ExactPi) -> Dimensional v d a-  -- | Maps over the underlying representation of a dimensional value.-  -- The caller is responsible for ensuring that the supplied function respects the dimensional abstraction.-  -- This means that the function must preserve numerical values, or linearly scale them while preserving the origin.-  dmap :: (a1 -> a2) -> Dimensional v d a1 -> Dimensional v d a2--deriving instance Typeable Dimensional--instance KnownVariant ('DQuantity s) where-  newtype Dimensional ('DQuantity s) d a = Quantity a-    deriving (Eq, Ord, AEq, Data, Generic, Generic1-#if MIN_VERSION_base(4,8,0)-     , Typeable -- GHC 7.8 doesn't support deriving this instance-#endif-    )-  type (ScaleFactor ('DQuantity s)) = s-  extractValue (Quantity x) = (x, Nothing)-  extractName _ = Nothing-  injectValue _ (x, _) = Quantity x-  dmap = coerce--instance (Typeable m) => KnownVariant ('DUnit m) where-  data Dimensional ('DUnit m) d a = Unit !(UnitName m) !ExactPi !a-    deriving (Generic, Generic1-#if MIN_VERSION_base(4,8,0)-     , Typeable -- GHC 7.8 doesn't support deriving this instance-#endif-    )-  type (ScaleFactor ('DUnit m)) = E.One-  extractValue (Unit _ e x) = (x, Just e)-  extractName (Unit n _ _) = Just . Name.weaken $ n-  injectValue (Just n) (x, Just e) | Just n' <- relax n = Unit n' e x-                                   | otherwise          = error "Shouldn't be reachable. Needed a metric name but got a non-metric one."-  injectValue _        _ = error "Shouldn't be reachable. Needed to name a quantity."-  dmap f (Unit n e x) = Unit n e (f x)---- GHC is somewhat unclear about why, but it won't derive this instance, so we give it explicitly.-instance (Bounded a) => Bounded (SQuantity s d a) where-  minBound = Quantity minBound-  maxBound = Quantity maxBound--#if MIN_VERSION_base(4,9,0)-instance Eq1 (SQuantity s d) where-  liftEq = coerce--instance Ord1 (SQuantity s d) where-  liftCompare = coerce-#endif--instance HasInterchangeName (Unit m d a) where-  interchangeName (Unit n _ _) = interchangeName n--{--Since quantities form a monoid under addition, but not under multiplication unless they are dimensionless,-we will define a monoid instance that adds.--}---- | 'Quantity's of a given 'Dimension' form a 'Semigroup' under addition.-instance (Num a) => Semigroup (SQuantity s d a) where-  (<>) = liftQ2 (+)---- | 'Quantity's of a given 'Dimension' form a 'Monoid' under addition.-instance (Num a) => Monoid (SQuantity s d a) where-  mempty = Quantity 0-  mappend = liftQ2 (+)--{---= Dimensionless =--For dimensionless quantities pretty much any operation is applicable.-We provide this freedom by making 'Dimensionless' an instance of-'Functor'.--}--instance Functor (SQuantity s DOne) where-  fmap = dmap--instance (KnownDimension d) => HasDynamicDimension (Dimensional v d a) where--instance (KnownDimension d) => HasDimension (Dimensional v d a) where-  dimension _ = dimension (Proxy :: Proxy d)---- | A polymorphic 'Unit' which can be used in place of the coherent--- SI base unit of any dimension. This allows polymorphic quantity--- creation and destruction without exposing the 'Dimensional' constructor.-siUnit :: forall d a.(KnownDimension d, Num a) => Unit 'NonMetric d a-siUnit = Unit (baseUnitName $ dimension (Proxy :: Proxy d)) 1 1--instance NFData a => NFData (Quantity d a) -- instance is derived from Generic instance--instance Storable a => Storable (SQuantity s d a) where-  sizeOf _ = sizeOf (undefined::a)-  {-# INLINE sizeOf #-}-  alignment _ = alignment (undefined::a)-  {-# INLINE alignment #-}-  poke ptr = poke (castPtr ptr :: Ptr a) . coerce-  {-# INLINE poke #-}-  peek ptr = liftM Quantity (peek (castPtr ptr :: Ptr a))-  {-# INLINE peek #-}--{--Instances for vectors of quantities.--}-newtype instance U.Vector (SQuantity s d a)    =  V_Quantity {unVQ :: U.Vector a}-newtype instance U.MVector v (SQuantity s d a) = MV_Quantity {unMVQ :: U.MVector v a}-instance U.Unbox a => U.Unbox (SQuantity s d a)--instance (M.MVector U.MVector a) => M.MVector U.MVector (SQuantity s d a) where-  basicLength          = M.basicLength . unMVQ-  {-# INLINE basicLength #-}-  basicUnsafeSlice m n = MV_Quantity . M.basicUnsafeSlice m n . unMVQ-  {-# INLINE basicUnsafeSlice #-}-  basicOverlaps u v    = M.basicOverlaps (unMVQ u) (unMVQ v)-  {-# INLINE basicOverlaps #-}-  basicUnsafeNew       = liftM MV_Quantity . M.basicUnsafeNew-  {-# INLINE basicUnsafeNew #-}-  basicUnsafeRead v    = liftM Quantity . M.basicUnsafeRead (unMVQ v)-  {-# INLINE basicUnsafeRead #-}-  basicUnsafeWrite v i = M.basicUnsafeWrite (unMVQ v) i . coerce-  {-# INLINE basicUnsafeWrite #-}-#if MIN_VERSION_vector(0,11,0)-  basicInitialize      = M.basicInitialize . unMVQ-  {-# INLINE basicInitialize #-}-#endif--instance (G.Vector U.Vector a) => G.Vector U.Vector (SQuantity s d a) where-  basicUnsafeFreeze    = liftM V_Quantity  . G.basicUnsafeFreeze . unMVQ-  {-# INLINE basicUnsafeFreeze #-}-  basicUnsafeThaw      = liftM MV_Quantity . G.basicUnsafeThaw   . unVQ-  {-# INLINE basicUnsafeThaw #-}-  basicLength          = G.basicLength . unVQ-  {-# INLINE basicLength #-}-  basicUnsafeSlice m n = V_Quantity . G.basicUnsafeSlice m n . unVQ-  {-# INLINE basicUnsafeSlice #-}-  basicUnsafeIndexM v  = liftM Quantity . G.basicUnsafeIndexM (unVQ v)-  {-# INLINE basicUnsafeIndexM #-}--{--We will conclude by providing a reasonable 'Show' instance for-quantities. The SI unit of the quantity is inferred-from its dimension.--}-instance (KnownDimension d, E.KnownExactPi s, Show a, Real a) => Show (SQuantity s d a) where-  show (Quantity x) | isExactOne s' = show x ++ showName n-                    | otherwise = "Quantity " ++ show x ++ " {- " ++ show q ++ " -}"-    where-      s' = E.exactPiVal (Proxy :: Proxy s)-      s'' = approximateValue s' :: Double-      q = Quantity (realToFrac x P.* s'') :: Quantity d Double-      (Unit n _ _) = siUnit :: Unit 'NonMetric d a---- | Shows the value of a 'Quantity' expressed in a specified 'Unit' of the same 'Dimension'.------ >>> showIn watt $ (37 *~ volt) * (4 *~ ampere)--- "148.0 W"-showIn :: (Show a, Fractional a) => Unit m d a -> Quantity d a -> String-showIn (Unit n _ y) (Quantity x) = show (x / y) ++ (showName . Name.weaken $ n)--showName :: UnitName 'NonMetric -> String-showName n | n == nOne = ""-           | otherwise = " " ++ show n--instance (Show a) => Show (Unit m d a) where-  show (Unit n e x) = "The unit " ++ show n ++ ", with value " ++ show e ++ " (or " ++ show x ++ ")"---- Operates on a dimensional value using a unary operation on values, possibly yielding a Unit.-liftD :: (KnownVariant v1, KnownVariant v2) => (ExactPi -> ExactPi) -> (a -> b) -> UnitNameTransformer -> (Dimensional v1 d1 a) -> (Dimensional v2 d2 b)-liftD fe f nt x = let (x', e') = extractValue x-                      n = extractName x-                      n' = (liftA nt) n-                   in injectValue n' (f x', fmap fe e')---- Operates on a dimensional value using a unary operation on values, yielding a Quantity.-liftQ :: (a -> a) -> SQuantity s1 d1 a -> SQuantity s2 d2 a-liftQ = coerce---- Combines two dimensional values using a binary operation on values, possibly yielding a Unit.-liftD2 :: (KnownVariant v1, KnownVariant v2, KnownVariant v3) => (ExactPi -> ExactPi -> ExactPi) -> (a -> a -> a) -> UnitNameTransformer2 -> Dimensional v1 d1 a -> Dimensional v2 d2 a -> Dimensional v3 d3 a-liftD2 fe f nt x1 x2 = let (x1', e1') = extractValue x1-                           (x2', e2') = extractValue x2-                           n1 = extractName x1-                           n2 = extractName x2-                           n' = (liftA2 nt) n1 n2-                        in injectValue n' (f x1' x2', fe <$> e1' <*> e2')---- Combines two dimensional values using a binary operation on values, yielding a Quantity.-liftQ2 :: (a -> a -> a) -> SQuantity s1 d1 a -> SQuantity s2 d2 a -> SQuantity s3 d3 a-liftQ2 = coerce+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE MultiParamTypeClasses #-} -- for Vector instances only
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE TypeSynonymInstances #-}
+
+module Numeric.Units.Dimensional.Internal
+(
+  KnownVariant(..),
+  Dimensional(..),
+  type Unit, type Quantity, type SQuantity,
+  siUnit, showIn,
+  liftD, liftD2,
+  liftQ, liftQ2
+)
+where
+
+import Control.Applicative
+import Control.DeepSeq
+import Control.Monad (liftM)
+import Data.AEq (AEq)
+import Data.Coerce (coerce)
+import Data.Data
+import Data.Kind
+import Data.ExactPi
+#if MIN_VERSION_base(4,9,0)
+import Data.Functor.Classes (Eq1(..), Ord1(..))
+#endif
+import qualified Data.ExactPi.TypeLevel as E
+import Data.Monoid (Monoid(..))
+import Data.Semigroup (Semigroup(..))
+import Foreign.Ptr (Ptr, castPtr)
+import Foreign.Storable (Storable(..))
+import GHC.Generics
+import Numeric.Units.Dimensional.Dimensions
+import Numeric.Units.Dimensional.Variants
+import Numeric.Units.Dimensional.UnitNames hiding ((*), (/), (^), weaken, strengthen)
+import qualified Numeric.Units.Dimensional.UnitNames.Internal as Name
+import Numeric.Units.Dimensional.UnitNames.InterchangeNames (HasInterchangeName(..))
+import qualified Data.Vector.Generic.Mutable as M
+import qualified Data.Vector.Generic as G
+import qualified Data.Vector.Unboxed.Base as U
+import Prelude
+  ( Show, Eq(..), Ord, Bounded(..), Num, Fractional, Functor, Real(..)
+  , String, Maybe(..), Double
+  , (.), ($), (++), (+), (/)
+  , show, otherwise, undefined, error, fmap, realToFrac
+  )
+import qualified Prelude as P
+
+-- $setup
+-- >>> :set -XNoImplicitPrelude
+-- >>> import Numeric.Units.Dimensional.Prelude
+
+-- | A unit of measurement.
+type Unit (m :: Metricality) = Dimensional ('DUnit m)
+
+-- | A dimensional quantity.
+type Quantity = SQuantity E.One
+
+-- | A dimensional quantity, stored as an 'ExactPi'' multiple of its value in its dimension's SI coherent unit.
+--
+-- The name is an abbreviation for scaled quantity.
+type SQuantity s = Dimensional ('DQuantity s)
+
+-- | A KnownVariant is one whose term-level 'Dimensional' values we can represent with an associated data family instance
+-- and manipulate with certain functions, not all of which are exported from the package.
+--
+-- Each validly constructed type of kind 'Variant' has a 'KnownVariant' instance.
+class KnownVariant (v :: Variant) where
+  -- | A dimensional value, either a 'Quantity' or a 'Unit', parameterized by its 'Dimension' and representation.
+  data Dimensional v :: Dimension -> Type -> Type
+  -- | A scale factor by which the numerical value of this dimensional value is implicitly multiplied.
+  type ScaleFactor v :: E.ExactPi'
+  extractValue :: Dimensional v d a -> (a, Maybe ExactPi)
+  extractName :: Dimensional v d a -> Maybe (UnitName 'NonMetric)
+  injectValue :: (Maybe (UnitName 'NonMetric)) -> (a, Maybe ExactPi) -> Dimensional v d a
+  -- | Maps over the underlying representation of a dimensional value.
+  -- The caller is responsible for ensuring that the supplied function respects the dimensional abstraction.
+  -- This means that the function must preserve numerical values, or linearly scale them while preserving the origin.
+  dmap :: (a1 -> a2) -> Dimensional v d a1 -> Dimensional v d a2
+
+deriving instance Typeable Dimensional
+
+instance KnownVariant ('DQuantity s) where
+  newtype Dimensional ('DQuantity s) d a = Quantity a
+    deriving (Eq, Ord, AEq, Data, Generic, Generic1
+#if MIN_VERSION_base(4,8,0)
+     , Typeable -- GHC 7.8 doesn't support deriving this instance
+#endif
+    )
+  type (ScaleFactor ('DQuantity s)) = s
+  extractValue (Quantity x) = (x, Nothing)
+  extractName _ = Nothing
+  injectValue _ (x, _) = Quantity x
+  dmap = coerce
+
+instance (Typeable m) => KnownVariant ('DUnit m) where
+  data Dimensional ('DUnit m) d a = Unit !(UnitName m) !ExactPi !a
+    deriving (Generic, Generic1
+#if MIN_VERSION_base(4,8,0)
+     , Typeable -- GHC 7.8 doesn't support deriving this instance
+#endif
+    )
+  type (ScaleFactor ('DUnit m)) = E.One
+  extractValue (Unit _ e x) = (x, Just e)
+  extractName (Unit n _ _) = Just . Name.weaken $ n
+  injectValue (Just n) (x, Just e) | Just n' <- relax n = Unit n' e x
+                                   | otherwise          = error "Shouldn't be reachable. Needed a metric name but got a non-metric one."
+  injectValue _        _ = error "Shouldn't be reachable. Needed to name a quantity."
+  dmap f (Unit n e x) = Unit n e (f x)
+
+-- GHC is somewhat unclear about why, but it won't derive this instance, so we give it explicitly.
+instance (Bounded a) => Bounded (SQuantity s d a) where
+  minBound = Quantity minBound
+  maxBound = Quantity maxBound
+
+#if MIN_VERSION_base(4,9,0)
+instance Eq1 (SQuantity s d) where
+  liftEq = coerce
+
+instance Ord1 (SQuantity s d) where
+  liftCompare = coerce
+#endif
+
+instance HasInterchangeName (Unit m d a) where
+  interchangeName (Unit n _ _) = interchangeName n
+
+{-
+Since quantities form a monoid under addition, but not under multiplication unless they are dimensionless,
+we will define a monoid instance that adds.
+-}
+
+-- | 'Quantity's of a given 'Dimension' form a 'Semigroup' under addition.
+instance (Num a) => Semigroup (SQuantity s d a) where
+  (<>) = liftQ2 (+)
+
+-- | 'Quantity's of a given 'Dimension' form a 'Monoid' under addition.
+instance (Num a) => Monoid (SQuantity s d a) where
+  mempty = Quantity 0
+  mappend = liftQ2 (+)
+
+{-
+
+= Dimensionless =
+
+For dimensionless quantities pretty much any operation is applicable.
+We provide this freedom by making 'Dimensionless' an instance of
+'Functor'.
+-}
+
+instance Functor (SQuantity s DOne) where
+  fmap = dmap
+
+instance (KnownDimension d) => HasDynamicDimension (Dimensional v d a) where
+
+instance (KnownDimension d) => HasDimension (Dimensional v d a) where
+  dimension _ = dimension (Proxy :: Proxy d)
+
+-- | A polymorphic 'Unit' which can be used in place of the coherent
+-- SI base unit of any dimension. This allows polymorphic quantity
+-- creation and destruction without exposing the 'Dimensional' constructor.
+siUnit :: forall d a.(KnownDimension d, Num a) => Unit 'NonMetric d a
+siUnit = Unit (baseUnitName $ dimension (Proxy :: Proxy d)) 1 1
+
+instance NFData a => NFData (Quantity d a) -- instance is derived from Generic instance
+
+instance Storable a => Storable (SQuantity s d a) where
+  sizeOf _ = sizeOf (undefined::a)
+  {-# INLINE sizeOf #-}
+  alignment _ = alignment (undefined::a)
+  {-# INLINE alignment #-}
+  poke ptr = poke (castPtr ptr :: Ptr a) . coerce
+  {-# INLINE poke #-}
+  peek ptr = liftM Quantity (peek (castPtr ptr :: Ptr a))
+  {-# INLINE peek #-}
+
+{-
+Instances for vectors of quantities.
+-}
+newtype instance U.Vector (SQuantity s d a)    =  V_Quantity {unVQ :: U.Vector a}
+newtype instance U.MVector v (SQuantity s d a) = MV_Quantity {unMVQ :: U.MVector v a}
+instance U.Unbox a => U.Unbox (SQuantity s d a)
+
+instance (M.MVector U.MVector a) => M.MVector U.MVector (SQuantity s d a) where
+  basicLength          = M.basicLength . unMVQ
+  {-# INLINE basicLength #-}
+  basicUnsafeSlice m n = MV_Quantity . M.basicUnsafeSlice m n . unMVQ
+  {-# INLINE basicUnsafeSlice #-}
+  basicOverlaps u v    = M.basicOverlaps (unMVQ u) (unMVQ v)
+  {-# INLINE basicOverlaps #-}
+  basicUnsafeNew       = liftM MV_Quantity . M.basicUnsafeNew
+  {-# INLINE basicUnsafeNew #-}
+  basicUnsafeRead v    = liftM Quantity . M.basicUnsafeRead (unMVQ v)
+  {-# INLINE basicUnsafeRead #-}
+  basicUnsafeWrite v i = M.basicUnsafeWrite (unMVQ v) i . coerce
+  {-# INLINE basicUnsafeWrite #-}
+#if MIN_VERSION_vector(0,11,0)
+  basicInitialize      = M.basicInitialize . unMVQ
+  {-# INLINE basicInitialize #-}
+#endif
+
+instance (G.Vector U.Vector a) => G.Vector U.Vector (SQuantity s d a) where
+  basicUnsafeFreeze    = liftM V_Quantity  . G.basicUnsafeFreeze . unMVQ
+  {-# INLINE basicUnsafeFreeze #-}
+  basicUnsafeThaw      = liftM MV_Quantity . G.basicUnsafeThaw   . unVQ
+  {-# INLINE basicUnsafeThaw #-}
+  basicLength          = G.basicLength . unVQ
+  {-# INLINE basicLength #-}
+  basicUnsafeSlice m n = V_Quantity . G.basicUnsafeSlice m n . unVQ
+  {-# INLINE basicUnsafeSlice #-}
+  basicUnsafeIndexM v  = liftM Quantity . G.basicUnsafeIndexM (unVQ v)
+  {-# INLINE basicUnsafeIndexM #-}
+
+{-
+We will conclude by providing a reasonable 'Show' instance for
+quantities. The SI unit of the quantity is inferred
+from its dimension.
+-}
+instance (KnownDimension d, E.KnownExactPi s, Show a, Real a) => Show (SQuantity s d a) where
+  show (Quantity x) | isExactOne s' = show x ++ showName n
+                    | otherwise = "Quantity " ++ show x ++ " {- " ++ show q ++ " -}"
+    where
+      s' = E.exactPiVal (Proxy :: Proxy s)
+      s'' = approximateValue s' :: Double
+      q = Quantity (realToFrac x P.* s'') :: Quantity d Double
+      (Unit n _ _) = siUnit :: Unit 'NonMetric d a
+
+-- | Shows the value of a 'Quantity' expressed in a specified 'Unit' of the same 'Dimension'.
+--
+-- >>> showIn watt $ (37 *~ volt) * (4 *~ ampere)
+-- "148.0 W"
+showIn :: (Show a, Fractional a) => Unit m d a -> Quantity d a -> String
+showIn (Unit n _ y) (Quantity x) = show (x / y) ++ (showName . Name.weaken $ n)
+
+showName :: UnitName 'NonMetric -> String
+showName n | n == nOne = ""
+           | otherwise = " " ++ show n
+
+instance (Show a) => Show (Unit m d a) where
+  show (Unit n e x) = "The unit " ++ show n ++ ", with value " ++ show e ++ " (or " ++ show x ++ ")"
+
+-- Operates on a dimensional value using a unary operation on values, possibly yielding a Unit.
+liftD :: (KnownVariant v1, KnownVariant v2) => (ExactPi -> ExactPi) -> (a -> b) -> UnitNameTransformer -> (Dimensional v1 d1 a) -> (Dimensional v2 d2 b)
+liftD fe f nt x = let (x', e') = extractValue x
+                      n = extractName x
+                      n' = (liftA nt) n
+                   in injectValue n' (f x', fmap fe e')
+
+-- Operates on a dimensional value using a unary operation on values, yielding a Quantity.
+liftQ :: (a -> a) -> SQuantity s1 d1 a -> SQuantity s2 d2 a
+liftQ = coerce
+
+-- Combines two dimensional values using a binary operation on values, possibly yielding a Unit.
+liftD2 :: (KnownVariant v1, KnownVariant v2, KnownVariant v3) => (ExactPi -> ExactPi -> ExactPi) -> (a -> a -> a) -> UnitNameTransformer2 -> Dimensional v1 d1 a -> Dimensional v2 d2 a -> Dimensional v3 d3 a
+liftD2 fe f nt x1 x2 = let (x1', e1') = extractValue x1
+                           (x2', e2') = extractValue x2
+                           n1 = extractName x1
+                           n2 = extractName x2
+                           n' = (liftA2 nt) n1 n2
+                        in injectValue n' (f x1' x2', fe <$> e1' <*> e2')
+
+-- Combines two dimensional values using a binary operation on values, yielding a Quantity.
+liftQ2 :: (a -> a -> a) -> SQuantity s1 d1 a -> SQuantity s2 d2 a -> SQuantity s3 d3 a
+liftQ2 = coerce
src/Numeric/Units/Dimensional/NonSI.hs view
@@ -1,891 +1,891 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE NumDecimals #-}--{- |-   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter-   License    : BSD3--   Maintainer : bjorn@buckwalter.se-   Stability  : Stable-   Portability: GHC only--= Summary--This module defines units that are not part of the SI, with the-exception of those defined in the "Numeric.Units.Dimensional.SIUnits" module (units outside-of the SI accepted for use with the SI).--Any chapters, sections or tables referenced are from <#note1 [1]> unless-otherwise specified.--== Neper, bel, shannon and the like--The units of section 5.1.2 are purposefully (but not permanently)-omitted. In fact the logarithmic units (see section 8.7) are-problematic and it is not clear how to implement them. Perhaps with-a conversion function similar to for degrees Celsius.--= References--1. #note1# http://physics.nist.gov/Pubs/SP811/-2. #note2# http://www.iau.org/science/publications/proceedings_rules/units/-3. #note3# http://en.m.wikipedia.org/wiki/Pressure-4. #note4# http://en.m.wikipedia.org/wiki/Torr---}--module Numeric.Units.Dimensional.NonSI-(-  -- * Units Defined By Experiment-  -- $values-obtained-experimentally-  electronVolt, unifiedAtomicMassUnit, dalton,-  -- * Standard Gravity-  gee,-  -- * Inch-pound Units-  -- $inch-pound-units-  poundMass, ounce, poundForce, horsepower, btu, shortTon,-  nauticalMile, knot,-  revolution, solid,-  slug, psi,-  teaspoon,-  -- ** International Foot-  foot, inch, mil, yard, mile, acre,-  -- ** US Survey Foot-  usSurveyFoot, usSurveyInch, usSurveyMil, usSurveyYard, usSurveyMile, usSurveyAcre,-  -- * Years-  -- $year-  year, century,-  -- * Pressure Units-  -- $pressure-units-  bar, atmosphere, technicalAtmosphere, mmHg, inHg, inHg_UCUM, inHg_NIST, torr,-  -- * Radiation Units-  rad,-  -- * Kinematic Viscosity-  stokes,-  -- * Temperature-  -- $temperature-  degreeFahrenheit, degreeRankine,-  -- * Imperial Volumes-  -- $imperial-volumes-  imperialGallon, imperialQuart, imperialPint, imperialCup, imperialGill, imperialFluidOunce,-  -- * US Customary Volumes-  -- $us-customary-volumes-  usGallon, usQuart, usPint, usCup, usGill, usFluidOunce,-  -- * Atomic-Scale Units-  angstrom,-  -- * Units from the Centimeter-Gram-Second Electrostatic System of Units-  gauss-)-where--import Numeric.Units.Dimensional.Prelude-import Numeric.Units.Dimensional.UnitNames.Internal (ucumMetric, ucum, dimensionalAtom)-import qualified Prelude---- $setup--- >>> import Data.ExactPi--- >>> import Data.Function (on)--- >>> import Numeric.Units.Dimensional.Coercion--- >>> default (Double)--- >>> :{--- >>>   let infix 4 ===--- >>>       (===) = areExactlyEqual `on` unQuantity :: Quantity d ExactPi -> Quantity d ExactPi -> Bool--- >>> :}--{- $values-obtained-experimentally--From Table 7, units accepted for use with the SI whose values in SI units are-obtained experimentally.--When <#note1 [1]> was published the electron volt had a standard combined-uncertainity of 0.00000049e-19 J and the unified atomic mass unit-had a combined uncertainty of 0.0000010e-27 kg.---}--electronVolt :: Floating a => Unit 'Metric DEnergy a-electronVolt = mkUnitR (ucumMetric "eV" "eV" "electron volt") 1.60217733e-19 $ joule--unifiedAtomicMassUnit :: Floating a => Unit 'Metric DMass a-unifiedAtomicMassUnit = mkUnitR (ucumMetric "u" "u" "atomic mass unit") 1.6605402e-27 $ kilo gram--dalton :: Floating a => Unit 'Metric DMass a-dalton = mkUnitR (ucumMetric "u" "Da" "Dalton") 1 $ unifiedAtomicMassUnit---- | One gee is the standard value of the acceleration due to gravity at the--- Earth's surface, as standardized by CIPM.------ Note that local values of acceleration due to gravity will differ from the--- standard gravity.------ See <https://en.wikipedia.org/wiki/Standard_gravity here> for further information.------ >>> 1 *~ gee--- 9.80665 m s^-2------ >>> 1 *~ gee :: Acceleration Rational--- 196133 % 20000 m s^-2-gee :: Fractional a => Unit 'Metric DAcceleration a-gee = mkUnitQ (ucumMetric "[g]" "g" "gee") 9.80665 $ meter / second ^ pos2--{- $inch-pound-units-Some US customary (that is, inch-pound) units.--}---- | One international foot is one third of an international 'yard'.------ See <https://en.wikipedia.org/wiki/Foot_%28unit%29#International_foot here> for further information.------ >>> 1 *~ foot--- 0.3048 m------ prop> 3 *~ foot === 1 *~ yard------ >>> 1 *~ foot :: Length Rational--- 381 % 1250 m-foot :: Fractional a => Unit 'NonMetric DLength a-foot = mkUnitQ (ucum "[ft_i]" "ft" "foot") (1 Prelude./ 3) $ yard---- | One inch is one twelth of a 'foot'.------ This inch is based on the international 'foot'.------ See <https://en.wikipedia.org/wiki/Inch#Modern_standardisation here> for further information.------ >>> 1 *~ inch--- 2.54e-2 m------ prop> 12 *~ inch === 1 *~ foot------ >>> 1 *~ inch :: Length Rational--- 127 % 5000 m-inch :: Fractional a => Unit 'NonMetric DLength a-inch = mkUnitQ (ucum "[in_i]" "in" "inch") (1 Prelude./ 12) $ foot---- | One mil is one thousandth of an 'inch'.------ This mil is based on the international 'inch'.------ See <https://en.wikipedia.org/wiki/Thousandth_of_an_inch here> for further information.------ >>> 1 *~ mil--- 2.54e-5 m------ prop> 1000 *~ mil === 1 *~ inch------ >>> 1 *~ mil :: Length Rational--- 127 % 5000000 m-mil :: Fractional a => Unit 'NonMetric DLength a-mil = mkUnitQ (ucum "[mil_i]" "mil" "mil") 0.001 $ inch---- | One yard, as defined by international agreement in 1959, is precisely--- 0.9144 'meter'.------ See <https://en.wikipedia.org/wiki/Yard here> for further information.------ >>> 1 *~ yard--- 0.9144 m------ >>> 1 *~ yard :: Length Rational--- 1143 % 1250 m-yard :: (Fractional a) => Unit 'NonMetric DLength a-yard = mkUnitQ (ucum "[yd_i]" "yd" "yard") 0.9144 $ meter---- | One mile is 5 280 feet.------ This mile is based on the international 'foot'.------ See <https://en.wikipedia.org/wiki/Mile#International_mile here> for further information.------ >>> 1 *~ mile--- 1609.344 m------ prop> 1 *~ mile === 5280 *~ foot------ >>> 1 *~ mile :: Length Rational--- 201168 % 125 m-mile :: (Fractional a) => Unit 'NonMetric DLength a-mile = mkUnitQ (ucum "[mi_i]" "mi" "mile") 5280 $ foot---- | One acre is 43 560 square feet.------ This acre is based on the international 'foot'. For the acre based on the US Survey Foot,--- see 'usSurveyAcre'. While both acres are in use, the difference between them is of little consequence--- for most applications in which either is used.------ See <https://en.wikipedia.org/wiki/Acre#Differences_between_international_and_US_survey_acres here> for further information.------ >>> 1 *~ acre--- 4046.8564224 m^2------ prop> 1 *~ acre === 43560 *~ foot ^ pos2------ >>> 1 *~ acre :: Area Rational--- 316160658 % 78125 m^2-acre :: (Fractional a) => Unit 'NonMetric DArea a-acre = mkUnitQ (dimensionalAtom "[acr_i]" "ac" "acre") 43560 $ square foot---- | One US survey foot is 1200/3937 'meter'.------ For the international foot, see 'foot'. Note that this is not the foot in routine use--- in the United States.------ See <https://en.wikipedia.org/wiki/Foot_%28unit%29#US_survey_foot here> for further information.------ >>> 1 *~ usSurveyFoot--- 0.3048006096012192 m------ >>> 1 *~ usSurveyFoot :: Length Rational--- 1200 % 3937 m-usSurveyFoot :: Fractional a => Unit 'NonMetric DLength a-usSurveyFoot = mkUnitQ (ucum "[ft_us]" "ft" "foot") (1200 Prelude./ 3937) $ meter---- | One inch is one twelth of a foot.------ This inch is based on the 'usSurveyFoot'. For the inch based on the international foot,--- see 'inch'. Note that this is not the inch in routine use in the United States.------ See <https://en.wikipedia.org/wiki/Inch here> for further information.------ >>> 1 *~ usSurveyInch--- 2.54000508001016e-2 m------ prop> 12 *~ usSurveyInch === 1 *~ usSurveyFoot------ >>> 1 *~ usSurveyInch :: Length Rational--- 100 % 3937 m-usSurveyInch :: Fractional a => Unit 'NonMetric DLength a-usSurveyInch = mkUnitQ (ucum "[in_us]" "in" "inch") (1 Prelude./ 12) $ usSurveyFoot---- | One mil is one thousandth of an inch.------ This mil is based on the 'usSurveyInch'. For the mil based on the international inch,--- see 'mil'. Note that this is not the mil in routine use in the United States.------ See <https://en.wikipedia.org/wiki/Thousandth_of_an_inch here> for further information.------ >>> 1 *~ usSurveyMil--- 2.54000508001016e-5 m------ prop> 1000 *~ usSurveyMil === 1 *~ usSurveyInch------ >>> 1 *~ usSurveyMil :: Length Rational--- 1 % 39370 m-usSurveyMil :: Fractional a => Unit 'NonMetric DLength a-usSurveyMil = mkUnitQ (ucum "[mil_us]" "mil" "mil") 0.001 $ usSurveyInch---- | One yard is three feet.------ This yard is based on the 'usSurveyFoot'. For the international yard,--- see 'yard'. Note that this is not the yard in routine use in the United States.------ See <https://en.wikipedia.org/wiki/Yard here> for further information.------ >>> 1 *~ usSurveyYard--- 0.9144018288036576 m------ prop> 1 *~ usSurveyYard === 3 *~ usSurveyFoot------ >>> 1 *~ usSurveyYard :: Length Rational--- 3600 % 3937 m-usSurveyYard :: (Fractional a) => Unit 'NonMetric DLength a-usSurveyYard = mkUnitQ (ucum "[yd_us]" "yd" "yard") 3 $ usSurveyFoot---- | One US survey mile is 5 280 US survey feet.------ This mile is based on the 'usSurveyFoot'. For the mile based on the international foot,--- see 'mile'. Note that this is not the mile in routine use in the United States.------ See <https://en.wikipedia.org/wiki/Mile#US_survey_mile here> for further information.------ >>> 1 *~ usSurveyMile--- 1609.3472186944373 m------ prop> 1 *~ usSurveyMile === 5280 *~ usSurveyFoot------ >>> 1 *~ usSurveyMile :: Length Rational--- 6336000 % 3937 m-usSurveyMile :: (Fractional a) => Unit 'NonMetric DLength a-usSurveyMile = mkUnitQ (ucum "[mi_us]" "mi" "mile") 5280 $ usSurveyFoot---- | One acre is 43 560 square feet.------ This acre is based on the 'usSurveyFoot'. For the acre based on the international foot,--- see 'acre'. While both acres are in use, the difference between them is of little consequence--- for most applications in which either is used. This is the only acre defined by the UCUM.------ See <https://en.wikipedia.org/wiki/Acre#Differences_between_international_and_US_survey_acres here> for further information.------ >>> 1 *~ usSurveyAcre--- 4046.872609874252 m^2------ prop> 1 *~ usSurveyAcre === 43560 *~ usSurveyFoot ^ pos2------ >>> 1 *~ usSurveyAcre :: Area Rational--- 62726400000 % 15499969 m^2-usSurveyAcre :: (Fractional a) => Unit 'NonMetric DArea a-usSurveyAcre = mkUnitQ (ucum "[acr_us]" "ac" "acre") 43560 $ square usSurveyFoot---- | One avoirdupois pound is a mass, exactly defined in terms of the kilogram by the international--- yard and pound agreement of 1959.------ See <https://en.wikipedia.org/wiki/Avoirdupois#Internationalization here> for further information.------ >>> 1 *~ poundMass--- 0.45359237 kg------ >>> 1 *~ poundMass :: Mass Rational--- 45359237 % 100000000 kg-poundMass :: Fractional a => Unit 'NonMetric DMass a-poundMass = mkUnitQ (ucum "[lb_av]" "lb" "pound") 0.45359237 $ kilo gram---- | One avoirdupois ounce is one sixteenth of a 'poundMass'.------ See <https://en.wikipedia.org/wiki/Ounce#International_avoirdupois_ounce here> for further information.------ >>> 1 *~ ounce--- 2.8349523125e-2 kg------ prop> 16 *~ ounce === 1 *~ poundMass------ >>> 1 *~ ounce :: Mass Rational--- 45359237 % 1600000000 kg-ounce :: Fractional a => Unit 'NonMetric DMass a-ounce = mkUnitQ (ucum "[oz_av]" "oz" "ounce") (1 Prelude./ 16) $ poundMass---- | One short ton is two thousand 'poundMass'.------ See <https://en.wikipedia.org/wiki/Short_ton#United_States here> for further information.------ >>> 1 *~ shortTon--- 907.18474 kg------ >>> 1 *~ shortTon :: Mass Rational--- 45359237 % 50000 kg-shortTon :: Fractional a => Unit 'NonMetric DMass a-shortTon = mkUnitQ (ucum "[ston_av]" "ton" "short ton") 2000 $ poundMass---- | The pound-force is equal to the gravitational force exerted on a mass--- of one avoirdupois pound on the surface of Earth.------ This definition is based on standard gravity (the 'gee') and the--- international avoirdupois 'poundMass'.------ See <https://en.wikipedia.org/wiki/Pound_%28force%29 here> for further information.------ >>> 1 *~ poundForce--- 4.4482216152605 m kg s^-2------ prop> 1 *~ poundForce === 1 *~ poundMass * (1 *~ gee)------ >>> 1 *~ poundForce :: Force Rational--- 8896443230521 % 2000000000000 m kg s^-2-poundForce :: Fractional a => Unit 'NonMetric DForce a-poundForce = mkUnitQ (ucum "[lbf_av]" "lbf" "pound force") 1 $ poundMass * gee---- | One mechanical horsepower is by definition the power necessary--- to apply a force of 550 'poundForce' through a distance of one 'foot'--- per 'second'.------ See <https://en.wikipedia.org/wiki/Horsepower#Mechanical_horsepower here> for further information.------ >>> 1 *~ horsepower--- 745.6998715822702 m^2 kg s^-3------ prop> 1 *~ horsepower === 550 *~ poundForce * (1 *~ foot) / (1 *~ second)------ >>> 1 *~ horsepower :: Power Rational--- 37284993579113511 % 50000000000000 m^2 kg s^-3-horsepower :: Fractional a => Unit 'NonMetric DPower a-horsepower = mkUnitQ (ucum "[HP]" "hp" "horsepower") 550 $ foot * poundForce / second---- | The slug is a unit of mass associated with Imperial units and United States customary units.--- It is a mass that accelerates by 1 foot per second per second when a force of one pound is exerted on it.------ This definition is based on standard gravity (the 'gee'), the international 'foot', and the international avoirdupois 'poundMass'.------ See <https://en.wikipedia.org/wiki/Slug_%28mass%29 here> for further information.------ >>> 1 *~ slug--- 14.593902937206364 kg------ >>> 1 *~ slug :: Mass Rational--- 8896443230521 % 609600000000 kg-slug :: Fractional a => Unit 'NonMetric DMass a-slug = mkUnitQ (dimensionalAtom "slug" "slug" "slug") 1 $ poundForce * (second^pos2) / foot---- | One psi is a pressure of one 'poundForce' per 'square' 'inch' of area.------ See <https://en.wikipedia.org/wiki/Pounds_per_square_inch here> for further information.------ >>> 1 *~ psi--- 6894.757293168362 m^-1 kg s^-2------ >>> 1 *~ psi :: Pressure Rational--- 8896443230521 % 1290320000 m^-1 kg s^-2-psi :: Fractional a => Unit 'NonMetric DPressure a-psi = mkUnitQ (ucum "[psi]" "psi" "pound per square inch") 1 $ poundForce / inch ^ pos2---- | One nautical mile is a unit of length, set by international agreement as being exactly 1 852 meters.------ Historically, it was defined as the distance spanned by one minute of arc along a meridian of the Earth.------ See <https://en.wikipedia.org/wiki/Nautical_mile here> for further information.------ >>> 1 *~ nauticalMile--- 1852.0 m------ >>> 1 *~ nauticalMile :: Length Rational--- 1852 % 1 m-nauticalMile :: (Num a) => Unit 'NonMetric DLength a-nauticalMile = mkUnitZ (ucum "[nmi_i]" "NM" "nautical mile") 1852 $ meter---- | One knot is a velocity equal to one 'nauticalMile' per 'hour'.------ See <https://en.wikipedia.org/wiki/Knot_%28unit%29 here> for further information.------ >>> 1 *~ knot--- 0.5144444444444445 m s^-1------ >>> 1 *~ knot :: Velocity Rational--- 463 % 900 m s^-1-knot :: (Fractional a) => Unit 'NonMetric DVelocity a-knot = mkUnitQ (ucum "[kt_i]" "kt" "knot") 1 $ nauticalMile / hour---- | One revolution is an angle equal to 2 pi radians; a full circle.------ See <https://en.wikipedia.org/wiki/Turn_%28geometry%29 here> for further information.------ >>> 1 *~ revolution--- 6.283185307179586------ prop> 1 *~ revolution === _2 * pi * (1 *~ radian)------ prop> 1 *~ revolution === 360 *~ degree-revolution :: (Floating a) => Unit 'NonMetric DOne a-revolution = mkUnitR (dimensionalAtom "rev" "rev" "revolution") (2 Prelude.* Prelude.pi) $ radian--solid :: (Floating a) => Unit 'NonMetric DOne a-solid = mkUnitR (dimensionalAtom "solid" "solid" "solid") (4 Prelude.* Prelude.pi) $ steradian--teaspoon :: (Fractional a) => Unit 'NonMetric DVolume a-teaspoon = mkUnitQ (ucum "[tsp_m]" "tsp" "teaspoon") 5 $ milli liter---- | One btu is is the 'QuantityOfHeat' required to raise the temperature--- of 1 avoirdupois 'poundMass' of liquid water by 1 'degreeFahrenheit' at a constant pressure of one 'atmosphere'.------ Because this value must be determined experimentally and varies with temperature, several standardized--- values of the btu have arisen. This is the value based on the International Steam Table calorie,--- defined by the Fifth International Conference on the Properties of Steam.------ See <https://en.wikipedia.org/wiki/British_thermal_unit#Definitions here> for further information.------ >>> 1 *~ btu--- 1055.05585262 m^2 kg s^-2------ >>> 1 *~ btu :: Energy Rational--- 52752792631 % 50000000 m^2 kg s^-2-btu :: Fractional a => Unit 'NonMetric DEnergy a-btu = mkUnitQ (ucum "[Btu_IT]" "btu" "British thermal unit") 1055.05585262 $ joule---{- $year--The IAU recommends <#note2 [2]> that:--  Although there are several different kinds of year (as there are-  several kinds of day), it is best to regard a year as a julian-  year of 365.25 days (31.5576 Ms) unless otherwise specified.---}---- | One mean Julian year is a unit of measurement of time defined as exactly 365.25 days of 86 400 'second's each.------ See <https://en.wikipedia.org/wiki/Julian_year_%28astronomy%29 here> for further information.------ >>> 1 *~ year--- 3.15576e7 s------ >>> 1 *~ year :: Time Rational--- 31557600 % 1 s-year :: Num a => Unit 'NonMetric DTime a-year = mkUnitZ (ucum "a_j" "a" "mean Julian year") 31557600 $ second---- | One mean Julian century is one hundred mean Julian 'year's.------ >>> 1 *~ century--- 3.15576e9 s------ >>> 1 *~ century :: Time Rational--- 3155760000 % 1 s-century :: Num a => Unit 'NonMetric DTime a-century = mkUnitZ (dimensionalAtom "c_j" "cen" "mean Julian century") 100 $ year--{- $pressure-units-It seems that nearly every area of application has its own customary unit for measuring pressure.-We include some of the common ones here. 'psi' was defined earlier.--}---- | The bar is exactly 100 000 'Numeric.Units.Dimensional.SIUnits.pascal'.------ From Wikipedia:------  It is about equal to the atmospheric pressure on Earth at sea level.------ >>> 1 *~ bar--- 100000.0 m^-1 kg s^-2------ >>> 1 *~ bar :: Pressure Rational--- 100000 % 1 m^-1 kg s^-2-bar :: (Num a) => Unit 'Metric DPressure a-bar = mkUnitZ (ucumMetric "bar" "bar" "bar") 1e5 $ pascal---- | The "standard atmosphere".------ From Wikipedia <#note3 [3]>:------  The standard atmosphere (atm) is an established constant. It is---  approximately equal to typical air pressure at earth mean sea---  level.------ >>> 1 *~ atmosphere--- 101325.0 m^-1 kg s^-2------ >>> 1 *~ atmosphere :: Pressure Rational--- 101325 % 1 m^-1 kg s^-2-atmosphere :: (Num a) => Unit 'NonMetric DPressure a-atmosphere = mkUnitZ (ucum "atm" "atm" "standard atmosphere") 101325 $ pascal---- | The "technical atmosphere"------ From Wikipedia:------  A technical atmosphere (symbol: at) is a non-SI unit of pressure equal---  to one kilogram-force per square centimeter.------ >>> 1 *~ technicalAtmosphere--- 98066.5 m^-1 kg s^-2------ >>> 1 *~ technicalAtmosphere :: Pressure Rational--- 196133 % 2 m^-1 kg s^-2-technicalAtmosphere :: (Fractional a) => Unit 'NonMetric DPressure a-technicalAtmosphere = mkUnitQ (ucum "att" "at" "technical atmosphere") 1 $ kilo gram * gee * centi meter ^ neg2---- | The conventional value for the pressure exerted by a 1 mm high column of mercury.------ Per Wikipedia <#note4 [4]>, one mmHg (millimeter of mercury) is defined as:------  The pressure exerted at the base of a column of fluid exactly 1 mm high,---  when the density of the fluid is exactly 13.5951 g/cm^3, at a place---  where the acceleration of gravity is exactly 9.80665 m/s^2.------ The chosen fluid density approximately corresponds to that of mercury--- at 0 deg. Under most conditions, 1 mmHg is approximately equal to 1 'torr'.------ >>> 1 *~ mmHg--- 133.322 m^-1 kg s^-2------ >>> 1 *~ mmHg :: Pressure Rational--- 66661 % 500 m^-1 kg s^-2-mmHg :: (Fractional a) => Unit 'NonMetric DPressure a-mmHg = milli mHg--mHg :: (Fractional a) => Unit 'Metric DPressure a-mHg = mkUnitQ (ucumMetric "m[Hg]" "m Hg" "meter of mercury") 133.3220 $ kilo pascal---- | The conventional value for the pressure exerted by a 1 inch high column of mercury.------ Column inches of mercury are also used to measure pressure, especially in--- meteorological or aeronautical contexts in the United States.------ This is the value defined by UCUM. For the value defined by NIST, see 'inHg_NIST'.------ >>> 1 *~ inHg--- 3386.3788 m^-1 kg s^-2------ >>> 1 *~ inHg :: Pressure Rational--- 8465947 % 2500 m^-1 kg s^-2-inHg :: (Fractional a) => Unit 'NonMetric DPressure a-inHg = inHg_UCUM---- | The conventional value for the pressure exerted by a 1 inch high column of mercury.------ Column inches of mercury are also used to measure pressure, especially in--- meteorological or aeronautical contexts in the United States.------ This is the value defined by UCUM. For the value defined by NIST, see 'inHg_NIST'.------ >>> 1 *~ inHg_UCUM--- 3386.3788 m^-1 kg s^-2------ >>> 1 *~ inHg_UCUM :: Pressure Rational--- 8465947 % 2500 m^-1 kg s^-2-inHg_UCUM :: (Fractional a) => Unit 'NonMetric DPressure a-inHg_UCUM = mkUnitQ (ucum "[in_i'Hg]" "in Hg" "inch of mercury") 1 $ mHg * inch / meter---- | The conventional value for the pressure exerted by a 1 inch high column of mercury.------ Column inches of mercury are also used to measure pressure, especially in--- meteorological or aeronautical contexts in the United States.------ This is the value defined by NIST. For the value defined by UCUM, see 'inHg_UCUM'.------ >>> 1 *~ inHg_NIST--- 3386.389 m^-1 kg s^-2------ >>> 1 *~ inHg_NIST :: Pressure Rational--- 3386389 % 1000 m^-1 kg s^-2-inHg_NIST :: (Fractional a) => Unit 'NonMetric DPressure a-inHg_NIST = mkUnitQ (dimensionalAtom "[in_i'Hg_NIST]" "in Hg" "inch of mercury") 3.386389e3 $ pascal---- | One torr (symbol: Torr) is defined as 1/760 'atmosphere', which is approximately equal to 1 'mmHg'.------ See <https://en.wikipedia.org/wiki/Torr here> for further information.------ >>> 1 *~ torr--- 133.32236842105263 m^-1 kg s^-2------ >>> 1 *~ torr :: Pressure Rational--- 20265 % 152 m^-1 kg s^-2-torr :: (Fractional a) => Unit 'NonMetric DPressure a-torr = mkUnitQ (dimensionalAtom "Torr" "Torr" "Torr") (1 Prelude./ 760) $ atmosphere---- | The rad is a deprecated unit of 'AbsorbedDose', defined as--- 0.01 'gray'.------ See <https://en.wikipedia.org/wiki/Rad_%28unit%29 here> for further information.------ >>> 1 *~ rad--- 1.0e-2 m^2 s^-2------ >>> 1 *~ rad :: AbsorbedDose Rational--- 1 % 100 m^2 s^-2-rad :: (Fractional a) => Unit 'Metric DAbsorbedDose a-rad = mkUnitQ (ucumMetric "RAD" "RAD" "RAD") 1 $ centi gray---- | One Stokes is a unit of 'KinematicViscosity' equal to @1 cm^2 / s@.------ See <https://en.wikipedia.org/wiki/Viscosity#Kinematic_viscosity_.CE.BD here> for further information.------ >>> 1 *~ stokes--- 1.0e-4 m^2 s^-1------ >>> 1 *~ stokes :: KinematicViscosity Rational--- 1 % 10000 m^2 s^-1-stokes :: (Fractional a) => Unit 'Metric DKinematicViscosity a-stokes = mkUnitQ (ucumMetric "St" "St" "Stokes") 1 $ centi meter ^ pos2 / second--{- $temperature-These units of temperature are relative. For absolute temperatures, see 'Numeric.Units.Dimensional.SIUnits.fromDegreeCelsiusAbsolute'.--}---- | One degree Fahrenheit is a unit of relative temperature equal to 5/9 'kelvin'.------ Note that although the Fahrenheit scale is an absolute temperature scale, this unit is a unit of difference within--- that scale and measures relative temperature.------ See <https://en.wikipedia.org/wiki/Fahrenheit#Definition_and_conversions here> for further information.------ >>> 1 *~ degreeFahrenheit--- 0.5555555555555556 K------ >>> 1 *~ degreeFahrenheit :: ThermodynamicTemperature Rational--- 5 % 9 K-degreeFahrenheit :: (Fractional a) => Unit 'NonMetric DThermodynamicTemperature a-degreeFahrenheit = mkUnitQ (ucum "[degF]" "°F" "degree Fahrenheit") (5 Prelude./ 9) $ degreeCelsius---- | One degree Rankine is a unit of relative temperature equal to 5/9 'kelvin'.------ Note that although the Rankine scale is an absolute temperature scale, this unit is a unit of difference within--- that scale and measures relative temperature.------ See <https://en.wikipedia.org/wiki/Rankine_scale here> for further information.------ >>> 1 *~ degreeRankine--- 0.5555555555555556 K------ >>> 1 *~ degreeRankine :: ThermodynamicTemperature Rational--- 5 % 9 K-degreeRankine :: (Fractional a) => Unit 'NonMetric DThermodynamicTemperature a-degreeRankine = mkUnitQ (ucum "[degR]" "°R" "degree Rankine") 1 $ degreeFahrenheit--{- $imperial-volumes-Per http://en.wikipedia.org/wiki/Imperial_units and http://en.wikipedia.org/wiki/Cup_(unit)#Imperial_cup.--}---- | One imperial gallon is defined exactly in terms of the 'liter'--- by the Weights and Measures Act 1985.------ See <https://en.wikipedia.org/wiki/Imperial_units#Volume here> for further information.------ >>> 1 *~ imperialGallon--- 4.54609e-3 m^3------ >>> 1 *~ imperialGallon :: Volume Rational--- 454609 % 100000000 m^3-imperialGallon :: (Fractional a) => Unit 'NonMetric DVolume a-imperialGallon = mkUnitQ (ucum "[gal_br]" "gal" "gallon") 4.54609 $ liter---- | One imperial quart is one quarter of an 'imperialGallon'.------ See <https://en.wikipedia.org/wiki/Imperial_units#Volume here> for further information.------ >>> 1 *~ imperialQuart--- 1.1365225e-3 m^3------ >>> 1 *~ imperialQuart :: Volume Rational--- 454609 % 400000000 m^3-imperialQuart :: (Fractional a) => Unit 'NonMetric DVolume a-imperialQuart = mkUnitQ (ucum "[qt_br]" "qt" "quart") (1 Prelude./ 4) $ imperialGallon---- | One imperial pint is one half of an 'imperialQuart'.------ See <https://en.wikipedia.org/wiki/Imperial_units#Volume here> for further information.------ >>> 1 *~ imperialPint--- 5.6826125e-4 m^3------ >>> 1 *~ imperialPint :: Volume Rational--- 454609 % 800000000 m^3-imperialPint :: (Fractional a) => Unit 'NonMetric DVolume a-imperialPint = mkUnitQ (ucum "[pt_br]" "pt" "pint") (1 Prelude./ 8) $ imperialGallon---- | One imperial cup is one half of an 'imperialPint'.------ This unit is not in common use and is does not appear in some sources--- describing the imperial fluid volume units.------ See <https://en.wikipedia.org/wiki/Cup_%28unit%29#Imperial_cup here> for further information.------ >>> 1 *~ imperialCup--- 2.84130625e-4 m^3------ >>> 1 *~ imperialCup :: Volume Rational--- 454609 % 1600000000 m^3-imperialCup :: (Fractional a) => Unit 'NonMetric DVolume a-imperialCup = mkUnitQ (dimensionalAtom "[cup_br]" "cup" "cup") 0.5 $ imperialPint---- | One imperial gill is one quarter of an 'imperialPint'.------ See <https://en.wikipedia.org/wiki/Imperial_units#Volume here> for further information.------ >>> 1 *~ imperialGill--- 1.420653125e-4 m^3------ >>> 1 *~ imperialGill :: Volume Rational--- 454609 % 3200000000 m^3-imperialGill :: (Fractional a) => Unit 'NonMetric DVolume a-imperialGill = mkUnitQ (ucum "[gil_br]" "gill" "gill") (1 Prelude./ 4) $ imperialPint---- | One imperial fluid ounce is one twentieth of an 'imperialPint'.------ See <https://en.wikipedia.org/wiki/Imperial_units#Volume here> for further information.------ >>> 1 *~ imperialFluidOunce--- 2.84130625e-5 m^3------ >>> 1 *~ imperialFluidOunce :: Volume Rational--- 454609 % 16000000000 m^3-imperialFluidOunce :: (Fractional a) => Unit 'NonMetric DVolume a-imperialFluidOunce = mkUnitQ (ucum "[foz_br]" "fl oz" "fluid ounce") (1 Prelude./ 20) $ imperialPint--{- $us-customary-volumes-Per http://www.nist.gov/pml/wmd/pubs/upload/2012-hb44-final.pdf page 452 and http://en.wikipedia.org/wiki/United_States_customary_units#Fluid_volume-Note that there exist rarely-used "dry" variants of units with overlapping names.--}---- | One US liquid gallon is a volume of 231 cubic inches.------ See <https://en.wikipedia.org/wiki/Gallon#The_US_liquid_gallon here> for further information.------ >>> 1 *~ usGallon--- 3.785411784e-3 m^3------ >>> 1 *~ usGallon :: Volume Rational--- 473176473 % 125000000000 m^3-usGallon :: (Fractional a) => Unit 'NonMetric DVolume a-usGallon = mkUnitQ (ucum "[gal_us]" "gal" "gallon") 231 $ (cubic inch)---- | One US liquid quart is one quarter of a 'usGallon'.------ See <https://en.wikipedia.org/wiki/United_States_customary_units#Fluid_volume here> for further information.------ >>> 1 *~ usQuart--- 9.46352946e-4 m^3------ >>> 1 *~ usQuart :: Volume Rational--- 473176473 % 500000000000 m^3-usQuart :: (Fractional a) => Unit 'NonMetric DVolume a-usQuart = mkUnitQ (ucum "[qt_us]" "qt" "quart") (1 Prelude./ 4) $ usGallon---- | One US liquid pint is one half of a 'usQuart'.------ See <https://en.wikipedia.org/wiki/United_States_customary_units#Fluid_volume here> for further information.------ >>> 1 *~ usPint--- 4.73176473e-4 m^3------ >>> 1 *~ usPint :: Volume Rational--- 473176473 % 1000000000000 m^3-usPint :: (Fractional a) => Unit 'NonMetric DVolume a-usPint = mkUnitQ (ucum "[pt_us]" "pt" "pint") (1 Prelude./ 8) $ usGallon---- | One US liquid cup is one half of a 'usPint'.------ See <https://en.wikipedia.org/wiki/United_States_customary_units#Fluid_volume here> for further information.------ >>> 1 *~ usCup--- 2.365882365e-4 m^3------ >>> 1 *~ usCup :: Volume Rational--- 473176473 % 2000000000000 m^3-usCup :: (Fractional a) => Unit 'NonMetric DVolume a-usCup = mkUnitQ (ucum "[cup_us]" "cup" "cup") (1 Prelude./ 2) $ usPint---- | One US liquid gill is one half of a 'usCup'.------ See <https://en.wikipedia.org/wiki/United_States_customary_units#Fluid_volume here> for further information.------ >>> 1 *~ usGill--- 1.1829411825e-4 m^3------ >>> 1 *~ usGill :: Volume Rational--- 473176473 % 4000000000000 m^3-usGill :: (Fractional a) => Unit 'NonMetric DVolume a-usGill = mkUnitQ (ucum "[gil_us]" "gill" "gill") (1 Prelude./ 4) $ usPint---- | One US fluid ounce is 1/128 'usGallon' or 1/8 'usCup'.------ See <https://en.wikipedia.org/wiki/United_States_customary_units#Fluid_volume here> for further information.------ >>> 1 *~ usFluidOunce--- 2.95735295625e-5 m^3------ >>> 1 *~ usFluidOunce :: Volume Rational--- 473176473 % 16000000000000 m^3-usFluidOunce :: (Fractional a) => Unit 'NonMetric DVolume a-usFluidOunce = mkUnitQ (ucum "[foz_us]" "fl oz" "fluid ounce") (1 Prelude./ 16) $ usPint -- sic, does not match factor used in imperial system---- | One Ångström is 1/10 'nano' 'meter'.------ See <https://en.wikipedia.org/wiki/%C3%85ngstr%C3%B6m here> for further information.------ >>> 1 *~ angstrom--- 1.0e-10 m------ >>> 1 *~ angstrom :: Length Rational--- 1 % 10000000000 m-angstrom :: (Fractional a) => Unit 'NonMetric DLength a-angstrom = mkUnitQ (ucum "Ao" "Å" "Ångström") 0.1 $ nano meter---- | One Gauss is 1/10000 'tesla'.------ See <https://en.wikipedia.org/wiki/Gauss_%28unit%29 here> for further information.------ >>> 1 *~ gauss--- 1.0e-4 kg s^-2 A^-1------ >>> 1 *~ gauss :: MagneticFluxDensity Rational--- 1 % 10000 kg s^-2 A^-1-gauss :: (Fractional a) => Unit 'NonMetric DMagneticFluxDensity a-gauss = mkUnitQ (ucum "G" "G" "Gauss") 1e-4 $ tesla+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE NumDecimals #-}
+
+{- |
+   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+= Summary
+
+This module defines units that are not part of the SI, with the
+exception of those defined in the "Numeric.Units.Dimensional.SIUnits" module (units outside
+of the SI accepted for use with the SI).
+
+Any chapters, sections or tables referenced are from <#note1 [1]> unless
+otherwise specified.
+
+== Neper, bel, shannon and the like
+
+The units of section 5.1.2 are purposefully (but not permanently)
+omitted. In fact the logarithmic units (see section 8.7) are
+problematic and it is not clear how to implement them. Perhaps with
+a conversion function similar to for degrees Celsius.
+
+= References
+
+1. #note1# http://physics.nist.gov/Pubs/SP811/
+2. #note2# http://www.iau.org/science/publications/proceedings_rules/units/
+3. #note3# http://en.m.wikipedia.org/wiki/Pressure
+4. #note4# http://en.m.wikipedia.org/wiki/Torr
+
+-}
+
+module Numeric.Units.Dimensional.NonSI
+(
+  -- * Units Defined By Experiment
+  -- $values-obtained-experimentally
+  electronVolt, unifiedAtomicMassUnit, dalton,
+  -- * Standard Gravity
+  gee,
+  -- * Inch-pound Units
+  -- $inch-pound-units
+  poundMass, ounce, poundForce, horsepower, btu, shortTon,
+  nauticalMile, knot,
+  revolution, solid,
+  slug, psi,
+  teaspoon,
+  -- ** International Foot
+  foot, inch, mil, yard, mile, acre,
+  -- ** US Survey Foot
+  usSurveyFoot, usSurveyInch, usSurveyMil, usSurveyYard, usSurveyMile, usSurveyAcre,
+  -- * Years
+  -- $year
+  year, century,
+  -- * Pressure Units
+  -- $pressure-units
+  bar, atmosphere, technicalAtmosphere, mmHg, inHg, inHg_UCUM, inHg_NIST, torr,
+  -- * Radiation Units
+  rad,
+  -- * Kinematic Viscosity
+  stokes,
+  -- * Temperature
+  -- $temperature
+  degreeFahrenheit, degreeRankine,
+  -- * Imperial Volumes
+  -- $imperial-volumes
+  imperialGallon, imperialQuart, imperialPint, imperialCup, imperialGill, imperialFluidOunce,
+  -- * US Customary Volumes
+  -- $us-customary-volumes
+  usGallon, usQuart, usPint, usCup, usGill, usFluidOunce,
+  -- * Atomic-Scale Units
+  angstrom,
+  -- * Units from the Centimeter-Gram-Second Electrostatic System of Units
+  gauss
+)
+where
+
+import Numeric.Units.Dimensional.Prelude
+import Numeric.Units.Dimensional.UnitNames.Internal (ucumMetric, ucum, dimensionalAtom)
+import qualified Prelude
+
+-- $setup
+-- >>> import Data.ExactPi
+-- >>> import Data.Function (on)
+-- >>> import Numeric.Units.Dimensional.Coercion
+-- >>> default (Double)
+-- >>> :{
+-- >>>   let infix 4 ===
+-- >>>       (===) = areExactlyEqual `on` unQuantity :: Quantity d ExactPi -> Quantity d ExactPi -> Bool
+-- >>> :}
+
+{- $values-obtained-experimentally
+
+From Table 7, units accepted for use with the SI whose values in SI units are
+obtained experimentally.
+
+When <#note1 [1]> was published the electron volt had a standard combined
+uncertainity of 0.00000049e-19 J and the unified atomic mass unit
+had a combined uncertainty of 0.0000010e-27 kg.
+
+-}
+
+electronVolt :: Floating a => Unit 'Metric DEnergy a
+electronVolt = mkUnitR (ucumMetric "eV" "eV" "electron volt") 1.60217733e-19 $ joule
+
+unifiedAtomicMassUnit :: Floating a => Unit 'Metric DMass a
+unifiedAtomicMassUnit = mkUnitR (ucumMetric "u" "u" "atomic mass unit") 1.6605402e-27 $ kilo gram
+
+dalton :: Floating a => Unit 'Metric DMass a
+dalton = mkUnitR (ucumMetric "u" "Da" "Dalton") 1 $ unifiedAtomicMassUnit
+
+-- | One gee is the standard value of the acceleration due to gravity at the
+-- Earth's surface, as standardized by CIPM.
+--
+-- Note that local values of acceleration due to gravity will differ from the
+-- standard gravity.
+--
+-- See <https://en.wikipedia.org/wiki/Standard_gravity here> for further information.
+--
+-- >>> 1 *~ gee
+-- 9.80665 m s^-2
+--
+-- >>> 1 *~ gee :: Acceleration Rational
+-- 196133 % 20000 m s^-2
+gee :: Fractional a => Unit 'Metric DAcceleration a
+gee = mkUnitQ (ucumMetric "[g]" "g" "gee") 9.80665 $ meter / second ^ pos2
+
+{- $inch-pound-units
+Some US customary (that is, inch-pound) units.
+-}
+
+-- | One international foot is one third of an international 'yard'.
+--
+-- See <https://en.wikipedia.org/wiki/Foot_%28unit%29#International_foot here> for further information.
+--
+-- >>> 1 *~ foot
+-- 0.3048 m
+--
+-- prop> 3 *~ foot === 1 *~ yard
+--
+-- >>> 1 *~ foot :: Length Rational
+-- 381 % 1250 m
+foot :: Fractional a => Unit 'NonMetric DLength a
+foot = mkUnitQ (ucum "[ft_i]" "ft" "foot") (1 Prelude./ 3) $ yard
+
+-- | One inch is one twelth of a 'foot'.
+--
+-- This inch is based on the international 'foot'.
+--
+-- See <https://en.wikipedia.org/wiki/Inch#Modern_standardisation here> for further information.
+--
+-- >>> 1 *~ inch
+-- 2.54e-2 m
+--
+-- prop> 12 *~ inch === 1 *~ foot
+--
+-- >>> 1 *~ inch :: Length Rational
+-- 127 % 5000 m
+inch :: Fractional a => Unit 'NonMetric DLength a
+inch = mkUnitQ (ucum "[in_i]" "in" "inch") (1 Prelude./ 12) $ foot
+
+-- | One mil is one thousandth of an 'inch'.
+--
+-- This mil is based on the international 'inch'.
+--
+-- See <https://en.wikipedia.org/wiki/Thousandth_of_an_inch here> for further information.
+--
+-- >>> 1 *~ mil
+-- 2.54e-5 m
+--
+-- prop> 1000 *~ mil === 1 *~ inch
+--
+-- >>> 1 *~ mil :: Length Rational
+-- 127 % 5000000 m
+mil :: Fractional a => Unit 'NonMetric DLength a
+mil = mkUnitQ (ucum "[mil_i]" "mil" "mil") 0.001 $ inch
+
+-- | One yard, as defined by international agreement in 1959, is precisely
+-- 0.9144 'meter'.
+--
+-- See <https://en.wikipedia.org/wiki/Yard here> for further information.
+--
+-- >>> 1 *~ yard
+-- 0.9144 m
+--
+-- >>> 1 *~ yard :: Length Rational
+-- 1143 % 1250 m
+yard :: (Fractional a) => Unit 'NonMetric DLength a
+yard = mkUnitQ (ucum "[yd_i]" "yd" "yard") 0.9144 $ meter
+
+-- | One mile is 5 280 feet.
+--
+-- This mile is based on the international 'foot'.
+--
+-- See <https://en.wikipedia.org/wiki/Mile#International_mile here> for further information.
+--
+-- >>> 1 *~ mile
+-- 1609.344 m
+--
+-- prop> 1 *~ mile === 5280 *~ foot
+--
+-- >>> 1 *~ mile :: Length Rational
+-- 201168 % 125 m
+mile :: (Fractional a) => Unit 'NonMetric DLength a
+mile = mkUnitQ (ucum "[mi_i]" "mi" "mile") 5280 $ foot
+
+-- | One acre is 43 560 square feet.
+--
+-- This acre is based on the international 'foot'. For the acre based on the US Survey Foot,
+-- see 'usSurveyAcre'. While both acres are in use, the difference between them is of little consequence
+-- for most applications in which either is used.
+--
+-- See <https://en.wikipedia.org/wiki/Acre#Differences_between_international_and_US_survey_acres here> for further information.
+--
+-- >>> 1 *~ acre
+-- 4046.8564224 m^2
+--
+-- prop> 1 *~ acre === 43560 *~ foot ^ pos2
+--
+-- >>> 1 *~ acre :: Area Rational
+-- 316160658 % 78125 m^2
+acre :: (Fractional a) => Unit 'NonMetric DArea a
+acre = mkUnitQ (dimensionalAtom "[acr_i]" "ac" "acre") 43560 $ square foot
+
+-- | One US survey foot is 1200/3937 'meter'.
+--
+-- For the international foot, see 'foot'. Note that this is not the foot in routine use
+-- in the United States.
+--
+-- See <https://en.wikipedia.org/wiki/Foot_%28unit%29#US_survey_foot here> for further information.
+--
+-- >>> 1 *~ usSurveyFoot
+-- 0.3048006096012192 m
+--
+-- >>> 1 *~ usSurveyFoot :: Length Rational
+-- 1200 % 3937 m
+usSurveyFoot :: Fractional a => Unit 'NonMetric DLength a
+usSurveyFoot = mkUnitQ (ucum "[ft_us]" "ft" "foot") (1200 Prelude./ 3937) $ meter
+
+-- | One inch is one twelth of a foot.
+--
+-- This inch is based on the 'usSurveyFoot'. For the inch based on the international foot,
+-- see 'inch'. Note that this is not the inch in routine use in the United States.
+--
+-- See <https://en.wikipedia.org/wiki/Inch here> for further information.
+--
+-- >>> 1 *~ usSurveyInch
+-- 2.54000508001016e-2 m
+--
+-- prop> 12 *~ usSurveyInch === 1 *~ usSurveyFoot
+--
+-- >>> 1 *~ usSurveyInch :: Length Rational
+-- 100 % 3937 m
+usSurveyInch :: Fractional a => Unit 'NonMetric DLength a
+usSurveyInch = mkUnitQ (ucum "[in_us]" "in" "inch") (1 Prelude./ 12) $ usSurveyFoot
+
+-- | One mil is one thousandth of an inch.
+--
+-- This mil is based on the 'usSurveyInch'. For the mil based on the international inch,
+-- see 'mil'. Note that this is not the mil in routine use in the United States.
+--
+-- See <https://en.wikipedia.org/wiki/Thousandth_of_an_inch here> for further information.
+--
+-- >>> 1 *~ usSurveyMil
+-- 2.54000508001016e-5 m
+--
+-- prop> 1000 *~ usSurveyMil === 1 *~ usSurveyInch
+--
+-- >>> 1 *~ usSurveyMil :: Length Rational
+-- 1 % 39370 m
+usSurveyMil :: Fractional a => Unit 'NonMetric DLength a
+usSurveyMil = mkUnitQ (ucum "[mil_us]" "mil" "mil") 0.001 $ usSurveyInch
+
+-- | One yard is three feet.
+--
+-- This yard is based on the 'usSurveyFoot'. For the international yard,
+-- see 'yard'. Note that this is not the yard in routine use in the United States.
+--
+-- See <https://en.wikipedia.org/wiki/Yard here> for further information.
+--
+-- >>> 1 *~ usSurveyYard
+-- 0.9144018288036576 m
+--
+-- prop> 1 *~ usSurveyYard === 3 *~ usSurveyFoot
+--
+-- >>> 1 *~ usSurveyYard :: Length Rational
+-- 3600 % 3937 m
+usSurveyYard :: (Fractional a) => Unit 'NonMetric DLength a
+usSurveyYard = mkUnitQ (ucum "[yd_us]" "yd" "yard") 3 $ usSurveyFoot
+
+-- | One US survey mile is 5 280 US survey feet.
+--
+-- This mile is based on the 'usSurveyFoot'. For the mile based on the international foot,
+-- see 'mile'. Note that this is not the mile in routine use in the United States.
+--
+-- See <https://en.wikipedia.org/wiki/Mile#US_survey_mile here> for further information.
+--
+-- >>> 1 *~ usSurveyMile
+-- 1609.3472186944373 m
+--
+-- prop> 1 *~ usSurveyMile === 5280 *~ usSurveyFoot
+--
+-- >>> 1 *~ usSurveyMile :: Length Rational
+-- 6336000 % 3937 m
+usSurveyMile :: (Fractional a) => Unit 'NonMetric DLength a
+usSurveyMile = mkUnitQ (ucum "[mi_us]" "mi" "mile") 5280 $ usSurveyFoot
+
+-- | One acre is 43 560 square feet.
+--
+-- This acre is based on the 'usSurveyFoot'. For the acre based on the international foot,
+-- see 'acre'. While both acres are in use, the difference between them is of little consequence
+-- for most applications in which either is used. This is the only acre defined by the UCUM.
+--
+-- See <https://en.wikipedia.org/wiki/Acre#Differences_between_international_and_US_survey_acres here> for further information.
+--
+-- >>> 1 *~ usSurveyAcre
+-- 4046.872609874252 m^2
+--
+-- prop> 1 *~ usSurveyAcre === 43560 *~ usSurveyFoot ^ pos2
+--
+-- >>> 1 *~ usSurveyAcre :: Area Rational
+-- 62726400000 % 15499969 m^2
+usSurveyAcre :: (Fractional a) => Unit 'NonMetric DArea a
+usSurveyAcre = mkUnitQ (ucum "[acr_us]" "ac" "acre") 43560 $ square usSurveyFoot
+
+-- | One avoirdupois pound is a mass, exactly defined in terms of the kilogram by the international
+-- yard and pound agreement of 1959.
+--
+-- See <https://en.wikipedia.org/wiki/Avoirdupois#Internationalization here> for further information.
+--
+-- >>> 1 *~ poundMass
+-- 0.45359237 kg
+--
+-- >>> 1 *~ poundMass :: Mass Rational
+-- 45359237 % 100000000 kg
+poundMass :: Fractional a => Unit 'NonMetric DMass a
+poundMass = mkUnitQ (ucum "[lb_av]" "lb" "pound") 0.45359237 $ kilo gram
+
+-- | One avoirdupois ounce is one sixteenth of a 'poundMass'.
+--
+-- See <https://en.wikipedia.org/wiki/Ounce#International_avoirdupois_ounce here> for further information.
+--
+-- >>> 1 *~ ounce
+-- 2.8349523125e-2 kg
+--
+-- prop> 16 *~ ounce === 1 *~ poundMass
+--
+-- >>> 1 *~ ounce :: Mass Rational
+-- 45359237 % 1600000000 kg
+ounce :: Fractional a => Unit 'NonMetric DMass a
+ounce = mkUnitQ (ucum "[oz_av]" "oz" "ounce") (1 Prelude./ 16) $ poundMass
+
+-- | One short ton is two thousand 'poundMass'.
+--
+-- See <https://en.wikipedia.org/wiki/Short_ton#United_States here> for further information.
+--
+-- >>> 1 *~ shortTon
+-- 907.18474 kg
+--
+-- >>> 1 *~ shortTon :: Mass Rational
+-- 45359237 % 50000 kg
+shortTon :: Fractional a => Unit 'NonMetric DMass a
+shortTon = mkUnitQ (ucum "[ston_av]" "ton" "short ton") 2000 $ poundMass
+
+-- | The pound-force is equal to the gravitational force exerted on a mass
+-- of one avoirdupois pound on the surface of Earth.
+--
+-- This definition is based on standard gravity (the 'gee') and the
+-- international avoirdupois 'poundMass'.
+--
+-- See <https://en.wikipedia.org/wiki/Pound_%28force%29 here> for further information.
+--
+-- >>> 1 *~ poundForce
+-- 4.4482216152605 m kg s^-2
+--
+-- prop> 1 *~ poundForce === 1 *~ poundMass * (1 *~ gee)
+--
+-- >>> 1 *~ poundForce :: Force Rational
+-- 8896443230521 % 2000000000000 m kg s^-2
+poundForce :: Fractional a => Unit 'NonMetric DForce a
+poundForce = mkUnitQ (ucum "[lbf_av]" "lbf" "pound force") 1 $ poundMass * gee
+
+-- | One mechanical horsepower is by definition the power necessary
+-- to apply a force of 550 'poundForce' through a distance of one 'foot'
+-- per 'second'.
+--
+-- See <https://en.wikipedia.org/wiki/Horsepower#Mechanical_horsepower here> for further information.
+--
+-- >>> 1 *~ horsepower
+-- 745.6998715822702 m^2 kg s^-3
+--
+-- prop> 1 *~ horsepower === 550 *~ poundForce * (1 *~ foot) / (1 *~ second)
+--
+-- >>> 1 *~ horsepower :: Power Rational
+-- 37284993579113511 % 50000000000000 m^2 kg s^-3
+horsepower :: Fractional a => Unit 'NonMetric DPower a
+horsepower = mkUnitQ (ucum "[HP]" "hp" "horsepower") 550 $ foot * poundForce / second
+
+-- | The slug is a unit of mass associated with Imperial units and United States customary units.
+-- It is a mass that accelerates by 1 foot per second per second when a force of one pound is exerted on it.
+--
+-- This definition is based on standard gravity (the 'gee'), the international 'foot', and the international avoirdupois 'poundMass'.
+--
+-- See <https://en.wikipedia.org/wiki/Slug_%28mass%29 here> for further information.
+--
+-- >>> 1 *~ slug
+-- 14.593902937206364 kg
+--
+-- >>> 1 *~ slug :: Mass Rational
+-- 8896443230521 % 609600000000 kg
+slug :: Fractional a => Unit 'NonMetric DMass a
+slug = mkUnitQ (dimensionalAtom "slug" "slug" "slug") 1 $ poundForce * (second^pos2) / foot
+
+-- | One psi is a pressure of one 'poundForce' per 'square' 'inch' of area.
+--
+-- See <https://en.wikipedia.org/wiki/Pounds_per_square_inch here> for further information.
+--
+-- >>> 1 *~ psi
+-- 6894.757293168362 m^-1 kg s^-2
+--
+-- >>> 1 *~ psi :: Pressure Rational
+-- 8896443230521 % 1290320000 m^-1 kg s^-2
+psi :: Fractional a => Unit 'NonMetric DPressure a
+psi = mkUnitQ (ucum "[psi]" "psi" "pound per square inch") 1 $ poundForce / inch ^ pos2
+
+-- | One nautical mile is a unit of length, set by international agreement as being exactly 1 852 meters.
+--
+-- Historically, it was defined as the distance spanned by one minute of arc along a meridian of the Earth.
+--
+-- See <https://en.wikipedia.org/wiki/Nautical_mile here> for further information.
+--
+-- >>> 1 *~ nauticalMile
+-- 1852.0 m
+--
+-- >>> 1 *~ nauticalMile :: Length Rational
+-- 1852 % 1 m
+nauticalMile :: (Num a) => Unit 'NonMetric DLength a
+nauticalMile = mkUnitZ (ucum "[nmi_i]" "NM" "nautical mile") 1852 $ meter
+
+-- | One knot is a velocity equal to one 'nauticalMile' per 'hour'.
+--
+-- See <https://en.wikipedia.org/wiki/Knot_%28unit%29 here> for further information.
+--
+-- >>> 1 *~ knot
+-- 0.5144444444444445 m s^-1
+--
+-- >>> 1 *~ knot :: Velocity Rational
+-- 463 % 900 m s^-1
+knot :: (Fractional a) => Unit 'NonMetric DVelocity a
+knot = mkUnitQ (ucum "[kt_i]" "kt" "knot") 1 $ nauticalMile / hour
+
+-- | One revolution is an angle equal to 2 pi radians; a full circle.
+--
+-- See <https://en.wikipedia.org/wiki/Turn_%28geometry%29 here> for further information.
+--
+-- >>> 1 *~ revolution
+-- 6.283185307179586
+--
+-- prop> 1 *~ revolution === _2 * pi * (1 *~ radian)
+--
+-- prop> 1 *~ revolution === 360 *~ degree
+revolution :: (Floating a) => Unit 'NonMetric DOne a
+revolution = mkUnitR (dimensionalAtom "rev" "rev" "revolution") (2 Prelude.* Prelude.pi) $ radian
+
+solid :: (Floating a) => Unit 'NonMetric DOne a
+solid = mkUnitR (dimensionalAtom "solid" "solid" "solid") (4 Prelude.* Prelude.pi) $ steradian
+
+teaspoon :: (Fractional a) => Unit 'NonMetric DVolume a
+teaspoon = mkUnitQ (ucum "[tsp_m]" "tsp" "teaspoon") 5 $ milli liter
+
+-- | One btu is is the 'QuantityOfHeat' required to raise the temperature
+-- of 1 avoirdupois 'poundMass' of liquid water by 1 'degreeFahrenheit' at a constant pressure of one 'atmosphere'.
+--
+-- Because this value must be determined experimentally and varies with temperature, several standardized
+-- values of the btu have arisen. This is the value based on the International Steam Table calorie,
+-- defined by the Fifth International Conference on the Properties of Steam.
+--
+-- See <https://en.wikipedia.org/wiki/British_thermal_unit#Definitions here> for further information.
+--
+-- >>> 1 *~ btu
+-- 1055.05585262 m^2 kg s^-2
+--
+-- >>> 1 *~ btu :: Energy Rational
+-- 52752792631 % 50000000 m^2 kg s^-2
+btu :: Fractional a => Unit 'NonMetric DEnergy a
+btu = mkUnitQ (ucum "[Btu_IT]" "btu" "British thermal unit") 1055.05585262 $ joule
+
+
+{- $year
+
+The IAU recommends <#note2 [2]> that:
+
+  Although there are several different kinds of year (as there are
+  several kinds of day), it is best to regard a year as a julian
+  year of 365.25 days (31.5576 Ms) unless otherwise specified.
+
+-}
+
+-- | One mean Julian year is a unit of measurement of time defined as exactly 365.25 days of 86 400 'second's each.
+--
+-- See <https://en.wikipedia.org/wiki/Julian_year_%28astronomy%29 here> for further information.
+--
+-- >>> 1 *~ year
+-- 3.15576e7 s
+--
+-- >>> 1 *~ year :: Time Rational
+-- 31557600 % 1 s
+year :: Num a => Unit 'NonMetric DTime a
+year = mkUnitZ (ucum "a_j" "a" "mean Julian year") 31557600 $ second
+
+-- | One mean Julian century is one hundred mean Julian 'year's.
+--
+-- >>> 1 *~ century
+-- 3.15576e9 s
+--
+-- >>> 1 *~ century :: Time Rational
+-- 3155760000 % 1 s
+century :: Num a => Unit 'NonMetric DTime a
+century = mkUnitZ (dimensionalAtom "c_j" "cen" "mean Julian century") 100 $ year
+
+{- $pressure-units
+It seems that nearly every area of application has its own customary unit for measuring pressure.
+We include some of the common ones here. 'psi' was defined earlier.
+-}
+
+-- | The bar is exactly 100 000 'Numeric.Units.Dimensional.SIUnits.pascal'.
+--
+-- From Wikipedia:
+--
+--  It is about equal to the atmospheric pressure on Earth at sea level.
+--
+-- >>> 1 *~ bar
+-- 100000.0 m^-1 kg s^-2
+--
+-- >>> 1 *~ bar :: Pressure Rational
+-- 100000 % 1 m^-1 kg s^-2
+bar :: (Num a) => Unit 'Metric DPressure a
+bar = mkUnitZ (ucumMetric "bar" "bar" "bar") 1e5 $ pascal
+
+-- | The "standard atmosphere".
+--
+-- From Wikipedia <#note3 [3]>:
+--
+--  The standard atmosphere (atm) is an established constant. It is
+--  approximately equal to typical air pressure at earth mean sea
+--  level.
+--
+-- >>> 1 *~ atmosphere
+-- 101325.0 m^-1 kg s^-2
+--
+-- >>> 1 *~ atmosphere :: Pressure Rational
+-- 101325 % 1 m^-1 kg s^-2
+atmosphere :: (Num a) => Unit 'NonMetric DPressure a
+atmosphere = mkUnitZ (ucum "atm" "atm" "standard atmosphere") 101325 $ pascal
+
+-- | The "technical atmosphere"
+--
+-- From Wikipedia:
+--
+--  A technical atmosphere (symbol: at) is a non-SI unit of pressure equal
+--  to one kilogram-force per square centimeter.
+--
+-- >>> 1 *~ technicalAtmosphere
+-- 98066.5 m^-1 kg s^-2
+--
+-- >>> 1 *~ technicalAtmosphere :: Pressure Rational
+-- 196133 % 2 m^-1 kg s^-2
+technicalAtmosphere :: (Fractional a) => Unit 'NonMetric DPressure a
+technicalAtmosphere = mkUnitQ (ucum "att" "at" "technical atmosphere") 1 $ kilo gram * gee * centi meter ^ neg2
+
+-- | The conventional value for the pressure exerted by a 1 mm high column of mercury.
+--
+-- Per Wikipedia <#note4 [4]>, one mmHg (millimeter of mercury) is defined as:
+--
+--  The pressure exerted at the base of a column of fluid exactly 1 mm high,
+--  when the density of the fluid is exactly 13.5951 g/cm^3, at a place
+--  where the acceleration of gravity is exactly 9.80665 m/s^2.
+--
+-- The chosen fluid density approximately corresponds to that of mercury
+-- at 0 deg. Under most conditions, 1 mmHg is approximately equal to 1 'torr'.
+--
+-- >>> 1 *~ mmHg
+-- 133.322 m^-1 kg s^-2
+--
+-- >>> 1 *~ mmHg :: Pressure Rational
+-- 66661 % 500 m^-1 kg s^-2
+mmHg :: (Fractional a) => Unit 'NonMetric DPressure a
+mmHg = milli mHg
+
+mHg :: (Fractional a) => Unit 'Metric DPressure a
+mHg = mkUnitQ (ucumMetric "m[Hg]" "m Hg" "meter of mercury") 133.3220 $ kilo pascal
+
+-- | The conventional value for the pressure exerted by a 1 inch high column of mercury.
+--
+-- Column inches of mercury are also used to measure pressure, especially in
+-- meteorological or aeronautical contexts in the United States.
+--
+-- This is the value defined by UCUM. For the value defined by NIST, see 'inHg_NIST'.
+--
+-- >>> 1 *~ inHg
+-- 3386.3788 m^-1 kg s^-2
+--
+-- >>> 1 *~ inHg :: Pressure Rational
+-- 8465947 % 2500 m^-1 kg s^-2
+inHg :: (Fractional a) => Unit 'NonMetric DPressure a
+inHg = inHg_UCUM
+
+-- | The conventional value for the pressure exerted by a 1 inch high column of mercury.
+--
+-- Column inches of mercury are also used to measure pressure, especially in
+-- meteorological or aeronautical contexts in the United States.
+--
+-- This is the value defined by UCUM. For the value defined by NIST, see 'inHg_NIST'.
+--
+-- >>> 1 *~ inHg_UCUM
+-- 3386.3788 m^-1 kg s^-2
+--
+-- >>> 1 *~ inHg_UCUM :: Pressure Rational
+-- 8465947 % 2500 m^-1 kg s^-2
+inHg_UCUM :: (Fractional a) => Unit 'NonMetric DPressure a
+inHg_UCUM = mkUnitQ (ucum "[in_i'Hg]" "in Hg" "inch of mercury") 1 $ mHg * inch / meter
+
+-- | The conventional value for the pressure exerted by a 1 inch high column of mercury.
+--
+-- Column inches of mercury are also used to measure pressure, especially in
+-- meteorological or aeronautical contexts in the United States.
+--
+-- This is the value defined by NIST. For the value defined by UCUM, see 'inHg_UCUM'.
+--
+-- >>> 1 *~ inHg_NIST
+-- 3386.389 m^-1 kg s^-2
+--
+-- >>> 1 *~ inHg_NIST :: Pressure Rational
+-- 3386389 % 1000 m^-1 kg s^-2
+inHg_NIST :: (Fractional a) => Unit 'NonMetric DPressure a
+inHg_NIST = mkUnitQ (dimensionalAtom "[in_i'Hg_NIST]" "in Hg" "inch of mercury") 3.386389e3 $ pascal
+
+-- | One torr (symbol: Torr) is defined as 1/760 'atmosphere', which is approximately equal to 1 'mmHg'.
+--
+-- See <https://en.wikipedia.org/wiki/Torr here> for further information.
+--
+-- >>> 1 *~ torr
+-- 133.32236842105263 m^-1 kg s^-2
+--
+-- >>> 1 *~ torr :: Pressure Rational
+-- 20265 % 152 m^-1 kg s^-2
+torr :: (Fractional a) => Unit 'NonMetric DPressure a
+torr = mkUnitQ (dimensionalAtom "Torr" "Torr" "Torr") (1 Prelude./ 760) $ atmosphere
+
+-- | The rad is a deprecated unit of 'AbsorbedDose', defined as
+-- 0.01 'gray'.
+--
+-- See <https://en.wikipedia.org/wiki/Rad_%28unit%29 here> for further information.
+--
+-- >>> 1 *~ rad
+-- 1.0e-2 m^2 s^-2
+--
+-- >>> 1 *~ rad :: AbsorbedDose Rational
+-- 1 % 100 m^2 s^-2
+rad :: (Fractional a) => Unit 'Metric DAbsorbedDose a
+rad = mkUnitQ (ucumMetric "RAD" "RAD" "RAD") 1 $ centi gray
+
+-- | One Stokes is a unit of 'KinematicViscosity' equal to @1 cm^2 / s@.
+--
+-- See <https://en.wikipedia.org/wiki/Viscosity#Kinematic_viscosity_.CE.BD here> for further information.
+--
+-- >>> 1 *~ stokes
+-- 1.0e-4 m^2 s^-1
+--
+-- >>> 1 *~ stokes :: KinematicViscosity Rational
+-- 1 % 10000 m^2 s^-1
+stokes :: (Fractional a) => Unit 'Metric DKinematicViscosity a
+stokes = mkUnitQ (ucumMetric "St" "St" "Stokes") 1 $ centi meter ^ pos2 / second
+
+{- $temperature
+These units of temperature are relative. For absolute temperatures, see 'Numeric.Units.Dimensional.SIUnits.fromDegreeCelsiusAbsolute'.
+-}
+
+-- | One degree Fahrenheit is a unit of relative temperature equal to 5/9 'kelvin'.
+--
+-- Note that although the Fahrenheit scale is an absolute temperature scale, this unit is a unit of difference within
+-- that scale and measures relative temperature.
+--
+-- See <https://en.wikipedia.org/wiki/Fahrenheit#Definition_and_conversions here> for further information.
+--
+-- >>> 1 *~ degreeFahrenheit
+-- 0.5555555555555556 K
+--
+-- >>> 1 *~ degreeFahrenheit :: ThermodynamicTemperature Rational
+-- 5 % 9 K
+degreeFahrenheit :: (Fractional a) => Unit 'NonMetric DThermodynamicTemperature a
+degreeFahrenheit = mkUnitQ (ucum "[degF]" "°F" "degree Fahrenheit") (5 Prelude./ 9) $ degreeCelsius
+
+-- | One degree Rankine is a unit of relative temperature equal to 5/9 'kelvin'.
+--
+-- Note that although the Rankine scale is an absolute temperature scale, this unit is a unit of difference within
+-- that scale and measures relative temperature.
+--
+-- See <https://en.wikipedia.org/wiki/Rankine_scale here> for further information.
+--
+-- >>> 1 *~ degreeRankine
+-- 0.5555555555555556 K
+--
+-- >>> 1 *~ degreeRankine :: ThermodynamicTemperature Rational
+-- 5 % 9 K
+degreeRankine :: (Fractional a) => Unit 'NonMetric DThermodynamicTemperature a
+degreeRankine = mkUnitQ (ucum "[degR]" "°R" "degree Rankine") 1 $ degreeFahrenheit
+
+{- $imperial-volumes
+Per http://en.wikipedia.org/wiki/Imperial_units and http://en.wikipedia.org/wiki/Cup_(unit)#Imperial_cup.
+-}
+
+-- | One imperial gallon is defined exactly in terms of the 'liter'
+-- by the Weights and Measures Act 1985.
+--
+-- See <https://en.wikipedia.org/wiki/Imperial_units#Volume here> for further information.
+--
+-- >>> 1 *~ imperialGallon
+-- 4.54609e-3 m^3
+--
+-- >>> 1 *~ imperialGallon :: Volume Rational
+-- 454609 % 100000000 m^3
+imperialGallon :: (Fractional a) => Unit 'NonMetric DVolume a
+imperialGallon = mkUnitQ (ucum "[gal_br]" "gal" "gallon") 4.54609 $ liter
+
+-- | One imperial quart is one quarter of an 'imperialGallon'.
+--
+-- See <https://en.wikipedia.org/wiki/Imperial_units#Volume here> for further information.
+--
+-- >>> 1 *~ imperialQuart
+-- 1.1365225e-3 m^3
+--
+-- >>> 1 *~ imperialQuart :: Volume Rational
+-- 454609 % 400000000 m^3
+imperialQuart :: (Fractional a) => Unit 'NonMetric DVolume a
+imperialQuart = mkUnitQ (ucum "[qt_br]" "qt" "quart") (1 Prelude./ 4) $ imperialGallon
+
+-- | One imperial pint is one half of an 'imperialQuart'.
+--
+-- See <https://en.wikipedia.org/wiki/Imperial_units#Volume here> for further information.
+--
+-- >>> 1 *~ imperialPint
+-- 5.6826125e-4 m^3
+--
+-- >>> 1 *~ imperialPint :: Volume Rational
+-- 454609 % 800000000 m^3
+imperialPint :: (Fractional a) => Unit 'NonMetric DVolume a
+imperialPint = mkUnitQ (ucum "[pt_br]" "pt" "pint") (1 Prelude./ 8) $ imperialGallon
+
+-- | One imperial cup is one half of an 'imperialPint'.
+--
+-- This unit is not in common use and is does not appear in some sources
+-- describing the imperial fluid volume units.
+--
+-- See <https://en.wikipedia.org/wiki/Cup_%28unit%29#Imperial_cup here> for further information.
+--
+-- >>> 1 *~ imperialCup
+-- 2.84130625e-4 m^3
+--
+-- >>> 1 *~ imperialCup :: Volume Rational
+-- 454609 % 1600000000 m^3
+imperialCup :: (Fractional a) => Unit 'NonMetric DVolume a
+imperialCup = mkUnitQ (dimensionalAtom "[cup_br]" "cup" "cup") 0.5 $ imperialPint
+
+-- | One imperial gill is one quarter of an 'imperialPint'.
+--
+-- See <https://en.wikipedia.org/wiki/Imperial_units#Volume here> for further information.
+--
+-- >>> 1 *~ imperialGill
+-- 1.420653125e-4 m^3
+--
+-- >>> 1 *~ imperialGill :: Volume Rational
+-- 454609 % 3200000000 m^3
+imperialGill :: (Fractional a) => Unit 'NonMetric DVolume a
+imperialGill = mkUnitQ (ucum "[gil_br]" "gill" "gill") (1 Prelude./ 4) $ imperialPint
+
+-- | One imperial fluid ounce is one twentieth of an 'imperialPint'.
+--
+-- See <https://en.wikipedia.org/wiki/Imperial_units#Volume here> for further information.
+--
+-- >>> 1 *~ imperialFluidOunce
+-- 2.84130625e-5 m^3
+--
+-- >>> 1 *~ imperialFluidOunce :: Volume Rational
+-- 454609 % 16000000000 m^3
+imperialFluidOunce :: (Fractional a) => Unit 'NonMetric DVolume a
+imperialFluidOunce = mkUnitQ (ucum "[foz_br]" "fl oz" "fluid ounce") (1 Prelude./ 20) $ imperialPint
+
+{- $us-customary-volumes
+Per http://www.nist.gov/pml/wmd/pubs/upload/2012-hb44-final.pdf page 452 and http://en.wikipedia.org/wiki/United_States_customary_units#Fluid_volume
+Note that there exist rarely-used "dry" variants of units with overlapping names.
+-}
+
+-- | One US liquid gallon is a volume of 231 cubic inches.
+--
+-- See <https://en.wikipedia.org/wiki/Gallon#The_US_liquid_gallon here> for further information.
+--
+-- >>> 1 *~ usGallon
+-- 3.785411784e-3 m^3
+--
+-- >>> 1 *~ usGallon :: Volume Rational
+-- 473176473 % 125000000000 m^3
+usGallon :: (Fractional a) => Unit 'NonMetric DVolume a
+usGallon = mkUnitQ (ucum "[gal_us]" "gal" "gallon") 231 $ (cubic inch)
+
+-- | One US liquid quart is one quarter of a 'usGallon'.
+--
+-- See <https://en.wikipedia.org/wiki/United_States_customary_units#Fluid_volume here> for further information.
+--
+-- >>> 1 *~ usQuart
+-- 9.46352946e-4 m^3
+--
+-- >>> 1 *~ usQuart :: Volume Rational
+-- 473176473 % 500000000000 m^3
+usQuart :: (Fractional a) => Unit 'NonMetric DVolume a
+usQuart = mkUnitQ (ucum "[qt_us]" "qt" "quart") (1 Prelude./ 4) $ usGallon
+
+-- | One US liquid pint is one half of a 'usQuart'.
+--
+-- See <https://en.wikipedia.org/wiki/United_States_customary_units#Fluid_volume here> for further information.
+--
+-- >>> 1 *~ usPint
+-- 4.73176473e-4 m^3
+--
+-- >>> 1 *~ usPint :: Volume Rational
+-- 473176473 % 1000000000000 m^3
+usPint :: (Fractional a) => Unit 'NonMetric DVolume a
+usPint = mkUnitQ (ucum "[pt_us]" "pt" "pint") (1 Prelude./ 8) $ usGallon
+
+-- | One US liquid cup is one half of a 'usPint'.
+--
+-- See <https://en.wikipedia.org/wiki/United_States_customary_units#Fluid_volume here> for further information.
+--
+-- >>> 1 *~ usCup
+-- 2.365882365e-4 m^3
+--
+-- >>> 1 *~ usCup :: Volume Rational
+-- 473176473 % 2000000000000 m^3
+usCup :: (Fractional a) => Unit 'NonMetric DVolume a
+usCup = mkUnitQ (ucum "[cup_us]" "cup" "cup") (1 Prelude./ 2) $ usPint
+
+-- | One US liquid gill is one half of a 'usCup'.
+--
+-- See <https://en.wikipedia.org/wiki/United_States_customary_units#Fluid_volume here> for further information.
+--
+-- >>> 1 *~ usGill
+-- 1.1829411825e-4 m^3
+--
+-- >>> 1 *~ usGill :: Volume Rational
+-- 473176473 % 4000000000000 m^3
+usGill :: (Fractional a) => Unit 'NonMetric DVolume a
+usGill = mkUnitQ (ucum "[gil_us]" "gill" "gill") (1 Prelude./ 4) $ usPint
+
+-- | One US fluid ounce is 1/128 'usGallon' or 1/8 'usCup'.
+--
+-- See <https://en.wikipedia.org/wiki/United_States_customary_units#Fluid_volume here> for further information.
+--
+-- >>> 1 *~ usFluidOunce
+-- 2.95735295625e-5 m^3
+--
+-- >>> 1 *~ usFluidOunce :: Volume Rational
+-- 473176473 % 16000000000000 m^3
+usFluidOunce :: (Fractional a) => Unit 'NonMetric DVolume a
+usFluidOunce = mkUnitQ (ucum "[foz_us]" "fl oz" "fluid ounce") (1 Prelude./ 16) $ usPint -- sic, does not match factor used in imperial system
+
+-- | One Ångström is 1/10 'nano' 'meter'.
+--
+-- See <https://en.wikipedia.org/wiki/%C3%85ngstr%C3%B6m here> for further information.
+--
+-- >>> 1 *~ angstrom
+-- 1.0e-10 m
+--
+-- >>> 1 *~ angstrom :: Length Rational
+-- 1 % 10000000000 m
+angstrom :: (Fractional a) => Unit 'NonMetric DLength a
+angstrom = mkUnitQ (ucum "Ao" "Å" "Ångström") 0.1 $ nano meter
+
+-- | One Gauss is 1/10000 'tesla'.
+--
+-- See <https://en.wikipedia.org/wiki/Gauss_%28unit%29 here> for further information.
+--
+-- >>> 1 *~ gauss
+-- 1.0e-4 kg s^-2 A^-1
+--
+-- >>> 1 *~ gauss :: MagneticFluxDensity Rational
+-- 1 % 10000 kg s^-2 A^-1
+gauss :: (Fractional a) => Unit 'NonMetric DMagneticFluxDensity a
+gauss = mkUnitQ (ucum "G" "G" "Gauss") 1e-4 $ tesla
src/Numeric/Units/Dimensional/Prelude.hs view
@@ -1,52 +1,52 @@-{- |-   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter-   License    : BSD3--   Maintainer : bjorn@buckwalter.se-   Stability  : Stable-   Portability: GHC only--= Summary--This module supplies a convenient set of imports for working with the dimensional package, including aliases for common 'Quantity's and 'Dimension's,-and a comprehensive set of SI units and units accepted for use with the SI.--It re-exports the "Prelude", hiding arithmetic functions whose names collide with the dimensionally-typed versions supplied by this package.---}-module Numeric.Units.Dimensional.Prelude-    ( module Numeric.Units.Dimensional-    , module Numeric.Units.Dimensional.Quantities-    , module Numeric.Units.Dimensional.SIUnits-    , module Numeric.NumType.DK.Integers-    , module Control.Category-    , module Data.Foldable-    , module Prelude-    ) where--import Numeric.Units.Dimensional hiding-    ( dmap-    )--import Numeric.Units.Dimensional.Quantities--import Numeric.Units.Dimensional.SIUnits--import Numeric.NumType.DK.Integers-    ( neg5, neg4, neg3, neg2, neg1, zero, pos1, pos2, pos3, pos4, pos5-    )  -- Used in exponents.--import Control.Category-    ( Category(..) )--import Data.Foldable-    ( minimum, maximum )--import Prelude hiding-    ( (+), (-), (*), (/), (^), (**)-    , abs, signum, negate, recip, pi, exp, log, logBase, sqrt-    , sin, cos, tan, asin, acos, atan, atan2-    , sinh, cosh, tanh, asinh, acosh, atanh-    , sum, product, minimum, maximum-    , id, (.)-    )  -- Hide definitions overridden by 'Numeric.Dimensional'.+{- |
+   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+= Summary
+
+This module supplies a convenient set of imports for working with the dimensional package, including aliases for common 'Quantity's and 'Dimension's,
+and a comprehensive set of SI units and units accepted for use with the SI.
+
+It re-exports the "Prelude", hiding arithmetic functions whose names collide with the dimensionally-typed versions supplied by this package.
+
+-}
+module Numeric.Units.Dimensional.Prelude
+    ( module Numeric.Units.Dimensional
+    , module Numeric.Units.Dimensional.Quantities
+    , module Numeric.Units.Dimensional.SIUnits
+    , module Numeric.NumType.DK.Integers
+    , module Control.Category
+    , module Data.Foldable
+    , module Prelude
+    ) where
+
+import Numeric.Units.Dimensional hiding
+    ( dmap
+    )
+
+import Numeric.Units.Dimensional.Quantities
+
+import Numeric.Units.Dimensional.SIUnits
+
+import Numeric.NumType.DK.Integers
+    ( neg5, neg4, neg3, neg2, neg1, zero, pos1, pos2, pos3, pos4, pos5
+    )  -- Used in exponents.
+
+import Control.Category
+    ( Category(..) )
+
+import Data.Foldable
+    ( minimum, maximum )
+
+import Prelude hiding
+    ( (+), (-), (*), (/), (^), (**)
+    , abs, signum, negate, recip, pi, exp, log, logBase, sqrt
+    , sin, cos, tan, asin, acos, atan, atan2
+    , sinh, cosh, tanh, asinh, acosh, atanh
+    , sum, product, minimum, maximum
+    , id, (.)
+    )  -- Hide definitions overridden by 'Numeric.Dimensional'.
src/Numeric/Units/Dimensional/Quantities.hs view
@@ -1,435 +1,435 @@-{-# OPTIONS_HADDOCK show-extensions #-}--{-# LANGUAGE DataKinds #-}--{- |-   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter-   License    : BSD3--   Maintainer : bjorn@buckwalter.se-   Stability  : Stable-   Portability: GHC only--= Summary--This module defines type synonyms for common dimensionalities and-the associated quantity types. Additional dimensionalities and-quantity types will be added on an as-needed basis.--The definitions in this module are grouped so that a type synonym-for the dimensionality is defined first in terms of base dimension-exponents. Then a type synonym for the corresponding quantity type-is defined. If there are several quantity types with the same-dimensionality type synonyms are provided for each quantity type.--= References--1. #note1# http://physics.nist.gov/Pubs/SP811/---}--module Numeric.Units.Dimensional.Quantities-(-  -- * Quantities from the NIST Guide-  -- $nist-guide-  Area, Volume, Velocity, Acceleration, WaveNumber, MassDensity, Density, SpecificVolume, CurrentDensity,-  MagneticFieldStrength, AmountOfSubstanceConcentration, Concentration, Luminance,-  -- $table3-  PlaneAngle, SolidAngle, Frequency, Force, Pressure, Stress, Energy, Work, QuantityOfHeat, Power, RadiantFlux,-  ElectricCharge, QuantityOfElectricity, ElectricPotential, PotentialDifference, ElectromotiveForce,-  Capacitance, ElectricResistance, ElectricConductance, MagneticFlux, MagneticFluxDensity,-  Inductance, LuminousFlux, Illuminance, CelsiusTemperature,-  Activity, AbsorbedDose, SpecificEnergy, Kerma, DoseEquivalent, AmbientDoseEquivalent, DirectionalDoseEquivalent, PersonalDoseEquivalent, EquivalentDose, CatalyticActivity,-  -- $table4-  AngularVelocity, AngularAcceleration, DynamicViscosity, MomentOfForce, SurfaceTension, HeatFluxDensity,-  Irradiance, RadiantIntensity, Radiance, HeatCapacity, Entropy, SpecificHeatCapacity, SpecificEntropy,-  ThermalConductivity, EnergyDensity, ElectricFieldStrength, ElectricChargeDensity, ElectricFluxDensity, Permittivity, Permeability,-  MolarEnergy, MolarEntropy, MolarHeatCapacity, Exposure, AbsorbedDoseRate,-  -- * Quantities not from the NIST Guide-  -- $not-nist-guide-  Impulse, Momentum, MassFlow, VolumeFlow, GravitationalParameter, KinematicViscosity, FirstMassMoment, MomentOfInertia, AngularMomentum,-  ThermalResistivity, ThermalConductance, ThermalResistance, HeatTransferCoefficient, ThermalAdmittance, ThermalInsulance,-  Jerk, Angle, Thrust, Torque, EnergyPerUnitMass,-  -- * Powers of Unit Lengths-  -- $powers-of-length-units-  square, cubic,-  -- * Dimension Aliases-  -- $dimension-aliases-  DArea, DVolume, DVelocity, DAcceleration, DWaveNumber, DMassDensity, DDensity, DSpecificVolume, DCurrentDensity,-  DMagneticFieldStrength, DAmountOfSubstanceConcentration, DConcentration, DLuminance,-  DPlaneAngle, DSolidAngle, DFrequency, DForce, DPressure, DStress, DEnergy, DWork, DQuantityOfHeat, DPower, DRadiantFlux,-  DElectricCharge, DQuantityOfElectricity, DElectricPotential, DPotentialDifference, DElectromotiveForce,-  DCapacitance, DElectricResistance, DElectricConductance, DMagneticFlux, DMagneticFluxDensity,-  DInductance, DLuminousFlux, DIlluminance, DCelsiusTemperature,-  DActivity, DAbsorbedDose, DSpecificEnergy, DKerma, DDoseEquivalent, DAmbientDoseEquivalent, DDirectionalDoseEquivalent, DPersonalDoseEquivalent, DEquivalentDose, DCatalyticActivity,-  DAngularVelocity, DAngularAcceleration, DDynamicViscosity, DMomentOfForce, DSurfaceTension, DHeatFluxDensity,-  DIrradiance, DRadiantIntensity, DRadiance, DHeatCapacity, DEntropy, DSpecificHeatCapacity, DSpecificEntropy,-  DThermalConductivity, DEnergyDensity, DElectricFieldStrength, DElectricChargeDensity, DElectricFluxDensity, DPermittivity, DPermeability,-  DMolarEnergy, DMolarEntropy, DMolarHeatCapacity, DExposure, DAbsorbedDoseRate,-  DImpulse, DMomentum, DMassFlow, DVolumeFlow, DGravitationalParameter, DKinematicViscosity, DFirstMassMoment, DMomentOfInertia, DAngularMomentum,-  DThermalResistivity, DThermalConductance, DThermalResistance, DHeatTransferCoefficient, DThermalAdmittance, DThermalInsulance,-  DJerk, DAngle, DThrust, DTorque, DEnergyPerUnitMass-)-where--import Numeric.Units.Dimensional-  ( Dimension (Dim), Quantity, Dimensionless-  , DOne, DLuminousIntensity, DThermodynamicTemperature-  , Unit, DLength, (^)  -- Used only for 'square' and 'cubic'.-  , Metricality(..)-  )-import Numeric.NumType.DK.Integers-  ( TypeInt (Neg3, Neg2, Neg1, Zero, Pos1, Pos2, Pos3, Pos4)-  , pos2, pos3  -- Used only for 'square' and 'cubic'.-  )-import Prelude (Fractional)-import Data.Typeable--{- $nist-guide-The following quantities are all from the NIST publication "Guide-for the Use of the International System of Units (SI)" <#note1 [1]>. Any-chapters, sections or tables referenced are from <#note1 [1]> unless otherwise-specified.--For lack of better organization we provide definitions grouped by-table in <#note1 [1]>.--== Table 2--"Examples of SI derived units expressed in terms of SI base units."---}--{- $dimension-aliases-For each 'Quantity' alias supplied above, we also supply a corresponding 'Dimension' alias.--These dimension aliases may be convenient for supplying type signatures for 'Unit's or for other type-level dimensional programming.--}--type DArea = 'Dim 'Pos2 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero-type Area  = Quantity DArea--type DVolume = 'Dim 'Pos3 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero-type Volume  = Quantity DVolume--type DVelocity = 'Dim 'Pos1 'Zero 'Neg1 'Zero 'Zero 'Zero 'Zero-type Velocity  = Quantity DVelocity--type DAcceleration = 'Dim 'Pos1 'Zero 'Neg2 'Zero 'Zero 'Zero 'Zero-type Acceleration  = Quantity DAcceleration--type DWaveNumber = 'Dim 'Neg1 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero-type WaveNumber  = Quantity DWaveNumber--type DMassDensity = 'Dim 'Neg3 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero-type DDensity     = DMassDensity-type MassDensity  = Quantity DMassDensity-type Density      = MassDensity -- Short name.--type DSpecificVolume = 'Dim 'Pos3 'Neg1 'Zero 'Zero 'Zero 'Zero 'Zero-type SpecificVolume  = Quantity DSpecificVolume--type DCurrentDensity = 'Dim 'Neg2 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero-type CurrentDensity  = Quantity DCurrentDensity--type DMagneticFieldStrength = 'Dim 'Neg1 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero-type MagneticFieldStrength  = Quantity DMagneticFieldStrength--type DAmountOfSubstanceConcentration = 'Dim 'Neg3 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero-type DConcentration                  = DAmountOfSubstanceConcentration-type AmountOfSubstanceConcentration  = Quantity DAmountOfSubstanceConcentration-type Concentration                   = AmountOfSubstanceConcentration -- Short name.--type DLuminance = 'Dim 'Neg2 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1-type Luminance  = Quantity DLuminance---{- $table3-== Table 3--SI coherent derived units with special names and symbols.---}--type DPlaneAngle = DOne-type PlaneAngle  = Dimensionless--type DSolidAngle = DOne-type SolidAngle  = Dimensionless--type DFrequency = 'Dim 'Zero 'Zero 'Neg1 'Zero 'Zero 'Zero 'Zero-type Frequency  = Quantity DFrequency--type DForce = 'Dim 'Pos1 'Pos1 'Neg2 'Zero 'Zero 'Zero 'Zero-type Force  = Quantity DForce--type DPressure = 'Dim 'Neg1 'Pos1 'Neg2 'Zero 'Zero 'Zero 'Zero-type DStress   = DPressure-type Pressure  = Quantity DPressure-type Stress    = Quantity DStress--type DEnergy         = 'Dim 'Pos2 'Pos1 'Neg2 'Zero 'Zero 'Zero 'Zero-type DWork           = DEnergy-type DQuantityOfHeat = DEnergy-type Energy          = Quantity DEnergy-type Work            = Quantity DWork-type QuantityOfHeat  = Quantity DQuantityOfHeat--type DPower       = 'Dim 'Pos2 'Pos1 'Neg3 'Zero 'Zero 'Zero 'Zero-type DRadiantFlux = DPower-type Power        = Quantity DPower-type RadiantFlux  = Quantity DRadiantFlux--type DElectricCharge        = 'Dim 'Zero 'Zero 'Pos1 'Pos1 'Zero 'Zero 'Zero-type DQuantityOfElectricity = DElectricCharge-type ElectricCharge         = Quantity DElectricCharge-type QuantityOfElectricity  = Quantity DQuantityOfElectricity--type DElectricPotential   = 'Dim 'Pos2 'Pos1 'Neg3 'Neg1 'Zero 'Zero 'Zero-type DPotentialDifference = DElectricPotential-type DElectromotiveForce  = DElectricPotential-type ElectricPotential    = Quantity DElectricPotential-type PotentialDifference  = Quantity DPotentialDifference-type ElectromotiveForce   = Quantity DElectromotiveForce--type DCapacitance = 'Dim 'Neg2 'Neg1 'Pos4 'Pos2 'Zero 'Zero 'Zero-type Capacitance  = Quantity DCapacitance--type DElectricResistance = 'Dim 'Pos2 'Pos1 'Neg3 'Neg2 'Zero 'Zero 'Zero-type ElectricResistance  = Quantity DElectricResistance--type DElectricConductance = 'Dim 'Neg2 'Neg1 'Pos3 'Pos2 'Zero 'Zero 'Zero-type ElectricConductance  = Quantity DElectricConductance--type DMagneticFlux = 'Dim 'Pos2 'Pos1 'Neg2 'Neg1 'Zero 'Zero 'Zero-type MagneticFlux  = Quantity DMagneticFlux--type DMagneticFluxDensity = 'Dim 'Zero 'Pos1 'Neg2 'Neg1 'Zero 'Zero 'Zero-type MagneticFluxDensity  = Quantity DMagneticFluxDensity--type DInductance = 'Dim 'Pos2 'Pos1 'Neg2 'Neg2 'Zero 'Zero 'Zero-type Inductance  = Quantity DInductance--type DLuminousFlux = DLuminousIntensity-type LuminousFlux  = Quantity DLuminousFlux--type DIlluminance = 'Dim 'Neg2 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1-type Illuminance  = Quantity DIlluminance--type DCelsiusTemperature = DThermodynamicTemperature-type CelsiusTemperature  = Quantity DCelsiusTemperature--type DActivity = DFrequency -- Activity of a radionuclide.-type Activity  = Quantity DActivity--type DAbsorbedDose   = 'Dim 'Pos2 'Zero 'Neg2 'Zero 'Zero 'Zero 'Zero-type DSpecificEnergy = DAbsorbedDose-type DKerma          = DAbsorbedDose-type AbsorbedDose    = Quantity DAbsorbedDose-type SpecificEnergy  = Quantity DSpecificEnergy -- Specific energy imparted.-type Kerma           = Quantity DKerma--type DDoseEquivalent            = DAbsorbedDose-type DAmbientDoseEquivalent     = DDoseEquivalent-type DDirectionalDoseEquivalent = DDoseEquivalent-type DPersonalDoseEquivalent    = DDoseEquivalent-type DEquivalentDose            = DDoseEquivalent-type DoseEquivalent             = Quantity DDoseEquivalent-type AmbientDoseEquivalent      = DoseEquivalent-type DirectionalDoseEquivalent  = DoseEquivalent-type PersonalDoseEquivalent     = DoseEquivalent-type EquivalentDose             = DoseEquivalent--type DCatalyticActivity = 'Dim 'Zero 'Zero 'Neg1 'Zero 'Zero 'Pos1 'Zero-type CatalyticActivity  = Quantity DCatalyticActivity--{- $table4-== Table 4--"Examples of SI coherent derived units expressed with the aid of SI derived-units having special names and symbols."--We use the same grouping as for table 2.---}--type DAngularVelocity = DFrequency-type AngularVelocity  = Quantity DAngularVelocity--type DAngularAcceleration = 'Dim 'Zero 'Zero 'Neg2 'Zero 'Zero 'Zero 'Zero-type AngularAcceleration  = Quantity DAngularAcceleration--type DDynamicViscosity = 'Dim 'Neg1 'Pos1 'Neg1 'Zero 'Zero 'Zero 'Zero-type DynamicViscosity  = Quantity DDynamicViscosity--type DMomentOfForce = DEnergy-type MomentOfForce  = Quantity DMomentOfForce--type DSurfaceTension = 'Dim 'Zero 'Pos1 'Neg2 'Zero 'Zero 'Zero 'Zero-type SurfaceTension  = Quantity DSurfaceTension--type DHeatFluxDensity = 'Dim 'Zero 'Pos1 'Neg3 'Zero 'Zero 'Zero 'Zero-type DIrradiance      = DHeatFluxDensity-type HeatFluxDensity  = Quantity DHeatFluxDensity-type Irradiance       = Quantity DIrradiance--type DRadiantIntensity = DPower-type RadiantIntensity  = Quantity DRadiantIntensity--type DRadiance = DIrradiance-type Radiance  = Quantity DRadiance--type DHeatCapacity = 'Dim 'Pos2 'Pos1 'Neg2 'Zero 'Neg1 'Zero 'Zero-type DEntropy      = DHeatCapacity-type HeatCapacity  = Quantity DHeatCapacity-type Entropy       = Quantity DEntropy--type DSpecificHeatCapacity = 'Dim 'Pos2 'Zero 'Neg2 'Zero 'Neg1 'Zero 'Zero-type DSpecificEntropy      = DSpecificHeatCapacity-type SpecificHeatCapacity  = Quantity DSpecificHeatCapacity-type SpecificEntropy       = Quantity DSpecificEntropy--{---Specific energy was already defined in table 3.---}--type DThermalConductivity = 'Dim 'Pos1 'Pos1 'Neg3 'Zero 'Neg1 'Zero 'Zero-type ThermalConductivity  = Quantity DThermalConductivity--type DEnergyDensity = DPressure-type EnergyDensity  = Quantity DEnergyDensity--type DElectricFieldStrength = 'Dim 'Pos1 'Pos1 'Neg3 'Neg1 'Zero 'Zero 'Zero-type ElectricFieldStrength  = Quantity DElectricFieldStrength--type DElectricChargeDensity = 'Dim 'Neg3 'Zero 'Pos1 'Pos1 'Zero 'Zero 'Zero-type ElectricChargeDensity  = Quantity DElectricChargeDensity--type DElectricFluxDensity = 'Dim 'Neg2 'Zero 'Pos1 'Pos1 'Zero 'Zero 'Zero-type ElectricFluxDensity  = Quantity DElectricFluxDensity--type DPermittivity = 'Dim 'Neg3 'Neg1 'Pos4 'Pos2 'Zero 'Zero 'Zero-type Permittivity  = Quantity DPermittivity--type DPermeability = 'Dim 'Pos1 'Pos1 'Neg2 'Neg2 'Zero 'Zero 'Zero-type Permeability  = Quantity DPermeability--type DMolarEnergy = 'Dim 'Pos2 'Pos1 'Neg2 'Zero 'Zero 'Neg1 'Zero-type MolarEnergy  = Quantity DMolarEnergy--type DMolarEntropy      = 'Dim 'Pos2 'Pos1 'Neg2 'Zero 'Neg1 'Neg1 'Zero-type DMolarHeatCapacity = DMolarEntropy-type MolarEntropy       = Quantity DMolarEntropy-type MolarHeatCapacity  = Quantity DMolarHeatCapacity--type DExposure = 'Dim 'Zero 'Neg1 'Pos1 'Pos1 'Zero 'Zero 'Zero-type Exposure  = Quantity DExposure -- Exposure to x and gamma rays.--type DAbsorbedDoseRate = 'Dim 'Pos2 'Zero 'Neg3 'Zero 'Zero 'Zero 'Zero-type AbsorbedDoseRate  = Quantity DAbsorbedDoseRate--{- $not-nist-guide-Here we define additional quantities on an as-needed basis. We also-provide some synonyms that we anticipate will be useful.--}--type DImpulse = 'Dim 'Pos1 'Pos1 'Neg1 'Zero 'Zero 'Zero 'Zero-type Impulse  = Quantity DImpulse--type DMomentum = DImpulse-type Momentum = Quantity DMomentum--type DMassFlow = 'Dim 'Zero 'Pos1 'Neg1 'Zero 'Zero 'Zero 'Zero-type MassFlow  = Quantity DMassFlow--type DVolumeFlow = 'Dim 'Pos3 'Zero 'Neg1 'Zero 'Zero 'Zero 'Zero-type VolumeFlow = Quantity DVolumeFlow--type DGravitationalParameter = 'Dim 'Pos3 'Zero 'Neg2 'Zero 'Zero 'Zero 'Zero-type GravitationalParameter  = Quantity DGravitationalParameter--type DKinematicViscosity = 'Dim 'Pos2 'Zero 'Neg1 'Zero 'Zero 'Zero 'Zero-type KinematicViscosity  = Quantity DKinematicViscosity--type DFirstMassMoment = 'Dim 'Pos1 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero-type FirstMassMoment = Quantity DFirstMassMoment--type DMomentOfInertia = 'Dim 'Pos2 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero-type MomentOfInertia = Quantity DMomentOfInertia--type DAngularMomentum = 'Dim 'Pos2 'Pos1 'Neg1 'Zero 'Zero 'Zero 'Zero-type AngularMomentum = Quantity DAngularMomentum--{---The reciprocal of thermal conductivity.---}--type DThermalResistivity = 'Dim 'Neg1 'Neg1 'Pos3 'Zero 'Pos1 'Zero 'Zero-type ThermalResistivity = Quantity DThermalResistivity--{---Thermal conductance and resistance quantities after http://en.wikipedia.org/wiki/Thermal_conductivity#Definitions.---}--type DThermalConductance = 'Dim 'Pos2 'Pos1 'Neg3 'Zero 'Neg1 'Zero 'Zero-type ThermalConductance = Quantity DThermalConductance--type DThermalResistance = 'Dim 'Neg2 'Neg1 'Pos3 'Zero 'Pos1 'Zero 'Zero-type ThermalResistance = Quantity DThermalResistance--type DHeatTransferCoefficient = 'Dim 'Zero 'Pos1 'Neg3 'Zero 'Neg1 'Zero 'Zero-type HeatTransferCoefficient = Quantity DHeatTransferCoefficient--type DThermalAdmittance = DHeatTransferCoefficient-type ThermalAdmittance = HeatTransferCoefficient--type DThermalInsulance = 'Dim 'Zero 'Neg1 'Pos3 'Zero 'Pos1 'Zero 'Zero-type ThermalInsulance = Quantity DThermalInsulance--type DJerk = 'Dim 'Pos1 'Zero 'Neg3 'Zero 'Zero 'Zero 'Zero-type Jerk = Quantity DJerk--type Angle = PlaneAngle -- Abbreviation-type DAngle = DPlaneAngle -- Abbreviation--type Thrust = Force-type DThrust = DForce--type Torque = MomentOfForce-type DTorque = DMomentOfForce--type EnergyPerUnitMass = SpecificEnergy-type DEnergyPerUnitMass = DSpecificEnergy--{- $powers-of-length-units-It is permissible to express powers of length units by prefixing-'square' and 'cubic' (see section 9.6 "Spelling unit names raised-to powers" of <#note1 [1]>).--These definitions may seem slightly out of place but these is no-obvious place where they should be. Here they are at least close-to the definitions of 'DArea' and 'DVolume'.--}---- $setup--- >>> import Numeric.Units.Dimensional.Prelude---- | Constructs a unit of area from a unit of length, taking the area of a square whose sides are that length.------ >>> 64 *~ square meter == (8 *~ meter) ^ pos2--- True-square :: (Fractional a, Typeable m) => Unit m DLength a -> Unit 'NonMetric DArea a-square x = x ^ pos2---- | Constructs a unit of volume from a unit of length, taking the volume of a cube whose sides are that length.------ >>> 64 *~ cubic meter == (4 *~ meter) ^ pos3--- True-cubic  :: (Fractional a, Typeable m) => Unit m DLength a -> Unit 'NonMetric DVolume a-cubic  x = x ^ pos3+{-# OPTIONS_HADDOCK show-extensions #-}
+
+{-# LANGUAGE DataKinds #-}
+
+{- |
+   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+= Summary
+
+This module defines type synonyms for common dimensionalities and
+the associated quantity types. Additional dimensionalities and
+quantity types will be added on an as-needed basis.
+
+The definitions in this module are grouped so that a type synonym
+for the dimensionality is defined first in terms of base dimension
+exponents. Then a type synonym for the corresponding quantity type
+is defined. If there are several quantity types with the same
+dimensionality type synonyms are provided for each quantity type.
+
+= References
+
+1. #note1# http://physics.nist.gov/Pubs/SP811/
+
+-}
+
+module Numeric.Units.Dimensional.Quantities
+(
+  -- * Quantities from the NIST Guide
+  -- $nist-guide
+  Area, Volume, Velocity, Acceleration, WaveNumber, MassDensity, Density, SpecificVolume, CurrentDensity,
+  MagneticFieldStrength, AmountOfSubstanceConcentration, Concentration, Luminance,
+  -- $table3
+  PlaneAngle, SolidAngle, Frequency, Force, Pressure, Stress, Energy, Work, QuantityOfHeat, Power, RadiantFlux,
+  ElectricCharge, QuantityOfElectricity, ElectricPotential, PotentialDifference, ElectromotiveForce,
+  Capacitance, ElectricResistance, ElectricConductance, MagneticFlux, MagneticFluxDensity,
+  Inductance, LuminousFlux, Illuminance, CelsiusTemperature,
+  Activity, AbsorbedDose, SpecificEnergy, Kerma, DoseEquivalent, AmbientDoseEquivalent, DirectionalDoseEquivalent, PersonalDoseEquivalent, EquivalentDose, CatalyticActivity,
+  -- $table4
+  AngularVelocity, AngularAcceleration, DynamicViscosity, MomentOfForce, SurfaceTension, HeatFluxDensity,
+  Irradiance, RadiantIntensity, Radiance, HeatCapacity, Entropy, SpecificHeatCapacity, SpecificEntropy,
+  ThermalConductivity, EnergyDensity, ElectricFieldStrength, ElectricChargeDensity, ElectricFluxDensity, Permittivity, Permeability,
+  MolarEnergy, MolarEntropy, MolarHeatCapacity, Exposure, AbsorbedDoseRate,
+  -- * Quantities not from the NIST Guide
+  -- $not-nist-guide
+  Impulse, Momentum, MassFlow, VolumeFlow, GravitationalParameter, KinematicViscosity, FirstMassMoment, MomentOfInertia, AngularMomentum,
+  ThermalResistivity, ThermalConductance, ThermalResistance, HeatTransferCoefficient, ThermalAdmittance, ThermalInsulance,
+  Jerk, Angle, Thrust, Torque, EnergyPerUnitMass,
+  -- * Powers of Unit Lengths
+  -- $powers-of-length-units
+  square, cubic,
+  -- * Dimension Aliases
+  -- $dimension-aliases
+  DArea, DVolume, DVelocity, DAcceleration, DWaveNumber, DMassDensity, DDensity, DSpecificVolume, DCurrentDensity,
+  DMagneticFieldStrength, DAmountOfSubstanceConcentration, DConcentration, DLuminance,
+  DPlaneAngle, DSolidAngle, DFrequency, DForce, DPressure, DStress, DEnergy, DWork, DQuantityOfHeat, DPower, DRadiantFlux,
+  DElectricCharge, DQuantityOfElectricity, DElectricPotential, DPotentialDifference, DElectromotiveForce,
+  DCapacitance, DElectricResistance, DElectricConductance, DMagneticFlux, DMagneticFluxDensity,
+  DInductance, DLuminousFlux, DIlluminance, DCelsiusTemperature,
+  DActivity, DAbsorbedDose, DSpecificEnergy, DKerma, DDoseEquivalent, DAmbientDoseEquivalent, DDirectionalDoseEquivalent, DPersonalDoseEquivalent, DEquivalentDose, DCatalyticActivity,
+  DAngularVelocity, DAngularAcceleration, DDynamicViscosity, DMomentOfForce, DSurfaceTension, DHeatFluxDensity,
+  DIrradiance, DRadiantIntensity, DRadiance, DHeatCapacity, DEntropy, DSpecificHeatCapacity, DSpecificEntropy,
+  DThermalConductivity, DEnergyDensity, DElectricFieldStrength, DElectricChargeDensity, DElectricFluxDensity, DPermittivity, DPermeability,
+  DMolarEnergy, DMolarEntropy, DMolarHeatCapacity, DExposure, DAbsorbedDoseRate,
+  DImpulse, DMomentum, DMassFlow, DVolumeFlow, DGravitationalParameter, DKinematicViscosity, DFirstMassMoment, DMomentOfInertia, DAngularMomentum,
+  DThermalResistivity, DThermalConductance, DThermalResistance, DHeatTransferCoefficient, DThermalAdmittance, DThermalInsulance,
+  DJerk, DAngle, DThrust, DTorque, DEnergyPerUnitMass
+)
+where
+
+import Numeric.Units.Dimensional
+  ( Dimension (Dim), Quantity, Dimensionless
+  , DOne, DLuminousIntensity, DThermodynamicTemperature
+  , Unit, DLength, (^)  -- Used only for 'square' and 'cubic'.
+  , Metricality(..)
+  )
+import Numeric.NumType.DK.Integers
+  ( TypeInt (Neg3, Neg2, Neg1, Zero, Pos1, Pos2, Pos3, Pos4)
+  , pos2, pos3  -- Used only for 'square' and 'cubic'.
+  )
+import Prelude (Fractional)
+import Data.Typeable
+
+{- $nist-guide
+The following quantities are all from the NIST publication "Guide
+for the Use of the International System of Units (SI)" <#note1 [1]>. Any
+chapters, sections or tables referenced are from <#note1 [1]> unless otherwise
+specified.
+
+For lack of better organization we provide definitions grouped by
+table in <#note1 [1]>.
+
+== Table 2
+
+"Examples of SI derived units expressed in terms of SI base units."
+
+-}
+
+{- $dimension-aliases
+For each 'Quantity' alias supplied above, we also supply a corresponding 'Dimension' alias.
+
+These dimension aliases may be convenient for supplying type signatures for 'Unit's or for other type-level dimensional programming.
+-}
+
+type DArea = 'Dim 'Pos2 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
+type Area  = Quantity DArea
+
+type DVolume = 'Dim 'Pos3 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
+type Volume  = Quantity DVolume
+
+type DVelocity = 'Dim 'Pos1 'Zero 'Neg1 'Zero 'Zero 'Zero 'Zero
+type Velocity  = Quantity DVelocity
+
+type DAcceleration = 'Dim 'Pos1 'Zero 'Neg2 'Zero 'Zero 'Zero 'Zero
+type Acceleration  = Quantity DAcceleration
+
+type DWaveNumber = 'Dim 'Neg1 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
+type WaveNumber  = Quantity DWaveNumber
+
+type DMassDensity = 'Dim 'Neg3 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero
+type DDensity     = DMassDensity
+type MassDensity  = Quantity DMassDensity
+type Density      = MassDensity -- Short name.
+
+type DSpecificVolume = 'Dim 'Pos3 'Neg1 'Zero 'Zero 'Zero 'Zero 'Zero
+type SpecificVolume  = Quantity DSpecificVolume
+
+type DCurrentDensity = 'Dim 'Neg2 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero
+type CurrentDensity  = Quantity DCurrentDensity
+
+type DMagneticFieldStrength = 'Dim 'Neg1 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero
+type MagneticFieldStrength  = Quantity DMagneticFieldStrength
+
+type DAmountOfSubstanceConcentration = 'Dim 'Neg3 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero
+type DConcentration                  = DAmountOfSubstanceConcentration
+type AmountOfSubstanceConcentration  = Quantity DAmountOfSubstanceConcentration
+type Concentration                   = AmountOfSubstanceConcentration -- Short name.
+
+type DLuminance = 'Dim 'Neg2 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1
+type Luminance  = Quantity DLuminance
+
+
+{- $table3
+== Table 3
+
+SI coherent derived units with special names and symbols.
+
+-}
+
+type DPlaneAngle = DOne
+type PlaneAngle  = Dimensionless
+
+type DSolidAngle = DOne
+type SolidAngle  = Dimensionless
+
+type DFrequency = 'Dim 'Zero 'Zero 'Neg1 'Zero 'Zero 'Zero 'Zero
+type Frequency  = Quantity DFrequency
+
+type DForce = 'Dim 'Pos1 'Pos1 'Neg2 'Zero 'Zero 'Zero 'Zero
+type Force  = Quantity DForce
+
+type DPressure = 'Dim 'Neg1 'Pos1 'Neg2 'Zero 'Zero 'Zero 'Zero
+type DStress   = DPressure
+type Pressure  = Quantity DPressure
+type Stress    = Quantity DStress
+
+type DEnergy         = 'Dim 'Pos2 'Pos1 'Neg2 'Zero 'Zero 'Zero 'Zero
+type DWork           = DEnergy
+type DQuantityOfHeat = DEnergy
+type Energy          = Quantity DEnergy
+type Work            = Quantity DWork
+type QuantityOfHeat  = Quantity DQuantityOfHeat
+
+type DPower       = 'Dim 'Pos2 'Pos1 'Neg3 'Zero 'Zero 'Zero 'Zero
+type DRadiantFlux = DPower
+type Power        = Quantity DPower
+type RadiantFlux  = Quantity DRadiantFlux
+
+type DElectricCharge        = 'Dim 'Zero 'Zero 'Pos1 'Pos1 'Zero 'Zero 'Zero
+type DQuantityOfElectricity = DElectricCharge
+type ElectricCharge         = Quantity DElectricCharge
+type QuantityOfElectricity  = Quantity DQuantityOfElectricity
+
+type DElectricPotential   = 'Dim 'Pos2 'Pos1 'Neg3 'Neg1 'Zero 'Zero 'Zero
+type DPotentialDifference = DElectricPotential
+type DElectromotiveForce  = DElectricPotential
+type ElectricPotential    = Quantity DElectricPotential
+type PotentialDifference  = Quantity DPotentialDifference
+type ElectromotiveForce   = Quantity DElectromotiveForce
+
+type DCapacitance = 'Dim 'Neg2 'Neg1 'Pos4 'Pos2 'Zero 'Zero 'Zero
+type Capacitance  = Quantity DCapacitance
+
+type DElectricResistance = 'Dim 'Pos2 'Pos1 'Neg3 'Neg2 'Zero 'Zero 'Zero
+type ElectricResistance  = Quantity DElectricResistance
+
+type DElectricConductance = 'Dim 'Neg2 'Neg1 'Pos3 'Pos2 'Zero 'Zero 'Zero
+type ElectricConductance  = Quantity DElectricConductance
+
+type DMagneticFlux = 'Dim 'Pos2 'Pos1 'Neg2 'Neg1 'Zero 'Zero 'Zero
+type MagneticFlux  = Quantity DMagneticFlux
+
+type DMagneticFluxDensity = 'Dim 'Zero 'Pos1 'Neg2 'Neg1 'Zero 'Zero 'Zero
+type MagneticFluxDensity  = Quantity DMagneticFluxDensity
+
+type DInductance = 'Dim 'Pos2 'Pos1 'Neg2 'Neg2 'Zero 'Zero 'Zero
+type Inductance  = Quantity DInductance
+
+type DLuminousFlux = DLuminousIntensity
+type LuminousFlux  = Quantity DLuminousFlux
+
+type DIlluminance = 'Dim 'Neg2 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1
+type Illuminance  = Quantity DIlluminance
+
+type DCelsiusTemperature = DThermodynamicTemperature
+type CelsiusTemperature  = Quantity DCelsiusTemperature
+
+type DActivity = DFrequency -- Activity of a radionuclide.
+type Activity  = Quantity DActivity
+
+type DAbsorbedDose   = 'Dim 'Pos2 'Zero 'Neg2 'Zero 'Zero 'Zero 'Zero
+type DSpecificEnergy = DAbsorbedDose
+type DKerma          = DAbsorbedDose
+type AbsorbedDose    = Quantity DAbsorbedDose
+type SpecificEnergy  = Quantity DSpecificEnergy -- Specific energy imparted.
+type Kerma           = Quantity DKerma
+
+type DDoseEquivalent            = DAbsorbedDose
+type DAmbientDoseEquivalent     = DDoseEquivalent
+type DDirectionalDoseEquivalent = DDoseEquivalent
+type DPersonalDoseEquivalent    = DDoseEquivalent
+type DEquivalentDose            = DDoseEquivalent
+type DoseEquivalent             = Quantity DDoseEquivalent
+type AmbientDoseEquivalent      = DoseEquivalent
+type DirectionalDoseEquivalent  = DoseEquivalent
+type PersonalDoseEquivalent     = DoseEquivalent
+type EquivalentDose             = DoseEquivalent
+
+type DCatalyticActivity = 'Dim 'Zero 'Zero 'Neg1 'Zero 'Zero 'Pos1 'Zero
+type CatalyticActivity  = Quantity DCatalyticActivity
+
+{- $table4
+== Table 4
+
+"Examples of SI coherent derived units expressed with the aid of SI derived
+units having special names and symbols."
+
+We use the same grouping as for table 2.
+
+-}
+
+type DAngularVelocity = DFrequency
+type AngularVelocity  = Quantity DAngularVelocity
+
+type DAngularAcceleration = 'Dim 'Zero 'Zero 'Neg2 'Zero 'Zero 'Zero 'Zero
+type AngularAcceleration  = Quantity DAngularAcceleration
+
+type DDynamicViscosity = 'Dim 'Neg1 'Pos1 'Neg1 'Zero 'Zero 'Zero 'Zero
+type DynamicViscosity  = Quantity DDynamicViscosity
+
+type DMomentOfForce = DEnergy
+type MomentOfForce  = Quantity DMomentOfForce
+
+type DSurfaceTension = 'Dim 'Zero 'Pos1 'Neg2 'Zero 'Zero 'Zero 'Zero
+type SurfaceTension  = Quantity DSurfaceTension
+
+type DHeatFluxDensity = 'Dim 'Zero 'Pos1 'Neg3 'Zero 'Zero 'Zero 'Zero
+type DIrradiance      = DHeatFluxDensity
+type HeatFluxDensity  = Quantity DHeatFluxDensity
+type Irradiance       = Quantity DIrradiance
+
+type DRadiantIntensity = DPower
+type RadiantIntensity  = Quantity DRadiantIntensity
+
+type DRadiance = DIrradiance
+type Radiance  = Quantity DRadiance
+
+type DHeatCapacity = 'Dim 'Pos2 'Pos1 'Neg2 'Zero 'Neg1 'Zero 'Zero
+type DEntropy      = DHeatCapacity
+type HeatCapacity  = Quantity DHeatCapacity
+type Entropy       = Quantity DEntropy
+
+type DSpecificHeatCapacity = 'Dim 'Pos2 'Zero 'Neg2 'Zero 'Neg1 'Zero 'Zero
+type DSpecificEntropy      = DSpecificHeatCapacity
+type SpecificHeatCapacity  = Quantity DSpecificHeatCapacity
+type SpecificEntropy       = Quantity DSpecificEntropy
+
+{-
+
+Specific energy was already defined in table 3.
+
+-}
+
+type DThermalConductivity = 'Dim 'Pos1 'Pos1 'Neg3 'Zero 'Neg1 'Zero 'Zero
+type ThermalConductivity  = Quantity DThermalConductivity
+
+type DEnergyDensity = DPressure
+type EnergyDensity  = Quantity DEnergyDensity
+
+type DElectricFieldStrength = 'Dim 'Pos1 'Pos1 'Neg3 'Neg1 'Zero 'Zero 'Zero
+type ElectricFieldStrength  = Quantity DElectricFieldStrength
+
+type DElectricChargeDensity = 'Dim 'Neg3 'Zero 'Pos1 'Pos1 'Zero 'Zero 'Zero
+type ElectricChargeDensity  = Quantity DElectricChargeDensity
+
+type DElectricFluxDensity = 'Dim 'Neg2 'Zero 'Pos1 'Pos1 'Zero 'Zero 'Zero
+type ElectricFluxDensity  = Quantity DElectricFluxDensity
+
+type DPermittivity = 'Dim 'Neg3 'Neg1 'Pos4 'Pos2 'Zero 'Zero 'Zero
+type Permittivity  = Quantity DPermittivity
+
+type DPermeability = 'Dim 'Pos1 'Pos1 'Neg2 'Neg2 'Zero 'Zero 'Zero
+type Permeability  = Quantity DPermeability
+
+type DMolarEnergy = 'Dim 'Pos2 'Pos1 'Neg2 'Zero 'Zero 'Neg1 'Zero
+type MolarEnergy  = Quantity DMolarEnergy
+
+type DMolarEntropy      = 'Dim 'Pos2 'Pos1 'Neg2 'Zero 'Neg1 'Neg1 'Zero
+type DMolarHeatCapacity = DMolarEntropy
+type MolarEntropy       = Quantity DMolarEntropy
+type MolarHeatCapacity  = Quantity DMolarHeatCapacity
+
+type DExposure = 'Dim 'Zero 'Neg1 'Pos1 'Pos1 'Zero 'Zero 'Zero
+type Exposure  = Quantity DExposure -- Exposure to x and gamma rays.
+
+type DAbsorbedDoseRate = 'Dim 'Pos2 'Zero 'Neg3 'Zero 'Zero 'Zero 'Zero
+type AbsorbedDoseRate  = Quantity DAbsorbedDoseRate
+
+{- $not-nist-guide
+Here we define additional quantities on an as-needed basis. We also
+provide some synonyms that we anticipate will be useful.
+-}
+
+type DImpulse = 'Dim 'Pos1 'Pos1 'Neg1 'Zero 'Zero 'Zero 'Zero
+type Impulse  = Quantity DImpulse
+
+type DMomentum = DImpulse
+type Momentum = Quantity DMomentum
+
+type DMassFlow = 'Dim 'Zero 'Pos1 'Neg1 'Zero 'Zero 'Zero 'Zero
+type MassFlow  = Quantity DMassFlow
+
+type DVolumeFlow = 'Dim 'Pos3 'Zero 'Neg1 'Zero 'Zero 'Zero 'Zero
+type VolumeFlow = Quantity DVolumeFlow
+
+type DGravitationalParameter = 'Dim 'Pos3 'Zero 'Neg2 'Zero 'Zero 'Zero 'Zero
+type GravitationalParameter  = Quantity DGravitationalParameter
+
+type DKinematicViscosity = 'Dim 'Pos2 'Zero 'Neg1 'Zero 'Zero 'Zero 'Zero
+type KinematicViscosity  = Quantity DKinematicViscosity
+
+type DFirstMassMoment = 'Dim 'Pos1 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero
+type FirstMassMoment = Quantity DFirstMassMoment
+
+type DMomentOfInertia = 'Dim 'Pos2 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero
+type MomentOfInertia = Quantity DMomentOfInertia
+
+type DAngularMomentum = 'Dim 'Pos2 'Pos1 'Neg1 'Zero 'Zero 'Zero 'Zero
+type AngularMomentum = Quantity DAngularMomentum
+
+{-
+
+The reciprocal of thermal conductivity.
+
+-}
+
+type DThermalResistivity = 'Dim 'Neg1 'Neg1 'Pos3 'Zero 'Pos1 'Zero 'Zero
+type ThermalResistivity = Quantity DThermalResistivity
+
+{-
+
+Thermal conductance and resistance quantities after http://en.wikipedia.org/wiki/Thermal_conductivity#Definitions.
+
+-}
+
+type DThermalConductance = 'Dim 'Pos2 'Pos1 'Neg3 'Zero 'Neg1 'Zero 'Zero
+type ThermalConductance = Quantity DThermalConductance
+
+type DThermalResistance = 'Dim 'Neg2 'Neg1 'Pos3 'Zero 'Pos1 'Zero 'Zero
+type ThermalResistance = Quantity DThermalResistance
+
+type DHeatTransferCoefficient = 'Dim 'Zero 'Pos1 'Neg3 'Zero 'Neg1 'Zero 'Zero
+type HeatTransferCoefficient = Quantity DHeatTransferCoefficient
+
+type DThermalAdmittance = DHeatTransferCoefficient
+type ThermalAdmittance = HeatTransferCoefficient
+
+type DThermalInsulance = 'Dim 'Zero 'Neg1 'Pos3 'Zero 'Pos1 'Zero 'Zero
+type ThermalInsulance = Quantity DThermalInsulance
+
+type DJerk = 'Dim 'Pos1 'Zero 'Neg3 'Zero 'Zero 'Zero 'Zero
+type Jerk = Quantity DJerk
+
+type Angle = PlaneAngle -- Abbreviation
+type DAngle = DPlaneAngle -- Abbreviation
+
+type Thrust = Force
+type DThrust = DForce
+
+type Torque = MomentOfForce
+type DTorque = DMomentOfForce
+
+type EnergyPerUnitMass = SpecificEnergy
+type DEnergyPerUnitMass = DSpecificEnergy
+
+{- $powers-of-length-units
+It is permissible to express powers of length units by prefixing
+'square' and 'cubic' (see section 9.6 "Spelling unit names raised
+to powers" of <#note1 [1]>).
+
+These definitions may seem slightly out of place but these is no
+obvious place where they should be. Here they are at least close
+to the definitions of 'DArea' and 'DVolume'.
+-}
+
+-- $setup
+-- >>> import Numeric.Units.Dimensional.Prelude
+
+-- | Constructs a unit of area from a unit of length, taking the area of a square whose sides are that length.
+--
+-- >>> 64 *~ square meter == (8 *~ meter) ^ pos2
+-- True
+square :: (Fractional a, Typeable m) => Unit m DLength a -> Unit 'NonMetric DArea a
+square x = x ^ pos2
+
+-- | Constructs a unit of volume from a unit of length, taking the volume of a cube whose sides are that length.
+--
+-- >>> 64 *~ cubic meter == (4 *~ meter) ^ pos3
+-- True
+cubic  :: (Fractional a, Typeable m) => Unit m DLength a -> Unit 'NonMetric DVolume a
+cubic  x = x ^ pos3
src/Numeric/Units/Dimensional/SIUnits.hs view
@@ -1,315 +1,315 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE NumDecimals #-}-{-# LANGUAGE RankNTypes #-}--{- |-   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter-   License    : BSD3--   Maintainer : bjorn@buckwalter.se-   Stability  : Stable-   Portability: GHC only--= Summary--This module defines the SI prefixes, the SI base units and the SI-derived units. It also defines the units outside of the SI that are-accepted for use with the SI. Any chapters, sections or tables-referenced are from <#note1 [1]> unless otherwise specified.--= References--1. #note1# http://physics.nist.gov/Pubs/SP811/-2. #note2# http://en.wikipedia.org/wiki/Minute_of_arc-3. #note3# http://en.wikipedia.org/wiki/Astronomical_unit---}--module Numeric.Units.Dimensional.SIUnits-(-  -- * SI Base Units-  -- $base-units-  metre, meter, gram, second, ampere, kelvin, mole, candela,-  -- * SI Derived Units-  -- $derived-units-  radian, steradian, hertz, newton, pascal, joule, watt, coulomb, volt, farad, ohm, siemens, weber, tesla, henry, lumen, lux,-  -- ** Celsius Temperature-  -- $celsius-  degreeCelsius, fromDegreeCelsiusAbsolute, toDegreeCelsiusAbsolute,-  -- ** Units Admitted for Reasons of Safeguarding Human Health-  -- $health-  becquerel, gray, sievert, katal,-  -- * Units Accepted for Use with the SI-  -- $accepted-units-  minute, hour, day,-  hectare, litre, liter, tonne, metricTon,-  -- ** Units of Plane Angle-  -- $arc-units-  degree, arcminute, arcsecond,-  -- $arc-units-alternate-  degreeOfArc, minuteOfArc, secondOfArc,-  -- ** Units Formerly Defined By Experiment-  -- $values-obtained-experimentally-  astronomicalUnit,-  -- * SI Prefixes-  -- $multiples-  deka, deca, hecto, kilo, mega, giga, tera, peta, exa, zetta, yotta,-  -- $submultiples-  deci, centi, milli, micro, nano, pico, femto, atto, zepto, yocto,-  -- $reified-prefixes-  Prefix, applyPrefix, siPrefixes-)-where--import Data.Ratio-import Numeric.Units.Dimensional-import Numeric.Units.Dimensional.Quantities-import Numeric.Units.Dimensional.UnitNames (Prefix, siPrefixes)-import qualified Numeric.Units.Dimensional.UnitNames as N-import Numeric.Units.Dimensional.UnitNames.Internal (ucum, ucumMetric)-import qualified Numeric.Units.Dimensional.UnitNames.Internal as I-import Numeric.NumType.DK.Integers ( pos3 )-import Prelude ( Eq(..), ($), Num, Fractional, Floating, otherwise, error)-import qualified Prelude--{- $multiples-Prefixes are used to form decimal multiples and submultiples of SI-Units as described in section 4.4. We will define the SI prefixes-in terms of the 'prefix' function which applies a scale factor to a-unit.--By defining SI prefixes as functions applied to a 'Unit' we satisfy-section 6.2.6 "Unacceptability of stand-alone prefixes".--We define all SI prefixes from Table 5. Multiples first.--}--applyMultiple :: (Num a) => Prefix -> Unit 'Metric d a -> Unit 'NonMetric d a-applyMultiple p u | denominator x == 1 = mkUnitZ n' (numerator x) u-                  | otherwise = error "Attempt to apply a submultiple prefix as a multiple."-  where-    n' = N.applyPrefix p (name u)-    x = N.scaleFactor p--deka, deca, hecto, kilo, mega, giga, tera, peta, exa, zetta, yotta-  :: Num a => Unit 'Metric d a -> Unit 'NonMetric d a-deka  = applyMultiple I.deka -- International English.-deca  = deka      -- American English.-hecto = applyMultiple I.hecto-kilo  = applyMultiple I.kilo-mega  = applyMultiple I.mega-giga  = applyMultiple I.giga-tera  = applyMultiple I.tera-peta  = applyMultiple I.peta-exa   = applyMultiple I.exa-zetta = applyMultiple I.zetta-yotta = applyMultiple I.yotta--{- $submultiples-Then the submultiples.--}--applyPrefix :: (Fractional a) => Prefix -> Unit 'Metric d a -> Unit 'NonMetric d a-applyPrefix p u = mkUnitQ n' x u-  where-    n' = N.applyPrefix p (name u)-    x = N.scaleFactor p--deci, centi, milli, micro, nano, pico, femto, atto, zepto, yocto-  :: Fractional a => Unit 'Metric d a -> Unit 'NonMetric d a-deci  = applyPrefix I.deci-centi = applyPrefix I.centi-milli = applyPrefix I.milli-micro = applyPrefix I.micro-nano  = applyPrefix I.nano-pico  = applyPrefix I.pico-femto = applyPrefix I.femto-atto  = applyPrefix I.atto-zepto = applyPrefix I.zepto-yocto = applyPrefix I.yocto--{- $reified-prefixes--We supply an explicit representation of an SI prefix, along with a function to apply one and a-list of all prefixes defined by the SI.---}--{- $base-units-These are the base units from section 4.1. To avoid a-myriad of one-letter functions that would doubtlessly cause clashes-and frustration in users' code we spell out all unit names in full,-as we did for prefixes. We also elect to spell the unit names in-singular form, as allowed by section 9.7 "Other spelling conventions".--We define the SI base units in the order of table 1.--}--metre, meter :: Num a => Unit 'Metric DLength a-metre = mkUnitZ I.nMeter 1 siUnit -- International English.-meter = metre         -- American English.--{---For mass the SI base unit is kilogram. For sensible prefixes we-define gram here (see section 6.2.7 "Prefixes and the kilogram").-The drawback is that we are forced to use 'Fractional'.---}--gram    :: Fractional a => Unit 'Metric DMass a-gram    = mkUnitQ I.nGram 1e-3 siUnit-second  :: Num a => Unit 'Metric DTime a-second  = mkUnitZ I.nSecond 1 siUnit-ampere  :: Num a => Unit 'Metric DElectricCurrent a-ampere  = mkUnitZ I.nAmpere 1 siUnit-kelvin  :: Num a => Unit 'Metric DThermodynamicTemperature a-kelvin  = mkUnitZ I.nKelvin 1 siUnit-mole    :: Num a => Unit 'Metric DAmountOfSubstance a-mole    = mkUnitZ I.nMole 1 siUnit-candela :: Num a => Unit 'Metric DLuminousIntensity a-candela = mkUnitZ I.nCandela 1 siUnit--{- $derived-units-From Table 3, SI derived units with special names and symbols, including the-radian and steradian.--}--radian :: Num a => Unit 'Metric DPlaneAngle a-radian = mkUnitZ (ucumMetric "rad" "rad" "radian") 1 siUnit -- meter * meter ^ neg1-steradian :: Num a => Unit 'Metric DSolidAngle a-steradian = mkUnitZ (ucumMetric "sr" "sr" "steradian") 1 siUnit -- meter ^ pos2 * meter ^ neg2-hertz :: Num a => Unit 'Metric DFrequency a-hertz = mkUnitZ (ucumMetric "Hz" "Hz" "Hertz") 1 $ siUnit-newton :: Num a => Unit 'Metric DForce a-newton = mkUnitZ (ucumMetric "N" "N" "Newton") 1 $ siUnit-pascal :: Num a => Unit 'Metric DPressure a-pascal = mkUnitZ (ucumMetric "Pa" "Pa" "Pascal") 1 $ siUnit-joule :: Num a => Unit 'Metric DEnergy a-joule = mkUnitZ (ucumMetric "J" "J" "Joule") 1 $ siUnit-watt :: Num a => Unit 'Metric DPower a-watt = mkUnitZ (ucumMetric "W" "W" "Watt") 1 $ siUnit-coulomb :: Num a => Unit 'Metric DElectricCharge a-coulomb = mkUnitZ (ucumMetric "C" "C" "Coulomb") 1 $ siUnit-volt :: Num a => Unit 'Metric DElectricPotential a-volt = mkUnitZ (ucumMetric "V" "V" "Volt") 1 $ siUnit-farad :: Num a => Unit 'Metric DCapacitance a-farad = mkUnitZ (ucumMetric "F" "F" "Farad") 1 $ siUnit-ohm :: Num a => Unit 'Metric DElectricResistance a-ohm = mkUnitZ (ucumMetric "Ohm" "Ω" "Ohm") 1 $ siUnit-siemens :: Num a => Unit 'Metric DElectricConductance a-siemens = mkUnitZ (ucumMetric "S" "S" "Siemens") 1 $ siUnit-weber :: Num a => Unit 'Metric DMagneticFlux a-weber = mkUnitZ (ucumMetric "Wb" "Wb" "Weber") 1 $ siUnit-tesla :: Num a => Unit 'Metric DMagneticFluxDensity a-tesla = mkUnitZ (ucumMetric "T" "T" "Tesla") 1 $ siUnit-henry :: Num a => Unit 'Metric DInductance a-henry = mkUnitZ (ucumMetric "H" "H" "Henry") 1 $ siUnit--{--We defer the definition of Celcius temperature to another section (would-appear here if we stricly followed table 3).--}--lumen :: Num a => Unit 'Metric DLuminousFlux a-lumen = mkUnitZ (ucumMetric "lm" "lm" "lumen") 1 $ siUnit-lux :: Num a => Unit 'Metric DIlluminance a-lux = mkUnitZ (ucumMetric "lx" "lx" "lux") 1 $ siUnit--{- $celsius-A problematic area is units which increase proportionally to the-base SI units but cross zero at a different point. An example would-be degrees Celsius (see section 4.2.1.1). The author feels that it-is appropriate to define a unit for use with relative quantities-(taking only into account the proportionality) and complement the-unit with functions for converting absolute values.--The function 'fromDegreeCelsiusAbsolute' should be used in lieu of-"*~ degreeCelsius" when working with absolute temperatures. Similarily,-'toDegreeCelsiusAbsolute' should be used in lieu of "/~ degreeCelsius"-when working with absolute temperatures.--}--degreeCelsius :: Num a => Unit 'Metric DCelsiusTemperature a-degreeCelsius = kelvin--fromDegreeCelsiusAbsolute :: Floating a => a -> ThermodynamicTemperature a-fromDegreeCelsiusAbsolute x = x *~ degreeCelsius + 273.15 *~ degreeCelsius-toDegreeCelsiusAbsolute :: Floating a => ThermodynamicTemperature a -> a-toDegreeCelsiusAbsolute x = (x - 273.15 *~ degreeCelsius) /~ degreeCelsius--{- $health--The last units from Table 3 are SI derived units with special names and symbols admitted for reasons-of safeguarding human health.--}--becquerel :: Num a => Unit 'Metric DActivity a-becquerel = mkUnitZ (ucumMetric "Bq" "Bq" "Becquerel") 1 $ siUnit-gray :: Num a => Unit 'Metric DAbsorbedDose a-gray = mkUnitZ (ucumMetric "Gy" "Gy" "Gray") 1 $ siUnit-sievert :: Num a => Unit 'Metric DDoseEquivalent a-sievert = mkUnitZ (ucumMetric "Sv" "Sv" "Sievert") 1 $ siUnit-katal :: Num a => Unit 'Metric DCatalyticActivity a-katal = mkUnitZ (ucumMetric "kat" "kat" "katal") 1 $ siUnit--{- $accepted-units-There are several units that are not strictly part of the SI but-are either permanently or temporarily accepted for use with the SI.-We define the permanently accepted ones in this module.--From Table 6, Units accepted for use with the SI.--We start with time which we grant exclusive rights to 'minute' and-'second'.--}-minute, hour, day :: Num a => Unit 'NonMetric DTime a-minute = mkUnitZ (ucum "min" "min" "minute") 60 $ second-hour   = mkUnitZ (ucum "h" "h" "hour")       60 $ minute-day    = mkUnitZ (ucum "d" "d" "day")        24 $ hour -- Mean solar day.--{- $arc-units--Since 'minute' and 'second' are already in use for time we use-'arcminute' and 'arcsecond' <#note2 [2]> for plane angle instead.--}--degree, arcminute, arcsecond :: Floating a => Unit 'NonMetric DPlaneAngle a-degree    = mkUnitR (ucum "deg" "°" "degree")    (Prelude.pi Prelude./ 180) $ radian-arcminute = mkUnitR (ucum "'" "'" "arcminute")   (Prelude.recip 60)         $ degreeOfArc-arcsecond = mkUnitR (ucum "''" "''" "arcsecond") (Prelude.recip 60)         $ minuteOfArc--{- $arc-units-alternate-Alternate (longer) forms of the above. In particular 'degreeOfArc'-can be used if there is a percieved need to disambiguate from e.g.-temperature.--}--degreeOfArc, minuteOfArc, secondOfArc :: Floating a => Unit 'NonMetric DPlaneAngle a-degreeOfArc = degree-secondOfArc = arcsecond-minuteOfArc = arcminute--hectare :: Fractional a => Unit 'NonMetric DArea a-hectare = square (hecto meter)--litre, liter :: Fractional a => Unit 'Metric DVolume a-litre = mkUnitQ (ucumMetric "L" "L" "litre") 1 $ deci meter ^ pos3 -- International English.-liter = litre             -- American English.--tonne, metricTon :: Num a => Unit 'Metric DMass a-tonne     = mkUnitZ (ucumMetric "t" "t" "tonne") 1000 $ siUnit -- Name in original SI text.-metricTon = tonne                   -- American name.--{- $values-obtained-experimentally-We decline to provide here those units - listed in Table 7 - which,-while accepted for use with the SI, have values which are determined experimentally.-For versioning purposes, those units can be found in "Numeric.Units.Dimensional.NonSI".--However, in 2012 the IAU redefined the astronomical unit as a conventional-unit of length directly tied to the meter, with a length of exactly-149 597 870 700 m and the official abbreviation of au <#note3 [3]>. We therefore include it here.--}--astronomicalUnit :: Num a => Unit 'NonMetric DLength a-astronomicalUnit = mkUnitZ (ucum "AU" "AU" "astronomical unit") 149597870700 $ meter+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE NumDecimals #-}
+{-# LANGUAGE RankNTypes #-}
+
+{- |
+   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+= Summary
+
+This module defines the SI prefixes, the SI base units and the SI
+derived units. It also defines the units outside of the SI that are
+accepted for use with the SI. Any chapters, sections or tables
+referenced are from <#note1 [1]> unless otherwise specified.
+
+= References
+
+1. #note1# http://physics.nist.gov/Pubs/SP811/
+2. #note2# http://en.wikipedia.org/wiki/Minute_of_arc
+3. #note3# http://en.wikipedia.org/wiki/Astronomical_unit
+
+-}
+
+module Numeric.Units.Dimensional.SIUnits
+(
+  -- * SI Base Units
+  -- $base-units
+  metre, meter, gram, second, ampere, kelvin, mole, candela,
+  -- * SI Derived Units
+  -- $derived-units
+  radian, steradian, hertz, newton, pascal, joule, watt, coulomb, volt, farad, ohm, siemens, weber, tesla, henry, lumen, lux,
+  -- ** Celsius Temperature
+  -- $celsius
+  degreeCelsius, fromDegreeCelsiusAbsolute, toDegreeCelsiusAbsolute,
+  -- ** Units Admitted for Reasons of Safeguarding Human Health
+  -- $health
+  becquerel, gray, sievert, katal,
+  -- * Units Accepted for Use with the SI
+  -- $accepted-units
+  minute, hour, day,
+  hectare, litre, liter, tonne, metricTon,
+  -- ** Units of Plane Angle
+  -- $arc-units
+  degree, arcminute, arcsecond,
+  -- $arc-units-alternate
+  degreeOfArc, minuteOfArc, secondOfArc,
+  -- ** Units Formerly Defined By Experiment
+  -- $values-obtained-experimentally
+  astronomicalUnit,
+  -- * SI Prefixes
+  -- $multiples
+  deka, deca, hecto, kilo, mega, giga, tera, peta, exa, zetta, yotta,
+  -- $submultiples
+  deci, centi, milli, micro, nano, pico, femto, atto, zepto, yocto,
+  -- $reified-prefixes
+  Prefix, applyPrefix, siPrefixes
+)
+where
+
+import Data.Ratio
+import Numeric.Units.Dimensional
+import Numeric.Units.Dimensional.Quantities
+import Numeric.Units.Dimensional.UnitNames (Prefix, siPrefixes)
+import qualified Numeric.Units.Dimensional.UnitNames as N
+import Numeric.Units.Dimensional.UnitNames.Internal (ucum, ucumMetric)
+import qualified Numeric.Units.Dimensional.UnitNames.Internal as I
+import Numeric.NumType.DK.Integers ( pos3 )
+import Prelude ( Eq(..), ($), Num, Fractional, Floating, otherwise, error)
+import qualified Prelude
+
+{- $multiples
+Prefixes are used to form decimal multiples and submultiples of SI
+Units as described in section 4.4. We will define the SI prefixes
+in terms of the 'prefix' function which applies a scale factor to a
+unit.
+
+By defining SI prefixes as functions applied to a 'Unit' we satisfy
+section 6.2.6 "Unacceptability of stand-alone prefixes".
+
+We define all SI prefixes from Table 5. Multiples first.
+-}
+
+applyMultiple :: (Num a) => Prefix -> Unit 'Metric d a -> Unit 'NonMetric d a
+applyMultiple p u | denominator x == 1 = mkUnitZ n' (numerator x) u
+                  | otherwise = error "Attempt to apply a submultiple prefix as a multiple."
+  where
+    n' = N.applyPrefix p (name u)
+    x = N.scaleFactor p
+
+deka, deca, hecto, kilo, mega, giga, tera, peta, exa, zetta, yotta
+  :: Num a => Unit 'Metric d a -> Unit 'NonMetric d a
+deka  = applyMultiple I.deka -- International English.
+deca  = deka      -- American English.
+hecto = applyMultiple I.hecto
+kilo  = applyMultiple I.kilo
+mega  = applyMultiple I.mega
+giga  = applyMultiple I.giga
+tera  = applyMultiple I.tera
+peta  = applyMultiple I.peta
+exa   = applyMultiple I.exa
+zetta = applyMultiple I.zetta
+yotta = applyMultiple I.yotta
+
+{- $submultiples
+Then the submultiples.
+-}
+
+applyPrefix :: (Fractional a) => Prefix -> Unit 'Metric d a -> Unit 'NonMetric d a
+applyPrefix p u = mkUnitQ n' x u
+  where
+    n' = N.applyPrefix p (name u)
+    x = N.scaleFactor p
+
+deci, centi, milli, micro, nano, pico, femto, atto, zepto, yocto
+  :: Fractional a => Unit 'Metric d a -> Unit 'NonMetric d a
+deci  = applyPrefix I.deci
+centi = applyPrefix I.centi
+milli = applyPrefix I.milli
+micro = applyPrefix I.micro
+nano  = applyPrefix I.nano
+pico  = applyPrefix I.pico
+femto = applyPrefix I.femto
+atto  = applyPrefix I.atto
+zepto = applyPrefix I.zepto
+yocto = applyPrefix I.yocto
+
+{- $reified-prefixes
+
+We supply an explicit representation of an SI prefix, along with a function to apply one and a
+list of all prefixes defined by the SI.
+
+-}
+
+{- $base-units
+These are the base units from section 4.1. To avoid a
+myriad of one-letter functions that would doubtlessly cause clashes
+and frustration in users' code we spell out all unit names in full,
+as we did for prefixes. We also elect to spell the unit names in
+singular form, as allowed by section 9.7 "Other spelling conventions".
+
+We define the SI base units in the order of table 1.
+-}
+
+metre, meter :: Num a => Unit 'Metric DLength a
+metre = mkUnitZ I.nMeter 1 siUnit -- International English.
+meter = metre         -- American English.
+
+{-
+
+For mass the SI base unit is kilogram. For sensible prefixes we
+define gram here (see section 6.2.7 "Prefixes and the kilogram").
+The drawback is that we are forced to use 'Fractional'.
+
+-}
+
+gram    :: Fractional a => Unit 'Metric DMass a
+gram    = mkUnitQ I.nGram 1e-3 siUnit
+second  :: Num a => Unit 'Metric DTime a
+second  = mkUnitZ I.nSecond 1 siUnit
+ampere  :: Num a => Unit 'Metric DElectricCurrent a
+ampere  = mkUnitZ I.nAmpere 1 siUnit
+kelvin  :: Num a => Unit 'Metric DThermodynamicTemperature a
+kelvin  = mkUnitZ I.nKelvin 1 siUnit
+mole    :: Num a => Unit 'Metric DAmountOfSubstance a
+mole    = mkUnitZ I.nMole 1 siUnit
+candela :: Num a => Unit 'Metric DLuminousIntensity a
+candela = mkUnitZ I.nCandela 1 siUnit
+
+{- $derived-units
+From Table 3, SI derived units with special names and symbols, including the
+radian and steradian.
+-}
+
+radian :: Num a => Unit 'Metric DPlaneAngle a
+radian = mkUnitZ (ucumMetric "rad" "rad" "radian") 1 siUnit -- meter * meter ^ neg1
+steradian :: Num a => Unit 'Metric DSolidAngle a
+steradian = mkUnitZ (ucumMetric "sr" "sr" "steradian") 1 siUnit -- meter ^ pos2 * meter ^ neg2
+hertz :: Num a => Unit 'Metric DFrequency a
+hertz = mkUnitZ (ucumMetric "Hz" "Hz" "Hertz") 1 $ siUnit
+newton :: Num a => Unit 'Metric DForce a
+newton = mkUnitZ (ucumMetric "N" "N" "Newton") 1 $ siUnit
+pascal :: Num a => Unit 'Metric DPressure a
+pascal = mkUnitZ (ucumMetric "Pa" "Pa" "Pascal") 1 $ siUnit
+joule :: Num a => Unit 'Metric DEnergy a
+joule = mkUnitZ (ucumMetric "J" "J" "Joule") 1 $ siUnit
+watt :: Num a => Unit 'Metric DPower a
+watt = mkUnitZ (ucumMetric "W" "W" "Watt") 1 $ siUnit
+coulomb :: Num a => Unit 'Metric DElectricCharge a
+coulomb = mkUnitZ (ucumMetric "C" "C" "Coulomb") 1 $ siUnit
+volt :: Num a => Unit 'Metric DElectricPotential a
+volt = mkUnitZ (ucumMetric "V" "V" "Volt") 1 $ siUnit
+farad :: Num a => Unit 'Metric DCapacitance a
+farad = mkUnitZ (ucumMetric "F" "F" "Farad") 1 $ siUnit
+ohm :: Num a => Unit 'Metric DElectricResistance a
+ohm = mkUnitZ (ucumMetric "Ohm" "Ω" "Ohm") 1 $ siUnit
+siemens :: Num a => Unit 'Metric DElectricConductance a
+siemens = mkUnitZ (ucumMetric "S" "S" "Siemens") 1 $ siUnit
+weber :: Num a => Unit 'Metric DMagneticFlux a
+weber = mkUnitZ (ucumMetric "Wb" "Wb" "Weber") 1 $ siUnit
+tesla :: Num a => Unit 'Metric DMagneticFluxDensity a
+tesla = mkUnitZ (ucumMetric "T" "T" "Tesla") 1 $ siUnit
+henry :: Num a => Unit 'Metric DInductance a
+henry = mkUnitZ (ucumMetric "H" "H" "Henry") 1 $ siUnit
+
+{-
+We defer the definition of Celcius temperature to another section (would
+appear here if we stricly followed table 3).
+-}
+
+lumen :: Num a => Unit 'Metric DLuminousFlux a
+lumen = mkUnitZ (ucumMetric "lm" "lm" "lumen") 1 $ siUnit
+lux :: Num a => Unit 'Metric DIlluminance a
+lux = mkUnitZ (ucumMetric "lx" "lx" "lux") 1 $ siUnit
+
+{- $celsius
+A problematic area is units which increase proportionally to the
+base SI units but cross zero at a different point. An example would
+be degrees Celsius (see section 4.2.1.1). The author feels that it
+is appropriate to define a unit for use with relative quantities
+(taking only into account the proportionality) and complement the
+unit with functions for converting absolute values.
+
+The function 'fromDegreeCelsiusAbsolute' should be used in lieu of
+"*~ degreeCelsius" when working with absolute temperatures. Similarily,
+'toDegreeCelsiusAbsolute' should be used in lieu of "/~ degreeCelsius"
+when working with absolute temperatures.
+-}
+
+degreeCelsius :: Num a => Unit 'Metric DCelsiusTemperature a
+degreeCelsius = kelvin
+
+fromDegreeCelsiusAbsolute :: Floating a => a -> ThermodynamicTemperature a
+fromDegreeCelsiusAbsolute x = x *~ degreeCelsius + 273.15 *~ degreeCelsius
+toDegreeCelsiusAbsolute :: Floating a => ThermodynamicTemperature a -> a
+toDegreeCelsiusAbsolute x = (x - 273.15 *~ degreeCelsius) /~ degreeCelsius
+
+{- $health
+
+The last units from Table 3 are SI derived units with special names and symbols admitted for reasons
+of safeguarding human health.
+-}
+
+becquerel :: Num a => Unit 'Metric DActivity a
+becquerel = mkUnitZ (ucumMetric "Bq" "Bq" "Becquerel") 1 $ siUnit
+gray :: Num a => Unit 'Metric DAbsorbedDose a
+gray = mkUnitZ (ucumMetric "Gy" "Gy" "Gray") 1 $ siUnit
+sievert :: Num a => Unit 'Metric DDoseEquivalent a
+sievert = mkUnitZ (ucumMetric "Sv" "Sv" "Sievert") 1 $ siUnit
+katal :: Num a => Unit 'Metric DCatalyticActivity a
+katal = mkUnitZ (ucumMetric "kat" "kat" "katal") 1 $ siUnit
+
+{- $accepted-units
+There are several units that are not strictly part of the SI but
+are either permanently or temporarily accepted for use with the SI.
+We define the permanently accepted ones in this module.
+
+From Table 6, Units accepted for use with the SI.
+
+We start with time which we grant exclusive rights to 'minute' and
+'second'.
+-}
+minute, hour, day :: Num a => Unit 'NonMetric DTime a
+minute = mkUnitZ (ucum "min" "min" "minute") 60 $ second
+hour   = mkUnitZ (ucum "h" "h" "hour")       60 $ minute
+day    = mkUnitZ (ucum "d" "d" "day")        24 $ hour -- Mean solar day.
+
+{- $arc-units
+
+Since 'minute' and 'second' are already in use for time we use
+'arcminute' and 'arcsecond' <#note2 [2]> for plane angle instead.
+-}
+
+degree, arcminute, arcsecond :: Floating a => Unit 'NonMetric DPlaneAngle a
+degree    = mkUnitR (ucum "deg" "°" "degree")    (Prelude.pi Prelude./ 180) $ radian
+arcminute = mkUnitR (ucum "'" "'" "arcminute")   (Prelude.recip 60)         $ degreeOfArc
+arcsecond = mkUnitR (ucum "''" "''" "arcsecond") (Prelude.recip 60)         $ minuteOfArc
+
+{- $arc-units-alternate
+Alternate (longer) forms of the above. In particular 'degreeOfArc'
+can be used if there is a percieved need to disambiguate from e.g.
+temperature.
+-}
+
+degreeOfArc, minuteOfArc, secondOfArc :: Floating a => Unit 'NonMetric DPlaneAngle a
+degreeOfArc = degree
+secondOfArc = arcsecond
+minuteOfArc = arcminute
+
+hectare :: Fractional a => Unit 'NonMetric DArea a
+hectare = square (hecto meter)
+
+litre, liter :: Fractional a => Unit 'Metric DVolume a
+litre = mkUnitQ (ucumMetric "L" "L" "litre") 1 $ deci meter ^ pos3 -- International English.
+liter = litre             -- American English.
+
+tonne, metricTon :: Num a => Unit 'Metric DMass a
+tonne     = mkUnitZ (ucumMetric "t" "t" "tonne") 1000 $ siUnit -- Name in original SI text.
+metricTon = tonne                   -- American name.
+
+{- $values-obtained-experimentally
+We decline to provide here those units - listed in Table 7 - which,
+while accepted for use with the SI, have values which are determined experimentally.
+For versioning purposes, those units can be found in "Numeric.Units.Dimensional.NonSI".
+
+However, in 2012 the IAU redefined the astronomical unit as a conventional
+unit of length directly tied to the meter, with a length of exactly
+149 597 870 700 m and the official abbreviation of au <#note3 [3]>. We therefore include it here.
+-}
+
+astronomicalUnit :: Num a => Unit 'NonMetric DLength a
+astronomicalUnit = mkUnitZ (ucum "AU" "AU" "astronomical unit") 149597870700 $ meter
src/Numeric/Units/Dimensional/UnitNames.hs view
@@ -1,37 +1,37 @@-{-# LANGUAGE PatternSynonyms #-}--{- |-   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter-   License    : BSD3--   Maintainer : bjorn@buckwalter.se-   Stability  : Stable-   Portability: GHC only--This module provides types and functions for manipulating unit names.--Please note that the details of the name representation may be less stable than the other APIs-provided by this package, as new features using them are still being developed.---}-module Numeric.Units.Dimensional.UnitNames-(-  -- * Data Types-  UnitName, NameAtom, Prefix, PrefixName, Metricality(..),-  -- * Construction of Unit Names-  atom, applyPrefix, (*), (/), (^), product, reduce, grouped,-  -- * Standard Names-  baseUnitName, siPrefixes, nOne,-  -- * Inspecting Prefixes-  prefixName, scaleFactor,-  -- * Convenience Type Synonyms for Unit Name Transformations-  UnitNameTransformer, UnitNameTransformer2,-  -- * Forgetting Unwanted Phantom Types-  weaken, strengthen, relax,-  name_en, abbreviation_en, asAtomic-)-where--import Numeric.Units.Dimensional.UnitNames.Internal-import Numeric.Units.Dimensional.Variants-import Prelude hiding ((*), (/), (^), product)+{-# LANGUAGE PatternSynonyms #-}
+
+{- |
+   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+This module provides types and functions for manipulating unit names.
+
+Please note that the details of the name representation may be less stable than the other APIs
+provided by this package, as new features using them are still being developed.
+
+-}
+module Numeric.Units.Dimensional.UnitNames
+(
+  -- * Data Types
+  UnitName, NameAtom, Prefix, PrefixName, Metricality(..),
+  -- * Construction of Unit Names
+  atom, applyPrefix, (*), (/), (^), product, reduce, grouped,
+  -- * Standard Names
+  baseUnitName, siPrefixes, nOne,
+  -- * Inspecting Prefixes
+  prefixName, scaleFactor,
+  -- * Convenience Type Synonyms for Unit Name Transformations
+  UnitNameTransformer, UnitNameTransformer2,
+  -- * Forgetting Unwanted Phantom Types
+  weaken, strengthen, relax,
+  name_en, abbreviation_en, asAtomic
+)
+where
+
+import Numeric.Units.Dimensional.UnitNames.Internal
+import Numeric.Units.Dimensional.Variants
+import Prelude hiding ((*), (/), (^), product)
src/Numeric/Units/Dimensional/UnitNames/InterchangeNames.hs view
@@ -1,41 +1,41 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}--module Numeric.Units.Dimensional.UnitNames.InterchangeNames-(-  InterchangeNameAuthority(..),-  InterchangeName(..),-  HasInterchangeName(..)-)-where--import Control.DeepSeq-import Data.Data-import GHC.Generics-import Prelude---- | Represents the authority which issued an interchange name for a unit.-data InterchangeNameAuthority = UCUM -- ^ The interchange name originated with the Unified Code for Units of Measure.-                              | DimensionalLibrary -- ^ The interchange name originated with the dimensional library.-                              | Custom -- ^ The interchange name originated with a user of the dimensional library.-  deriving (Eq, Ord, Show, Data, Typeable, Generic)--instance NFData InterchangeNameAuthority where -- instance is derived from Generic instance--data InterchangeName = InterchangeName { name :: String, authority :: InterchangeNameAuthority, isAtomic :: Bool }-  deriving (Eq, Ord, Data, Typeable, Generic)--instance NFData InterchangeName where -- instance is derived from Generic instance--instance Show InterchangeName where-  show n = name n ++ " (Issued by " ++ show (authority n) ++ ")"---- | Determines the authority which issued the interchange name of a unit or unit name.--- For composite units, this is the least-authoritative interchange name of any constituent name.------ Note that the least-authoritative authority is the one sorted as greatest by the 'Ord' instance of 'InterchangeNameAuthority'.-class HasInterchangeName a where-  interchangeName :: a -> InterchangeName--instance HasInterchangeName InterchangeName where-  interchangeName = id+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric #-}
+
+module Numeric.Units.Dimensional.UnitNames.InterchangeNames
+(
+  InterchangeNameAuthority(..),
+  InterchangeName(..),
+  HasInterchangeName(..)
+)
+where
+
+import Control.DeepSeq
+import Data.Data
+import GHC.Generics
+import Prelude
+
+-- | Represents the authority which issued an interchange name for a unit.
+data InterchangeNameAuthority = UCUM -- ^ The interchange name originated with the Unified Code for Units of Measure.
+                              | DimensionalLibrary -- ^ The interchange name originated with the dimensional library.
+                              | Custom -- ^ The interchange name originated with a user of the dimensional library.
+  deriving (Eq, Ord, Show, Data, Typeable, Generic)
+
+instance NFData InterchangeNameAuthority where -- instance is derived from Generic instance
+
+data InterchangeName = InterchangeName { name :: String, authority :: InterchangeNameAuthority, isAtomic :: Bool }
+  deriving (Eq, Ord, Data, Typeable, Generic)
+
+instance NFData InterchangeName where -- instance is derived from Generic instance
+
+instance Show InterchangeName where
+  show n = name n ++ " (Issued by " ++ show (authority n) ++ ")"
+
+-- | Determines the authority which issued the interchange name of a unit or unit name.
+-- For composite units, this is the least-authoritative interchange name of any constituent name.
+--
+-- Note that the least-authoritative authority is the one sorted as greatest by the 'Ord' instance of 'InterchangeNameAuthority'.
+class HasInterchangeName a where
+  interchangeName :: a -> InterchangeName
+
+instance HasInterchangeName InterchangeName where
+  interchangeName = id
src/Numeric/Units/Dimensional/UnitNames/Internal.hs view
@@ -1,361 +1,361 @@-{-# OPTIONS_HADDOCK not-home #-}--{-# LANGUAGE AutoDeriveTypeable #-}-{-# LANGUAGE CPP #-}-{-# 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)-#if MIN_VERSION_base(4, 8, 0)-import Data.Foldable (toList)-#else-import Data.Foldable (Foldable, toList)-#endif-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 n = case n of-    One -> ()-    MetricAtomic a -> rnf a-    Atomic a -> rnf a-    Prefixed p n' -> rnf p `seq` rnf n'-    Product n1 n2 -> rnf n1 `seq` rnf n2-    Quotient n1 n2 -> rnf n1 `seq` rnf n2-    Power n' e -> rnf n' `seq` rnf e-    Grouped n' -> rnf n'-    Weaken n' -> rnf n'--instance Show (UnitName m) where-  show One = "1"-  show (MetricAtomic a) = abbreviation_en a-  show (Atomic a) = abbreviation_en a-  show (Prefixed a n) = abbreviation_en a ++ show n-  show (Product n1 n2) = show n1 ++ " " ++ show n2-  show (Quotient n1 n2) = show n1 ++ " / " ++ show n2-  show (Power x n) = show x ++ "^" ++ show n-  show (Grouped n) = "(" ++ show n ++ ")"-  show (Weaken n) = show n--asAtomic :: UnitName m -> Maybe (NameAtom ('UnitAtom m))-asAtomic (MetricAtomic a) = Just a-asAtomic (Atomic a) = Just a-asAtomic (Weaken n) = fmap coerce $ asAtomic n-asAtomic _ = Nothing--isAtomic :: UnitName m -> Bool-isAtomic (One) = True-isAtomic (MetricAtomic _) = True-isAtomic (Atomic _) = True-isAtomic (Prefixed _ _) = True-isAtomic (Grouped _) = True-isAtomic (Weaken n) = isAtomic n-isAtomic _ = False--isAtomicOrProduct :: UnitName m -> Bool-isAtomicOrProduct (Product _ _) = True-isAtomicOrProduct n = isAtomic n---- reduce by algebraic simplifications-reduce :: UnitName m -> UnitName m-reduce (One) = One-reduce n@(MetricAtomic _) = n-reduce n@(Atomic _) = n-reduce n@(Prefixed _ _) = n-reduce (Product n1 n2) = reduce' (reduce n1 * reduce n2)-reduce (Quotient n1 n2) = reduce' (reduce n1 * reduce n2)-reduce (Power n x) = reduce' ((reduce n) ^ x)-reduce (Grouped n) = reduce' (Grouped (reduce n))-reduce (Weaken n) = reduce' (Weaken (reduce n))---- reduce, knowing that subterms are already in reduced form-reduce' :: UnitName m -> UnitName m-reduce' (Product One n) = reduce' n-reduce' (Product n One) = reduce' n-reduce' (Power (Power n x1) x2) = reduce (n ^ (x1 P.* x2))-reduce' (Power (Grouped (Power n x1)) x2) = reduce (n ^ (x1 P.* x2))-reduce' (Power _ 0) = One-reduce' (Power n 1) = reduce' n-reduce' (Grouped n) = reduce' n-reduce' n@(Weaken (MetricAtomic _)) = n-reduce' n = n--data NameAtomType = UnitAtom Metricality-                  | PrefixAtom-  deriving (Eq, Ord, Data, Typeable, 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.-                prefixName :: PrefixName,-                -- | The scale factor denoted by a metric prefix.-                scaleFactor :: Rational-              }-  deriving (Eq, Data, Typeable, Generic)--instance Ord Prefix where-  compare = comparing scaleFactor--instance NFData Prefix where -- instance is derived from Generic instance--instance HasInterchangeName Prefix where-  interchangeName = interchangeName . prefixName---- | The name of the unit of dimensionless values.-nOne :: UnitName 'NonMetric-nOne = One--nMeter :: UnitName 'Metric-nMeter = ucumMetric "m" "m" "metre"--nGram :: UnitName 'Metric-nGram = ucumMetric "g" "g" "gram"--nKilogram :: UnitName 'NonMetric-nKilogram = applyPrefix kilo nGram--nSecond :: UnitName 'Metric-nSecond = ucumMetric "s" "s" "second"--nAmpere :: UnitName 'Metric-nAmpere = ucumMetric "A" "A" "Ampere"--nKelvin :: UnitName 'Metric-nKelvin = ucumMetric "K" "K" "Kelvin"--nMole :: UnitName 'Metric-nMole = ucumMetric "mol" "mol" "mole"--nCandela :: UnitName 'Metric-nCandela = ucumMetric "cd" "cd" "candela"---- | The name of the base unit associated with a specified dimension.-baseUnitName :: Dimension' -> UnitName 'NonMetric-baseUnitName d = let powers = asList $ dimension d-                  in reduce . product $ zipWith (^) baseUnitNames powers--baseUnitNames :: [UnitName 'NonMetric]-baseUnitNames = [weaken nMeter, nKilogram, weaken nSecond, weaken nAmpere, weaken nKelvin, weaken nMole, weaken nCandela]--deka, hecto, kilo, mega, giga, tera, peta, exa, zetta, yotta :: Prefix-deka  = prefix "da" "da" "deka" 1e1-hecto = prefix "h" "h" "hecto"  1e2-kilo  = prefix "k" "k" "kilo"   1e3-mega  = prefix "M" "M" "mega"   1e6-giga  = prefix "G" "G" "giga"   1e9-tera  = prefix "T" "T" "tera"   1e12-peta  = prefix "P" "P" "peta"   1e15-exa   = prefix "E" "E" "exa"    1e18-zetta = prefix "Z" "Z" "zetta"  1e21-yotta = prefix "Y" "Y" "yotta"  1e24-deci, centi, milli, micro, nano, pico, femto, atto, zepto, yocto :: Prefix-deci  = prefix "d" "d" "deci"   1e-1-centi = prefix "c" "c" "centi"  1e-2-milli = prefix "m" "m" "milli"  1e-3-micro = prefix "u" "μ" "micro"  1e-6-nano  = prefix "n" "n" "nano"   1e-9-pico  = prefix "p" "p" "pico"   1e-12-femto = prefix "f" "f" "femto"  1e-15-atto  = prefix "a" "a" "atto"   1e-18-zepto = prefix "z" "z" "zepto"  1e-21-yocto = prefix "y" "y" "yocto"  1e-24---- | A list of all 'Prefix'es defined by the SI.-siPrefixes :: [Prefix]-siPrefixes = [yocto, zepto, atto, femto, pico, nano, micro, milli, centi, deci, deka, hecto, kilo, mega, giga, tera, peta, exa, zetta, yotta]---- | Forms a 'UnitName' from a 'Metric' name by applying a metric prefix.-applyPrefix :: Prefix -> UnitName 'Metric -> UnitName 'NonMetric-applyPrefix = Prefixed . 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 * b = Product (weaken a) (weaken b)---- | Form a 'UnitName' by dividing one by another.-(/) :: UnitName m1 -> UnitName m2 -> UnitName 'NonMetric-n1 / n2 | isAtomicOrProduct n1 = Quotient (weaken n1) (weaken n2)-        | otherwise            = Quotient (grouped n1) (weaken n2)---- | Form a 'UnitName' by raising a name to an integer power.-(^) :: UnitName m -> Int -> UnitName 'NonMetric-x ^ n | isAtomic x = Power (weaken x) n-      | otherwise  = Power (grouped x) n---- | Convert a 'UnitName' which may or may not be 'Metric' to one--- which is certainly 'NonMetric'.-weaken :: UnitName m -> UnitName 'NonMetric-weaken n@(MetricAtomic _) = Weaken n -- we really only need this one case and a catchall, but the typechecker can't see it-weaken n@One = n-weaken n@(Atomic _) = n-weaken n@(Prefixed _ _) = n-weaken n@(Product _ _) = n-weaken n@(Quotient _ _) = n-weaken n@(Power _ _) = n-weaken n@(Grouped _) = n-weaken n@(Weaken _) = 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 n@(MetricAtomic _) = Just n-strengthen (Weaken n) = strengthen n-strengthen _ = 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 n = go (typeRep (Proxy :: Proxy m1)) (typeRep (Proxy :: Proxy m2)) n-  where-    metric = typeRep (Proxy :: Proxy 'Metric)-    nonMetric = typeRep (Proxy :: Proxy 'NonMetric)-    go :: TypeRep -> TypeRep -> UnitName m1 -> Maybe (UnitName m2)-    go p1 p2 | p1 == p2 = cast-             | (p1 == nonMetric) && (p2 == metric) = join . fmap gcast . strengthen-             | (p1 == metric) && (p2 == nonMetric) = cast . weaken-             | otherwise = 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 = Grouped . weaken---- | Represents the name of an atomic unit or prefix.-data NameAtom (m :: NameAtomType)-  = NameAtom-  {-    _interchangeName :: InterchangeName, -- ^ The interchange name of the unit.-    abbreviation_en :: String, -- ^ The abbreviated name of the unit in international English-    name_en :: String -- ^ The full name of the unit in international English-  }-  deriving (Eq, Ord, Data, Typeable, Generic)--instance NFData (NameAtom m) where -- instance is derived from Generic instance--instance HasInterchangeName (NameAtom m) where-  interchangeName = _interchangeName--instance HasInterchangeName (UnitName m) where-  interchangeName One = InterchangeName { name = "1", authority = UCUM, I.isAtomic = True }-  interchangeName (MetricAtomic a) = interchangeName a-  interchangeName (Atomic a) = interchangeName a-  interchangeName (Prefixed p n) = let n' = (name . interchangeName $ p) ++ (name . interchangeName $ n)-                                       a' = max (authority . interchangeName $ p) (authority . interchangeName $ n)-                                    in InterchangeName { name = n', authority = a', I.isAtomic = False }-  interchangeName (Product n1 n2) = let n' = (name . interchangeName $ n1) ++ "." ++ (name . interchangeName $ n2)-                                        a' = max (authority . interchangeName $ n1) (authority . interchangeName $ n2)-                                     in InterchangeName { name = n', authority = a', I.isAtomic = False }-  interchangeName (Quotient n1 n2) = let n' = (name . interchangeName $ n1) ++ "/" ++ (name . interchangeName $ n2)-                                         a' = max (authority . interchangeName $ n1) (authority . interchangeName $ n2)-                                      in InterchangeName { name = n', authority = a', I.isAtomic = 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 x) = let n' = (name . interchangeName $ n) ++ (show x)-                                 in InterchangeName { name = n', authority = authority . interchangeName $ n, I.isAtomic = False }-  interchangeName (Grouped n) = let n' = "(" ++ (name . interchangeName $ n) ++ ")"-                                 in InterchangeName { name = n', authority = authority . interchangeName $ n, I.isAtomic = False }-  interchangeName (Weaken n) = interchangeName n--prefix :: String -> String -> String -> Rational -> Prefix-prefix i a f q = Prefix n q-  where-    n = NameAtom (InterchangeName i UCUM True) a f--ucumMetric :: String -> String -> String -> UnitName 'Metric-ucumMetric i a f = MetricAtomic $ NameAtom (InterchangeName i UCUM True) a f--ucum :: String -> String -> String -> UnitName 'NonMetric-ucum i a f = Atomic $ NameAtom (InterchangeName i UCUM True) a f--dimensionalAtom :: String -> String -> String -> UnitName 'NonMetric-dimensionalAtom i a f = Atomic $ NameAtom (InterchangeName i DimensionalLibrary True) a 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 i a f = Atomic $ NameAtom (InterchangeName i Custom True) a 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 = go . 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 [] = nOne-    go [n] = n-    go (n : ns) = n * go ns+{-# OPTIONS_HADDOCK not-home #-}
+
+{-# LANGUAGE AutoDeriveTypeable #-}
+{-# LANGUAGE CPP #-}
+{-# 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)
+#if MIN_VERSION_base(4, 8, 0)
+import Data.Foldable (toList)
+#else
+import Data.Foldable (Foldable, toList)
+#endif
+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 n = case n of
+    One -> ()
+    MetricAtomic a -> rnf a
+    Atomic a -> rnf a
+    Prefixed p n' -> rnf p `seq` rnf n'
+    Product n1 n2 -> rnf n1 `seq` rnf n2
+    Quotient n1 n2 -> rnf n1 `seq` rnf n2
+    Power n' e -> rnf n' `seq` rnf e
+    Grouped n' -> rnf n'
+    Weaken n' -> rnf n'
+
+instance Show (UnitName m) where
+  show One = "1"
+  show (MetricAtomic a) = abbreviation_en a
+  show (Atomic a) = abbreviation_en a
+  show (Prefixed a n) = abbreviation_en a ++ show n
+  show (Product n1 n2) = show n1 ++ " " ++ show n2
+  show (Quotient n1 n2) = show n1 ++ " / " ++ show n2
+  show (Power x n) = show x ++ "^" ++ show n
+  show (Grouped n) = "(" ++ show n ++ ")"
+  show (Weaken n) = show n
+
+asAtomic :: UnitName m -> Maybe (NameAtom ('UnitAtom m))
+asAtomic (MetricAtomic a) = Just a
+asAtomic (Atomic a) = Just a
+asAtomic (Weaken n) = fmap coerce $ asAtomic n
+asAtomic _ = Nothing
+
+isAtomic :: UnitName m -> Bool
+isAtomic (One) = True
+isAtomic (MetricAtomic _) = True
+isAtomic (Atomic _) = True
+isAtomic (Prefixed _ _) = True
+isAtomic (Grouped _) = True
+isAtomic (Weaken n) = isAtomic n
+isAtomic _ = False
+
+isAtomicOrProduct :: UnitName m -> Bool
+isAtomicOrProduct (Product _ _) = True
+isAtomicOrProduct n = isAtomic n
+
+-- reduce by algebraic simplifications
+reduce :: UnitName m -> UnitName m
+reduce (One) = One
+reduce n@(MetricAtomic _) = n
+reduce n@(Atomic _) = n
+reduce n@(Prefixed _ _) = n
+reduce (Product n1 n2) = reduce' (reduce n1 * reduce n2)
+reduce (Quotient n1 n2) = reduce' (reduce n1 * reduce n2)
+reduce (Power n x) = reduce' ((reduce n) ^ x)
+reduce (Grouped n) = reduce' (Grouped (reduce n))
+reduce (Weaken n) = reduce' (Weaken (reduce n))
+
+-- reduce, knowing that subterms are already in reduced form
+reduce' :: UnitName m -> UnitName m
+reduce' (Product One n) = reduce' n
+reduce' (Product n One) = reduce' n
+reduce' (Power (Power n x1) x2) = reduce (n ^ (x1 P.* x2))
+reduce' (Power (Grouped (Power n x1)) x2) = reduce (n ^ (x1 P.* x2))
+reduce' (Power _ 0) = One
+reduce' (Power n 1) = reduce' n
+reduce' (Grouped n) = reduce' n
+reduce' n@(Weaken (MetricAtomic _)) = n
+reduce' n = n
+
+data NameAtomType = UnitAtom Metricality
+                  | PrefixAtom
+  deriving (Eq, Ord, Data, Typeable, 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.
+                prefixName :: PrefixName,
+                -- | The scale factor denoted by a metric prefix.
+                scaleFactor :: Rational
+              }
+  deriving (Eq, Data, Typeable, Generic)
+
+instance Ord Prefix where
+  compare = comparing scaleFactor
+
+instance NFData Prefix where -- instance is derived from Generic instance
+
+instance HasInterchangeName Prefix where
+  interchangeName = interchangeName . prefixName
+
+-- | The name of the unit of dimensionless values.
+nOne :: UnitName 'NonMetric
+nOne = One
+
+nMeter :: UnitName 'Metric
+nMeter = ucumMetric "m" "m" "metre"
+
+nGram :: UnitName 'Metric
+nGram = ucumMetric "g" "g" "gram"
+
+nKilogram :: UnitName 'NonMetric
+nKilogram = applyPrefix kilo nGram
+
+nSecond :: UnitName 'Metric
+nSecond = ucumMetric "s" "s" "second"
+
+nAmpere :: UnitName 'Metric
+nAmpere = ucumMetric "A" "A" "Ampere"
+
+nKelvin :: UnitName 'Metric
+nKelvin = ucumMetric "K" "K" "Kelvin"
+
+nMole :: UnitName 'Metric
+nMole = ucumMetric "mol" "mol" "mole"
+
+nCandela :: UnitName 'Metric
+nCandela = ucumMetric "cd" "cd" "candela"
+
+-- | The name of the base unit associated with a specified dimension.
+baseUnitName :: Dimension' -> UnitName 'NonMetric
+baseUnitName d = let powers = asList $ dimension d
+                  in reduce . product $ zipWith (^) baseUnitNames powers
+
+baseUnitNames :: [UnitName 'NonMetric]
+baseUnitNames = [weaken nMeter, nKilogram, weaken nSecond, weaken nAmpere, weaken nKelvin, weaken nMole, weaken nCandela]
+
+deka, hecto, kilo, mega, giga, tera, peta, exa, zetta, yotta :: Prefix
+deka  = prefix "da" "da" "deka" 1e1
+hecto = prefix "h" "h" "hecto"  1e2
+kilo  = prefix "k" "k" "kilo"   1e3
+mega  = prefix "M" "M" "mega"   1e6
+giga  = prefix "G" "G" "giga"   1e9
+tera  = prefix "T" "T" "tera"   1e12
+peta  = prefix "P" "P" "peta"   1e15
+exa   = prefix "E" "E" "exa"    1e18
+zetta = prefix "Z" "Z" "zetta"  1e21
+yotta = prefix "Y" "Y" "yotta"  1e24
+deci, centi, milli, micro, nano, pico, femto, atto, zepto, yocto :: Prefix
+deci  = prefix "d" "d" "deci"   1e-1
+centi = prefix "c" "c" "centi"  1e-2
+milli = prefix "m" "m" "milli"  1e-3
+micro = prefix "u" "μ" "micro"  1e-6
+nano  = prefix "n" "n" "nano"   1e-9
+pico  = prefix "p" "p" "pico"   1e-12
+femto = prefix "f" "f" "femto"  1e-15
+atto  = prefix "a" "a" "atto"   1e-18
+zepto = prefix "z" "z" "zepto"  1e-21
+yocto = prefix "y" "y" "yocto"  1e-24
+
+-- | A list of all 'Prefix'es defined by the SI.
+siPrefixes :: [Prefix]
+siPrefixes = [yocto, zepto, atto, femto, pico, nano, micro, milli, centi, deci, deka, hecto, kilo, mega, giga, tera, peta, exa, zetta, yotta]
+
+-- | Forms a 'UnitName' from a 'Metric' name by applying a metric prefix.
+applyPrefix :: Prefix -> UnitName 'Metric -> UnitName 'NonMetric
+applyPrefix = Prefixed . 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 * b = Product (weaken a) (weaken b)
+
+-- | Form a 'UnitName' by dividing one by another.
+(/) :: UnitName m1 -> UnitName m2 -> UnitName 'NonMetric
+n1 / n2 | isAtomicOrProduct n1 = Quotient (weaken n1) (weaken n2)
+        | otherwise            = Quotient (grouped n1) (weaken n2)
+
+-- | Form a 'UnitName' by raising a name to an integer power.
+(^) :: UnitName m -> Int -> UnitName 'NonMetric
+x ^ n | isAtomic x = Power (weaken x) n
+      | otherwise  = Power (grouped x) n
+
+-- | Convert a 'UnitName' which may or may not be 'Metric' to one
+-- which is certainly 'NonMetric'.
+weaken :: UnitName m -> UnitName 'NonMetric
+weaken n@(MetricAtomic _) = Weaken n -- we really only need this one case and a catchall, but the typechecker can't see it
+weaken n@One = n
+weaken n@(Atomic _) = n
+weaken n@(Prefixed _ _) = n
+weaken n@(Product _ _) = n
+weaken n@(Quotient _ _) = n
+weaken n@(Power _ _) = n
+weaken n@(Grouped _) = n
+weaken n@(Weaken _) = 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 n@(MetricAtomic _) = Just n
+strengthen (Weaken n) = strengthen n
+strengthen _ = 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 n = go (typeRep (Proxy :: Proxy m1)) (typeRep (Proxy :: Proxy m2)) n
+  where
+    metric = typeRep (Proxy :: Proxy 'Metric)
+    nonMetric = typeRep (Proxy :: Proxy 'NonMetric)
+    go :: TypeRep -> TypeRep -> UnitName m1 -> Maybe (UnitName m2)
+    go p1 p2 | p1 == p2 = cast
+             | (p1 == nonMetric) && (p2 == metric) = join . fmap gcast . strengthen
+             | (p1 == metric) && (p2 == nonMetric) = cast . weaken
+             | otherwise = 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 = Grouped . weaken
+
+-- | Represents the name of an atomic unit or prefix.
+data NameAtom (m :: NameAtomType)
+  = NameAtom
+  {
+    _interchangeName :: InterchangeName, -- ^ The interchange name of the unit.
+    abbreviation_en :: String, -- ^ The abbreviated name of the unit in international English
+    name_en :: String -- ^ The full name of the unit in international English
+  }
+  deriving (Eq, Ord, Data, Typeable, Generic)
+
+instance NFData (NameAtom m) where -- instance is derived from Generic instance
+
+instance HasInterchangeName (NameAtom m) where
+  interchangeName = _interchangeName
+
+instance HasInterchangeName (UnitName m) where
+  interchangeName One = InterchangeName { name = "1", authority = UCUM, I.isAtomic = True }
+  interchangeName (MetricAtomic a) = interchangeName a
+  interchangeName (Atomic a) = interchangeName a
+  interchangeName (Prefixed p n) = let n' = (name . interchangeName $ p) ++ (name . interchangeName $ n)
+                                       a' = max (authority . interchangeName $ p) (authority . interchangeName $ n)
+                                    in InterchangeName { name = n', authority = a', I.isAtomic = False }
+  interchangeName (Product n1 n2) = let n' = (name . interchangeName $ n1) ++ "." ++ (name . interchangeName $ n2)
+                                        a' = max (authority . interchangeName $ n1) (authority . interchangeName $ n2)
+                                     in InterchangeName { name = n', authority = a', I.isAtomic = False }
+  interchangeName (Quotient n1 n2) = let n' = (name . interchangeName $ n1) ++ "/" ++ (name . interchangeName $ n2)
+                                         a' = max (authority . interchangeName $ n1) (authority . interchangeName $ n2)
+                                      in InterchangeName { name = n', authority = a', I.isAtomic = 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 x) = let n' = (name . interchangeName $ n) ++ (show x)
+                                 in InterchangeName { name = n', authority = authority . interchangeName $ n, I.isAtomic = False }
+  interchangeName (Grouped n) = let n' = "(" ++ (name . interchangeName $ n) ++ ")"
+                                 in InterchangeName { name = n', authority = authority . interchangeName $ n, I.isAtomic = False }
+  interchangeName (Weaken n) = interchangeName n
+
+prefix :: String -> String -> String -> Rational -> Prefix
+prefix i a f q = Prefix n q
+  where
+    n = NameAtom (InterchangeName i UCUM True) a f
+
+ucumMetric :: String -> String -> String -> UnitName 'Metric
+ucumMetric i a f = MetricAtomic $ NameAtom (InterchangeName i UCUM True) a f
+
+ucum :: String -> String -> String -> UnitName 'NonMetric
+ucum i a f = Atomic $ NameAtom (InterchangeName i UCUM True) a f
+
+dimensionalAtom :: String -> String -> String -> UnitName 'NonMetric
+dimensionalAtom i a f = Atomic $ NameAtom (InterchangeName i DimensionalLibrary True) a 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 i a f = Atomic $ NameAtom (InterchangeName i Custom True) a 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 = go . 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 [] = nOne
+    go [n] = n
+    go (n : ns) = n * go ns
src/Numeric/Units/Dimensional/Variants.hs view
@@ -1,94 +1,94 @@-{-# OPTIONS_HADDOCK not-home, show-extensions #-}--{-# LANGUAGE AutoDeriveTypeable #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}--{- |-   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter-   License    : BSD3--   Maintainer : bjorn@buckwalter.se-   Stability  : Stable-   Portability: GHC only--Provides a type level representation of 'Variant's of dimensional values,-which may be quantities or units.--}-module Numeric.Units.Dimensional.Variants-(-  type Variant(..),-  Metricality(..),-  type (*), type (/), type Weaken,-  type CompatibleVariants-)-where--import Control.DeepSeq-import Data.Data-import qualified Data.ExactPi.TypeLevel as E-import GHC.Generics-import Prelude---- | Encodes whether a unit is a metric unit, that is, whether it can be combined--- with a metric prefix to form a related unit.-data Metricality = Metric    -- ^ Capable of receiving a metric prefix.-                 | NonMetric -- ^ Incapable of receiving a metric prefix.-  deriving (Eq, Ord, Data, Typeable, Generic)--instance NFData Metricality where -- instance is derived from Generic instance--{--The variety 'v' of 'Dimensional'--The phantom type variable v is used to distinguish between units-and quantities. It must be one of the following:--}---- | The kind of variants of dimensional values.-data Variant = DQuantity E.ExactPi' -- ^ The value is a quantity, stored as an `ExactPi` multiple of its value in its dimension's SI coherent unit.-             | DUnit Metricality  -- ^ The value is a unit, possibly a 'Metric' unit.-  deriving (Typeable, Generic)--{--We will reuse the operators and function names from the Prelude.-To prevent unpleasant surprises we give operators the same fixity-as the Prelude.--}--infixl 7  *---- | Forms the product of two 'Variant's.------ The product of units is a non-metric unit.------ The product of quantities is a quantity.-type family (v1 :: Variant) * (v2 :: Variant) :: Variant where-  'DUnit m1 * 'DUnit m2 = 'DUnit 'NonMetric-  'DQuantity s1 * 'DQuantity s2 = 'DQuantity (s1 E.* s2)--type family (v1 :: Variant) / (v2 :: Variant) :: Variant where-  'DUnit m1 / 'DUnit m2 = 'DUnit 'NonMetric-  'DQuantity s1 / 'DQuantity s2 = 'DQuantity (s1 E./ s2)---- | Weakens a 'Variant' by forgetting possibly uninteresting type-level information.-type family Weaken (v :: Variant) :: Variant where-  Weaken ('DQuantity s) = 'DQuantity s-  Weaken ('DUnit m) = 'DUnit 'NonMetric---- | Two 'Variant's are compatible when dimensional values of the first may be converted--- into the second merely by changing the representation of their values.-type family AreCompatible (v1 :: Variant) (v2 :: Variant) :: Bool where-  AreCompatible ('DQuantity s1)  ('DQuantity s2) = 'True-  AreCompatible ('DUnit m) ('DUnit 'NonMetric)   = 'True-  AreCompatible s s   = 'True-  AreCompatible s1 s2 = 'False---- | Two 'Variant's are compatible when dimensional values of the first may be converted--- into the second merely by changing the representation of their values.-type CompatibleVariants v1 v2 = ('True ~ AreCompatible v1 v2)+{-# OPTIONS_HADDOCK not-home, show-extensions #-}
+
+{-# LANGUAGE AutoDeriveTypeable #-}
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+
+{- |
+   Copyright  : Copyright (C) 2006-2018 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+Provides a type level representation of 'Variant's of dimensional values,
+which may be quantities or units.
+-}
+module Numeric.Units.Dimensional.Variants
+(
+  type Variant(..),
+  Metricality(..),
+  type (*), type (/), type Weaken,
+  type CompatibleVariants
+)
+where
+
+import Control.DeepSeq
+import Data.Data
+import qualified Data.ExactPi.TypeLevel as E
+import GHC.Generics
+import Prelude
+
+-- | Encodes whether a unit is a metric unit, that is, whether it can be combined
+-- with a metric prefix to form a related unit.
+data Metricality = Metric    -- ^ Capable of receiving a metric prefix.
+                 | NonMetric -- ^ Incapable of receiving a metric prefix.
+  deriving (Eq, Ord, Data, Typeable, Generic)
+
+instance NFData Metricality where -- instance is derived from Generic instance
+
+{-
+The variety 'v' of 'Dimensional'
+
+The phantom type variable v is used to distinguish between units
+and quantities. It must be one of the following:
+-}
+
+-- | The kind of variants of dimensional values.
+data Variant = DQuantity E.ExactPi' -- ^ The value is a quantity, stored as an `ExactPi` multiple of its value in its dimension's SI coherent unit.
+             | DUnit Metricality  -- ^ The value is a unit, possibly a 'Metric' unit.
+  deriving (Typeable, Generic)
+
+{-
+We will reuse the operators and function names from the Prelude.
+To prevent unpleasant surprises we give operators the same fixity
+as the Prelude.
+-}
+
+infixl 7  *
+
+-- | Forms the product of two 'Variant's.
+--
+-- The product of units is a non-metric unit.
+--
+-- The product of quantities is a quantity.
+type family (v1 :: Variant) * (v2 :: Variant) :: Variant where
+  'DUnit m1 * 'DUnit m2 = 'DUnit 'NonMetric
+  'DQuantity s1 * 'DQuantity s2 = 'DQuantity (s1 E.* s2)
+
+type family (v1 :: Variant) / (v2 :: Variant) :: Variant where
+  'DUnit m1 / 'DUnit m2 = 'DUnit 'NonMetric
+  'DQuantity s1 / 'DQuantity s2 = 'DQuantity (s1 E./ s2)
+
+-- | Weakens a 'Variant' by forgetting possibly uninteresting type-level information.
+type family Weaken (v :: Variant) :: Variant where
+  Weaken ('DQuantity s) = 'DQuantity s
+  Weaken ('DUnit m) = 'DUnit 'NonMetric
+
+-- | Two 'Variant's are compatible when dimensional values of the first may be converted
+-- into the second merely by changing the representation of their values.
+type family AreCompatible (v1 :: Variant) (v2 :: Variant) :: Bool where
+  AreCompatible ('DQuantity s1)  ('DQuantity s2) = 'True
+  AreCompatible ('DUnit m) ('DUnit 'NonMetric)   = 'True
+  AreCompatible s s   = 'True
+  AreCompatible s1 s2 = 'False
+
+-- | Two 'Variant's are compatible when dimensional values of the first may be converted
+-- into the second merely by changing the representation of their values.
+type CompatibleVariants v1 v2 = ('True ~ AreCompatible v1 v2)
tests/DocTests.hs view
@@ -1,10 +1,17 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE TypeSynonymInstances #-}--module Main (main) where--import System.FilePath.Glob (glob)-import Test.DocTest (doctest)--main :: IO ()-main = glob "src/**/*.hs" >>= doctest+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TypeSynonymInstances #-}
+
+module Main (main) where
+
+import System.FilePath.Glob (glob)
+import Test.DocTest (doctest)
+
+#if MIN_VERSION_base(4,12,0)
+doctestFlags = ["-XNoStarIsType"]
+#else
+doctestFlags = []
+#endif
+
+main :: IO ()
+main = glob "src/**/*.hs" >>= (doctest . (doctestFlags++))
tests/Numeric/Units/Dimensional/DynamicSpec.hs view
@@ -1,157 +1,157 @@-module Numeric.Units.Dimensional.DynamicSpec where--import Numeric.Units.Dimensional.Prelude-import Numeric.Units.Dimensional.Dynamic hiding ((*),(/),(^),(*~),(/~), recip)-import Numeric.Units.Dimensional.Dimensions.TermLevel (hasSomeDimension)-import qualified Numeric.Units.Dimensional.Dynamic as Dyn-import qualified Prelude as P-import Test.Hspec-import Test.QuickCheck--spec :: Spec-spec = do-         describe "Dynamic quantity promotion and demotion" $ do-           it "round-trips through AnyQuantity" $ property $-             \x -> let x' = x *~ kilo newton-                       x'' = demoteQuantity x' :: AnyQuantity Double-                    in Just x' == promoteQuantity x''-           it "round-trips through DynQuantity" $ property $-             \x -> let x' = x *~ micro watt-                       x'' = demoteQuantity x' :: DynQuantity Rational-                    in Just x' == promoteQuantity x''-           it "round-trips through AnyQuantity then DynQuantity" $ property $-             \x -> let x' = x *~ gram-                       x'' = demoteQuantity x' :: AnyQuantity Double-                       x''' = demoteQuantity x'' :: DynQuantity Double-                    in Just x' == promoteQuantity x'''-           it "doesn't promote invalid quantities" $ do-             (promoteQuantity invalidQuantity :: Maybe (Length Double)) `shouldBe` Nothing-           it "doesn't promote AnyQuantity to the wrong dimension" $ do-             let x = 12.3 *~ meter-                 x' = demoteQuantity x :: AnyQuantity Double-             (promoteQuantity x' :: Maybe (Mass Double)) `shouldBe` Nothing-           it "doesn't promote DynQuantity to the wrong dimension" $ do-             let x = 12.3 *~ mole-                 x' = demoteQuantity x :: DynQuantity Double-             (promoteQuantity x' :: Maybe (Time Double)) `shouldBe` Nothing-           it "properly combines with dynamic units" $ do-             let meter' = demoteUnit' meter-             (promoteQuantity (139.4 Dyn.*~ meter' :: AnyQuantity Double)) `shouldBe` Just (139.4 *~ meter)-           it "properly eliminates dynamic units" $ do-             let ampere' = demoteUnit' ampere-                 i = demoteQuantity $ 47 *~ ampere :: AnyQuantity Double-             i Dyn./~ ampere' `shouldBe` Just 47-           it "doesn't eliminate dynamic units of the wrong dimension" $ do-             let ampere' = demoteUnit' ampere-                 i = demoteQuantity $ 47 *~ joule :: AnyQuantity Double-             i Dyn./~ ampere' `shouldBe` Nothing-         describe "DynQuantity arithmetic" $ do-           -- declare some static quantities and their dynamic counterparts for arithmetic tests-           let x1 = 12.3 *~ meter-               x2 = (-7.9) *~ meter-               a = 93 *~ square (kilo meter)-               m = 147 *~ kilo gram-               t = 14.9 *~ second-               f = 87.2 *~ milli newton-               phi = 1.61803398875 *~ one-               x1' = demoteQuantity x1 :: DynQuantity Double-               x2' = demoteQuantity x2 :: DynQuantity Double-               a' = demoteQuantity a :: DynQuantity Double-               m' = demoteQuantity m :: DynQuantity Double-               t' = demoteQuantity t :: DynQuantity Double-               f' = demoteQuantity f :: DynQuantity Double-               phi' = demoteQuantity phi :: DynQuantity Double-           context "Num instance" $ do-             it "matches static addition" $ do-               (x1' P.+ x2') `shouldBe` demoteQuantity (x1 + x2)-             it "allows addition with polydimensional zero" $ do-               (t' P.+ polydimensionalZero) `shouldBe` t'-               (polydimensionalZero P.+ t') `shouldBe` t'-               (polydimensionalZero P.+ polydimensionalZero) `shouldBe` (polydimensionalZero :: DynQuantity Double)               -             it "propagates witnesses to zero during addition" $ do-               -- We want to test that the witness for polymorphic zero was actually added to the other addend.-               -- The reason for this property is that if the other addend is some element of the underlying type-               -- which can't act as a divisor (such as a propagating nAn), then we want that information to still-               -- be around when we go to promote the result.-               let nan = 0 P./ 0 :: Double-                   x = demoteQuantity $ nan *~ meter-                   Just y = promoteQuantity (polydimensionalZero P.+ x) :: Maybe (Length Double)-               (y /~ meter) `shouldSatisfy` P.isNaN-             it "matches static subtraction" $ do-               (x2' P.- x1') `shouldBe` demoteQuantity (x2 - x1)-             it "allows subtraction with polydimensional zero" $ do-               (m' P.- polydimensionalZero) `shouldBe` m'-               (polydimensionalZero P.- m') `shouldBe` (P.negate m')-               (polydimensionalZero P.- polydimensionalZero) `shouldBe` (polydimensionalZero :: DynQuantity Double)               -             it "matches static multiplication" $ do-               promoteQuantity (x1' P.* f') `shouldBe` Just (x1 * f)-             it "allows multiplication with polydimensional zero" $ do-               (f' P.* polydimensionalZero) `shouldBe` polydimensionalZero-               (polydimensionalZero P.* m') `shouldBe` polydimensionalZero-               (polydimensionalZero P.* polydimensionalZero) `shouldBe` (polydimensionalZero :: DynQuantity Double)-             it "matches static negation" $ do-               (P.negate m') `shouldBe` demoteQuantity (negate m)-             it "negates polydimensional zero" $ do-               (P.negate polydimensionalZero) `shouldBe` (polydimensionalZero :: DynQuantity Double)-             it "matches static absolute value" $ do-               (P.abs x2') `shouldBe` demoteQuantity (abs x2)-             it "takes absolute value of polydimensional zero" $ do-               (P.abs polydimensionalZero) `shouldBe` (polydimensionalZero :: DynQuantity Double)-             it "matches static signum" $ do-               (P.signum x1') `shouldBe` demoteQuantity (signum x1)-               (P.signum x2') `shouldBe` demoteQuantity (signum x2)-             it "takes signum of polydimensional zero" $ do-               (P.signum polydimensionalZero) `shouldBe` demoteQuantity (_0 :: Dimensionless Double)-             it "implements fromInteger with dimensionless result" $ do-               (P.fromInteger 7 :: DynQuantity Double) `shouldBe` demoteQuantity _7-           context "Fractional instance" $ do-             it "matches static division" $ do-               ((f' P.* x1') P./ t') `shouldBe` demoteQuantity ((f * x1) / t)-             it "matches static reciprocal" $ do-               (P.recip m') `shouldBe` demoteQuantity (recip m)-             it "implements fromRational with dimensionless result" $ do-               let pi' = 22 P./ 7 :: Rational-               (P.fromRational pi' :: DynQuantity Rational) `shouldBe` demoteQuantity (pi' *~ one)-             it "permits polydimensional zero as a dividend" $ do-               (polydimensionalZero P./ m') `shouldBe` polydimensionalZero-             it "propagates witnesses to zero during division" $ do-               -- We want to test that the witness for polymorphic zero was actually divided by the divisor.-               -- The reason for this property is that if the divisor is itself zero (but not polydimensionalZero),-               -- or some other element of the underlying type which can't act as a divisor (such as a propagating nAn),-               -- then we want that information to still be around when we go to promote the result.-               let nan = 0 P./ 0 :: Double-                   x = demoteQuantity $ nan *~ meter-                   y = polydimensionalZero P./ x-                   Just y' = promoteQuantity y :: Maybe (Length Double)-               (y' /~ meter) `shouldSatisfy` P.isNaN-           context "Floating instance" $ do-             it "implements dimensionless pi" $ do-               (P.pi :: DynQuantity Double) `shouldBe` demoteQuantity pi-             it "implements dimensionless sin" $ do-               -- this will serve as a test for all the single-argument dimensionless functions-               (P.sin phi') `shouldBe` demoteQuantity (sin phi)-             it "rejects non-dimensionless arguments to sin" $ do-               (P.sin m') `shouldBe` invalidQuantity-             it "implements dimensionless sin of polydimensional zero" $ do-               (P.sin polydimensionalZero) `shouldBe` (0 :: DynQuantity Double)-             it "matches static square root" $ do-               (P.sqrt a') `shouldBe` demoteQuantity (sqrt a)-             it "rejects arguments to square root with non-square dimensions" $ do-               (P.sqrt f') `shouldNotSatisfy` hasSomeDimension-             it "takes the square root of polydimensional zero" $ do-               (P.sqrt polydimensionalZero) `shouldBe` (polydimensionalZero :: DynQuantity Double)-             it "matches static dimensionless exponentiation" $ do-               (phi' P.** phi') `shouldBe` demoteQuantity (phi ** phi)-             it "rejects non-dimensionless arguments to dimensionless exponentiation" $ do-               (phi' P.** m') `shouldNotSatisfy` hasSomeDimension-               (x1' P.** phi') `shouldNotSatisfy` hasSomeDimension-             it "matches static logBase" $ do-               (P.logBase 10 phi') `shouldBe` demoteQuantity (logBase (10 *~ one) phi)-             it "rejects non-dimensionless arguments to logBase" $ do-               (P.logBase 10 x1') `shouldNotSatisfy` hasSomeDimension-               (P.logBase x1' 10) `shouldNotSatisfy` hasSomeDimension-         describe "Dynamic units" $ do-           describe "Promotion and demotion" $ do-             return ()-           describe "Arithmetic" $ do-             return ()+module Numeric.Units.Dimensional.DynamicSpec where
+
+import Numeric.Units.Dimensional.Prelude
+import Numeric.Units.Dimensional.Dynamic hiding ((*),(/),(^),(*~),(/~), recip)
+import Numeric.Units.Dimensional.Dimensions.TermLevel (hasSomeDimension)
+import qualified Numeric.Units.Dimensional.Dynamic as Dyn
+import qualified Prelude as P
+import Test.Hspec
+import Test.QuickCheck
+
+spec :: Spec
+spec = do
+         describe "Dynamic quantity promotion and demotion" $ do
+           it "round-trips through AnyQuantity" $ property $
+             \x -> let x' = x *~ kilo newton
+                       x'' = demoteQuantity x' :: AnyQuantity Double
+                    in Just x' == promoteQuantity x''
+           it "round-trips through DynQuantity" $ property $
+             \x -> let x' = x *~ micro watt
+                       x'' = demoteQuantity x' :: DynQuantity Rational
+                    in Just x' == promoteQuantity x''
+           it "round-trips through AnyQuantity then DynQuantity" $ property $
+             \x -> let x' = x *~ gram
+                       x'' = demoteQuantity x' :: AnyQuantity Double
+                       x''' = demoteQuantity x'' :: DynQuantity Double
+                    in Just x' == promoteQuantity x'''
+           it "doesn't promote invalid quantities" $ do
+             (promoteQuantity invalidQuantity :: Maybe (Length Double)) `shouldBe` Nothing
+           it "doesn't promote AnyQuantity to the wrong dimension" $ do
+             let x = 12.3 *~ meter
+                 x' = demoteQuantity x :: AnyQuantity Double
+             (promoteQuantity x' :: Maybe (Mass Double)) `shouldBe` Nothing
+           it "doesn't promote DynQuantity to the wrong dimension" $ do
+             let x = 12.3 *~ mole
+                 x' = demoteQuantity x :: DynQuantity Double
+             (promoteQuantity x' :: Maybe (Time Double)) `shouldBe` Nothing
+           it "properly combines with dynamic units" $ do
+             let meter' = demoteUnit' meter
+             (promoteQuantity (139.4 Dyn.*~ meter' :: AnyQuantity Double)) `shouldBe` Just (139.4 *~ meter)
+           it "properly eliminates dynamic units" $ do
+             let ampere' = demoteUnit' ampere
+                 i = demoteQuantity $ 47 *~ ampere :: AnyQuantity Double
+             i Dyn./~ ampere' `shouldBe` Just 47
+           it "doesn't eliminate dynamic units of the wrong dimension" $ do
+             let ampere' = demoteUnit' ampere
+                 i = demoteQuantity $ 47 *~ joule :: AnyQuantity Double
+             i Dyn./~ ampere' `shouldBe` Nothing
+         describe "DynQuantity arithmetic" $ do
+           -- declare some static quantities and their dynamic counterparts for arithmetic tests
+           let x1 = 12.3 *~ meter
+               x2 = (-7.9) *~ meter
+               a = 93 *~ square (kilo meter)
+               m = 147 *~ kilo gram
+               t = 14.9 *~ second
+               f = 87.2 *~ milli newton
+               phi = 1.61803398875 *~ one
+               x1' = demoteQuantity x1 :: DynQuantity Double
+               x2' = demoteQuantity x2 :: DynQuantity Double
+               a' = demoteQuantity a :: DynQuantity Double
+               m' = demoteQuantity m :: DynQuantity Double
+               t' = demoteQuantity t :: DynQuantity Double
+               f' = demoteQuantity f :: DynQuantity Double
+               phi' = demoteQuantity phi :: DynQuantity Double
+           context "Num instance" $ do
+             it "matches static addition" $ do
+               (x1' P.+ x2') `shouldBe` demoteQuantity (x1 + x2)
+             it "allows addition with polydimensional zero" $ do
+               (t' P.+ polydimensionalZero) `shouldBe` t'
+               (polydimensionalZero P.+ t') `shouldBe` t'
+               (polydimensionalZero P.+ polydimensionalZero) `shouldBe` (polydimensionalZero :: DynQuantity Double)               
+             it "propagates witnesses to zero during addition" $ do
+               -- We want to test that the witness for polymorphic zero was actually added to the other addend.
+               -- The reason for this property is that if the other addend is some element of the underlying type
+               -- which can't act as a divisor (such as a propagating nAn), then we want that information to still
+               -- be around when we go to promote the result.
+               let nan = 0 P./ 0 :: Double
+                   x = demoteQuantity $ nan *~ meter
+                   Just y = promoteQuantity (polydimensionalZero P.+ x) :: Maybe (Length Double)
+               (y /~ meter) `shouldSatisfy` P.isNaN
+             it "matches static subtraction" $ do
+               (x2' P.- x1') `shouldBe` demoteQuantity (x2 - x1)
+             it "allows subtraction with polydimensional zero" $ do
+               (m' P.- polydimensionalZero) `shouldBe` m'
+               (polydimensionalZero P.- m') `shouldBe` (P.negate m')
+               (polydimensionalZero P.- polydimensionalZero) `shouldBe` (polydimensionalZero :: DynQuantity Double)               
+             it "matches static multiplication" $ do
+               promoteQuantity (x1' P.* f') `shouldBe` Just (x1 * f)
+             it "allows multiplication with polydimensional zero" $ do
+               (f' P.* polydimensionalZero) `shouldBe` polydimensionalZero
+               (polydimensionalZero P.* m') `shouldBe` polydimensionalZero
+               (polydimensionalZero P.* polydimensionalZero) `shouldBe` (polydimensionalZero :: DynQuantity Double)
+             it "matches static negation" $ do
+               (P.negate m') `shouldBe` demoteQuantity (negate m)
+             it "negates polydimensional zero" $ do
+               (P.negate polydimensionalZero) `shouldBe` (polydimensionalZero :: DynQuantity Double)
+             it "matches static absolute value" $ do
+               (P.abs x2') `shouldBe` demoteQuantity (abs x2)
+             it "takes absolute value of polydimensional zero" $ do
+               (P.abs polydimensionalZero) `shouldBe` (polydimensionalZero :: DynQuantity Double)
+             it "matches static signum" $ do
+               (P.signum x1') `shouldBe` demoteQuantity (signum x1)
+               (P.signum x2') `shouldBe` demoteQuantity (signum x2)
+             it "takes signum of polydimensional zero" $ do
+               (P.signum polydimensionalZero) `shouldBe` demoteQuantity (_0 :: Dimensionless Double)
+             it "implements fromInteger with dimensionless result" $ do
+               (P.fromInteger 7 :: DynQuantity Double) `shouldBe` demoteQuantity _7
+           context "Fractional instance" $ do
+             it "matches static division" $ do
+               ((f' P.* x1') P./ t') `shouldBe` demoteQuantity ((f * x1) / t)
+             it "matches static reciprocal" $ do
+               (P.recip m') `shouldBe` demoteQuantity (recip m)
+             it "implements fromRational with dimensionless result" $ do
+               let pi' = 22 P./ 7 :: Rational
+               (P.fromRational pi' :: DynQuantity Rational) `shouldBe` demoteQuantity (pi' *~ one)
+             it "permits polydimensional zero as a dividend" $ do
+               (polydimensionalZero P./ m') `shouldBe` polydimensionalZero
+             it "propagates witnesses to zero during division" $ do
+               -- We want to test that the witness for polymorphic zero was actually divided by the divisor.
+               -- The reason for this property is that if the divisor is itself zero (but not polydimensionalZero),
+               -- or some other element of the underlying type which can't act as a divisor (such as a propagating nAn),
+               -- then we want that information to still be around when we go to promote the result.
+               let nan = 0 P./ 0 :: Double
+                   x = demoteQuantity $ nan *~ meter
+                   y = polydimensionalZero P./ x
+                   Just y' = promoteQuantity y :: Maybe (Length Double)
+               (y' /~ meter) `shouldSatisfy` P.isNaN
+           context "Floating instance" $ do
+             it "implements dimensionless pi" $ do
+               (P.pi :: DynQuantity Double) `shouldBe` demoteQuantity pi
+             it "implements dimensionless sin" $ do
+               -- this will serve as a test for all the single-argument dimensionless functions
+               (P.sin phi') `shouldBe` demoteQuantity (sin phi)
+             it "rejects non-dimensionless arguments to sin" $ do
+               (P.sin m') `shouldBe` invalidQuantity
+             it "implements dimensionless sin of polydimensional zero" $ do
+               (P.sin polydimensionalZero) `shouldBe` (0 :: DynQuantity Double)
+             it "matches static square root" $ do
+               (P.sqrt a') `shouldBe` demoteQuantity (sqrt a)
+             it "rejects arguments to square root with non-square dimensions" $ do
+               (P.sqrt f') `shouldNotSatisfy` hasSomeDimension
+             it "takes the square root of polydimensional zero" $ do
+               (P.sqrt polydimensionalZero) `shouldBe` (polydimensionalZero :: DynQuantity Double)
+             it "matches static dimensionless exponentiation" $ do
+               (phi' P.** phi') `shouldBe` demoteQuantity (phi ** phi)
+             it "rejects non-dimensionless arguments to dimensionless exponentiation" $ do
+               (phi' P.** m') `shouldNotSatisfy` hasSomeDimension
+               (x1' P.** phi') `shouldNotSatisfy` hasSomeDimension
+             it "matches static logBase" $ do
+               (P.logBase 10 phi') `shouldBe` demoteQuantity (logBase (10 *~ one) phi)
+             it "rejects non-dimensionless arguments to logBase" $ do
+               (P.logBase 10 x1') `shouldNotSatisfy` hasSomeDimension
+               (P.logBase x1' 10) `shouldNotSatisfy` hasSomeDimension
+         describe "Dynamic units" $ do
+           describe "Promotion and demotion" $ do
+             return ()
+           describe "Arithmetic" $ do
+             return ()
tests/Numeric/Units/Dimensional/QuantitiesSpec.hs view
@@ -1,137 +1,137 @@-module Numeric.Units.Dimensional.QuantitiesSpec where--import Numeric.Units.Dimensional.Prelude-import Test.Hspec--spec :: Spec-spec = do-         describe "Quantity synonyms" $ do-           it "compile with correct dimensions" $ do-             success -- If I compiled I'm OK!--success :: IO ()-success = return ()---- These definitions simply verify that the type synonyms are--- consistent with the appropriate units from table 2. If the--- definitions compile the type synonyms are good.--x1 :: Area Double-x1 = 1 *~ meter ^ pos2-x2 :: Volume Double-x2 = 1 *~ meter ^ pos3-x3 :: Velocity Double-x3 = 1 *~ (meter / second)-x4 :: Acceleration Double-x4 = 1 *~ (meter / second ^ pos2)-x5 :: WaveNumber Double-x5 = 1 *~ meter ^ neg1-x6 :: Density Double-x6 = 1 *~ (kilo gram / meter ^ pos3)-x7 :: SpecificVolume Double-x7 = 1 *~ (meter ^ pos3 / kilo gram)-x8 :: CurrentDensity Double-x8 = 1 *~ (ampere / meter ^ pos2)-x9 :: MagneticFieldStrength Double-x9 = 1 *~ (ampere / meter)-x10 :: Concentration Double-x10 = 1 *~ (mole / meter ^ pos3)-x11 :: Luminance Double-x11 = 1 *~ (candela / meter ^ pos2)---- These definitions simply verify that the type synonyms are--- consistent with the appropriate units from table 3. If the--- definitions compile the type synonyms are good.--y1 :: PlaneAngle Double-y1 = 1 *~ (meter / meter)-y2 :: SolidAngle Double-y2 = 1 *~ (meter ^ pos2 / meter ^ pos2)-y3 :: Frequency Double-y3 = 1 *~ (one / second)-y4 :: Force Double-y4 = 1 *~ (meter * kilo gram / second ^ pos2)-y5 :: Pressure Double-y5 = 1 *~ (newton / meter ^ pos2)-y6 :: Energy Double-y6 = 1 *~ (newton * meter)-y7 :: Power Double-y7 = 1 *~ (joule / second)-y8 :: ElectricCharge Double-y8 = 1 *~ (second * ampere)-y9 :: ElectricPotential Double-y9 = 1 *~ (watt / ampere)-y10 :: Capacitance Double-y10 = 1 *~ (coulomb / volt)-y11 :: ElectricResistance Double-y11 = 1 *~ (volt / ampere)-y12 :: ElectricConductance Double-y12 = 1 *~ (ampere / volt)-y13 :: MagneticFlux Double-y13 = 1 *~ (volt * second)-y14 :: MagneticFluxDensity Double-y14 = 1 *~ (weber / meter ^ pos2)-y15 :: Inductance Double-y15 = 1 *~ (weber / ampere)-y16 :: LuminousFlux Double-y16 = 1 *~ (candela * steradian)-y17 :: Illuminance Double-y17 = 1 *~ (lumen / meter ^ pos2)-y18 :: Activity Double-y18 = 1 *~ (one / second)-y19 :: AbsorbedDose Double-y19 = 1 *~ (joule / kilo gram)-y20 :: DoseEquivalent Double-y20 = 1 *~ (joule / kilo gram)-y21 :: CatalyticActivity Double-y21 = 1 *~ (mole / second)---- Verification of table 4. If the definitions compile the type--- synonyms are good.--z1 :: AngularVelocity Double-z1 = 1 *~ (radian / second)-z2 :: AngularAcceleration Double-z2 = 1 *~ (radian / second ^ pos2)-z3 :: DynamicViscosity Double-z3 = 1 *~ (pascal * second)-z4 :: MomentOfForce Double-z4 = 1 *~ (newton * meter)-z5 :: SurfaceTension Double-z5 = 1 *~ (newton / meter)-z6 :: HeatFluxDensity Double-z6 = 1 *~ (watt / meter ^ pos2)-z7 :: RadiantIntensity Double-z7 = 1 *~ (watt / steradian)-z8 :: Radiance Double-z8 = 1 *~ (watt / (meter ^ pos2 * steradian))-z9 :: HeatCapacity Double-z9 = 1 *~ (joule / kelvin)-z10 :: SpecificHeatCapacity Double-z10 = 1 *~ (joule / (kilo gram * kelvin))-z11 :: ThermalConductivity Double-z11 = 1 *~ (watt / (meter * kelvin))-z12 :: EnergyDensity Double-z12 = 1 *~ (joule / meter ^ pos3)-z13 :: ElectricFieldStrength Double-z13 = 1 *~ (volt / meter)-z14 :: ElectricChargeDensity Double-z14 = 1 *~ (coulomb / meter ^ pos3)-z15 :: ElectricFluxDensity Double-z15 = 1 *~ (coulomb / meter ^ pos2)-z16 :: Permittivity Double-z16 = 1 *~ (farad / meter)-z17 :: Permeability Double-z17 = 1 *~ (henry / meter)-z18 :: MolarEnergy Double-z18 = 1 *~ (joule / mole)-z19 :: MolarEntropy Double-z19 = 1 *~ (joule / (mole * kelvin))-z20 :: Exposure Double-z20 = 1 *~ (coulomb / kilo gram)-z21 :: AbsorbedDoseRate Double-z21 = 1 *~ (gray / second)---- Other quantitites.-mu :: GravitationalParameter Double-mu = 398600.4418 *~ (kilo meter ^ pos3 / second ^ pos2)+module Numeric.Units.Dimensional.QuantitiesSpec where
+
+import Numeric.Units.Dimensional.Prelude
+import Test.Hspec
+
+spec :: Spec
+spec = do
+         describe "Quantity synonyms" $ do
+           it "compile with correct dimensions" $ do
+             success -- If I compiled I'm OK!
+
+success :: IO ()
+success = return ()
+
+-- These definitions simply verify that the type synonyms are
+-- consistent with the appropriate units from table 2. If the
+-- definitions compile the type synonyms are good.
+
+x1 :: Area Double
+x1 = 1 *~ meter ^ pos2
+x2 :: Volume Double
+x2 = 1 *~ meter ^ pos3
+x3 :: Velocity Double
+x3 = 1 *~ (meter / second)
+x4 :: Acceleration Double
+x4 = 1 *~ (meter / second ^ pos2)
+x5 :: WaveNumber Double
+x5 = 1 *~ meter ^ neg1
+x6 :: Density Double
+x6 = 1 *~ (kilo gram / meter ^ pos3)
+x7 :: SpecificVolume Double
+x7 = 1 *~ (meter ^ pos3 / kilo gram)
+x8 :: CurrentDensity Double
+x8 = 1 *~ (ampere / meter ^ pos2)
+x9 :: MagneticFieldStrength Double
+x9 = 1 *~ (ampere / meter)
+x10 :: Concentration Double
+x10 = 1 *~ (mole / meter ^ pos3)
+x11 :: Luminance Double
+x11 = 1 *~ (candela / meter ^ pos2)
+
+-- These definitions simply verify that the type synonyms are
+-- consistent with the appropriate units from table 3. If the
+-- definitions compile the type synonyms are good.
+
+y1 :: PlaneAngle Double
+y1 = 1 *~ (meter / meter)
+y2 :: SolidAngle Double
+y2 = 1 *~ (meter ^ pos2 / meter ^ pos2)
+y3 :: Frequency Double
+y3 = 1 *~ (one / second)
+y4 :: Force Double
+y4 = 1 *~ (meter * kilo gram / second ^ pos2)
+y5 :: Pressure Double
+y5 = 1 *~ (newton / meter ^ pos2)
+y6 :: Energy Double
+y6 = 1 *~ (newton * meter)
+y7 :: Power Double
+y7 = 1 *~ (joule / second)
+y8 :: ElectricCharge Double
+y8 = 1 *~ (second * ampere)
+y9 :: ElectricPotential Double
+y9 = 1 *~ (watt / ampere)
+y10 :: Capacitance Double
+y10 = 1 *~ (coulomb / volt)
+y11 :: ElectricResistance Double
+y11 = 1 *~ (volt / ampere)
+y12 :: ElectricConductance Double
+y12 = 1 *~ (ampere / volt)
+y13 :: MagneticFlux Double
+y13 = 1 *~ (volt * second)
+y14 :: MagneticFluxDensity Double
+y14 = 1 *~ (weber / meter ^ pos2)
+y15 :: Inductance Double
+y15 = 1 *~ (weber / ampere)
+y16 :: LuminousFlux Double
+y16 = 1 *~ (candela * steradian)
+y17 :: Illuminance Double
+y17 = 1 *~ (lumen / meter ^ pos2)
+y18 :: Activity Double
+y18 = 1 *~ (one / second)
+y19 :: AbsorbedDose Double
+y19 = 1 *~ (joule / kilo gram)
+y20 :: DoseEquivalent Double
+y20 = 1 *~ (joule / kilo gram)
+y21 :: CatalyticActivity Double
+y21 = 1 *~ (mole / second)
+
+-- Verification of table 4. If the definitions compile the type
+-- synonyms are good.
+
+z1 :: AngularVelocity Double
+z1 = 1 *~ (radian / second)
+z2 :: AngularAcceleration Double
+z2 = 1 *~ (radian / second ^ pos2)
+z3 :: DynamicViscosity Double
+z3 = 1 *~ (pascal * second)
+z4 :: MomentOfForce Double
+z4 = 1 *~ (newton * meter)
+z5 :: SurfaceTension Double
+z5 = 1 *~ (newton / meter)
+z6 :: HeatFluxDensity Double
+z6 = 1 *~ (watt / meter ^ pos2)
+z7 :: RadiantIntensity Double
+z7 = 1 *~ (watt / steradian)
+z8 :: Radiance Double
+z8 = 1 *~ (watt / (meter ^ pos2 * steradian))
+z9 :: HeatCapacity Double
+z9 = 1 *~ (joule / kelvin)
+z10 :: SpecificHeatCapacity Double
+z10 = 1 *~ (joule / (kilo gram * kelvin))
+z11 :: ThermalConductivity Double
+z11 = 1 *~ (watt / (meter * kelvin))
+z12 :: EnergyDensity Double
+z12 = 1 *~ (joule / meter ^ pos3)
+z13 :: ElectricFieldStrength Double
+z13 = 1 *~ (volt / meter)
+z14 :: ElectricChargeDensity Double
+z14 = 1 *~ (coulomb / meter ^ pos3)
+z15 :: ElectricFluxDensity Double
+z15 = 1 *~ (coulomb / meter ^ pos2)
+z16 :: Permittivity Double
+z16 = 1 *~ (farad / meter)
+z17 :: Permeability Double
+z17 = 1 *~ (henry / meter)
+z18 :: MolarEnergy Double
+z18 = 1 *~ (joule / mole)
+z19 :: MolarEntropy Double
+z19 = 1 *~ (joule / (mole * kelvin))
+z20 :: Exposure Double
+z20 = 1 *~ (coulomb / kilo gram)
+z21 :: AbsorbedDoseRate Double
+z21 = 1 *~ (gray / second)
+
+-- Other quantitites.
+mu :: GravitationalParameter Double
+mu = 398600.4418 *~ (kilo meter ^ pos3 / second ^ pos2)
tests/Numeric/Units/DimensionalSpec.hs view
@@ -1,48 +1,48 @@-module Numeric.Units.DimensionalSpec where--import Numeric.Units.Dimensional.Prelude-import Test.Hspec-import qualified Prelude as P--spec :: Spec-spec = do-         describe "Exponentiation operators" $ do-           it "correctly exponentiate quantities with integer exponents" $ do-             ((9::Double) *~ one) `shouldBe` (3 *~ one) ^ pos2-             ((1::Double) *~ one) `shouldBe` (12.1231 *~ one) ^ zero-             ((0.25::Double) *~ one) `shouldBe` (2 *~ one) ^ neg2-           it "correctly exponentiate dimensionless quantities with floating point exponents" $ do-             (3 P.** 2::Double) *~ one `shouldBe` (3 *~ one) ** (2 *~ one)-             (3 P.** (-2.231)::Double) *~ one `shouldBe` (3 *~ one) ** ((-2.231) *~ one)--         describe "Show instance" $ do-           it "properly prints basic quantities" $ do-             show ((1.0::Double) *~ one) `shouldBe` "1.0"-             show ((2.0::Double) *~ meter) `shouldBe` "2.0 m"-             show ((2.0::Double) *~ (meter / second)) `shouldBe` "2.0 m s^-1"-             show ((2.0::Double) *~ (meter ^ pos2 / second ^ pos2)) `shouldBe` "2.0 m^2 s^-2"--         describe "Ord instance" $ do-           it "properly sorts quantities" $ do-             compare ((1 :: Integer) *~ one) (3 *~ one) `shouldBe` LT-             compare ((1 :: Double) *~ (kilo meter)) (1 *~ meter) `shouldBe` GT-             compare ((0 :: Double) *~ second) (_0) `shouldBe` EQ--         describe "Enumeration function nFromTo" $ do-           it "handles zero intermediate values" $ do-             nFromTo' _1 _6 0 `shouldBe` [_1, _6]-           it "handles negative number of intermediate values" $ do-             nFromTo' _1 _6 (-1) `shouldBe` [_1, _6]-           it "handles straightforward cases" $ do-             nFromTo' _1 _3 1 `shouldBe` [_1, _2, _3]-             nFromTo' _1 _6 4 `shouldBe` [_1, _2, _3, _4, _5, _6]-             nFromTo' _0 _6 2 `shouldBe` [_0, _2, _4, _6]-           it "handles decreasing intervals" $ do-             nFromTo' _5 _2 2 `shouldBe` [_5, _4, _3, _2]-             nFromTo' _6 _0 2 `shouldBe` [_6, _4, _2, _0]-           it "handles empty intervals" $ do-             nFromTo' _1 _1 0 `shouldBe` [_1, _1]-             nFromTo' _0 _0 2 `shouldBe` [_0, _0, _0, _0]--nFromTo' :: Dimensionless Double -> Dimensionless Double -> Int -> [Dimensionless Double]-nFromTo' = nFromTo+module Numeric.Units.DimensionalSpec where
+
+import Numeric.Units.Dimensional.Prelude
+import Test.Hspec
+import qualified Prelude as P
+
+spec :: Spec
+spec = do
+         describe "Exponentiation operators" $ do
+           it "correctly exponentiate quantities with integer exponents" $ do
+             ((9::Double) *~ one) `shouldBe` (3 *~ one) ^ pos2
+             ((1::Double) *~ one) `shouldBe` (12.1231 *~ one) ^ zero
+             ((0.25::Double) *~ one) `shouldBe` (2 *~ one) ^ neg2
+           it "correctly exponentiate dimensionless quantities with floating point exponents" $ do
+             (3 P.** 2::Double) *~ one `shouldBe` (3 *~ one) ** (2 *~ one)
+             (3 P.** (-2.231)::Double) *~ one `shouldBe` (3 *~ one) ** ((-2.231) *~ one)
+
+         describe "Show instance" $ do
+           it "properly prints basic quantities" $ do
+             show ((1.0::Double) *~ one) `shouldBe` "1.0"
+             show ((2.0::Double) *~ meter) `shouldBe` "2.0 m"
+             show ((2.0::Double) *~ (meter / second)) `shouldBe` "2.0 m s^-1"
+             show ((2.0::Double) *~ (meter ^ pos2 / second ^ pos2)) `shouldBe` "2.0 m^2 s^-2"
+
+         describe "Ord instance" $ do
+           it "properly sorts quantities" $ do
+             compare ((1 :: Integer) *~ one) (3 *~ one) `shouldBe` LT
+             compare ((1 :: Double) *~ (kilo meter)) (1 *~ meter) `shouldBe` GT
+             compare ((0 :: Double) *~ second) (_0) `shouldBe` EQ
+
+         describe "Enumeration function nFromTo" $ do
+           it "handles zero intermediate values" $ do
+             nFromTo' _1 _6 0 `shouldBe` [_1, _6]
+           it "handles negative number of intermediate values" $ do
+             nFromTo' _1 _6 (-1) `shouldBe` [_1, _6]
+           it "handles straightforward cases" $ do
+             nFromTo' _1 _3 1 `shouldBe` [_1, _2, _3]
+             nFromTo' _1 _6 4 `shouldBe` [_1, _2, _3, _4, _5, _6]
+             nFromTo' _0 _6 2 `shouldBe` [_0, _2, _4, _6]
+           it "handles decreasing intervals" $ do
+             nFromTo' _5 _2 2 `shouldBe` [_5, _4, _3, _2]
+             nFromTo' _6 _0 2 `shouldBe` [_6, _4, _2, _0]
+           it "handles empty intervals" $ do
+             nFromTo' _1 _1 0 `shouldBe` [_1, _1]
+             nFromTo' _0 _0 2 `shouldBe` [_0, _0, _0, _0]
+
+nFromTo' :: Dimensionless Double -> Dimensionless Double -> Int -> [Dimensionless Double]
+nFromTo' = nFromTo
tests/Spec.hs view
@@ -1,4 +1,4 @@-{-# OPTIONS_GHC -F -pgmF hspec-discover #-}---- This module will automatically pull in all the Spec modules.--- See http://hspec.github.io/hspec-discover.html for a summary of how it works.+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
+
+-- This module will automatically pull in all the Spec modules.
+-- See http://hspec.github.io/hspec-discover.html for a summary of how it works.