A Prolog programme getting ERROR: >/2: Arguments are not sufficiently instantiated

StackOverflow https://stackoverflow.com/questions/20070594

  •  31-07-2022
  •  | 
  •  

문제

I have created a program, list(X,Y) to check whether all the elements in list Y are smaller than X.

The codes are as follows.

list(X,[]).
list(X,[Y|Z]):-X>Y,list(X,Z).

It works fine when I type list(3,[1,2]). However, if I type list(3,Y) in order to find lists which only contain elements smaller than 3, there is an error.

?- list(3,[1,2]).
true .

?- list(3,Y).
Y = [] ;
ERROR: >/2: Arguments are not sufficiently instantiated

I have read some posts which got the same error, but I still don't understand which part of my codes goes wrong.

Here comes a similar example found from internet. greater(X,Y,Z) returns the part Z of Y that is greater than X.

greater(X,[],[]).
greater(X,[H|Y],[H|Z]) :- H>X, greater(X,Y,Z).
greater(X,[H|Y],Z) :- H=<X, greater(X,Y,Z).


?- greater(2,[1,2,3], Y).
Y = [3].

The question is, what is the difference between the codes of greater(X,Y,Z) and list(X,Y) so that there is no error when calling greater(2,[1,2,3], Y)..

Thanks for any help provided.

도움이 되었습니까?

해결책

Since - judging from your comment - you seem to be reasoning over integers: That's a textbook example for using finite domain constraints, which are available in almost all modern Prolog implementations and generalize integer arithmetic so that you can use it in all directions.

Your code works exactly as expected with, among others, B-Prolog, GNU Prolog, SICStus, SWI and YAP if you just use the finite domain constraint (#>)/2 instead of the lower-level arithmetic primitive (>)/2:

:- use_module(library(clpfd)).

list(X, []).
list(X, [Y|Z]):- X#>Y, list(X,Z).

Constraints allow you to use this predicate, which you can also express with maplist/2 as in the queries below, in all directions:

?- maplist(#>(3), [1,2]).
true.

?- maplist(#>(X), [1,2]).
X in 3..sup.

?- maplist(#>(3), [A,B]).
A in inf..2,
B in inf..2.

?- maplist(#>(X), [Y,Z]).
Z#=<X+ -1,
Y#=<X+ -1.

Even the most general query, where none of the arguments is instantiated, gives useful answers:

?- maplist(#>(X), Ls).
Ls = [] ;
Ls = [_G1022],
_G1022#=<X+ -1 ;
Ls = [_G1187, _G1190],
_G1190#=<X+ -1,
_G1187#=<X+ -1 ;
etc.

EDIT: Also the example you now added can be made much more general with finite domain constraints:

:- use_module(library(clpfd)).

greater(_, [], []).
greater(X, [H|Y], [H|Z]) :- H #> X, greater(X, Y, Z).
greater(X, [H|Y], Z) :- H #=< X, greater(X, Y, Z).

You can now use it in all directions, for example:

?- greater(X, [E], Ls).
Ls = [E],
X#=<E+ -1 ;
Ls = [],
X#>=E.

This is not possible with the original version, whose author may not have been aware of constraints.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top