--------------------------------------------------------------------------------

-- |

--

-- Module      :  Data.Units.Base.Arithmetic

-- Description :  Addition, multiplication and exponentiation of quantities

-- Copyright   :  (c) Alice Rixte 2025

-- License     :  BSD 3

-- Maintainer  :  alice.rixte@u-bordeaux.fr

-- Stability   :  unstable

-- Portability :  non-portable (GHC extensions)

--

-- Addition, multiplication and exponentiation of quantities. Dimension analysis is done statically via the type system.

--

-- == Addition and multiplication of a quantity by a scalar

--

-- To add, multiply, divide, and so on, a quantity with a scalar , use its @'Fractional'@ instance :

--

-- >>> a = Milli (Second 5)

-- >>> 3 * a

-- quantity @(Milli Second) 15

--

-- [Warning] These instances are provided because they are convenient, but be careful !  This means that you can write:

--

-- >>> Second 2 * Second 3

-- Second 6

--

-- which does not respect dimension analysis: the multiplication of two time

-- quantities should be of dimension @T²@ and here it has dimension @T@.

--

-- Some of the operators proposed here solve this problem:

--

-- >>> Second 2 .*~ Second 3

-- quantity @(Second .^+ 2) 6

--

--------------------------------------------------------------------------------


module Data.Units.Base.Arithmetic
  (
  -- ** Addition

    (.+~)
  , (~+.)
  , (~+~)
  -- ** Subtraction

  , (.-~)
  , (~-.)
  , (~-~)
  -- ** Multiplication

  , (.*.)
  , (.*~)
  , (~*.)
  , (~*~)
  -- ** Division

  , (./.)
  , (./~)
  , (~/.)
  , (~/~)
  -- ** Exponentiation

  , (.^.)
  , (~^.)
  , (.^~)
  , (~^~)
  ) where

import Data.Type.Int

import Data.Units.Base.System
import Data.Units.Base.Convert

----------------------------------- Addition -----------------------------------


-- | Add two quantities of same dimension. The unit of the right operand is

-- converted to the unit of the left operand

--

-- >>> Kilo (Meter 5) .+~ Meter 80

-- quantity @(Kilo Meter) 5.08

--

-- >>> Meter 2 .+~ Second 3

--  • Cannot convert unit ‘s’ of dimension ‘T’

--    to unit ‘m’ of dimension ‘L’.

--

