Prolog成员资格谓词 [英] Prolog membership predicate
问题描述
我需要编写一个Prolog谓词,以免重复的答案出现在列表中多次出现的项目中,如以下示例查询所示:
I need to write a Prolog predicate that avoids redundant answers with items occurring multiple times in the list at hand, as shown in the following sample queries:
?- member(a, [a, b, a]).
true
?- member(X, [a, b, a]).
X = a ;
X = b ;
false.
?- member(X, [a, b, a, c, a, d, b]).
X = a ;
X = b ;
X = c ;
X = d ;
false.
我知道无论重复什么,以下内容都会输出所有内容:
I know that the following would output all of them regardless of the repeats:
member(X, [X|_]).
member(X, [_|T]) :- member(X, T).
推荐答案
比较这两个子句,是否存在同时适用的情况?
Compare both clauses, are there cases, where both apply?
member(X, [X|_T]).
member(X, [_Y| T]) :- member(X, T).
只需将两个子句的标题相互比较即可.或者,让Prolog为您做到:
Just compare both clauses' heads to each other. Or, let Prolog do it for you:
?- member(X, [X|_T]) = member(X, [_Y| T]).
X = _Y, _T = T.
因此,_Y
和X
必须相同.他们什么时候都一样?始终,如果第一个子句为真!因此,我们需要通过在第二个子句中添加另一个条件来排除这种情况.
So the _Y
and X
must be the same. When are they the same? Always, if the first clause is true! So we need to exclude that case by adding a further condition that in the second clause, they must be different.
memberd(X, [X|_T]).
memberd(X, [Y| T]) :- dif(X,Y), memberd(X, T).
?- member(X, [a, b, a, c, a, d, b]).
X = a
; X = b
; X = a
; X = c
; X = a
; X = d
; X = b
; false.
?- memberd(X, [a, b, a, c, a, d, b]).
X = a
; X = b
; X = c
; X = d
; false.
?- memberd(a, [a, b, a, c, a, d, b]).
true
; false.
可以使用我在Scryer中使用的library(reif)
来改进最后一个查询,但是 SWI :
The last query can be improved using library(reif)
which I use in Scryer, but which is also available for SICStus|SWI:
:- use_module(library(reif)).
memberd(E, [X|Xs]) :-
if_(E = X, true, memberd(E, Xs) ).
?- memberd(a, [a, b, a, c, a, d, b]).
true.
这篇关于Prolog成员资格谓词的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!