Tuesday, November 13, 2012

Three inconvenient things of F# Units of Measure

1. Becoming error when calculate between SI one and its scaled variation

For example, conversion between meter and kilometer is not self‐evident in F#.
For help type #help;;

> open Microsoft.FSharp.Data.UnitSystems.SI.UnitSymbols;;
> let a = 195<m>;;

val a : int<m> = 195

> [<Measure>] type km;;

[<Measure>]
type km

> let b = 42<km>;;

val b : int<km> = 42

> a + b;;

  a + b;;
  ----^

stdin(5,5): error FS0001: The unit of measure 'km' does not match the unit of measure 'm'
In this case, we must create some functions to convert these.

2. Becoming error when calculate with non-SI one

For example, conversion between meter and mile is not self‐evident in F#.
For help type #help;;

> open Microsoft.FSharp.Data.UnitSystems.SI.UnitSymbols;;
> let a = 10<m>;;

val a : int<m> = 10

> [<Measure>] type mile;;

[<Measure>]
type mile

> let b = 9<mile>;;

val b : int<mile> = 9

> a + b;;

  a + b;;
  ----^

stdin(5,5): error FS0001: The unit of measure 'mile' does not match the unit of measure 'm'
In this case too, we must create some functions to convert these.

3. Cannot instantiate collection of units values with range notation

Surprisingly, F# cannot allow to instantiate collection of units values with range notation.
For help type #help;;

> open Microsoft.FSharp.Data.UnitSystems.SI.UnitSymbols;;
> seq {1<g>..10<g>};;

  seq {1<g>..10<g>};;
  -----^^^^^

stdin(7,6): error FS0001: The type 'int<g>' does not match the type 'int'
In this case, we must do the redundant operation like below:
> seq { for i in [1..10] -> i * 1<g> };;
val it : seq<int<g>> = seq [1; 2; 3; 4; ...]

No comments:

Post a Comment