【发布时间】:2025-12-02 18:10:01
【问题描述】:
在 Prolog 中,似乎集合是使用列表来表示的。
例如,这里是来自 SWI-Prolog 的 union/3 的实现:
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 的例子。
【问题讨论】:
-
现在懒得回答了,但你至少应该看看 library(ordsets)。您还可以使用在 library(assoc) 和 SWI-Prolog 的
dict中实现的“查找表”作为一组:使用键,所有值都可以是原子true或类似的东西。它们没有为您的问题提供现成的答案,但至少它们是比您展示的更好的集合实现。
标签: list prolog set unification