Por que usamos '!' em prólogo

Este é o código que estou tentando entender.

co(X) :- co(X,[],L).
co([],A,A):- write(A).
co([X|Xs], A, L) :- p(X-Z,A,R), !, Z1 is Z+1, co(Xs, [X-Z1|R], L). 
co([X|Xs], A, L) :- co(Xs, [X-1|A], L). 

p(X-Y,[X-Y|R],R):- !.
p(X,[H|Y], [H|Z]) :- p(X,Y,Z).

Qual é o uso de '!' e o predicado p (,,) no código acima. OU Alguém pode simplesmente adicionar comentários em todas as etapas do código acima, para que eu possa entender. Obrigado.

questionAnswers(2)

yourAnswerToTheQuestion