В Прологе кажется, что множества представлены списками.
Например, вот реализация union/3
из SWI-Prolog:
union([], L, L) :- !.
union([H|T], L, R) :-
memberchk(H, L), !,
union(T, L, R).
union([H|T], L, [H|R]) :-
union(T, L, R).
Однако этот предикат не очень декларативен, например:
?- union([1,2,3],X,[1,2,3,4]).
X = [1, 2, 3, 4].
который должен оставить несколько точек выбора, или:
?- union(X,[1,2],[1,2,3,4]).
<infinite loop>
что даже не работает!
Помимо этого, мы также находим следующие проблемы:
?- union([1,2,3],[4,5],[1,2,3,5,4]).
false.
?- union([1,1,1],[4,5],[1,1,1,4,5]).
true.
что явно неверно, если мы действительно говорим о наборах.
Мы ясно видим, что использовать списки для обсуждения наборов непросто, потому что:
- Наборы не упорядочены, тогда как списки;
- Наборы не содержат повторяющихся значений, тогда как списки могут.
Как следствие, мы либо находим предикаты, работающие над наборами, которые сокращают возможные решения (например, эта реализация объединения, которая работает только в том случае, если набор упорядочен), либо предикаты, которые предоставляют бесполезные точки выбора в зависимости от экземпляра переменных (например, предикат объединения, который будет иметь как много точек выбора как количество перестановок в результирующем множестве).
Как следует правильно реализовать в Prolog предикаты, работающие с наборами?
Это очень общий вопрос, не относящийся к используемому здесь примеру union/3
.
dict
SWI-Prolog в виде набора: используйте ключи, все значения могут быть атомомtrue
или чем-то в этом роде. Они не дают готовых ответов на ваш вопрос, но, по крайней мере, они представляют собой лучшую реализацию, чем то, что вы показываете. - person   schedule 02.11.2016