Type level encoding of natural numbers in F# -
i trying encode natural numbers type in f# able check equality @ compile-time instead of run-time. best come was
type nat<'t> = abstract member asint : int type z() = interface nat<z> member __.asint = 0 type s<'p>(prev : nat<'p>) = interface nat<s<'p>> member __.asint = 1 + prev.asint type tnat = static member 0 = z() :> nat<z> static member succ (prev : nat<'p>) = s(prev) :> nat<s<'p>> static member 1 = tnat.succ(tnat.zero) static member 2 = tnat.succ(tnat.one)
i'm not sure if i'm happy code. can done in better (or easier) way overlooking?
and can ensure asint
calculated @ compile time?
in code, if try:
tnat.two = tnat.succ(tnat.one)
will yield false.
here's alternative implementation without interfaces:
type z = z static member (!!) z = 0 type s<'a> = s of 'a static member inline (!!) (s a) = !!a + 1 let inline asint x = !! x let 1 = s z let 2 = s 1
by using discriminated unions benefit of structural equality well, in solution have both type (at compile time) , value (at run time) equality.
by using inline, method called resolved @ compile time.
Comments
Post a Comment