Prolog 我怎样才能使它更具逻辑性?

Prolog 我怎样才能使它更具逻辑性?,prolog,Prolog,我试图从以下方面解决以下问题: 编写一个谓词集(InList,OutList),它接受一个任意列表作为输入,并返回一个列表,其中输入列表的每个元素只出现一次。例如,查询 set([2,2,foo,1,foo,[],[]],X)。 应该会有结果 X=[2,foo,1,[]. 我说到这里: set_([], [], []). set_([H|Bag], [H|Set], Dups):- set_(Bag, Set, Dups), \+ member(H, Set), \+ member(

我试图从以下方面解决以下问题:

编写一个谓词集(InList,OutList),它接受一个任意列表作为输入,并返回一个列表,其中输入列表的每个元素只出现一次。例如,查询

set([2,2,foo,1,foo,[],[]],X)。

应该会有结果

X=[2,foo,1,[].

我说到这里:

set_([], [], []).
set_([H|Bag], [H|Set], Dups):-
  set_(Bag, Set, Dups),
  \+ member(H, Set),
  \+ member(H, Dups).
set_([H|Bag], Set, [H|Dups]):-
  set_(Bag, Set, Dups),
  member(H, Set).

set(Bag, Set, Rest):-
    reverse(BagR, Bag),
    set_(BagR, SetR, RestR),
    reverse(SetR, Set),
    reverse(RestR, Rest).

set(Bag, Set):- set(Bag, Set, _).
但我对需要这3个
反向/2
并不感兴趣。有人能帮我想出一个更优雅的解决办法吗

我试图先做一个正确的递归解决方案,但它在试图证明问题可以“继续”时会陷入困境。例如,如果我调用
set([1,2,1],L,R)
,它将无法证明
set([1,2,2,1],[1,1])。
。如果您有关于如何避免这种情况的反馈,请告诉我

编辑1: 我最终使用了
foldl/4

pushForward(X, [Set0, Rest], [Set, Rest]):-
  \+ member(X, Set0),
  append([Set0, [X]], Set).
pushForward(X, [Set, Rest0], [Set, Rest]):-
  member(X, Set),
  append([Rest0, [X]], Rest).

set(Bag, Set, Rest):- foldl(pushForward, Bag, [[],[]], [Set, Rest]).

set(Bag, Set):- set(Bag, Set, _).

然而,这并没有真正触及问题的核心。我希望能够指定模型之间的关系,并询问“这些孔适合什么”。这个解决方案的作用正好相反——它接受一些值并将它们咀嚼,直到我们无事可做——这应该是Prolog的工作,而不是我的工作

在Prolog中,追求最简单的解决方案总是值得的,所以

  • 使用简单的递归将元素从InList复制到累加器,前提是它们尚未存在
  • 将生成的累加器反转为“超出显示”
作为一种微观优化,您可以使用memberchk/2而不是member/2来检查是否应该丢弃元素


由于您正在学习该语言,我将不展示完整的解决方案。

名称不理想。使用
库(reif)


是的,这就是反面已经在做的事情。我试图避免更多的累加器,因为
Set
Rest
感觉它们应该给我所有需要的记忆。在回顾中,我想我应该使用
append/2
,而不是坚持在子句标题中加前缀。什么是“Onlus 1遍历”?很抱歉,输入错误,在单元格中,无法编辑注释。我的意思是“只有一个反面”。类似于
set(L,S):-set(L,[],A),reverse(A,S)。
啊,我明白了,对不起!
list_nub([], []).
list_nub([E|Es], [E|Gs]) :-
   tfilter(dif(E), Es, Fs),
   list_nub(Fs, Gs).

?- Xs = [_,_,_], Ys = [_,_], list_nub(Xs, Ys).
   Xs = [_A,_A,_B], Ys = [_A,_B], dif(_A,_B)
;  Xs = [_A,_B,_A], Ys = [_A,_B], dif(_A,_B)
;  Xs = [_A,_B,_B], Ys = [_A,_B], dif(_A,_B)
;  false.
?- Xs = [_,_,_], Ys = [_], list_nub(Xs, Ys).
   Xs = [_A,_A,_A], Ys = [_A]
;  false.
?- Xs = [_,_,_], Ys = [_,_,_], list_nub(Xs, Ys).
   Xs = [_A,_B,_C], Ys = [_A,_B,_C], dif(_A,_B), dif(_A,_C), dif(_B,_C).
?- dif(A,B), Xs = [A|_], Ys = [B|_], list_nub(Xs, Ys).
   false.