Prolog no_duplicate函数

Nat*_*han 4 prolog prolog-dif

我正在尝试编写一个简单的过程来检查列表是否有任何重复.这是我到目前为止所尝试的:

% returns true if the list has no duplicate items.
no_duplicates([X|XS]) :- member(X,XS) -> false ; no_duplicates(XS).
no_duplicates([]) :- true. 
Run Code Online (Sandbox Code Playgroud)

如果我试试no_duplicates([1,2,3,3]).它说的是真的.为什么是这样?我可能在这里误解了Prolog,但任何帮助都表示赞赏.

fal*_*lse 7

回答你的问题:你的解决方案实际上失败了no_duplicates([1,2,3,3]).所以没有问题.

现在进行查询:

?- A = 1, no_duplicates([A, 2]).
A = 1.
?-        no_duplicates([A, 2]), A = 1.
Run Code Online (Sandbox Code Playgroud)

它们都意味着相同,所以我们应该期待Prolog会产生相同的答案.(更确切地说,我们期望相同的忽略错误和非终止).

但是,提出的四种解决方案不同 而那个没有的,不同的是:

?- A = 2, no_duplicates([A, 2]).
false.
?-        no_duplicates([A, 2]), A = 2.
Run Code Online (Sandbox Code Playgroud)

请注意,它总是第二个产生麻烦的查询.要解决这个问题,我们需要一个很好的答案no_duplicates([A, 2]).它不可能false,因为有一些值A可以使它成为现实.喜欢A = 1.也不是真的,因为有些价值观不合适,比如A = 2.

另一种可能性是instantiation_error在这种情况下发布.含义:我没有足够的信息,所以我最好停下来,而不是弄乱可能不正确的信息.

理想情况下,我们得到一个涵盖所有可能解决方案的答案.这个答案dif(A, 2)意味着所有A与2不同的是解决方案.

dif/2是最古老的内置谓词之一,Prolog 0确实拥有它.不幸的是,后来的发展在Prolog I和Edinburgh Prolog以及ISO Prolog中丢弃了它.

但是,包括SICStus,YAP,SWI在内的现有系统都提供它.还有就是一种安全的方式接近dif/2安全的ISO-序言

no_duplicates(Xs) :-
   all_different(Xs). % the common name

all_different([]).
all_different([X|Xs]) :-
   maplist(dif(X),Xs).
   all_different(Xs).
Run Code Online (Sandbox Code Playgroud)

见: