I am trying to print out every possible list for a given variable. With native functions, this is working fine, but as soon as I do this with lists, prolog throws an exception.
This is my code (simplified):
first(A, L) :- L = [K|_], A = K. % First element of L is A
second(A, L) :- L = [_|R], R=[F|_], A = F. % Second element of L is A
third(A, L) :- L = [_|R], second(A, R). % Third element of L is A
konst(S) :- first(X, S), second(Y,S), third(Z,S), X >= 0, Y >= 0, Z >= 0, X =< 3, Y =< 4, Z =< 5.
| ?- konst(S).
uncaught exception: error(instantiation_error,(>=)/2)
So basically it should print out every single list between [0,0,0] and [3,4,5].
Am I missing something here?
Your definition just speaks about lists but does not define that the values are numbers. In particular, the arithmetic predicates like =<
can only compare concrete numbers: 1 =< 2
succeeds but X =< 2
leads to the instantiation error you found.
To solve your problem you can use the predicate between/3
that succeeds if the range given by the first two arguments covers the third:
p([A,B,C]) :-
between(0, 3, A),
between(0, 4, B),
between(0, 5, C).
Then the query
?- p([A,B,C]), A < 1, B < 1, C < 1.
A = B, B = C, C = 0 ;
false.
works as expected. This is due to the limitations of Prolog's built-in arithmetic. If you want to go beyond that the keyword is (finite) constraint logic programming (CLP). One of the Prolog libraries for that is clp(Z).