{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PolyKinds #-}
module Units.Simple
  (-- *The @Quantity@ type
    Quantity ()
  , fromQuantity
  , Unit (..)
  , Units
  , SingleUnit
  , UnitRepr
  , showUnits

  -- * Basic arithmetic with quantities
  , (.+)
  , (.-)
  , (.*)
  , (./)

  -- *Base SI Units
  -- |Smart constructors for quantities in all the base SI Units, plus grams
  -- (see "SI Prefixes"). The constructors are provided in both unitary
  -- (non-ticked) and function (ticked) forms.
  --
  -- Examples:
  --
  -- >>> import Units.Simple
  -- >>> 273.0*kelvin -- unitary form
  -- 273.0 K
  -- >>> kelvin' 273.0 -- function form
  -- 273.0 K
  , adim
  , adim'
  , meter
  , meter'
  , kilogram
  , kilogram'
  , gram
  , gram'
  , second
  , second'
  , ampere
  , ampere'
  , kelvin
  , kelvin'
  , mole
  , mole'
  , candela
  , candela'

  -- *SI Prefixes
  -- |The 20 base SI prefixes representing powers of 10.
  -- Reference: <https://physics.nist.gov/cuu/Units/prefixes.html>
  --
  -- __Note:__ Though smart constructors for kilograms are provided, it is
  -- recommended to use the prefixes with the 'gram' and 'gram'' constructors.
  , yocto
  , yocto'
  , zepto
  , zepto'
  , atto
  , atto'
  , femto
  , femto'
  , pico
  , pico'
  , nano
  , nano'
  , micro
  , micro'
  , milli
  , milli'
  , centi
  , centi'
  , deci
  , deci'
  , deka
  , deka'
  , hecto
  , hecto'
  , kilo
  , kilo'
  , mega
  , mega'
  , giga
  , giga'
  , tera
  , tera'
  , peta
  , peta'
  , exa
  , exa'
  , zetta
  , zetta'
  , yotta
  , yotta'
  ) where


import Units.Simple.Quantity
import Units.Simple.Arithmetic
import Units.Simple.Unit

type SingleUnit (u :: Unit) = '( '[ '(u, 1)], '[])
type Adimensional = '( '[], '[])

-- | A 'Quantity' with no associated dimension. Can be multiplied or divided
-- by any other 'Quantity', but can only be added to or subtracted from
-- another adimensional 'Quantity'.
--
-- >>> 2*adim + 4*adim
-- 6 <adimensional>
-- >>> adim .+ meter
-- <BLANKLINE>
-- <interactive>... error:
--     • Unit mismatch: <adimensional> and m
--     • In the expression: adim .+ meter
--       In an equation for ‘it’: it = adim .+ meter
adim :: Num a => Quantity Adimensional a
adim :: Quantity Adimensional a
adim = a -> Quantity Adimensional a
forall (us :: Units) a. a -> Quantity us a
Quantity a
1

-- SI units
meter :: Num a => Quantity (SingleUnit 'Meter) a
meter :: Quantity (SingleUnit 'Meter) a
meter = a -> Quantity (SingleUnit 'Meter) a
forall (us :: Units) a. a -> Quantity us a
Quantity a
1

kilogram :: Num a => Quantity (SingleUnit 'Kilogram) a
kilogram :: Quantity (SingleUnit 'Kilogram) a
kilogram = a -> Quantity (SingleUnit 'Kilogram) a
forall (us :: Units) a. a -> Quantity us a
Quantity a
1

-- |A constructor for 1/1000th of a kilogram, to use with SI prefixes.
gram :: Fractional a => Quantity (SingleUnit 'Kilogram) a
gram :: Quantity (SingleUnit 'Kilogram) a
gram = a -> Quantity (SingleUnit 'Kilogram) a
forall (us :: Units) a. a -> Quantity us a
Quantity a
1e-3

second :: Num a => Quantity (SingleUnit 'Second) a
second :: Quantity (SingleUnit 'Second) a
second = a -> Quantity (SingleUnit 'Second) a
forall (us :: Units) a. a -> Quantity us a
Quantity a
1

ampere :: Num a => Quantity (SingleUnit 'Ampere) a
ampere :: Quantity (SingleUnit 'Ampere) a
ampere = a -> Quantity (SingleUnit 'Ampere) a
forall (us :: Units) a. a -> Quantity us a
Quantity a
1

kelvin :: Num a => Quantity (SingleUnit 'Kelvin) a
kelvin :: Quantity (SingleUnit 'Kelvin) a
kelvin = a -> Quantity (SingleUnit 'Kelvin) a
forall (us :: Units) a. a -> Quantity us a
Quantity a
1

mole :: Num a => Quantity (SingleUnit 'Mole) a
mole :: Quantity (SingleUnit 'Mole) a
mole = a -> Quantity (SingleUnit 'Mole) a
forall (us :: Units) a. a -> Quantity us a
Quantity a
1

candela :: Num a => Quantity (SingleUnit 'Candela) a
candela :: Quantity (SingleUnit 'Candela) a
candela = a -> Quantity (SingleUnit 'Candela) a
forall (us :: Units) a. a -> Quantity us a
Quantity a
1

adim' :: Num a => a -> Quantity Adimensional a
adim' :: a -> Quantity Adimensional a
adim' = a -> Quantity Adimensional a
forall (us :: Units) a. a -> Quantity us a
Quantity

meter' :: Num a => a -> Quantity (SingleUnit 'Meter) a
meter' :: a -> Quantity (SingleUnit 'Meter) a
meter' = a -> Quantity (SingleUnit 'Meter) a
forall (us :: Units) a. a -> Quantity us a
Quantity

kilogram' :: Num a => a -> Quantity (SingleUnit 'Kilogram) a
kilogram' :: a -> Quantity (SingleUnit 'Kilogram) a
kilogram' = a -> Quantity (SingleUnit 'Kilogram) a
forall (us :: Units) a. a -> Quantity us a
Quantity

-- |A constructor for 1/1000th of a kilogram, to use with SI prefixes.
gram' :: Fractional a => a -> Quantity (SingleUnit 'Kilogram) a
gram' :: a -> Quantity (SingleUnit 'Kilogram) a
gram' = (Quantity (SingleUnit 'Kilogram) a
-> Quantity (SingleUnit 'Kilogram) a
-> Quantity (SingleUnit 'Kilogram) a
forall a. Num a => a -> a -> a
*Quantity (SingleUnit 'Kilogram) a
1e-3) (Quantity (SingleUnit 'Kilogram) a
 -> Quantity (SingleUnit 'Kilogram) a)
-> (a -> Quantity (SingleUnit 'Kilogram) a)
-> a
-> Quantity (SingleUnit 'Kilogram) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Quantity (SingleUnit 'Kilogram) a
forall (us :: Units) a. a -> Quantity us a
Quantity

second' :: Num a => a -> Quantity (SingleUnit 'Second) a
second' :: a -> Quantity (SingleUnit 'Second) a
second' = a -> Quantity (SingleUnit 'Second) a
forall (us :: Units) a. a -> Quantity us a
Quantity

ampere' :: Num a => a -> Quantity (SingleUnit 'Ampere) a
ampere' :: a -> Quantity (SingleUnit 'Ampere) a
ampere' = a -> Quantity (SingleUnit 'Ampere) a
forall (us :: Units) a. a -> Quantity us a
Quantity

kelvin' :: Num a => a -> Quantity (SingleUnit 'Kelvin) a
kelvin' :: a -> Quantity (SingleUnit 'Kelvin) a
kelvin' = a -> Quantity (SingleUnit 'Kelvin) a
forall (us :: Units) a. a -> Quantity us a
Quantity

mole' :: Num a => a -> Quantity (SingleUnit 'Mole) a
mole' :: a -> Quantity (SingleUnit 'Mole) a
mole' = a -> Quantity (SingleUnit 'Mole) a
forall (us :: Units) a. a -> Quantity us a
Quantity

candela' :: Num a => a -> Quantity (SingleUnit 'Candela) a
candela' :: a -> Quantity (SingleUnit 'Candela) a
candela' = a -> Quantity (SingleUnit 'Candela) a
forall (us :: Units) a. a -> Quantity us a
Quantity

-- SI prefixes
yocto :: Fractional a => Quantity us a -> Quantity us a
yocto :: Quantity us a -> Quantity us a
yocto = (Quantity us a -> Quantity us a -> Quantity us a
forall a. Num a => a -> a -> a
* Quantity us a
1e-24)

yocto' :: Fractional a => (a -> Quantity us a) -> a -> Quantity us a
yocto' :: (a -> Quantity us a) -> a -> Quantity us a
yocto' a -> Quantity us a
constructor = Quantity us a -> Quantity us a
forall a (us :: Units).
Fractional a =>
Quantity us a -> Quantity us a
yocto (Quantity us a -> Quantity us a)
-> (a -> Quantity us a) -> a -> Quantity us a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Quantity us a
constructor

zepto :: Fractional a => Quantity us a -> Quantity us a
zepto :: Quantity us a -> Quantity us a
zepto = (Quantity us a -> Quantity us a -> Quantity us a
forall a. Num a => a -> a -> a
* Quantity us a
1e-21)

zepto' :: Fractional a => (a -> Quantity us a) -> a -> Quantity us a
zepto' :: (a -> Quantity us a) -> a -> Quantity us a
zepto' a -> Quantity us a
constructor = Quantity us a -> Quantity us a
forall a (us :: Units).
Fractional a =>
Quantity us a -> Quantity us a
zepto (Quantity us a -> Quantity us a)
-> (a -> Quantity us a) -> a -> Quantity us a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Quantity us a
constructor

atto :: Fractional a => Quantity us a -> Quantity us a
atto :: Quantity us a -> Quantity us a
atto = (Quantity us a -> Quantity us a -> Quantity us a
forall a. Num a => a -> a -> a
* Quantity us a
1e-18)

atto' :: Fractional a => (a -> Quantity us a) -> a -> Quantity us a
atto' :: (a -> Quantity us a) -> a -> Quantity us a
atto' a -> Quantity us a
constructor = Quantity us a -> Quantity us a
forall a (us :: Units).
Fractional a =>
Quantity us a -> Quantity us a
atto (Quantity us a -> Quantity us a)
-> (a -> Quantity us a) -> a -> Quantity us a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Quantity us a
constructor

femto :: Fractional a => Quantity us a -> Quantity us a
femto :: Quantity us a -> Quantity us a
femto = (Quantity us a -> Quantity us a -> Quantity us a
forall a. Num a => a -> a -> a
* Quantity us a
1e-15)

femto' :: Fractional a => (a -> Quantity us a) -> a -> Quantity us a
femto' :: (a -> Quantity us a) -> a -> Quantity us a
femto' a -> Quantity us a
constructor = Quantity us a -> Quantity us a
forall a (us :: Units).
Fractional a =>
Quantity us a -> Quantity us a
femto (Quantity us a -> Quantity us a)
-> (a -> Quantity us a) -> a -> Quantity us a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Quantity us a
constructor

pico :: Fractional a => Quantity us a -> Quantity us a
pico :: Quantity us a -> Quantity us a
pico = (Quantity us a -> Quantity us a -> Quantity us a
forall a. Num a => a -> a -> a
* Quantity us a
1e-12)

pico' :: Fractional a => (a -> Quantity us a) -> a -> Quantity us a
pico' :: (a -> Quantity us a) -> a -> Quantity us a
pico' a -> Quantity us a
constructor = Quantity us a -> Quantity us a
forall a (us :: Units).
Fractional a =>
Quantity us a -> Quantity us a
pico (Quantity us a -> Quantity us a)
-> (a -> Quantity us a) -> a -> Quantity us a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Quantity us a
constructor

nano :: Fractional a => Quantity us a -> Quantity us a
nano :: Quantity us a -> Quantity us a
nano = (Quantity us a -> Quantity us a -> Quantity us a
forall a. Num a => a -> a -> a
* Quantity us a
1e-9)

nano' :: Fractional a => (a -> Quantity us a) -> a -> Quantity us a
nano' :: (a -> Quantity us a) -> a -> Quantity us a
nano' a -> Quantity us a
constructor = Quantity us a -> Quantity us a
forall a (us :: Units).
Fractional a =>
Quantity us a -> Quantity us a
nano (Quantity us a -> Quantity us a)
-> (a -> Quantity us a) -> a -> Quantity us a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Quantity us a
constructor

micro :: Fractional a => Quantity us a -> Quantity us a
micro :: Quantity us a -> Quantity us a
micro = (Quantity us a -> Quantity us a -> Quantity us a
forall a. Num a => a -> a -> a
* Quantity us a
1e-6)

micro' :: Fractional a => (a -> Quantity us a) -> a -> Quantity us a
micro' :: (a -> Quantity us a) -> a -> Quantity us a
micro' a -> Quantity us a
constructor = Quantity us a -> Quantity us a
forall a (us :: Units).
Fractional a =>
Quantity us a -> Quantity us a
micro (Quantity us a -> Quantity us a)
-> (a -> Quantity us a) -> a -> Quantity us a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Quantity us a
constructor

milli :: Fractional a => Quantity us a -> Quantity us a
milli :: Quantity us a -> Quantity us a
milli = (Quantity us a -> Quantity us a -> Quantity us a
forall a. Num a => a -> a -> a
* Quantity us a
1e-3)

milli' :: Fractional a => (a -> Quantity us a) -> a -> Quantity us a
milli' :: (a -> Quantity us a) -> a -> Quantity us a
milli' a -> Quantity us a
constructor = Quantity us a -> Quantity us a
forall a (us :: Units).
Fractional a =>
Quantity us a -> Quantity us a
milli (Quantity us a -> Quantity us a)
-> (a -> Quantity us a) -> a -> Quantity us a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Quantity us a
constructor

centi :: Fractional a => Quantity us a -> Quantity us a
centi :: Quantity us a -> Quantity us a
centi = (Quantity us a -> Quantity us a -> Quantity us a
forall a. Num a => a -> a -> a
* Quantity us a
1e-2)

centi' :: Fractional a => (a -> Quantity us a) -> a -> Quantity us a
centi' :: (a -> Quantity us a) -> a -> Quantity us a
centi' a -> Quantity us a
constructor = Quantity us a -> Quantity us a
forall a (us :: Units).
Fractional a =>
Quantity us a -> Quantity us a
centi (Quantity us a -> Quantity us a)
-> (a -> Quantity us a) -> a -> Quantity us a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Quantity us a
constructor

deci :: Fractional a => Quantity us a -> Quantity us a
deci :: Quantity us a -> Quantity us a
deci = (Quantity us a -> Quantity us a -> Quantity us a
forall a. Num a => a -> a -> a
* Quantity us a
1e-1)

deci' :: Fractional a => (a -> Quantity us a) -> a -> Quantity us a
deci' :: (a -> Quantity us a) -> a -> Quantity us a
deci' a -> Quantity us a
constructor = Quantity us a -> Quantity us a
forall a (us :: Units).
Fractional a =>
Quantity us a -> Quantity us a
deci (Quantity us a -> Quantity us a)
-> (a -> Quantity us a) -> a -> Quantity us a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Quantity us a
constructor

deka :: Num a => Quantity us a -> Quantity us a
deka :: Quantity us a -> Quantity us a
deka = (Quantity us a -> Quantity us a -> Quantity us a
forall a. Num a => a -> a -> a
* Quantity us a
10)

deka' :: Num a => (a -> Quantity us a) -> a -> Quantity us a
deka' :: (a -> Quantity us a) -> a -> Quantity us a
deka' a -> Quantity us a
constructor = Quantity us a -> Quantity us a
forall a (us :: Units). Num a => Quantity us a -> Quantity us a
deka (Quantity us a -> Quantity us a)
-> (a -> Quantity us a) -> a -> Quantity us a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Quantity us a
constructor

hecto :: Num a => Quantity us a -> Quantity us a
hecto :: Quantity us a -> Quantity us a
hecto = (Quantity us a -> Quantity us a -> Quantity us a
forall a. Num a => a -> a -> a
* Quantity us a
100)

hecto' :: Num a => (a -> Quantity us a) -> a -> Quantity us a
hecto' :: (a -> Quantity us a) -> a -> Quantity us a
hecto' a -> Quantity us a
constructor = Quantity us a -> Quantity us a
forall a (us :: Units). Num a => Quantity us a -> Quantity us a
hecto (Quantity us a -> Quantity us a)
-> (a -> Quantity us a) -> a -> Quantity us a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Quantity us a
constructor

kilo :: Num a => Quantity us a -> Quantity us a
kilo :: Quantity us a -> Quantity us a
kilo = (Quantity us a -> Quantity us a -> Quantity us a
forall a. Num a => a -> a -> a
* Quantity us a
1000)

kilo' :: Num a => (a -> Quantity us a) -> a -> Quantity us a
kilo' :: (a -> Quantity us a) -> a -> Quantity us a
kilo' a -> Quantity us a
constructor = Quantity us a -> Quantity us a
forall a (us :: Units). Num a => Quantity us a -> Quantity us a
kilo (Quantity us a -> Quantity us a)
-> (a -> Quantity us a) -> a -> Quantity us a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Quantity us a
constructor

mega :: Num a => Quantity us a -> Quantity us a
mega :: Quantity us a -> Quantity us a
mega = (Quantity us a -> Quantity us a -> Quantity us a
forall a. Num a => a -> a -> a
* Quantity us a
1000000)

mega' :: Num a => (a -> Quantity us a) -> a -> Quantity us a
mega' :: (a -> Quantity us a) -> a -> Quantity us a
mega' a -> Quantity us a
constructor = Quantity us a -> Quantity us a
forall a (us :: Units). Num a => Quantity us a -> Quantity us a
mega (Quantity us a -> Quantity us a)
-> (a -> Quantity us a) -> a -> Quantity us a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Quantity us a
constructor

giga :: Num a => Quantity us a -> Quantity us a
giga :: Quantity us a -> Quantity us a
giga = (Quantity us a -> Quantity us a -> Quantity us a
forall a. Num a => a -> a -> a
* Quantity us a
1000000000)

giga' :: Num a => (a -> Quantity us a) -> a -> Quantity us a
giga' :: (a -> Quantity us a) -> a -> Quantity us a
giga' a -> Quantity us a
constructor = Quantity us a -> Quantity us a
forall a (us :: Units). Num a => Quantity us a -> Quantity us a
giga (Quantity us a -> Quantity us a)
-> (a -> Quantity us a) -> a -> Quantity us a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Quantity us a
constructor

tera :: Num a => Quantity us a -> Quantity us a
tera :: Quantity us a -> Quantity us a
tera = (Quantity us a -> Quantity us a -> Quantity us a
forall a. Num a => a -> a -> a
* Quantity us a
1000000000000)

tera' :: Num a => (a -> Quantity us a) -> a -> Quantity us a
tera' :: (a -> Quantity us a) -> a -> Quantity us a
tera' a -> Quantity us a
constructor = Quantity us a -> Quantity us a
forall a (us :: Units). Num a => Quantity us a -> Quantity us a
tera (Quantity us a -> Quantity us a)
-> (a -> Quantity us a) -> a -> Quantity us a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Quantity us a
constructor

peta :: Num a => Quantity us a -> Quantity us a
peta :: Quantity us a -> Quantity us a
peta = (Quantity us a -> Quantity us a -> Quantity us a
forall a. Num a => a -> a -> a
* Quantity us a
1000000000000000)

peta' :: Num a => (a -> Quantity us a) -> a -> Quantity us a
peta' :: (a -> Quantity us a) -> a -> Quantity us a
peta' a -> Quantity us a
constructor = Quantity us a -> Quantity us a
forall a (us :: Units). Num a => Quantity us a -> Quantity us a
peta (Quantity us a -> Quantity us a)
-> (a -> Quantity us a) -> a -> Quantity us a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Quantity us a
constructor

exa :: Num a => Quantity us a -> Quantity us a
exa :: Quantity us a -> Quantity us a
exa = (Quantity us a -> Quantity us a -> Quantity us a
forall a. Num a => a -> a -> a
* Quantity us a
1000000000000000000)

exa' :: Num a => (a -> Quantity us a) -> a -> Quantity us a
exa' :: (a -> Quantity us a) -> a -> Quantity us a
exa' a -> Quantity us a
constructor = Quantity us a -> Quantity us a
forall a (us :: Units). Num a => Quantity us a -> Quantity us a
exa (Quantity us a -> Quantity us a)
-> (a -> Quantity us a) -> a -> Quantity us a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Quantity us a
constructor

zetta :: Num a => Quantity us a -> Quantity us a
zetta :: Quantity us a -> Quantity us a
zetta = (Quantity us a -> Quantity us a -> Quantity us a
forall a. Num a => a -> a -> a
* Quantity us a
1000000000000000000000)

zetta' :: Num a => (a -> Quantity us a) -> a -> Quantity us a
zetta' :: (a -> Quantity us a) -> a -> Quantity us a
zetta' a -> Quantity us a
constructor = Quantity us a -> Quantity us a
forall a (us :: Units). Num a => Quantity us a -> Quantity us a
zetta (Quantity us a -> Quantity us a)
-> (a -> Quantity us a) -> a -> Quantity us a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Quantity us a
constructor

yotta :: Num a => Quantity us a -> Quantity us a
yotta :: Quantity us a -> Quantity us a
yotta = (Quantity us a -> Quantity us a -> Quantity us a
forall a. Num a => a -> a -> a
* Quantity us a
1000000000000000000000000)

yotta' :: Num a => (a -> Quantity us a) -> a -> Quantity us a
yotta' :: (a -> Quantity us a) -> a -> Quantity us a
yotta' a -> Quantity us a
constructor = Quantity us a -> Quantity us a
forall a (us :: Units). Num a => Quantity us a -> Quantity us a
yotta (Quantity us a -> Quantity us a)
-> (a -> Quantity us a) -> a -> Quantity us a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Quantity us a
constructor