所以基本上我的任务是创建一个给定List的Set,其中谓词包含2个参数。
第一个是列表,第二个是Set的值。
但不知何故,它给了我一个List,其中包含Set作为Head和带有变量的Tail:
2 ?- list2set([2,3,4,4] , X).
X = [2, 3, 4|_G2840] .
那就是代码:
list2set( [] , _).
list2set([ListH|ListT] , Set ) :- member(ListH, Set) , list2set(ListT , Set).
这似乎是我犯的一个非常基本的错误。
答案 0 :(得分:2)
首先,Prolog中没有套装。我们只列出 1 。因此,您可以做的是将列表与重复元素关联到列表中。 list_nub/2
就是这样一个定义。
根据您目前的定义:
已经list2set([], [a])
成功,这是不对的。所以你的定义太笼统了。您需要将list2set([],_)
替换为list2set([],[])
。
然后,将member(ListH, Set)
替换为member(ListH,ListT)
。
对于元素不存在的情况,您需要另一条规则:
list2set([] , []).
list2set([E|Es] , Set ) :-
member(E, Es) ,
list2set(Es , Set).
list2set([E|Es] , [E|Set] ) :-
maplist(dif(E), Es),
list2set(Es , Set).
避免冗余答案的更紧凑的定义是list_nub/2
。
1)严格来说,可以通过属性变量 2 扩展统一来实现ACI - 统一以拥有真实集合。
2)对于我的粗略理解,这需要在SICStus中实现属性变量。其他接口,如SWI或YAP中的电流很可能不足;因为他们已经为CLP(B)。有关详情,请参阅this discussion。
答案 1 :(得分:1)
填充唯一列表的好方法,保持开放性。
完成后,您可以通过电话length(Set, _)
或手动编码的等效电子邮件将其关闭(也可以将其设置为确定性的):
list2set([], S):-
% length( S, _), !
close_it(S). % use var/1
另外,请考虑拨打memberchk/2
而不是member/2
。
您还可以通过定义
来提供“智能”答案list2set(X, X).
并且说你允许在集合的表示中重复。
答案 2 :(得分:0)
这里是仅使用member / 2的定义。
% base case
set([], []).
% here we say that if the head is in the tail of the list
% we discard the head and create a set with the tail
% the exclamation mark is a "cut" which means that if member(H, T) was true
% prolog cannot backtrack from set([H|T], X) to set([H|T], [H|X]).
% this prevents giving extra answers that aren't sets, try removing it.
set([H|T], X):- member(H, T), !, set(T, X).
% and here we say that if the previous clause didn't match because
% head is not a member of tail then we create a set of the tail adding head.
set([H|T], [H|X]):- set(T, X).
希望有帮助!