除了已经发布的其他版本之外,还可以考虑一个没有 if-then-else 的版本,并为关系使用更具描述性的名称(将列表与其最小值相关联):
list_min([L|Ls], Min) :- list_min(Ls, L, Min).
list_min([], Min, Min).
list_min([L|Ls], Min0, Min) :-
Min1 is min(L, Min0),
list_min(Ls, Min1, Min).
这样的模式称为折叠(从左至右),我们可以用`foldl/4等效地写它:
list_min([L|Ls], Min) :- foldl(min_, Ls, L, Min).
min_(A, B, Min) :- Min is min(A, B).
查询示例:
?- list_min([1,0,2], Min).
Min = 0.
请注意,虽然这不是一个真正的关系,并且由于使用了低级算术,因此不能在所有方向上使用。例如,如果我们尝试在另一个方向使用它,我们会得到:
?- list_min([X,Y], 3)。
ERROR: is/2: 参数没有充分实例化
要使其成为真正的解决方案,请使用 约束,例如 clpfd 和 clpq。例如,对于 整数 的解决方案:
:- use_module(library(clpfd)).
list_min([L|Ls], Min) :- foldl(min_, Ls, L, Min).
min_(A, B, Min) :- Min #= min(A, B).
这适用于所有方向:
?- list_min([X,Y], 3).
X in 3..sup,
3#=min(Y, X),
Y in 3..sup.