I tried to implement Peano arithmetic on the type-level in Ocaml and came through a problem:
module Nat = struct
type zero = Z
type 'a succ = S
type 'a nat = Zero : zero nat | Succ : 'a nat -> 'a succ nat
end
Now, if I want to implement add, the two axioms regarding this operation are that:
I tried
let rec add : type n1 n2. n1 nat -> n2 nat -> 'a nat =
fun a b -> match b with Zero -> a | Succ b' -> Succ (add a b')
But
9 | fun a b -> match b with Zero -> a | Succ b' -> Succ (add a b')
^
Error: This expression has type n1 nat but an expression was expected of type
'a nat
The type constructor n1 would escape its scope
And I have an error for the second branch too:
let rec add : type n1 n2. n1 nat -> n2 nat -> 'a nat =
fun a b -> match b with Succ b' -> Succ (add a b') | Zero -> a
9 | fun a b -> match b with Succ b' -> Succ (add a b') | Zero -> a
^^^^^^^^^^
Error: This expression has type 'a succ nat
but an expression was expected of type 'a nat
The type variable 'a occurs inside 'a succ
If I put the Succ inside the recursive call:
let rec add : type n1 n2. n1 nat -> n2 nat -> 'a nat =
fun a b -> match b with Succ b' -> add (Succ a) b' | Zero -> a
9 | fun a b -> match b with Succ b' -> add (Succ a) b' | Zero -> a
^
Error: This expression has type n1 nat but an expression was expected of type
'a nat
The type constructor n1 would escape its scope
When I add another type variable, the error changes:
let rec add : type n1 n2 n3. n1 nat -> n2 nat -> n3 nat =
fun a b -> match b with Succ b' -> add (Succ a) b' | Zero -> a
9 | fun a b -> match b with Succ b' -> add (Succ a) b' | Zero -> a
^
Error: This expression has type n1 nat but an expression was expected of type
n3 nat
Type n1 is not compatible with type n3
I'm not used to GADT so I'm kind of lost as how to solve this typing problem and if it can even be solved.

