Consider in F# a square may have a width (in feet), and a height (in feet). Its area is equal to its width times its height. Its area must be feet squared.
With units of measurement, we can force the F# compiler to validate that our area is feet squared. We define measurements with the Measure attribute.
Let us demonstrate Measure in a simple program. We introduce two units, feet and area. Feet is a simple int
unit. And area is feet squared (feet times feet).
areaOfBox
variable. This has type of int
with measurement area. It is equal to a feet unit times another.AreaOfBox
here can only be created by multiplying two "feet" measurements together. They cannot be added or computed in another way.// Use feet as a unit of measure. [<Measure>] type feet // Area is feet squared. [<Measure>] type area = feet ^ 2 // Create a width and a height in feet. let width = 10<feet> let height = 5<feet> // Get the area by multiplying the width and the height. // ... This is an area measure. let (areaOfBox : int<area>) = width * height // Write value of areaOfBox. printfn "%A" areaOfBox50
Measurements allow the F# compiler to check programs for valid units. Here we try to get the area of the box by using division.
[<Measure>] type feet [<Measure>] type area = feet ^ 2 let width = 10<feet> let height = 5<feet> // This does not compile because an area is not based on a division. // ... It must be a multiplication of feet, not a division of feet. let (areaOfBox : int<area>) = width / heighterror FS0001: The type 'int<area>' does not match the type 'int'
Units of measurement are an advanced feature in F#. For quick programs they are not useful. But for important programs where compile-time checking is valuable, they can help.
In numeric problems we want to ensure the right numbers are used. Measures can help us do this. They can ensure our variables are applied in a consistent, sane way.