Search code examples
listprologclpfdsuccessor-arithmetics

Evaluating s(N) within a predicate's response, without losing functionality


I'm learning Prolog. I was experimenting with an elemindex predicate, with the form elemindex(element, index, list), such that, for instance, elemindex(1,0,[1,2,3,1]). or elemindex(3,0,[1,2,3,1])..

Due to instantiation restraints, I ended up with this:

elemindex(E, 0, [E|_]).
elemindex(E, s(M), [_|L]) :- elemindex(E,M,L).

However, if I query ?- elemindex(1,N,[1,2,3,1])., as in my example, Prolog responds:

N = 0
N = s(s(s(0)))
yes

This is certainly working, but I would like s(s(s(0))) to at least display as 3. Furthermore, I cannot execute queries like ?- elemindex(E, 3, [1,2,3,4])., but changing the code to use N is M+1 makes me lose the ability to evaluate the 1st kind of query.

So, my question is 2-fold:

  1. How can I get s(s(s(0))) to display as 3 in my results?
  2. How can I implement elemindex such that I can query for the element and the index?

Solution

  • #=/2 is part of the CLPFD library, which is what you'd use to "reason" over integers. The is/2 operator is designed to evaluate a completely known expression, so requires that the 2nd argument be completely bound so it's immediately evaluable. #=/2 doesn't have that restriction. You won't get the instantiation error, and Prolog will attempt to solve for the variables. Do a google search on "Prolog clpfd".

    Here's how it works with your code:

    elemindex(E, 0, [E|_]).
    elemindex(E, Index, [_|L]) :-
        Index #= N + 1,
        N #>= 0,
        elemindex(E, N, L).
    

    Then queries:

    | ?- elemindex(1,N,[1,2,3,1]).
    
    N = 0 ? a
    
    N = 3
    
    no
    | ?- elemindex(E, 3, [1,2,3,4]).
    
    E = 4 ? a
    
    no
    | ?-