考虑my answer 中提供的代码到相关问题“Finding the max in a list - Prolog”。
上述答案中的代码基于meta-predicatefoldl/4。
在这里,我将展示如何使用元谓词 combine/3 和 reduce/3 来实现。一、combine/3:
:- meta_predicate combine(3,?,?).
combine( _ ,[] ,[]).
combine(P_3,[X|Xs],Ys) :-
list_prev_combined_(Xs,X,Ys,P_3).
:- meta_predicate list_combined_(?,?,3).
list_combined_([] ,[], _ ).
list_combined_([X|Xs],Ys,P_3) :-
list_prev_combined_(Xs,X,Ys,P_3).
:- meta_predicate list_prev_combined_(?,?,?,3).
list_prev_combined_([] ,X ,[X] , _ ).
list_prev_combined_([X1|Xs],X0,[Y|Ys],P_3) :-
call(P_3,X0,X1,Y),
list_combined_(Xs,Ys,P_3).
在combine/3 的基础上,我们可以定义reduce/3 如下:
:- meta_predicate reduce(3,?,?).
reduce(P_3,[X|Xs],V) :-
list_aka_prev_reduced_(Xs,Xs,X,V,P_3).
:- meta_predicate list_aka_prev_reduced_(?,?,?,?,3).
list_aka_prev_reduced_([] ,_ ,V ,V, _ ).
list_aka_prev_reduced_([_|_],Xs,X0,V,P_3) :-
list_prev_combined_(Xs,X0,Ys,P_3),
reduce(P_3,Ys,V).
关于它们各自的证明树的形状,foldl/4 类似于列表,而combine/3 和reduce/3 类似于平衡二叉树。
考虑以下查询:
:- use_module(library(lambda)).
?- foldl(\X^Y^f(X,Y)^true, [1,2,3,4,5,6,7], 0,S).
S = f(7,f(6,f(5,f(4,f(3,f(2,f(1,0))))))).
?- combine(\X^Y^f(X,Y)^true, [1,2,3,4,5,6,7], S).
S = [f(1,2),f(3,4),f(5,6),7].
?- reduce(\X^Y^f(X,Y)^true, [1,2,3,4,5,6,7], S).
S = f(f(f(1,2),f(3,4)),f(f(5,6),7)).
reduce/3 基于combine/3 并应用它,直到所有项目合并为一个:
?- 结合(\X^Y^f(X,Y)^true, [1,2,3,4,5,6,7], S)。
S = [f(1,2),f(3,4),f(5,6),7]。
?- 结合(\X^Y^f(X,Y)^true, [f(1,2),f(3,4),f(5,6),7], S)。
S = [f(f(1,2),f(3,4)),f(f(5,6),7)]。
?- 结合(\X^Y^f(X,Y)^true, [f(f(1,2),f(3,4)),f(f(5,6),7)], S )。
S = [
f(f(f(1,2),f(3,4)),f(f(5,6),7))]。
?- 减少(\X^Y^f(X,Y)^true, [1,2,3,4,5,6,7], S)。
S =
f(f(f(1,2),f(3,4)),f(f(5,6),7))。
让我们用它来获取列表[1,5,2,4,3,8,7,2]中的最大整数Max:
:- 使用模块(库(clpfd))。
?- 减少(\X^Y^XY^(XY #= max(X,Y)), [1,5,2,4,3,8,7,2], Max)。
最大值 = 8。
℅ 如果不能使用 clpfd,只需使用 is/2 代替 (#=)/2:
?- 减少(\X^Y^XY^(XY
is max(X,Y)), [1,5,2,4,3,8,7,2], Max)。
最大值 = 8。