fal*_*lse 17 prolog logical-purity
memberchk/2是一个通常定义的谓词,它是这样定义的member/2:
memberchk(X, Xs) :-
once(member(X, Xs)).
Run Code Online (Sandbox Code Playgroud)
因此它只能成功地获得第一个答案member/2.它的完整程序意义不适合纯粹的关系.作为其非关系行为的一个例子考虑
?- memberchk(b, [X,b]), X = a.
false.
?- X = a, memberchk(b, [X,b]).
X = a.
Run Code Online (Sandbox Code Playgroud)
另一方面,在许多情况下,memberchk/2将使用充分实例化的参数调用,其中可以将其视为纯关系的有效近似.
背后的一个纯粹的关系是memberd/2(使用if_/3):
memberd(E, [X|Xs]) :-
if_(E = X, true, memberd(E, Xs) ).
Run Code Online (Sandbox Code Playgroud)
memberchk/2对于充分实例化的案例,是否还有其他可以近似的纯关系?
换句话说:是否是memberd/2一个完整的,声明性的替代品,memberchk/2或者是否仍然存在memberchk/2无法替代的合法案例memberd/2?
这是一个众所周知的例子member/2,不能用memberd/2:bridge.plPascal Van Hentenryck 给出的桥调度问题来表示。
在设置阶段member/2使用:
setup(K,Ende,Disj):-
jobs(L),
make_vars(L,K),
member([stop,_,Ende],K),
....
Run Code Online (Sandbox Code Playgroud)
因此,在这里,三元素列表中的第一个元素实际上用于选择特定任务,而memberd/2使用整个元素进行比较。因此,这setup/3留下了许多选择点(实际上是 219 个)。有些(如 SICStus)memberchk/2在这种情况下使用,从而冒着非单调性的风险。
使用以下纯替换,可避免所有选择点。
member3l([N,D,A], Plan) :-
tmember(l3_t(N,D,A), Plan).
l3_t(N,D,A, X, T) :-
X = [Ni|_],
if_(N = Ni, ( X=[N,D,A], T = true ), T = false ).
tmember(P_2, [X|Xs]) :-
if_( call(P_2, X), true, tmember(P_2, Xs) ).
Run Code Online (Sandbox Code Playgroud)
或者使用library(lambda):
member3li([N,Nd,Na], Plan) :-
tmember([N,Nd,Na]+\X^T^
( X=[Nk|_],
if_( Nk = N, ( X=[N,Nd,Na], T = true ), T = false ) ),
Plan).
Run Code Online (Sandbox Code Playgroud)
的其他用途tmember/2:
old_member(X, Xs) :-
tmember( X+\E^T^( X = E, T = true ; T = false ), Xs).
old_memberd(X, Xs) :-
tmember(=(X), Xs).
Run Code Online (Sandbox Code Playgroud)
这是一个更紧凑的表示:
member3l([N,D,A], Plan) :-
tmember({N,D,A}+\[Ni,Di,Ai]^cond_t(N = Ni, [D,A] = [Di,Ai] ), Plan).
Run Code Online (Sandbox Code Playgroud)
使用library(lambda)和cond_t/3:
cond_t(If_1, Then_0, T) :-
if_(If_1, ( Then_0, T = true ), T = false ).
Run Code Online (Sandbox Code Playgroud)