| Copyright | (c) Alice Rixte 2025 |
|---|---|
| License | BSD 3 |
| Maintainer | alice.rixte@u-bordeaux.fr |
| Stability | unstable |
| Portability | non-portable (GHC extensions) |
| Safe Haskell | None |
| Language | GHC2024 |
Data.Units.Core.Arithmetic
Description
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 instance :Fractional
>>>a = Milli (Second 5)>>>3 * aquantity @(Milli Second) 15
- Warning
- These instances are provided because they are convenient, but be careful ! This means that you can write:
>>>Second 2 * Second 3Second 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 3quantity @(Second .^+ 2) 6
Synopsis
- (.+~) :: forall u v a. FromTo' v u a => u a -> v a -> u a
- (~+.) :: FromTo' u v a => u a -> v a -> v a
- (~+~) :: (DimEq u v, ConversionFactor u a, ConversionFactor v a) => u a -> v a -> BaseUnitOf u a
- (.-~) :: forall u v a. FromTo' v u a => u a -> v a -> u a
- (~-.) :: FromTo' u v a => u a -> v a -> v a
- (~-~) :: (DimEq u v, ConversionFactor v a, ConversionFactor u a) => u a -> v a -> BaseUnitOf u a
- (.*.) :: (IsUnit u, IsUnit v, Num a) => u a -> v a -> (u .*. v) a
- (.*~) :: 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
- (~*.) :: 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
- (~*~) :: (u2 ~ (BaseUnitOf u .^+ 2), IsUnit u2, DimEq u v, ConversionFactor u a, ConversionFactor v a) => u a -> v a -> u2 a
- (./.) :: (IsUnit u, IsUnit v, IsUnit (u ./. v), Fractional a) => u a -> v a -> (u ./. v) a
- (./~) :: 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
- (~/.) :: 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
- (~/~) :: (DimEq u v, ConversionFactor u a, ConversionFactor v a) => u a -> v a -> NoUnit a
- (.^.) :: forall (n :: ZZ) proxy u a. (IsUnit u, KnownInt n, Fractional a) => u a -> proxy n -> (u .^. n) a
- (~^.) :: 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
- (.^~) :: 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
- (~^~) :: forall (n :: ZZ) proxy u un a. (KnownInt n, ConversionFactor u a, un ~ (BaseUnitOf u .^. n)) => u a -> proxy n -> un a
Addition
(.+~) :: forall u v a. FromTo' v u a => u a -> v a -> u a infixr 5 Source #
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 80quantity @(Kilo Meter) 5.08
>>>Meter 2 .+~ Second 3• Cannot convert unit ‘s’ of dimension ‘T’ to unit ‘m’ of dimension ‘L’.
(~+.) :: FromTo' u v a => u a -> v a -> v a infixr 5 Source #
Same as but it is the left operand that is converted.(.+~)
>>>Kilo (Meter 5) ~+. Meter 80quantity @(Kilo Meter) 5080.0
(~+~) :: (DimEq u v, ConversionFactor u a, ConversionFactor v a) => u a -> v a -> BaseUnitOf u a infixr 5 Source #
Add two quantities of same dimension and convert to the standard unit.
>>>Kilo (Meter 1) ~+~ Milli (Meter 150)Meter 1000.15
Subtraction
(.-~) :: forall u v a. FromTo' v u a => u a -> v a -> u a infixr 5 Source #
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 80quantity @(Kilo Meter) 4.92
(~-.) :: FromTo' u v a => u a -> v a -> v a infixr 5 Source #
Same as but it is the left operand that is converted.(.-~)
>>>Kilo (Meter 5) ~-. Meter 80Meter 4920.0
(~-~) :: (DimEq u v, ConversionFactor v a, ConversionFactor u a) => u a -> v a -> BaseUnitOf u a infixr 5 Source #
Subtract two quantities of same dimension and convert to the standard unit.
>>>Kilo (Meter 1) ~-~ Milli (Meter 150)Meter 999.85
Multiplication
(.*.) :: (IsUnit u, IsUnit v, Num a) => u a -> v a -> (u .*. v) a infixr 7 Source #
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
(.*~) :: 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 infixr 7 Source #
Multiply two quantities, and tries to normalize the resulting unit, without converting to base units.
>>>Meter 2 .*~ Meter 3 .*~ Meter 4quantity @(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 5quantity @(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 infixr 7 Source #
Same as (.*~) but with right priority
>>>Meter 2 ~*. Meter 3 ~*. Meter 4quantity @(Meter.^+3) 24
>>>Milli (Meter 2) ~*. Micro (Meter 3)quantity @(Micro Meter.^+2) 6000.000000000001
(~*~) :: (u2 ~ (BaseUnitOf u .^+ 2), IsUnit u2, DimEq u v, ConversionFactor u a, ConversionFactor v a) => u a -> v a -> u2 a infix 7 Source #
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
Division
(./.) :: (IsUnit u, IsUnit v, IsUnit (u ./. v), Fractional a) => u a -> v a -> (u ./. v) a infix 7 Source #
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
(./~) :: 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 infix 7 Source #
Same (.*~) but for division.
>>>Milli (Meter 3) ./~ quantity @(Meter .^+ 2) 2quantity @(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 infix 7 Source #
Same (~/.) but with right priority
>>>Milli (Meter 3) ~/. quantity @(Meter .^+ 2) 2quantity @(Meter.^-1) 1.5e-3
(~/~) :: (DimEq u v, ConversionFactor u a, ConversionFactor v a) => u a -> v a -> NoUnit a infix 6 Source #
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
Exponentiation
(.^.) :: forall (n :: ZZ) proxy u a. (IsUnit u, KnownInt n, Fractional a) => u a -> proxy n -> (u .^. n) a infix 8 Source #
Raise a quantity to a power.
>>>Meter 2 .^. pos2quantity @(Meter.^+2) 4.0
Usage is not recommended, as this will result non standard units.
For instance:
>>>(Meter 2 .*. Centi (Meter 30)) .^. pos2quantity @((Meter .*. Centi Meter).^+2) 3600.0
(~^.) :: 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 infix 8 Source #
Raise a quantity to a power and tries to normalize the resulting unit, without converting to base units.
This is meant to be used with singletons, like SZZpos, neg
or zero, and there other flavors like pos2, neg3, etc.
>>>Meter 2 ~^. pos2quantity @(Meter.^+2) 4.0
>>>Meter 2 ~^. pos @10quantity @(Meter.^+10) 1024.0
>>>(Meter 2 .*. Centi (Meter 30)) ~^. pos2quantity @(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 infix 8 Source #
Same as but with priority to rightmost units.(.^~)
>>>Meter 2 .^~ pos2quantity @(Meter.^+2) 4.0
>>>(Meter 2 .*. Centi (Meter 30)) ~^. pos2quantity @(Meter.^+4) 0.36000000000000004
(~^~) :: forall (n :: ZZ) proxy u un a. (KnownInt n, ConversionFactor u a, un ~ (BaseUnitOf u .^. n)) => u a -> proxy n -> un a infix 8 Source #
Raise a quantity to a power and convert to the standard unit.
>>>Kilo (Meter 2) ~^~ neg1quantity @(Meter .^- 1) 5.0e-4