Solution
%% The 2-place wrapper predicate. It calls the 3-place predicate %% max. The accumulator is instantiated to the head of the input list. max([Head|Tail],Max) :- max(Tail,Head,Max). %% The 3-place predicate max uses an accumulator to store the greatest %% element that has been found so far. The first argument is the part %% of the list that has not been processed so far, the second argument %% is the accumulator, and the third argument is for the final result. %% If the list is empty, the value that is in the accumulator (i.e., %% the current maximal element) is the maximum of the whole list. max([],Max,Max). %% If the head is greater than the value of the accumulator, then the %% head is greatest element that we have found so far. It becomes our %% new accumulator value. max([Head|Tail],Acc,Max) :- Head > Acc, max(Tail,Head,Max). %% If the head is smaller or equal to the accumulator value, the %% accumulator is still the greatest element that we have found so %% far. So, the accumulator stays as it is. max([Head|Tail],Acc,Max) :- Head =< Acc, max(Tail,Acc,Max).