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:
[<Measure>]
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>