You can include the general term in the list using =.. , for example
?- conj(conj(x,y),z) =.. List. List = [conj, conj(x, y), z].
By doing this recursively, you can smooth out the full term.
A general predicate that modifies certain nodes in an input member will look something like this:
change_term(NodeChanger, Term1, Term3) :- call(NodeChanger, Term1, Term2), change_term(NodeChanger, Term2, Term3), !. change_term(NodeChanger, Term1, Term2) :- Term1 =.. [Functor | SubTerms1], change_termlist(NodeChanger, SubTerms1, SubTerms2), Term2 =.. [Functor | SubTerms2]. change_termlist(_, [], []). change_termlist(NodeChanger, [Term1 | Terms1], [Term2 | Terms2]) :- change_term(NodeChanger, Term1, Term2), change_termlist(NodeChanger, Terms1, Terms2).
If you now define:
conj_changer(conj(X, Y), (X, Y)).
then you can define your reduction predicate:
reduce(Term1, Term2) :- change_term(conj_changer, Term1, Term2).
Using:
?- reduce(conj(conj(x,y),z), ReducedTerm). ReducedTerm = ((x, y), z).
You have to be careful, but as you define a NodeChanger , certain definitions can do a change_term/3 loop. Maybe someone can improve this.