Here I encode addition by 1 as wrapping in a tuple type and subtraction by 1 as extracting the second element of the tuple type:
type zero = unit * unit
type 'a minus1 = 'snd constraint 'a = unit * 'snd
type 'a plus1 = unit * 'a
So far, the encoding works:
type one = zero plus1
type two = one plus1
type two' = zero plus1 plus1
type two'' = unit * (unit * (unit * unit))
let minus1 ((), n) = n
let plus1 n = ((), n)
let zero = ((), ())
let one : one = plus1 zero
let two : two = plus1 one
let two : two = plus1 (plus1 zero)
let two : two' = two
let two : two'' = two
I'm trying to implement addition as subtracting the left-hand side by 1 and adding 1 to the right-hand side until the left-hand side is 0, but I don't know how to do such branching logic. If type-information had an or
, this would express what I'm looking for:
type ('a, 'b) plus = 'res
(constraint 'a = zero constraint 'res = 'b)
or (
constraint ('a_pred, 'b_succ) plus = 'res
constraint 'a_pred = 'a minus1
constraint 'b_succ = 'b plus1
)
Is there a way to implement plus
along these lines?