Instantiation error in argument 2 of (>)/2

754 views Asked by At

So im trying to define natural numbers so far i did this:

 1 nat(0).                        % 0 zero is a natural, can be a stoping case
 2 nat(X):- 0>X , !,fail.         %if is less then zero then its not a natural.
 3 nat(X):- nat(Z), X is Z+1.     %if its bigger than zero do recursively for the number-1   

When i do this it gives me "Instantiation error in argument 2 of (>)/2", so he can't instantiate X in line 2 but if take out the fail he does the comparation (>) fine and has no problem instantiating X , so why he complains if i put the fail?

1

There are 1 answers

0
Paulo Moura On BEST ANSWER

If you want to generate natural numbers, you can do it without using cuts or the fail/0 control construct. For example:

nat(Nat) :-
    next_integer(0, Nat).

next_integer(I, I).
next_integer(I, K) :-
    J is I + 1,
    next_integer(J, K).

Sample call:

| ?- nat(Nat).

Nat = 0 ? ;
Nat = 1 ? ;
Nat = 2 ? ;
Nat = 3 ?
...

But this predicate will not work if instead you want to test if a term is a natural number. For example, the following call will result in a stack overflow in most Prolog systems (as we cannot generate a negative integer by incrementing from zero):

| ?- nat(-3). 

If you are using a Prolog system providing a CLP(FD) library, you can use a better definition:

nat(Nat) :-
    Nat #>= 0,
    next_integer(0, Nat).

next_integer(I, I).
next_integer(I, K) :-
    J is I + 1,
    next_integer(J, K).

And then use the same predicate for generating and testing. For example, using SWI-Prolog and library(clpfd):

?- nat(Nat).
Nat = 0 ;
Nat = 1 ;
Nat = 2 ;
Nat = 3 
...

?- nat(-3).
false.

Without using a constraints library, you will need to write something like:

nat(Nat) :-
    (   var(Nat) ->
        next_integer(0, Nat)
    ;   integer(Nat), Nat >= 0
    ).