Safe Haskell | None |
---|---|
Language | Haskell2010 |
See Data.UnitsOfMeasure.Tutorial for how to use this module.
- data Unit
- type family Base b :: Unit
- type family One :: Unit
- type family u *: v :: Unit
- type family u /: v :: Unit
- type family u ^: n :: Unit
- data Quantity a u
- unQuantity :: Quantity a u -> a
- zero :: Num a => Quantity a u
- mk :: a -> Quantity a One
- (+:) :: Num a => Quantity a u -> Quantity a u -> Quantity a u
- (*:) :: (Num a, w ~~ (u *: v)) => Quantity a u -> Quantity a v -> Quantity a w
- (-:) :: Num a => Quantity a u -> Quantity a u -> Quantity a u
- negate' :: Num a => Quantity a u -> Quantity a u
- abs' :: Num a => Quantity a u -> Quantity a u
- signum' :: Num a => Quantity a u -> Quantity a One
- fromInteger' :: Integral a => Quantity Integer u -> Quantity a u
- (/:) :: (Fractional a, w ~~ (u /: v)) => Quantity a u -> Quantity a v -> Quantity a w
- recip' :: (Fractional a, w ~~ (One /: u)) => Quantity a u -> Quantity a w
- fromRational' :: Fractional a => Quantity Rational u -> Quantity a u
- sqrt' :: (Floating a, w ~~ (u ^: 2)) => Quantity a w -> Quantity a u
- u :: QuasiQuoter
- declareBaseUnit :: String -> Q [Dec]
- declareDerivedUnit :: String -> String -> Q [Dec]
- declareConvertibleUnit :: String -> Rational -> String -> Q [Dec]
- convert :: forall a u v. (Fractional a, Convertible u v) => Quantity a u -> Quantity a v
- type family MkUnit s :: Unit
- type family Pack u :: Unit
- type family Unpack u :: UnitSyntax Symbol
- class KnownUnit u
Type-level units of measure
type family u ^: n :: Unit infixr 8 Source
Exponentiation (to a positive power) for units of measure; negative exponents are not yet supported (they require an Integer kind)
Values indexed by their units
A Quantity a u
is represented identically to a value of
underlying numeric type a
, but with units u
.
Bounded a => Bounded (Quantity a u) Source | |
(Enum a, (~) Unit u One) => Enum (Quantity a u) Source | |
Eq a => Eq (Quantity a u) Source | |
(Floating a, (~) Unit u One) => Floating (Quantity a u) Source | |
(Fractional a, (~) Unit u One) => Fractional (Quantity a u) Source | |
(Integral a, (~) Unit u One) => Integral (Quantity a u) Source | |
(Num a, (~) Unit u One) => Num (Quantity a u) Source | |
Ord a => Ord (Quantity a u) Source | |
(Real a, (~) Unit u One) => Real (Quantity a u) Source | |
(RealFloat a, (~) Unit u One) => RealFloat (Quantity a u) Source | |
(RealFrac a, (~) Unit u One) => RealFrac (Quantity a u) Source | |
Storable a => Storable (Quantity a u) Source | |
NFData a => NFData (Quantity a u) Source |
unQuantity :: Quantity a u -> a Source
Extract the underlying value of a quantity
zero :: Num a => Quantity a u Source
Zero is polymorphic in its units: this is required because the
Num
instance constrains the quantity to be dimensionless, so
0 :: Quantity a u
is not well typed.
mk :: a -> Quantity a One Source
Construct a Quantity
from a dimensionless value. Note that for
numeric literals, the Num
and Fractional
instances allow them
to be treated as quantities directly.
Unit-safe Num
operations
(+:) :: Num a => Quantity a u -> Quantity a u -> Quantity a u infixl 6 Source
Addition (+
) of quantities requires the units to match.
(*:) :: (Num a, w ~~ (u *: v)) => Quantity a u -> Quantity a v -> Quantity a w infixl 7 Source
Multiplication (*
) of quantities multiplies the units.
(-:) :: Num a => Quantity a u -> Quantity a u -> Quantity a u infixl 6 Source
Subtraction (-
) of quantities requires the units to match.
negate' :: Num a => Quantity a u -> Quantity a u Source
Negation (negate
) of quantities is polymorphic in the units.
abs' :: Num a => Quantity a u -> Quantity a u Source
Absolute value (abs
) of quantities is polymorphic in the units.
signum' :: Num a => Quantity a u -> Quantity a One Source
The sign (signum
) of a quantity gives a dimensionless result.
fromInteger' :: Integral a => Quantity Integer u -> Quantity a u Source
Convert an Integer
quantity into any Integral
type (fromInteger
).
Unit-safe Fractional
operations
(/:) :: (Fractional a, w ~~ (u /: v)) => Quantity a u -> Quantity a v -> Quantity a w infixl 7 Source
Division (/
) of quantities divides the units.
recip' :: (Fractional a, w ~~ (One /: u)) => Quantity a u -> Quantity a w Source
Reciprocal (recip
) of quantities reciprocates the units.
fromRational' :: Fractional a => Quantity Rational u -> Quantity a u Source
Convert a Rational
quantity into any Fractional
type (fromRational
).
Unit-safe Floating
operations
sqrt' :: (Floating a, w ~~ (u ^: 2)) => Quantity a w -> Quantity a u Source
Taking the square root (sqrt
) of a quantity requires its units
to be a square. Fractional units are not currently supported.
TH constructor for quantities/units
u :: QuasiQuoter Source
The u
quasiquoter may be used to create units or quantities;
its meaning depends on the context:
- in a declaration context, it creates new base and derived units
from a comma-separated list of names with optional definitions,
for example
[
;u
|kg, m, s, N = kg * m/s^2|] - in a type context, it parses a single unit and converts it into
the corresponding type, so
[
becomes the typeu
|m/s|]
of kindBase
"m" /:Base
"s"Unit
; - in an expression context, it can be used to create a
Quantity
corresponding to a numeric literal, for example[
is an expression of typeu
|42 m|]
,Quantity
Integer
(Base
"m")[
is an expression of typeu
|-2.2 m|]
, andQuantity
Double
(Base
"m")[
alone is a function of typeu
|m|]a ->
;Quantity
a (Base
"m") - in a pattern context, it can be used to match on a particular
value of a quantity with an
Integer
orRational
representation type, for examplef [
is a (partial) function of typeu
| 42 m |] =True
.Quantity
Integer
[u|m|] -> Bool
Declaring units
declareBaseUnit :: String -> Q [Dec] Source
Declare a canonical base unit of the given name, which must not contain any spaces, e.g.
declareBaseUnit "m"
produces
type instance MkUnit "m" = Base "m" instance HasCanonicalBaseUnit "m"
This can also be written [
.u
| m |]
declareDerivedUnit :: String -> String -> Q [Dec] Source
Declare a derived unit with the given name and definition, e.g.
declareDerivedUnit "N" "kg m / s^2"
produces
type instance MkUnit "N" = Base "kg" *: Base "m" /: Base "s" ^: 2
This can also be written [
.u
| N = kg m / s^2 |]
declareConvertibleUnit :: String -> Rational -> String -> Q [Dec] Source
Declare a base unit of the given name, which is convertible to the canonical base unit, e.g.
declareConvertibleUnit "kilobyte" 1024 "byte"
produces
type instance MkUnit "kilobyte" = Base "kilobyte" instance HasCanonicalBaseUnit "kilobyte" where type CanonicalBaseUnit "kilobyte" = Base "byte" conversionBase _ = [u| 1 % 1024 kilobyte/byte |]
This can also be written [
.
See Data.UnitsOfMeasure.Convert for more information about conversions.u
| kilobyte = 1024 byte |]
Automatic unit conversions
convert :: forall a u v. (Fractional a, Convertible u v) => Quantity a u -> Quantity a v Source
Automatically convert a quantity with units u
so that its units
are v
, provided u
and v
have the same dimension.
Pay no attention to that man behind the curtain
type family MkUnit s :: Unit Source
This type family is used for translating unit names (as
type-level strings) into units. It will be Base
for base units
or expand the definition for derived units.
The instances displayed by Haddock are available only if Data.UnitsOfMeasure.Defs is imported.
type MkUnit "A" = Base "A" Source | |
type MkUnit "C" = (*:) (MkUnit "s") (MkUnit "A") Source | |
type MkUnit "F" = (/:) (MkUnit "C") (MkUnit "V") Source | |
type MkUnit "Hz" = (/:) One ((^:) (MkUnit "s") 1) Source | |
type MkUnit "J" = (*:) (MkUnit "N") (MkUnit "m") Source | |
type MkUnit "K" = Base "K" Source | |
type MkUnit "N" = (/:) ((*:) (MkUnit "kg") (MkUnit "m")) ((^:) (MkUnit "s") 2) Source | |
type MkUnit "Pa" = (/:) (MkUnit "N") ((^:) (MkUnit "m") 2) Source | |
type MkUnit "V" = (/:) (MkUnit "W") (MkUnit "A") Source | |
type MkUnit "W" = (/:) (MkUnit "J") (MkUnit "s") Source | |
type MkUnit "au" = Base "au" Source | |
type MkUnit "cd" = Base "cd" Source | |
type MkUnit "d" = Base "d" Source | |
type MkUnit "ft" = Base "ft" Source | |
type MkUnit "g" = Base "g" Source | |
type MkUnit "h" = Base "h" Source | |
type MkUnit "ha" = Base "ha" Source | |
type MkUnit "in" = Base "in" Source | |
type MkUnit "kg" = Base "kg" Source | |
type MkUnit "km" = Base "km" Source | |
type MkUnit "l" = Base "l" Source | |
type MkUnit "m" = Base "m" Source | |
type MkUnit "mi" = Base "mi" Source | |
type MkUnit "min" = Base "min" Source | |
type MkUnit "mol" = Base "mol" Source | |
type MkUnit "mph" = (/:) (MkUnit "mi") (MkUnit "h") Source | |
type MkUnit "ohm" = (/:) (MkUnit "V") (MkUnit "A") Source | |
type MkUnit "rad" = Base "rad" Source | |
type MkUnit "s" = Base "s" Source | |
type MkUnit "sr" = Base "sr" Source | |
type MkUnit "t" = Base "t" Source |
type family Pack u :: Unit Source
Pack up a syntactic representation of a unit as a unit. For example:
Pack
([]:/
[]) =One
Pack
(["m"]:/
["s","s"]) =Base
"m"/:
Base
"s" ^: 2
This is a perfectly ordinary closed type family. Pack
is a left
inverse of Unpack
up to the equational theory of units, but it is
not a right inverse (because there are multiple list
representations of the same unit).
type family Unpack u :: UnitSyntax Symbol Source
Unpack a unit as a syntactic representation, where the order of units is deterministic. For example:
Unpack
One
= []:/
[]
Unpack
(Base
"s"*:
Base
"m") = ["m","s"]:/
[]
This does not break type soundness because
Unpack
will reduce only when the unit is entirely constant, and
it does not allow the structure of the unit to be observed. The
reduction behaviour is implemented by the plugin, because we cannot
define it otherwise.