10

(这是该问题的后续行动)。

如何写lead1(Xs,Ys)哪个是真的,iff是去掉所有前导词Ys的后缀。因此,这个问题现在不是删除前导s,而是关于删除前导s。Xss(s(0))0s(s(0))

与原问题相比,难点在于办案s(X)s(s(X))妥善处理。

4

2 回答 2

5

这是带有if_/3=/3的版本:

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

使用 ground first 参数的查询确定性地成功:

?- 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 = [] ;
.
.
.

但是,这可以通过在目标长度/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 = [] ;
.
.
.
于 2017-11-25T17:42:04.203 回答
2

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).

这是一些示例运行,我选择了与我对上一个答案的回答类似的示例。我们看到当 list 参数逐渐实例化时 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 是协作原语。它们的纯度在文献中有很好的记载。根据这个来源,第一个带有 corouting 的 Prolog 系统是带有 geler/2 原语的 Prolog-II。该消息来源还提到了协程对引导约束求解器的重要性。

假设用交换性测试纯度,这里是一个示例测试:

?- 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 不一定保证完整性,正如我在第一个答案中已经写的那样,我们可能需要在“最后”做一些事情。意味着在查询之后,我们可能有一组挣扎的目标。在约束规划中,我们将开始标记。

freeze/2 和 when/2 也不能通过组合目标来找到早期失败,约束求解器可以这样做。

上面的示例在没有导入的情况下使用SWI-Prolog运行,并且在 Jekejeke Prolog 中使用Minlog 扩展和导入库(term/suspend)。

于 2016-10-07T08:12:19.640 回答