Solution
%% Wrapper: calls the 3-place predicate with the accumulator argument %% being instantiated to the empty list. my_flatten(In,Out) :- my_flatten(In,[],Out). %% When the list is empty, the accumulator contains the final result. my_flatten([],Acc,Acc). %% If the list is non-empty, flatten the tail of the list. The output %% is TOut. Then use TOut to instantiate the accumulator when %% flattening the head of the list. my_flatten([H|T],Acc,Out) :- my_flatten(T,Acc,TOut), my_flatten(H,TOut,Out). %% A special clause to deal with cases where my_flatten is called with %% a non-list as first argument. This can happen because the previous %% rule calls my_flatten for the head of its input list and this head %% is not necessarily a list. In this case, the term is simply added %% to the front of the accumulator. my_flatten(X,Acc,[X|Acc]) :- X \= [], X \= [_|_].