删除列表中的前导 s(s(0))

Remove leading s(s(0)) in list

(这是 的后续)。

如何写 lead1(Xs,Ys) 这是真的,当且仅当 YsXs 的后缀,所有前导 s(s(0)) 项都被删除。因此,这个问题现在不是删除前导 0s,而是关于删除前导 s(s(0))s.

相对于原题,难点在于s(X)s(s(X))的情况处理得当

Hiere 是我对上一个问题的回答的改编版。它显示了使用 when/2 而不是 freeze/2。 freeze/2 仅在第一个参数上遵循 nonvar/1 条件。 when/2 可以遵循更复杂的条件。

lead(X, Y) :- var(X), !, freeze(X, lead(X,Y)).
lead([X|Y], Z) :- \+ ground(X), !, when(ground(X), lead([X|Y],Z)).
lead([s(s(0))|X], Y) :- !, lead(X, Y).
lead(X, X).

这里有一些示例运行,我选择的示例与我对上一个答案的回答类似。当列表参数逐渐实例化时,我们看到 when/2 如何调整自己的条件:

?- lead([s(0),s(s(0)),s(s(0)),s(0)],Y).
Y = [s(0), s(s(0)), s(s(0)), s(0)].

?- lead([s(s(0)),s(s(0)),s(s(0)),s(0)],Y).
Y = [s(0)].

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(_).
X = s(_G3686),
when(ground(_G3686), lead([s(_G3686), s(s(0)), s(s(0)), s(0)], Y)).

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

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(s(_)).
X = s(s(_G3713)),
when(ground(_G3713), lead([s(s(_G3713)), s(s(0)), s(s(0)), s(0)], Y)).

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

freeze/2 和 when/2 是协程原语。它们的纯度在文献中有详细记载。根据这个 source 第一个具有协程的 Prolog 系统是具有 geler/2 原语的 Prolog-II。消息来源还提到协程对 bootstrap 约束求解器的重要性。

假设纯度是用交换性来检验的,这里是一个样本检验:

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

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

但是 freeze/2 和 when/2 不一定能保证完整性,正如我在第一个回答中所写的那样,我们可能需要做一些事情 'at the end'。意味着在查询之后我们可能有一组挣扎的目标。在约束规划中,我们将开始标记。

freeze/2 和 when/2 也无法像约束求解器那样通过组合目标发现早期失败。

上面的 eexample 使用 SWI-Prolog without some import, and in Jekejeke Prolog use the Minlog Extension 和导入库(term/suspend)运行。

这是 if_/3 and =/3 的版本:

list_suffix([],[]).
list_suffix([X|Xs],S) :-
   if_(X=s(s(0)), list_suffix(Xs,S), S=[X|Xs]).

带有地面第一个参数的查询确定性地成功:

?- list_suffix([s(0)],S).
S = [s(0)].

?- list_suffix([s(0),s(s(0))],S).
S = [s(0), s(s(0))].

?- list_suffix([s(s(0)),s(0),s(s(0))],S).
S = [s(0), s(s(0))].

?- list_suffix([s(s(0)), s(s(0)),s(0),s(s(0))],S).
S = [s(0), s(s(0))].

如果列表包含不同于 s/1 的术语,则说 f(_) 第二个列表与第一个相同:

?- list_suffix([f(_)],S).
S = [f(_G201)].

?- list_suffix([f(_)],[]).
false.

部分实例化的列表也可以工作:

?- list_suffix([X, s(s(0)),s(0),s(s(0))],S).
X = s(s(0)),
S = [s(0), s(s(0))] ;
S = [X, s(s(0)), s(0), s(s(0))],
dif(X, s(s(0))).

最一般的查询也有效,但以不公平的方式列出了答案:

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

但是,可以通过在目标前加上前缀来解决这个问题 length/2:

?- length(X,_), list_suffix(X,Y).
X = Y, Y = [] ;
X = [s(s(0))],
Y = [] ;
X = Y, Y = [_G155],
dif(_G155, s(s(0))) ;
X = [s(s(0)), s(s(0))],
Y = [] ;
X = [s(s(0)), _G79],
Y = [_G79],
dif(_G79, s(s(0))) ;
X = Y, Y = [_G155, _G158],
dif(_G155, s(s(0))) ;
X = [s(s(0)), s(s(0)), s(s(0))],
Y = [] ;
.
.
.