I'm playing around with F#'s type inferrer. Trying to get type level natural number working.
Here's the part that I managed to get working
type Zero = Zero type Succ<'a> = None type True = True type False = False type IsZero = | IsZero static member instance (IsZero, _ : Succ<'a>, _) = fun () -> False static member instance (IsZero, _ : Zero, _) = fun () -> True module TypeArithmetic = let inline zero x = (Inline.instance (IsZero, x) : unit -> 'a)() let dec (_ : Succ<'a>) = Unchecked.defaultof<'a> let inc (_ : 'a) = Unchecked.defaultof<Succ<'a>> The whole instance part is the same hack that makes FsControl possible. This file is also a part of my project.
So far this works. I can do things like
let a = inc Zero |> inc |> inc |> inc |> dec |> dec |> dec let b = dec a let x = zero a let y = zero b And x and y get correctly inferred to False and True respectively (with a being inferred to Succ and b being Zero).
Now the tricky part. I want to make the function add. It needs to be able to take both Succ and Zero, so again I need to use the overloading hack to make it work.
type Add = | Add static member instance (Add, _ : Zero, _ : Zero, _) = fun () -> Zero static member instance (Add, x : Succ<'a>, _ : Zero, _) = fun () -> x static member instance (Add, _ : Zero, y : Succ<'a>, _) = fun () -> y static member instance (Add, _ : Succ<'a>, _ : Succ<'b>, _) = fun () -> Inline.instance(Add, Unchecked.defaultof<Succ<Succ<'a>>>, Unchecked.defaultof<'b>) () And as far as I can tell, this should work. Shouldn't it? But it doesn't. I get an error on the Inline.instance call saying the ambiguity can't be resolved with the information given prior to that point. I kind of get why, since I'm not in an inline function it tries to resolve to a concrete type, but it doesn't have one yet. But I still have a feeling that I should be able to make it work somehow.
Is there a way to make it work?
Add, but marking your last function as inline solves the immediate problem.