I'm new to Prolog and have a question to a programming exercise:
I have a program, that is for my opinion working most of the time, but with a specific query, I do not get an answer
is_number(0).
is_number(s(N)) :-
is_number(N).
numberpair(pair(X,Y)) :-
is_number(X),
is_number(Y).
?- numberpair(pair(A,B)), A=s(s(0)), B=s(s(s(0))).
So I understand, that Prolog now tries every possible number for A and B -> [0,s(0),s(s(0)),s(s(s(0))), ...] but if it founds an answer for A (namely s(s(0))
) it fails at B and in the next call, it tries the next answer for A (namely s(s(s(0)))
) and so on.
Now the thing is, that I want Prolog to stop, if it founds an answer for A, and only searches now for an answer for B.
Can anybody give me a hint, how to solve this?
Edit: As false pointed out:
The reason you won't find an answer is that your rule numberpair/1 won't terminate. The reason you won't find an answer is that Prolog enumerates your answer in a way that it first lists all possibilities for A and then the possibilities for B (note that both have infinite possibilities). What Prolog tries is to find an answer first for the clause numberpair(pair(A,B)) but and then for the following clauses A=s(s(0)) and B=s(s(s(0))). But since numberpair already won't terminate, it won't "come" so far.
If you change the order of your clauses goals and simply call A=s(s(0)) before numberpair(pair(A,B)), it will give list you all answers for the possibilities of B (note that this still won't terminate!).
?- A=s(s(0)), numberpair(pair(A,B)).
A = s(s(0)),
B = 0 ;
A = s(s(0)),
B = s(0) ;
A = B, B = s(s(0)) ;
A = s(s(0)),
B = s(s(s(0))) .
Edit 2, to provide also a version, which will enumerates in a "fair" way!
is_number(0).
is_number(s(N)) :-
is_number(N).
number_number_sum(0,A,A).
number_number_sum(s(A),B,s(C)) :-
number_number_sum(A,B,C).
numberpair(pair(X,Y)) :-
is_number(Z),
number_number_sum(X,Y,Z).
Which will provide us with
?- numberpair(pair(A,B)).
A = B, B = 0 ;
A = 0,
B = s(0) ;
A = s(0),
B = 0 ;
A = 0,
B = s(s(0)) ;
A = B, B = s(0) ;
A = s(s(0)),
B = 0 ;
A = 0,
B = s(s(s(0))) ;
A = s(0),
B = s(s(0)) ;
A = s(s(0)),
B = s(0) ;
A = s(s(s(0))),
B = 0 .