Stay clean by defining comb/2 based on same_length/2 , prefix/2 , foldl/4 and select/3 :
comb (As, Bs): -
same_length (As, Full),
Bs = [_ | _],
prefix (Bs, Full),
foldl (select, Bs, As, _).
Here is an example of the query specified by OP:
?- comb([1,2,3],Xs). Xs = [1] ; Xs = [2] ; Xs = [3] ; Xs = [1,2] ; Xs = [1,3] ; Xs = [2,1] ; Xs = [2,3] ; Xs = [3,1] ; Xs = [3,2] ; Xs = [1,2,3] ; Xs = [1,3,2] ; Xs = [2,1,3] ; Xs = [2,3,1] ; Xs = [3,1,2] ; Xs = [3,2,1] ; false.
Ok! But what if the list specified as the first argument contains duplicates?
?- comb([1,1,2],Xs). Xs = [1] ; Xs = [1] % (redundant) ; Xs = [2] ; Xs = [1,1] ; Xs = [1,2] ; Xs = [1,1] % (redundant) ; Xs = [1,2] % (redundant) ; Xs = [2,1] ; Xs = [2,1] % (redundant) ; Xs = [1,1,2] ; Xs = [1,2,1] ; Xs = [1,1,2] % (redundant) ; Xs = [1,2,1] % (redundant) ; Xs = [2,1,1] ; Xs = [2,1,1] % (redundant) ; false.
Not really! Can we get rid of redundant answers? Yes, just use selectd/3 !
comb (As, Bs): -
same_length (As, Full),
Bs = [_ | _],
prefix (Bs, Full),
foldl (selectd, Bs, As, _).
So, re-run the query again with an improved comb/2 implementation!
?- comb([1,1,2],Xs). Xs = [1] ; Xs = [2] ; Xs = [1,1] ; Xs = [1,2] ; Xs = [2,1] ; Xs = [1,1,2] ; Xs = [1,2,1] ; Xs = [2,1,1] ; false.