Units of Measure
Prerequisites: Numbers and math
Units of measure attach units to numbers and have the compiler check them — like the physics rule that you can't add metres to seconds.
[<Measure>] type m
[<Measure>] type s
[<Measure>] type kg
let distance = 100.0<m>
let time = 9.58<s>
let speed = distance / time
printfn "%.2f m/s" (float speed)
let mass = 80.0<kg>
let momentum = mass * speed
printfn "%.1f" (float momentum)
10.44 m/s
835.1
The compiler infers speed as float<m/s> and momentum as
float<kg m/s>. Units exist only at compile time — at run time they're
plain floats, so there's no performance cost.
Catching unit mistakes
[<Measure>] type m
[<Measure>] type s
let total = 5.0<m> + 3.0<s>
main.fsx(4,22): error FS0001: The unit of measure 's' does not match the unit of measure 'm'
This is exactly the kind of error that has destroyed real spacecraft.
Conversions
[<Measure>] type m
[<Measure>] type km
[<Measure>] type mile
let metresPerKm = 1000.0<m/km>
let kmPerMile = 1.609344<km/mile>
let marathon = 26.2188<mile>
let inKm = marathon * kmPerMile
let inMetres = inKm * metresPerKm
printfn "%.3f km" (float inKm)
printfn "%.0f m" (float inMetres)
let toKm (x: float<m>) = x / metresPerKm
printfn "%.1f km" (float (toKm 5000.0<m>))
42.195 km
42195 m
5.0 km
Conversion factors are just values with a compound unit like
m/km. Multiplying cancels units the same way it does on paper.
Money, too
Units work on decimal and int as well, which is useful for keeping
currencies apart:
[<Measure>] type EUR
[<Measure>] type USD
let price = 20m<EUR>
let rate = 1.08m<USD/EUR>
let inDollars = price * rate
printfn "%M USD" (decimal inDollars)
let addPrices (a: decimal<EUR>) (b: decimal<EUR>) = a + b
printfn "%M EUR" (decimal (addPrices 20m<EUR> 5m<EUR>))
21.60 USD
25 EUR
- Declare units with
[<Measure>] type name. - Write values as
1.5<m>; strip the unit withfloat xordecimal x. - Add a unit to a plain number by multiplying:
x * 1.0<m>. - The standard SI units are predefined in
FSharp.Data.UnitSystems.SI.UnitNames(meter,second, ...).
What's next
Try the Intermediate Projects, then continue to Level 3 — Advanced: computation expressions, async programming, testing, web development, and taking F# to production.