Units of Measure in F# Type Providers
Use ProvidedMeasureBuilder to annotate numeric types exposed by a type provider with F# units of measure (e.g. float<kg>).
Standard SI Units
Use ProvidedMeasureBuilder.SI to reference standard units from
Microsoft.FSharp.Data.UnitSystems.SI. Pass either the unit symbol (e.g. "kg") or the
unit name in lowercase (e.g. "kilogram"):
let kg = ProvidedMeasureBuilder.SI "kg" // UnitSymbols.kg
let m = ProvidedMeasureBuilder.SI "m" // UnitSymbols.m
let s = ProvidedMeasureBuilder.SI "s" // UnitSymbols.s
let kelvin = ProvidedMeasureBuilder.SI "kelvin" // UnitNames.kelvin
Annotating Types with Units
Use ProvidedMeasureBuilder.AnnotateType to produce annotated numeric types such as float<kg>:
let kg = ProvidedMeasureBuilder.SI "kg"
let floatKg = ProvidedMeasureBuilder.AnnotateType(typeof<float>, [ kg ])
// floatKg represents float<kg>
let weightProp =
ProvidedProperty("WeightKg", floatKg, isStatic = true,
getterCode = fun _args -> <@@ 70.0 @@>)
myType.AddMember weightProp
Compound Units
ProvidedMeasureBuilder provides combinators for composing units:
let kg = ProvidedMeasureBuilder.SI "kg"
let m = ProvidedMeasureBuilder.SI "m"
let s = ProvidedMeasureBuilder.SI "s"
// Product: kg·m
let kgTimesM = ProvidedMeasureBuilder.Product(kg, m)
// Ratio: kg/m
let kgPerM = ProvidedMeasureBuilder.Ratio(kg, m)
// Square: m²
let mSquared = ProvidedMeasureBuilder.Square(m)
// Acceleration: m/s²
let accel = ProvidedMeasureBuilder.Ratio(m, ProvidedMeasureBuilder.Square(s))
// Inverse: 1/s (frequency in Hz)
let perSecond = ProvidedMeasureBuilder.Inverse(s)
// Dimensionless
let one = ProvidedMeasureBuilder.One
Non-Standard (Custom) Units
To expose a custom unit of measure (not from the SI library), define an erased
ProvidedTypeDefinition and use it directly as a measure argument to AnnotateType:
// Define a custom unit "USD" (US dollars)
let dollar = ProvidedTypeDefinition(asm, ns, "USD", None, isErased = true)
this.AddNamespace(ns, [ dollar ])
// Use the custom unit to annotate a type
let floatDollar = ProvidedMeasureBuilder.AnnotateType(typeof<float>, [ dollar ])
let priceProp = ProvidedProperty("Price", floatDollar, getterCode = fun _ -> <@@ 9.99 @@>)
myType.AddMember priceProp
Multiple Unit Arguments (Generic Types)
AnnotateType also supports generic types with multiple type arguments. For example, to produce
Vector<float, kg>:
let kg = ProvidedMeasureBuilder.SI "kg"
// Suppose vectorType is the generic definition of Vector<'T, 'U>
let annotated = ProvidedMeasureBuilder.AnnotateType(vectorType, [ typeof<float>; kg ])
val kg: obj
val m: obj
val s: obj
val kelvin: obj
val floatKg: obj
val typeof<'T> : System.Type
Multiple items
val float: value: 'T -> float (requires member op_Explicit)
--------------------
type float = System.Double
--------------------
type float<'Measure> = float
val float: value: 'T -> float (requires member op_Explicit)
--------------------
type float = System.Double
--------------------
type float<'Measure> = float
val weightProp: obj
val kgTimesM: obj
val kgPerM: obj
val mSquared: obj
val accel: obj
val perSecond: obj
val one: obj
val dollar: obj
union case Option.None: Option<'T>
val floatDollar: obj
val priceProp: obj
val annotated: obj
FSharp.TypeProviders.SDK