Exercise 09 on this page http://www.ic.unicamp.br/~meidanis/courses/mc336/2009s2/prolog/problemas/ asks you to create a predicate that contains duplicate elements in the lists.
Simple solution is simple
pack([], []). pack([H|T], [I|U]) :- split(H, T, I, P), pack(P, U).
where split split(Head, Tail, HeadGroup, Rest) is defined as
split(A, [], [A], []). split(A, [B|T], [A], [B|T]) :- A \= B. split(A, [A|T], [A|U], B) :- split(A, T, U, B).
which works great and pretty much matches the example solution presented on the aforementioned web page.
If this solution fails, these are requests of type pack(X, [[a], [b, b]]). . The correspondence between the two sets of solutions is bijective (for each A in pack(A, B) there is one and only one B ), therefore there should be a better solution.
One way to solve it is to change the evaluation order, helping the prolog to select a non-infinite branch depending on the type of argument, for example, the following
pack([], []). pack(A, B) :- ( var(A) -> A = [H|T], B = [I|U], pack(P, U), split(H, T, I, P) ; A = [H|T], B = [I|U], split(H, T, I, P), pack(P, U) ).
Two questions in this regard.
Firstly, it is incredibly ugly, so maybe the best way to choose the order of rules depending on the type of argument?
Secondly, perhaps a much more complex question is, is there a way to rewrite the solution without var(A) , and if not why?