首页 文章

在Prolog中对一组独特的设置进行否定和测试

提问于
浏览
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

为什么第一个回答“不”? (我希望成员返回false,否定为true,因此在uniqueElements的每次迭代中都不会返回true) . 我想我希望''表现得像'!'在C if子句中,或在Python中的'not'关键字 . 这是误会吗?

1 回答

  • 1

    uniqueElements 中,您没有为递归提供基本案例:

    uniqueElements([]).
    

    如果没有该子句,当特定的调用链到达空列表的情况时,它不会找到任何适用的子句,这意味着Prolog中的 fail . 含义,"unprovable" . 因此,您的调用 uniqueElements([1,2,3]) 已生成相当于 true && true && true && false 的内容 .

    现在它应该工作 .

    hasRepeatedElements 也没有为基本案例定义的子句,但是它未能找到空列表中是否有重复的元素 [] 与其语义一致 - 它应该发现空列表中没有重复的元素,第一名 .

    在Prolog中,“不”意味着“无法证明......” .

相关问题