# Types

## Overview

We define a `Unitful.Unit{U,D}`

type to represent a unit (`U`

is a symbol, like `:Meter`

, and `D`

keeps track of dimensional information). Fields of a `Unit`

object keep track of a rational exponents and a power-of-ten prefix. We don't allow arbitrary floating point exponents of units because they probably aren't very useful. The prefixes on units (e.g. `nm`

or `km`

) may help to avoid overflow issues and general ugliness.

Usually, the user interacts only with `Units`

objects, not `Unit`

objects. This is because generically, more than one unit is needed to describe a quantity. An abstract type `Unitful.Units{N,D}`

is defined, where `N`

is always a tuple of `Unit`

objects, and `D`

is a `Unitful.Dimensions{N}`

object such as `๐`

, the object representing the length dimension.

Subtypes of `Unitful.Units{N,D}`

are used to implement different behaviors for how to promote dimensioned quantities. The concrete subtypes have no fields and are therefore immutable singletons. Currently implemented subtypes of `Unitful.Units{N,D}`

include `Unitful.FreeUnits{N,D}`

, `Unitful.ContextUnits{N,D,P}`

, and `Unitful.FixedUnits{N,D}`

. Units defined in the Unitful.jl package itself are all `Unitful.FreeUnits{N,D}`

objects.

Finally, we define physical quantity types as `Quantity{T<:Number, D, U}`

, where `D :: Dimensions`

and `U <: Units`

. By putting units in the type signature of a quantity, staged functions can be used to offload as much of the unit computation to compile-time as is possible. By also having the dimensions explicitly in the type signature, dispatch can be done on dimensions: `isa(1u"m", Unitful.Length) == true`

. This works because `Length`

is a type alias for some subset of `Unitful.Quantity`

subtypes.

## API

### Quantities

`Unitful.AbstractQuantity`

โ Type`abstract type AbstractQuantity{T,D,U} <: Number end`

Represents a generic quantity type, whose dimensions and units are specified in the type signature. The dimensions and units are allowed to be the empty set, in which case a dimensionless, unitless number results.

The type parameter `T`

represents the numeric backing type. The type parameters `D ::`

`Unitful.Dimensions`

and `U <:`

`Unitful.Units`

. Of course, the dimensions follow from the units, but the type parameters are kept separate to permit convenient dispatch on dimensions.

`Unitful.Quantity`

โ Type`struct Quantity{T,D,U} <: AbstractQuantity{T,D,U}`

A concrete subtype of `Unitful.AbstractQuantity`

.

The type parameter `T`

represents the numeric backing type. The type parameters `D ::`

`Unitful.Dimensions`

and `U <:`

`Unitful.Units`

.

`Unitful.DimensionlessQuantity`

โ Type`DimensionlessQuantity{T,U} = AbstractQuantity{T, NoDims, U}`

Useful for dispatching on `Unitful.Quantity`

types that may have units but no dimensions. (Units with differing power-of-ten prefixes are not canceled out.)

Example:

```
julia> isa(1.0u"mV/V", DimensionlessQuantity)
true
```

### Units and dimensions

`Unitful.Unitlike`

โ Type`abstract type Unitlike end`

Represents units or dimensions. Dimensions are unit-like in the sense that they are not numbers but you can multiply or divide them and exponentiate by rationals.

`Unitful.Units`

โ Type`abstract type Units{N,D,A} <: Unitlike end`

Abstract supertype of all units objects, which can differ in their implementation details. `A`

is a translation for affine quantities; for non-affine quantities it is `nothing`

.

`Unitful.FreeUnits`

โ Type`struct FreeUnits{N,D,A} <: Units{N,D,A}`

Instances of this object represent units, possibly combinations thereof. These behave like units have behaved in previous versions of Unitful, and provide a basic level of functionality that should be acceptable to most users. See Basic promotion mechanisms in the docs for details.

Example: the unit `m`

is actually a singleton of type `Unitful.FreeUnits{(Unitful.Unit{:Meter, ๐}(0, 1//1),), ๐, nothing}`

. After dividing by `s`

, a singleton of type `Unitful.FreeUnits{(Unitful.Unit{:Meter, ๐}(0, 1//1), Unitful.Unit{:Second, ๐}(0, -1//1)), ๐/๐, nothing}`

is returned.

`Unitful.ContextUnits`

โ Type`struct ContextUnits{N,D,P,A} <: Units{N,D,A}`

Instances of this object represent units, possibly combinations thereof. It is in most respects like `FreeUnits{N,D,A}`

, except that the type parameter `P`

is again a `FreeUnits{M,D}`

type that specifies a preferred unit for promotion. See Advanced promotion mechanisms in the docs for details.

`Unitful.FixedUnits`

โ Type`struct FixedUnits{N,D,A} <: Units{N,D,A} end`

Instances of this object represent units, possibly combinations thereof. These are primarily intended for use when you would like to disable automatic unit conversions. See Advanced promotion mechanisms in the docs for details.

`Unitful.Dimensions`

โ Type`struct Dimensions{N} <: Unitlike`

Instances of this object represent dimensions, possibly combinations thereof.

`Unitful.Unit`

โ Type```
struct Unit{U,D}
tens::Int
power::Rational{Int}
end
```

Description of a physical unit, including powers-of-ten prefixes and powers of the unit. The name of the unit is encoded in the type parameter `U`

as a symbol, e.g. `:Meter`

, `:Second`

, `:Gram`

, etc. The type parameter `D`

is a `Dimensions{N}`

object, for instance `Unit{:Meter, ๐}`

or `Unit{:Liter, ๐^3}`

. Note that the dimension information refers to the unit, not powers of the unit.

`Unit{U,D}`

objects are almost never explicitly manipulated by the user. They are collected in a tuple, which is used for the type parameter `N`

of a `Units{N,D,A}`

object.

`Unitful.Dimension`

โ Type```
struct Dimension{D}
power::Rational{Int}
end
```

Description of a dimension. The name of the dimension `D`

is a symbol, e.g. `:Length`

, `:Time`

, `:Mass`

, etc.

`Dimension{D}`

objects are collected in a tuple, which is used for the type parameter `N`

of a `Dimensions{N}`

object.