1

我刚刚开始尝试使用 Prolog,我正在尝试编写一个规则来确定列表是否仅包含唯一元素。我让它在第二个变体中工作(通过否定阳性测试),但我完全不明白为什么第一个变体不起作用。

鉴于此文件:

uniqueElements([X|Y]) :-
     notmember(X, Y),
     uniqueElements(Y).

notmember(X, Y) :-
     \+ member(X, Y).

hasRepeatedElements([X|Y]) :-
     (
         member(X, Y) ->
         true
     ;   hasRepeatedElements(Y)
     ).

uniqueElements_2(X) :-
     \+ hasRepeatedElements(X).

GNU Prolog 解释器给出以下响应:

| ?- uniqueElements([1,2,3]).

no
| ?- uniqueElements([1,2,3,2,3]).

no

| ?- uniqueElements_2([1,2,3]).

yes
| ?- uniqueElements_2([1,2,3,2,3]).

no

为什么第一反应是“不”?(我本来希望 member 返回 false,被否定为 true,因此 notmemeber 在 uniqueElements 的每次迭代中都返回 true)。我想我期待 '\+' 表现得像 '!' 在 C if 子句或 Python 中的 'not' 关键字中执行。这是误会吗?

4

1 回答 1

2

uniqueElements中,您没有提供递归的基本情况:

uniqueElements([]).

如果没有该子句,当特定调用链到达空列表案例时,它不会找到任何适用的子句,这意味着fail在 Prolog 中。意思是“无法证明”。因此,您的调用uniqueElements([1,2,3])产生了等效的true && true && true && false.

现在它应该可以工作了。

hasRepeatedElements也没有为基本情况定义子句,但是它未能找到空列表中是否存在重复元素[]与其语义一致 - 它应该在第一个中发现空列表中没有重复元素地方。

在 Prolog 中,“not”的意思是“不能证明……”。

于 2012-08-08T07:23:37.563 回答