(.+~) :: forall u v a. FromTo' v u a => u a -> v a -> u a
u a
u .+~ :: forall (u :: Unit) (v :: Unit) a.
FromTo' v u a =>
u a -> v a -> u a
.+~ v a
v = a -> u a
forall (u :: Unit) a. IsUnit u => a -> u a
quantity (u a -> a
forall (u :: Unit) a. IsUnit u => u a -> a
unQuantity u a
u a -> a -> a
forall a. Num a => a -> a -> a
+ u a -> a
forall (u :: Unit) a. IsUnit u => u a -> a
unQuantity (v a -> u a
forall (u :: Unit) (v :: Unit) a. FromTo' u v a => u a -> v a
fromTo' v a
v :: u a))
{-# INLINE (.+~) #-}

infixr 5 .+~

-- | Same as @'(.+~)'@ but it is the left operand that is converted.

--

-- >>> Kilo (Meter 5) ~+. Meter 80

-- quantity @(Kilo Meter) 5080.0

--

(~+.) :: FromTo' u v a => u a -> v a -> v a
~+. :: forall (u :: Unit) (v :: Unit) a.
FromTo' u v a =>
u a -> v a -> v a
(~+.) = (v a -> u a -> v a) -> u a -> v a -> v a
forall a b c. (a -> b -> c) -> b -> a -> c
flip v a -> u a -> v a
forall (u :: Unit) (v :: Unit) a.
FromTo' v u a =>
u a -> v a -> u a
(.+~)
{-# INLINE (~+.) #-}

infixr 5 ~+.

-- | Add two quantities of same dimension and convert to the standard unit.

--

-- >>> Kilo (Meter 1) ~+~ Milli (Meter 150)

-- Meter 1000.15

--

(~+~) ::
  ( DimEq u v
  , ConversionFactor u a, ConversionFactor v a
  )
 => u a -> v a -> (BaseUnitOf u) a
u a
u ~+~ :: forall (u :: Unit) (v :: Unit) a.
(DimEq u v, ConversionFactor u a, ConversionFactor v a) =>
u a -> v a -> BaseUnitOf u a
~+~ v a
v = a -> DimToUnit (DimOf v) a
forall (u :: Unit) a. IsUnit u => a -> u a
quantity (DimToUnit (DimOf v) a -> a
forall (u :: Unit) a. IsUnit u => u a -> a
unQuantity (u a -> DimToUnit (DimOf u) a
forall (u :: Unit) a. ConversionFactor u a => u a -> BaseUnitOf u a
toBaseUnit' u a
u) a -> a -> a
forall a. Num a => a -> a -> a
+ DimToUnit (DimOf v) a -> a
forall (u :: Unit) a. IsUnit u => u a -> a
unQuantity (v a -> DimToUnit (DimOf v) a
forall (u :: Unit) a. ConversionFactor u a => u a -> BaseUnitOf u a
toBaseUnit' v a
v))
{-# INLINE (~+~) #-}

infixr 5 ~+~

--------------------------------- Subtraction ----------------------------------


-- | Subtract two quantities of same dimension. The unit of the right operand is converted to the unit of the left operand

--

-- >>> Kilo (Meter 5) .-~ Meter 80

-- quantity @(Kilo Meter) 4.92

--

(.-~) :: forall u v a. FromTo' v u a => u a -> v a -> u a
u a
u .-~ :: forall (u :: Unit) (v :: Unit) a.
FromTo' v u a =>
u a -> v a -> u a
.-~ v a
v = a -> u a
forall (u :: Unit) a. IsUnit u => a -> u a
quantity (u a -> a
forall (u :: Unit) a. IsUnit u => u a -> a
unQuantity u a
u a -> a -> a
forall a. Num a => a -> a -> a
- u a -> a
forall (u :: Unit) a. IsUnit u => u a -> a
unQuantity (v a -> u a
forall (u :: Unit) (v :: Unit) a. FromTo' u v a => u a -> v a
fromTo' v a
v :: u a))
{-# INLINE (.-~) #-}

infixr 5 .-~

-- | Same as @'(.-~)'@ but it is the left operand that is converted.

--

-- >>> Kilo (Meter 5) ~-. Meter 80

-- Meter 4920.0

--

(~-.) :: forall u v a. FromTo' u v a => u a -> v a -> v a
u a
u ~-. :: forall (u :: Unit) (v :: Unit) a.
FromTo' u v a =>
u a -> v a -> v a
~-. v a
v = a -> v a
forall (u :: Unit) a. IsUnit u => a -> u a
quantity (v a -> a
forall (u :: Unit) a. IsUnit u => u a -> a
unQuantity (u a -> v a
forall (u :: Unit) (v :: Unit) a. FromTo' u v a => u a -> v a
fromTo' u a
u :: v a) a -> a -> a
forall a. Num a => a -> a -> a
- v a -> a
forall (u :: Unit) a. IsUnit u => u a -> a
unQuantity v a
v)
-- {-# INLINE (~-.) #-}


infixr 5 ~-.

-- | Subtract two quantities of same dimension and convert to the standard unit.

--

-- >>> Kilo (Meter 1) ~-~ Milli (Meter 150)

-- Meter 999.85

--

(~-~) ::
  ( DimEq u v
  , ConversionFactor v a, ConversionFactor u a
  )
 => u a -> v a -> (BaseUnitOf u) a
u a
u ~-~ :: forall (u :: Unit) (v :: Unit) a.
(DimEq u v, ConversionFactor v a, ConversionFactor u a) =>
u a -> v a -> BaseUnitOf u a
~-~ v a
v = a -> DimToUnit (DimOf u) a
forall (u :: Unit) a. IsUnit u => a -> u a
quantity (a -> DimToUnit (DimOf u) a) -> a -> DimToUnit (DimOf u) a
forall a b. (a -> b) -> a -> b
$ DimToUnit (DimOf v) a -> a
forall (u :: Unit) a. IsUnit u => u a -> a
unQuantity (u a -> DimToUnit (DimOf u) a
forall (u :: Unit) a. ConversionFactor u a => u a -> BaseUnitOf u a
toBaseUnit' u a
u) a -> a -> a
forall a. Num a => a -> a -> a
- DimToUnit (DimOf v) a -> a
forall (u :: Unit) a. IsUnit u => u a -> a
unQuantity (v a -> DimToUnit (DimOf v) a
forall (u :: Unit) a. ConversionFactor u a => u a -> BaseUnitOf u a
toBaseUnit' v a
v)
{-# INLINE (~-~) #-}

infixr 5 ~-~

-------------------------------- Multiplication --------------------------------




-- | Multiply two quantities.

--

-- Usage is not recommended, as this will result non standard units.

--

-- For instance:

--

-- >>> Kilo (Meter 2) .*. Milli (Meter 4)

-- quantity @(Kilo Meter .*. Milli Meter) 8

--

(.*.) ::
  ( IsUnit u, IsUnit v
  , Num a
  )
 => u a -> v a -> (u .*. v) a
u a
u .*. :: forall (u :: Unit) (v :: Unit) a.
(IsUnit u, IsUnit v, Num a) =>
u a -> v a -> (.*.) u v a
.*. v a
v = a -> (.*.) u v a
forall (u :: Unit) a. IsUnit u => a -> u a
quantity (a -> (.*.) u v a) -> a -> (.*.) u v a
forall a b. (a -> b) -> a -> b
$ u a -> a
forall (u :: Unit) a. IsUnit u => u a -> a
unQuantity u a
u a -> a -> a
forall a. Num a => a -> a -> a
* v a -> a
forall (u :: Unit) a. IsUnit u => u a -> a
unQuantity v a
v
{-# INLINE (.*.) #-}

infixr 7 .*.

-- | Multiply two quantities, and tries to normalize the resulting unit, without

-- converting to base units.

--

-- >>> Meter 2 .*~ Meter 3 .*~ Meter 4

-- quantity @(Meter.^+3) 24

--

-- When two multiplied units have the same dimension, the right most unit is

-- converted to left most unit:

--

-- >>> Milli (Meter 2) .*~ Micro (Meter 3)

-- quantity @(Milli Meter.^+2) 6.0e-3

--

-- Derived units are not unfolded:

--

-- >>> Kilo Watt 3 .*~ Hour 5

-- quantity @(Kilo Watt .*. Hour) 14.999999999999998

--

-- Units are ordered, so that the result unit do not depend on the order of the

-- computations.

--

-- >>> Meter 2 .*~ Newton 2 .*~ Kilo (Meter 2) .*~ Kilo (Gram 1)

-- quantity @(Newton .*. Kilo Gram .*. Meter.^+2) 8000.0

--

(.*~) :: forall u v a uv.
  ( uv ~ u .*~ v
  , FromTo' (u .*. v) uv a
  , IsUnit u, IsUnit v, IsUnit uv
  , Num a
  )
  => u a -> v a -> uv a
u a
u .*~ :: forall (u :: Unit) (v :: Unit) a (uv :: Unit).
(uv ~ (u .*~ v), FromTo' (u .*. v) uv a, IsUnit u, IsUnit v,
 IsUnit uv, Num a) =>
u a -> v a -> uv a
.*~ v a
v = forall (v :: Unit) (u :: Unit) a. FromTo' u v a => u a -> v a
to' @uv (u a
u u a -> v a -> (.*.) u v a
forall (u :: Unit) (v :: Unit) a.
(IsUnit u, IsUnit v, Num a) =>
u a -> v a -> (.*.) u v a
.*. v a
v)
{-# INLINE (.*~) #-}

infixr 7 .*~

-- | Same as '(.*~)' but with right priority

--

-- >>> Meter 2 ~*. Meter 3 ~*. Meter 4

-- quantity @(Meter.^+3) 24

--

-- >>> Milli (Meter 2) ~*. Micro (Meter 3)

-- quantity @(Micro Meter.^+2) 6000.000000000001

--

(~*.) :: forall u v a uv.
  ( uv ~ u ~*. v
  , FromTo' (u .*. v) uv a
  , IsUnit u, IsUnit v, IsUnit uv
  , Num a
  )
  => u a -> v a -> uv a
u a
u ~*. :: forall (u :: Unit) (v :: Unit) a (uv :: Unit).
(uv ~ (u ~*. v), FromTo' (u .*. v) uv a, IsUnit u, IsUnit v,
 IsUnit uv, Num a) =>
u a -> v a -> uv a
~*. v a
v = forall (v :: Unit) (u :: Unit) a. FromTo' u v a => u a -> v a
to' @uv (u a
u u a -> v a -> (.*.) u v a
forall (u :: Unit) (v :: Unit) a.
(IsUnit u, IsUnit v, Num a) =>
u a -> v a -> (.*.) u v a
.*. v a
v)
{-# INLINE (~*.) #-}

infixr 7 ~*.

-- | Multiply two quantities of the same dimension and convert both of them to the corresponding standard unity.

--

-- >>> Milli (Meter 2) ~*~ Kilo (Meter 3)

-- quantity @(Meter .^+ 2) 6.0

--

-- >>> Meter 2 ~*~ Second 5

-- • Cannot convert unit ‘m’ to unit ‘s’ because their dimensions do not match.

--   Dimension of ‘m’ is: L

--   Dimension of ‘s’ is: T

--

(~*~) ::
  ( u2 ~ BaseUnitOf u .^+ 2, IsUnit u2
  , DimEq u v
  , ConversionFactor u a, ConversionFactor v a
  )
 => u a -> v a -> u2 a
u a
u ~*~ :: forall (u2 :: Unit) (u :: Unit) (v :: Unit) a.
(u2 ~ (BaseUnitOf u .^+ 2), IsUnit u2, DimEq u v,
 ConversionFactor u a, ConversionFactor v a) =>
u a -> v a -> u2 a
~*~ v a
v = a -> u2 a
forall (u :: Unit) a. IsUnit u => a -> u a
quantity (a -> u2 a) -> a -> u2 a
forall a b. (a -> b) -> a -> b
$ DimToUnit (DimOf v) a -> a
forall (u :: Unit) a. IsUnit u => u a -> a
unQuantity (u a -> BaseUnitOf u a
forall (u :: Unit) a. ConversionFactor u a => u a -> BaseUnitOf u a
toBaseUnit' u a
u) a -> a -> a
forall a. Num a => a -> a -> a
* DimToUnit (DimOf v) a -> a
forall (u :: Unit) a. IsUnit u => u a -> a
unQuantity (v a -> DimToUnit (DimOf v) a
forall (u :: Unit) a. ConversionFactor u a => u a -> BaseUnitOf u a
toBaseUnit' v a
v)
{-# INLINE (~*~) #-}

infix 7 ~*~


----------------------------------- Division -----------------------------------


-- | Multiply two quantities.

--

-- Usage is not recommended, as this will result non standard units.

--

-- For instance:

--

-- >>> Kilo (Meter 2) ./. Milli (Meter 4)

-- quantity @(Kilo Meter .*. Milli Meter.^-1) 0.5

--

(./.) ::
  ( IsUnit u, IsUnit v, IsUnit (u ./. v)
  , Fractional a
  )
  => u a -> v a -> (u ./. v) a
u a
u ./. :: forall (u :: Unit) (v :: Unit) a.
(IsUnit u, IsUnit v, IsUnit (u ./. v), Fractional a) =>
u a -> v a -> (./.) u v a
./. v a
v = a -> (.*.) u (InverseUnit v) a
forall (u :: Unit) a. IsUnit u => a -> u a
quantity (u a -> a
forall (u :: Unit) a. IsUnit u => u a -> a
unQuantity u a
u a -> a -> a
forall a. Fractional a => a -> a -> a
/ v a -> a
forall (u :: Unit) a. IsUnit u => u a -> a
unQuantity v a
v)
{-# INLINE (./.) #-}

infix 7 ./.

-- | Same '(.*~)' but for division.

--

-- >>> Milli (Meter 3) ./~ quantity @(Meter .^+ 2) 2

-- quantity @(Milli Meter.^-1) 1.5e-6

--

(./~) :: forall u v a uv.
  ( uv ~ u ./~ v
  , FromTo' (u ./. v) uv a
  , IsUnit u, IsUnit v, IsUnit uv
  , Num a
  )
  => u a -> v a -> uv a
u a
u ./~ :: forall (u :: Unit) (v :: Unit) a (uv :: Unit).
(uv ~ (u ./~ v), FromTo' (u ./. v) uv a, IsUnit u, IsUnit v,
 IsUnit uv, Num a) =>
u a -> v a -> uv a
./~ v a
v = forall (v :: Unit) (u :: Unit) a. FromTo' u v a => u a -> v a
to' @uv (u a
u u a -> v a -> (./.) u v a
forall (u :: Unit) (v :: Unit) a.
(IsUnit u, IsUnit v, IsUnit (u ./. v), Fractional a) =>
u a -> v a -> (./.) u v a
./. v a
v)
{-# INLINE (./~) #-}

infix 7 ./~

-- | Same '(~/.)' but with right priority

--

-- >>> Milli (Meter 3) ~/. quantity @(Meter .^+ 2) 2

-- quantity @(Meter.^-1) 1.5e-3

--

(~/.) :: forall u v a uv.
  ( uv ~ u ~/. v
  , FromTo' (u ./. v) uv a
  , IsUnit u, IsUnit v, IsUnit uv
  , Num a
  )
  => u a -> v a -> uv a
u a
u ~/. :: forall (u :: Unit) (v :: Unit) a (uv :: Unit).
(uv ~ (u ~/. v), FromTo' (u ./. v) uv a, IsUnit u, IsUnit v,
 IsUnit uv, Num a) =>
u a -> v a -> uv a
~/. v a
v = forall (v :: Unit) (u :: Unit) a. FromTo' u v a => u a -> v a
to' @uv (u a
u u a -> v a -> (./.) u v a
forall (u :: Unit) (v :: Unit) a.
(IsUnit u, IsUnit v, IsUnit (u ./. v), Fractional a) =>
u a -> v a -> (./.) u v a
./. v a
v)
{-# INLINE (~/.) #-}

infix 7 ~/.

-- | Divide two quantities of same dimensions. The numerator will be converted

-- to the denominator

--

-- Units of the same dimension are authorized only when the units are equal.

--

-- >>> Meter 4 ~/~ Kilo (Meter 1)

-- NoUnit 4.0e-3

--

(~/~) ::
  ( DimEq u v
  , ConversionFactor u a, ConversionFactor v a
  )
  => u a -> v a -> NoUnit a
u a
u ~/~ :: forall (u :: Unit) (v :: Unit) a.
(DimEq u v, ConversionFactor u a, ConversionFactor v a) =>
u a -> v a -> NoUnit a
~/~ v a
v = a -> NoUnit a
forall (u :: Unit) a. IsUnit u => a -> u a
quantity (a -> NoUnit a) -> a -> NoUnit a
forall a b. (a -> b) -> a -> b
$ DimToUnit (DimOf v) a -> a
forall (u :: Unit) a. IsUnit u => u a -> a
unQuantity (u a -> BaseUnitOf u a
forall (u :: Unit) a. ConversionFactor u a => u a -> BaseUnitOf u a
toBaseUnit' u a
u)  a -> a -> a
forall a. Fractional a => a -> a -> a
/ DimToUnit (DimOf v) a -> a
forall (u :: Unit) a. IsUnit u => u a -> a
unQuantity (v a -> DimToUnit (DimOf v) a
forall (u :: Unit) a. ConversionFactor u a => u a -> BaseUnitOf u a
toBaseUnit' v a
v)
{-# INLINE (~/~) #-}

infix 6 ~/~

-------------------------------- Exponentiation --------------------------------


-- | Raise a quantity to a power.

--

-- This is meant to be used with @'Data.Type.Int.Proxy'@

--

-- >>> Meter 2 .^. pos2

-- quantity @(Meter.^+2) 4.

--

-- Usage is not recommended, as this will result non standard units.

--

-- For instance:

--

-- >>> (Meter 2 .*. Centi (Meter 30)) .^. pos2

-- quantity @((Meter .*. Centi Meter).^+2) 3600.0

--

(.^.) :: forall (n :: ZZ) proxy u a. (IsUnit u, KnownInt n, Fractional a)
  => u a -> proxy n -> (u .^. n) a
u a
u .^. :: forall (n :: ZZ) (proxy :: ZZ -> *) (u :: Unit) a.
(IsUnit u, KnownInt n, Fractional a) =>
u a -> proxy n -> (.^.) u n a
.^. proxy n
p = a -> (.^.) u n a
forall (u :: Unit) a. IsUnit u => a -> u a
quantity (a -> (.^.) u n a) -> a -> (.^.) u n a
forall a b. (a -> b) -> a -> b
$ u a -> a
forall (u :: Unit) a. IsUnit u => u a -> a
unQuantity u a
u a -> Integer -> a
forall a b. (Fractional a, Integral b) => a -> b -> a
^^ proxy n -> Integer
forall (r :: ZZ) (proxy :: ZZ -> *).
KnownInt r =>
proxy r -> Integer
forall (proxy :: ZZ -> *). proxy n -> Integer
intVal proxy n
p
{-# INLINE (.^.) #-}

infix 8 .^.

-- | Raise a quantity to a power and tries to normalize the resulting unit,

-- without converting to base units.

--

-- >>> Meter 2 ~^. pos2

-- quantity @(Meter.^+2) 4.0

--

-- >>> (Meter 2 .*. Centi (Meter 30)) ~^. pos2

-- quantity @(Centi Meter.^+4) 3.6e7

(~^.) :: forall (n :: ZZ) proxy u a un.
  (un ~ u ~^. n, FromTo' (u .^. n) un a, IsUnit u, KnownInt n, Fractional a)
  => u a -> proxy n -> un a
u a
u ~^. :: forall (n :: ZZ) (proxy :: ZZ -> *) (u :: Unit) a (un :: Unit).
(un ~ (u ~^. n), FromTo' (u .^. n) un a, IsUnit u, KnownInt n,
 Fractional a) =>
u a -> proxy n -> un a
~^. proxy n
p = forall (v :: Unit) (u :: Unit) a. FromTo' u v a => u a -> v a
to' @un (u a
u u a -> proxy n -> (.^.) u n a
forall (n :: ZZ) (proxy :: ZZ -> *) (u :: Unit) a.
(IsUnit u, KnownInt n, Fractional a) =>
u a -> proxy n -> (.^.) u n a
.^. proxy n
p)
{-# INLINE (~^.) #-}

infix 8 ~^.

-- | Same as @'(.^~)'@ but with priority to rightmost units.

--

-- >>> Meter 2 .^~ pos2

-- quantity @(Meter.^+2) 4.0

--

-- >>> (Meter 2 .*. Centi (Meter 30)) ~^. pos2

-- quantity @(Meter.^+4) 0.36000000000000004

--

(.^~ ) :: forall (n :: ZZ) proxy u a un.
  (un ~ u .^~  n, FromTo' (u .^. n) un a, IsUnit u, KnownInt n, Fractional a)
  => u a -> proxy n -> un a
u a
u .^~ :: forall (n :: ZZ) (proxy :: ZZ -> *) (u :: Unit) a (un :: Unit).
(un ~ (u .^~ n), FromTo' (u .^. n) un a, IsUnit u, KnownInt n,
 Fractional a) =>
u a -> proxy n -> un a
.^~  proxy n
p = forall (v :: Unit) (u :: Unit) a. FromTo' u v a => u a -> v a
to' @un (u a
u u a -> proxy n -> (.^.) u n a
forall (n :: ZZ) (proxy :: ZZ -> *) (u :: Unit) a.
(IsUnit u, KnownInt n, Fractional a) =>
u a -> proxy n -> (.^.) u n a
.^. proxy n
p)
{-# INLINE (.^~ ) #-}

infix 8 .^~

-- | Raise a quantity to a power and convert to the standard unit.

--

-- >>> Kilo (Meter 2) ~^~ neg1

-- quantity @(Meter .^- 1) 5.0e-4

--

(~^~) :: forall (n :: ZZ) proxy u un a.
  (KnownInt n, ConversionFactor u a, un ~ BaseUnitOf u .^. n )
  => u a -> proxy n -> un a
u a
u ~^~ :: forall (n :: ZZ) (proxy :: ZZ -> *) (u :: Unit) (un :: Unit) a.
(KnownInt n, ConversionFactor u a, un ~ (BaseUnitOf u .^. n)) =>
u a -> proxy n -> un a
~^~ proxy n
p = forall (u :: Unit) a. IsUnit u => a -> u a
quantity @un (a -> un a) -> a -> un a
forall a b. (a -> b) -> a -> b
$ DimToUnit (DimOf u) a -> a
forall (u :: Unit) a. IsUnit u => u a -> a
unQuantity (u a -> DimToUnit (DimOf u) a
forall (u :: Unit) a. ConversionFactor u a => u a -> BaseUnitOf u a
toBaseUnit' u a
u) a -> Integer -> a
forall a b. (Fractional a, Integral b) => a -> b -> a
^^ proxy n -> Integer
forall (r :: ZZ) (proxy :: ZZ -> *).
KnownInt r =>
proxy r -> Integer
forall (proxy :: ZZ -> *). proxy n -> Integer
intVal proxy n
p
{-# INLINE (~^~) #-}

infix 8 ~^~