В дополнение к другим уже опубликованным версиям рассмотрите также версию без 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).
Такой шаблон называется fold (слева направо), и мы можем записать его эквивалентно, используя `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: Arguments are not sufficiently instantiated
Чтобы сделать это правильным решением, используйте ограничения, такие как 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.
person
mat
schedule
11.11.2011