General power function with units

The snippet demonstrates how to write a general power function that has correct type involving units-of-measure. The function uses numbers represented using types. The snippet is mainly an example of what can be done (not recommended for the real world).

Copy Source
Copy Link
Tools:
 1: [<Measure>] type cm
 2: 
 3: // Represents a number with units of measure powered to the
 4: // number's value (e.g "(S (S O))" has type Num<cm, cm^3>)
 5: type Num<[<Measure>] 'M, [<Measure>] 'N> = 
 6:   | O_ of int * float<'N>
 7:   | S_ of int * Num<'M, 'N / 'M>
 8: 
 9: // Constructors that hide that simplify the creation  
10: let O : Num<'M, 'M> = O_ (1, 0.0<_>)
11: let S n = match n with O_(i, _) | S_(i, _) -> S_(i + 1, n)
12: 
13: // Type-safe power function with units of measure
14: let pow (x:float<'M>) ((O_(i, _) | S_(i, _)):Num<'M, 'M 'N>) : float<'M 'N> =
15:   // Unsafe hacky implementation, which is hidden
16:   // from the user (for simplicity)
17:   unbox ((float x) ** float i)
18: 
19: let res = pow 2.0<cm> (S (S O))
Multiple items
module Measure

from Microsoft.FSharp.Math

--------------------

type MeasureAttribute =
  class
    inherit System.Attribute
    new : unit -> MeasureAttribute
  end

Full name: Microsoft.FSharp.Core.MeasureAttribute

  type: MeasureAttribute
  implements: System.Runtime.InteropServices._Attribute
  inherits: System.Attribute
[<Measure>]
type cm

Full name: Snippet.cm
type Num<'M,'N> =
  | O_ of int * float<'N>
  | S_ of int * Num<'M,'N/'M>

Full name: Snippet.Num<_,_>

  type: Num<'M,'N>
  implements: System.IEquatable<Num<'M,'N>>
  implements: System.Collections.IStructuralEquatable
  implements: System.IComparable<Num<'M,'N>>
  implements: System.IComparable
  implements: System.Collections.IStructuralComparable
union case Num.O_: int * float<'N> -> Num<'M,'N>
Multiple items
val int : 'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------

type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>

  type: int<'Measure>
  implements: System.IComparable
  implements: System.IConvertible
  implements: System.IFormattable
  implements: System.IComparable<int<'Measure>>
  implements: System.IEquatable<int<'Measure>>
  inherits: System.ValueType


--------------------

type int = int32

Full name: Microsoft.FSharp.Core.int

  type: int
  implements: System.IComparable
  implements: System.IFormattable
  implements: System.IConvertible
  implements: System.IComparable<int>
  implements: System.IEquatable<int>
  inherits: System.ValueType
Multiple items
val float : 'T -> float (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.float

--------------------

type float<'Measure> = float

Full name: Microsoft.FSharp.Core.float<_>

  type: float<'Measure>
  implements: System.IComparable
  implements: System.IConvertible
  implements: System.IFormattable
  implements: System.IComparable<float<'Measure>>
  implements: System.IEquatable<float<'Measure>>
  inherits: System.ValueType


--------------------

type float = System.Double

Full name: Microsoft.FSharp.Core.float

  type: float
  implements: System.IComparable
  implements: System.IFormattable
  implements: System.IConvertible
  implements: System.IComparable<float>
  implements: System.IEquatable<float>
  inherits: System.ValueType
union case Num.S_: int * Num<'M,'N/'M> -> Num<'M,'N>
val O : Num<'M,'M>

Full name: Snippet.O
val S : Num<'u,'v> -> Num<'u,'u 'v>

Full name: Snippet.S
val n : Num<'u,'v>

  type: Num<'u,'v>
  implements: System.IEquatable<Num<'u,'v>>
  implements: System.Collections.IStructuralEquatable
  implements: System.IComparable<Num<'u,'v>>
  implements: System.IComparable
  implements: System.Collections.IStructuralComparable
val i : int

  type: int
  implements: System.IComparable
  implements: System.IFormattable
  implements: System.IConvertible
  implements: System.IComparable<int>
  implements: System.IEquatable<int>
  inherits: System.ValueType
val pow : float<'M> -> Num<'M,'N> -> float<'N>

Full name: Snippet.pow
val x : float<'M>

  type: float<'M>
  implements: System.IComparable
  implements: System.IConvertible
  implements: System.IFormattable
  implements: System.IComparable<float<'M>>
  implements: System.IEquatable<float<'M>>
  inherits: System.ValueType
val unbox : obj -> 'T

Full name: Microsoft.FSharp.Core.Operators.unbox
val res : float<cm ^ 3>

Full name: Snippet.res

  type: float<cm ^ 3>
  implements: System.IComparable
  implements: System.IConvertible
  implements: System.IFormattable
  implements: System.IComparable<float<cm ^ 3>>
  implements: System.IEquatable<float<cm ^ 3>>
  inherits: System.ValueType

More information

Link: http://fssnip.net/4H
Posted: 3 years ago
Author: Tomas Petricek (website)
Tags: fsharp, types, units, units of measure