:- module nat_curry.

:- interface.

:- type nat --->
      z
    ; s(nat).

:- pred nat_add(nat, nat, nat).
:- mode nat_add(in, in, out) is det.
:- mode nat_add(out, out, in) is multi.

:- implementation.

% :- pragma promise_equivalent_clauses(nat_add/3).

nat_add(A, B, C) :-
    (
      A = z,
      B = C
    ;
      A = s(A0),
      C = s(C0),
      nat_add(A0, B, C0)
    ).

% nat_add(A::in, B::in, C::out) :-
%     (
%       A = z,
%       B = C
%     ;
%       A = s(N),
%       nat_add(N, s(B), C)
%     ).

% nat_add(A::out, B::out, C::in) :-
%     (
%       C = z,
%       A = z,
%       B = z
%     ;
%       C = s(N),
%       (
%         A = s(A0),
%         B = B0
%       ;
%         A = A0,
%         B = s(B0)
%       ),
%       nat_add(A0, B0, N)
%     ).
