纯 Prolog Peano 列表交集

问题描述

假设我们只查看 Peano 数字列表。让 假设 pure_2 Prolog 不是带有 diff/2 的 pure_1 Prolog,而是 使用带有 when/2 的 pure_1 Prolog。我们可以实现列表交集吗?

我们会退后一步,从编程语言中汲取灵感 哥德尔和 Nu-Prolog。因此对于任何需要的 if-then-else 我们会 借鉴这个答案 here。会是什么:

/* pure_2 Prolog = pure_1 Prolog with when/2 */
intersect(A,B,C) :- ??

请注意,尽管与 Gödel 和 Nu-Prolog 相反,为了在此问题上坚持 pure_2 Prolog,我们将不允许使用 ISO Prolog if-then-else (->;_) .但是我们可能会根据需要使用相隔关系here

一个测试用例是坚定的:

?- intersect([s(0)],[0],X).
X = []

?- intersect([X],[Y],Z),X = s(0),Y = 0.
X = []

解决方法

(从 thisthis 获取代码)

less(0,s(_)).
less(s(X),s(Y)) :- less(X,Y).

neq(X,Y) :- less(X,Y); less(Y,X).

eq(0,0).
eq(s(X),s(Y)) :- eq(X,Y).


horn_intersect([],_,[]).
horn_intersect(_,[],[]).

horn_intersect([X|Xs],List2,[X|Ms]) :- in(X,List2),horn_intersect(Xs,Ms).
horn_intersect([X|Xs],Ms)     :- not_in(X,Ms).

in(X,[K|_]) :- eq(X,K).
in(X,[K|Ms]) :- neq(X,K),in(X,Ms).

not_in(_,[]).
not_in(X,not_in(X,Ms).

测试:

?- horn_intersect([X],[Y],Z).
X = Y,Y = 0,Z = [0] ;
X = Y,Y = s(0),Z = [s(0)] ;
X = Y,Y = s(s(0)),Z = [s(s(0))] ;
X = Y,Y = s(s(s(0))),Z = [s(s(s(0)))] ;
X = Y,Y = s(s(s(s(0)))),Z = [s(s(s(s(0))))] ;
X = Y,Y = s(s(s(s(s(0))))),Z = [s(s(s(s(s(0)))))] ;
X = Y,Y = s(s(s(s(s(s(0)))))),Z = [s(s(s(s(s(s(0))))))] ;
X = Y,Y = s(s(s(s(s(s(s(0))))))),Z = [s(s(s(s(s(s(s(0)))))))] ;
X = Y,Y = s(s(s(s(s(s(s(s(0)))))))),Z = [s(s(s(s(s(s(s(s(0))))))))] ;
X = Y,Y = s(s(s(s(s(s(s(s(s(0))))))))),Z = [s(s(s(s(s(s(s(s(s(...)))))))))] ;
X = Y,Y = s(s(s(s(s(s(s(s(s(s(...)))))))))),Z = [s(s(s(s(s(s(s(s(s(...)))))))))] .

?- horn_intersect(X,Y,Z).
X = Z,Z = [] ;
Y = Z,Z = [] ;
X = Z,Z = [0],Y = [0|_2472] ;
X = Z,Z = [0,0],0|...],Y = [0|_2472] .
,

when/2 和 freeze/2 确实允许比 diff/2 更好的控制。这是一些代码 使用 when/2 和 freeze/2 并且这似乎是坚定的,也是失败的, 并且不会为地面输入留下选择点:

.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)

以下是一些测试稳定性的示例查询:

/* reified and delayed equality */
eq(X,R) :- when((nonvar(X),nonvar(Y)),eq2(X,R)).
eq2(0,1).
eq2(0,s(_),0).
eq2(s(_),0).
eq2(s(X),s(Y),R) :- eq(X,R).

/* reified and delayed disjunction */
or(X,or2(X,R)).
or2(0,0).
or2(0,1,1).
or2(1,1).

/* reified and delayed membership */
member(_,0).
member(X,[Y|Z],R) :-
   eq(X,H),or(H,J,R),member(X,Z,J).

/* reified and delayed if-then-else */
ite(B,P,Q) :- freeze(B,ite2(B,Q)).
ite2(1,_) :- P.
ite2(0,Q) :- Q.

/* */
intersect([],[]).
intersect([X|Y],T) :-
   ite(B,T = [X|R],T = R),B),intersect(Y,R).

这是一个测试失败稳定性的示例查询:

?- intersect([s(s(0))],[s(0)],X).
X = []

?- intersect([X],Z),X = s(s(0)),Y = s(0).
X = s(s(0)),Z = []

这是一个示例,显示了通过 when/2 延迟的内容:

?- intersect([s(_)],[0],X).
X = []

以上是用 Jekejeke Prolog 1.4.6 测试的,需要导入 library library(term/suspend) 才能使 when/2 可用。在 SWI-Prolog eq/3 中留下了一个选择点,但这和 here 是一样的问题。