General
Material
Lecture 1
Lecture 2
Lecture 3
Lecture 4
Lecture 5

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 \= [_|_].
    

Back to the exercise.