Question

This is my code:

numeral(0).
numeral(succ(X)) :- numeral(X).

convertToD(A,0).  
convertToD(succ(S), Y) :- numeral(S), Y1 is Y-1, convertToD(S, Y1). 

Why does this give me such an output?

convertTo(succ(succ(0)), N).
N = 0 ;
ERROR: convertTo/2: Arguments are not sufficiently instantiated
Was it helpful?

Solution

Well, you're getting more than one answer because of this:

convertToD(A,0).

What you mean to have here is convertToD(0, 0), because otherwise you're saying "convertToD is true between anything and 0" when you mean "convertToD is 0 for 0." This is also why Prolog thinks you have multiple results.

Having given it some thought and noticed a question this question is a duplicate of, I see what you were trying to accomplish with the second clause. What you're trying to do is emulate the clpfd solution from there in ordinary Prolog. With clpfd:

convertToD(succ(S), Y) :- numeral(S), Y0 #= Y-1, convertToD(S, Y0).

A straightforward copy of that into vanilla Prolog gets us your code here, but what doesn't happen is all the magic clpfd brings to the table. Without clpfd, it's very difficult to make a predicate that works for any instantiation combination and never loops. One thing that helps is to move the arithmetic last:

convertToD(succ(S), Y) :- numeral(S), convertToD(S, Y1), succ(Y1, Y).

This gets us a predicate with all the desirable properties, except it loops here:

?- convertToD(X, 3).
X = s(s(s(0))) ;
^CAction (h for help) ? abort

I've messed with this with when/2 and var/1/nonvar/1 and haven't been able to solve that little problem.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top