Skip to content
Units of Measure
step 1/4

Reading — step 1 of 4

Learn

~1 min readAsync and Domain Modeling

Units of measure add type-level units to numbers. Compile-time-checked, zero-cost.

[<Measure>] type m       // meters
[<Measure>] type s       // seconds
[<Measure>] type kg      // kilograms

let distance: float<m> = 100.0<m>
let time: float<s> = 9.58<s>
let speed = distance / time      // float<m/s>

The inferred unit is m/s — meters per second. The compiler tracks units through arithmetic.

Mixing fails at compile time:

let bad = distance + time      // ERROR — can't add m and s

Derived units:

[<Measure>] type N = kg * m / s^2     // newton
[<Measure>] type J = N * m              // joule

Common conversion functions — manual:

let feetToMeters (ft: float<ft>) : float<m> =
    ft * 0.3048<m/ft>

The constant has unit m/ft — multiplying gives the right unit for the result.

Currency:

[<Measure>] type USD
[<Measure>] type EUR

let wallet: decimal<USD> = 100m<USD>
let exchange = 0.92m<EUR/USD>
let inEur = wallet * exchange    // decimal<EUR>

No more accidentally adding USD to EUR. The Mars Climate Orbiter (lost in 1999 due to a unit mismatch between metric and imperial) wouldn't have happened in F#.

LanguagePrimitives.X<unit> for runtime-known units:

LanguagePrimitives.FloatWithMeasure<m> 3.14   // 3.14<m>

Caveats:

  • Only on numeric types (int, float, decimal, etc.)
  • Erased at runtime — float<m> is just a float
  • Doesn't catch ALL unit bugs (negative, ratio-based)

For financial code, scientific code, anywhere unit confusion matters — units of measure are a free correctness boost.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…