正如@false 所推荐的,最好的方法是使用library(clpfd)
. 但是,如果您不想使用该库,则可能的解决方案是考虑两种不同的情况:
% nat(?Natural, ?Peano)
nat(N, P) :-
( integer(N) -> nat_det(N, P)
; var(N) -> nat_nondet(N, P)).
nat_det(0, 0) :- !.
nat_det(N, s(P)) :-
succ(M, N),
nat_det(M, P).
nat_nondet(0, 0).
nat_nondet(N, s(P)) :-
nat_nondet(M, P),
succ(M, N).
这里有些例子:
?- nat(2, P).
P = s(s(0)).
?- nat(2, s(s(0))).
true.
?- nat(2, s(s(s(0)))).
false.
?- nat(N, s(s(s(0)))).
N = 3.
?- N = 4, nat(N, P).
N = 4,
P = s(s(s(s(0)))).
?- nat(N, P), N = 4, !. % we know that there exist only one solution!
N = 4,
P = s(s(s(s(0)))).
?- nat(N, P).
N = P, P = 0 ;
N = 1,
P = s(0) ;
N = 2,
P = s(s(0)) ;
N = 3,
P = s(s(s(0))) ;
...