I was trying to encode the natural numbers as a type in F# to be able to check an equality at compile-time instead of run-time. The best I could come up with was
type Nat<'T> = abstract member AsInt : int type Z() = interface Nat<Z> with member __.AsInt = 0 type S<'P>(prev : Nat<'P>) = interface Nat<S<'P>> with member __.AsInt = 1 + prev.AsInt type TNat = static member zero = Z() :> Nat<Z> static member succ (prev : Nat<'P>) = S(prev) :> Nat<S<'P>> static member one = TNat.succ(TNat.zero) static member two = TNat.succ(TNat.one) I'm not sure if I'm happy with the code. Can it be done in a better (or easier) way that I am overlooking?
And can I ensure that AsInt is calculated at compile time?
Moment<3>- which is stretching the type system too, but might be a bit nicer. See mindscapehq.com/blog/index.php/2011/09/19/…