% Modes: + means input, - means output.  As long as all inputs
% are ground, all outputs should be ground after successfully
% executing a clause.

% plus can be given three modes:
%   * the mode (+, +, -), where we interpret it as addition,
%   * the mode (-, +, +), where we interpret it as subtraction, or
%   * the mode (+, -, +), where we also interpret it as subtraction.

plus(z, N, N).

plus(s(M), N, s(P)) :- plus(M, N, P).


times(z, N, z).

% with the following subgoal order, we can give times
% the mode (+, +, -): as long as the first two inputs
% are ground, the third will be ground when we finish.
%
% we *cannot* give it the mode (-, +, +): MN is not
% ground in the first subgoal.
times(s(M), N, P) :-
    times(M, N, MN),
    plus(MN, N, P).

% with the following reversed subgoal order, we can now
% give times the mode (-, +, +) and interpret it as exact
% division.  but then we can no longer use it reliably to
% compute multiplication...
%
% note that we *cannot* give times the mode (+, -, +):
% MN is not known to be ground in the first subgoal.
times(s(M), N, P) :-
    plus(MN, N, P),
    times(M, N, MN).
