F# Using LanguagePrimitives to preserve or set units


When a function doesn't preserve units automatically due to lower-level operations, the LanguagePrimitives module can be used to set units on the primitives that support them:

/// This cast preserves units, while changing the underlying type
let inline castDoubleToSingle (x : float<'u>) : float32<'u> =
    LanguagePrimitives.Float32WithMeasure (float32 x)

To assign units of measure to a double-precision floating-point value, simply multiply by one with correct units:

type USD

let toMoneyImprecise (amount : float) =
   amount * 1.<USD>

To assign units of measure to a unit-less value that isn't System.Double, for example, arriving from a library written in another language, use a conversion:

open LanguagePrimitives

let toMoney amount =
   amount |> DecimalWithMeasure<'u>

Here are the function types reported by F# interactive:

val toMoney : amount:decimal -> decimal<'u>
val toMoneyImprecise : amount:float -> float<USD>