Prolog membership predicate

后端 未结 1 817
半阙折子戏
半阙折子戏 2021-01-22 23:45

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:



        
相关标签:
1条回答
  • 2021-01-23 00:25

    Compare both clauses, are there cases, where both apply?

    member(X, [X|_T]).
    member(X, [_Y| T]) :- member(X, T).
    

    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.
    

    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.
    

    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.
    
    0 讨论(0)
提交回复
热议问题