@PauloMoura already gave you the right answer. Is there anything to learn about this? How did you encounter that problem? And how can you locate such problems systematically? I assume that you did not jump into the debugger to look at all those traces for sheer curiosity and a low on supply of animated gifs.
You rather encountered a problem. That is, you had the goal sorted([[1],[2,3]]).
which you expected to succeed, but it did not. So you had here some unexpected failure. Sometimes also called insufficiency or incompleteness. This means that the definition for sorted/1
is too specialized, it describes a set of solutions that is too small — at least it misses sorted([[1],[2,3]])
.
It often helps to minimize the problem, first. Also sorted([[],[3]])
fails, although we expect it to succeed. And sorted([[],[]])
even loops.
Understanding non-termination
Loops? That's often even easier to localize in a pure Prolog program. I will add goals false
and goals like T = []
into the program. The resulting program fragment (called a failure slice) certainly will become completely dysfunctional. But it will retain a very nice property. For: if this new fragment loops, then also the original program will loop. Here is that program that still loops:
?- sorted([[],[]]), false.
sorted([]) :- false.
sorted([_]) :- false.
sorted([L1,L2 | T]) :- T = [], L1 = [], L2 = [],
shorter(L1, L2),
sorted([L2,T]).
shorter([],_).
shorter([_|T1], [_|T2]) :- false,
shorter(T1,T2).
in other words:
sorted([[],[]]) :-
shorter([],[]),
sorted([[],[]]).
So, procedurally speaking, that rule does not (always) reduce the length of the list.
Concluding reading
Another way to understand the problem is to read the recursive rule right-to-left in the direction the arrow is pointing. Actually, :-
is meant to symbolize ←, well, 1970s style (listen to this French 1972 summerhit to until you understand). So let's try this. I will read:
sorted([L1,L2 | T]) :- shorter2(L1, L2), sorted([L2,T]).
^^^^^^^^^^^^^^ starting here
I start on the right side and interpret this as:
Provided, sorted([L2,T])
is true.
Maybe some extra remark: Now, you might get pretty uneasy. You might say: Who knows this? Maybe that is not true at all! But the point is, it's just conditional. OK?
and provided shorter(L1, L2)
is true
then, we can conclude that sorted([L1, L2|T])
is true.
So we take a list of length 2 as granted and conclude that a list of length 2 or more holds as well.
But where do we actually state that a list of length 2 holds? There is no other place than this rule. Thus: Nowhere is this stated. And thus lists of length 2 or longer will never be sorted.