Prolog 中的 "logical purity" 是什么意思?

What is meant by "logical purity" in Prolog?

"logical purity" 是什么意思(在 Prolog 编程的上下文中)? tag info says "programs using only Horn clauses", but then, how would predicates like if_/3 符合条件,尽可能多地使用它进行切割,以及各种元逻辑(什么是正确的术语?var/1 等等)谓词,即低级的东西。

我知道它实现了一些 "pure" 效果,但这到底是什么意思?

如需更具体的说明,请解释 if_/3 如何符合逻辑纯,在使用中看到,例如in this answer

让我们先习惯声明式阅读逻辑程序。

声明性地,Prolog 程序声明什么是真实的

例如

natural_number(0).
natural_number(s(X)) :-
        natural_number(X).

第一个子句指出:0是一个自然数。

第二条规定:If X是自然数,then s(X)是自然数数.

现在让我们考虑更改此程序的效果。例如,当我们改变这两个子句的顺序时,会发生什么变化?

natural_number(s(X)) :-
        natural_number(X).
natural_number(0).

声明地,交换子句的顺序不会以任何方式改变程序的预期含义(析取是可交换的)。

操作上,即考虑到Prolog的实际执行策略,不同的子句顺序显然往往会产生显着差异。

然而,一个非常好的属性纯序言代码被保留,不管选择的子句顺序如何:

If a query Q succeeds with respect to a clause ordering O1, then Q does not fail with a different ordering O2.

请注意,我 不是 Q 也总是 成功 具有不同的顺序:这是因为查询也可能 循环 或产生不同顺序的错误。

对于两个查询 Q1Q2,我们说 G1 更一般化 当且仅当它包含 G2尊重句法统一。例如,查询 ?- parent_child(P, C). 比查询 ?- parent_child(0, s(0))..

更通用

现在,使用纯 Prolog 程序,另一个非常好的 属性 包含:

If a query Q1 succeeds, then every more general query Q2 does not fail.

再次注意,Q2 可能会循环而不是成功。

现在考虑您提到的 var/1 的情况,并考虑相关的谓词 nonvar/1。假设我们有:

my_pred(V) :-
        nonvar(V).

这什么时候成立?显然,当参数不是变量时它成立。

正如预期的那样,我们得到:

?- my_pred(a).
true.

但是,对于 更一般的 查询 ?- my_pred(X).,我们得到:

?- my_pred(X).
false.

这样的谓词称为非单调,因此属性不能将其视为真关系:这是因为答案false 在逻辑上意味着 没有任何解决方案 ,但在前面的示例中,我们看到 一个解决方案。因此,不合逻辑的是,通过添加约束构建的更具体查询使查询成功

?- X = a, my_pred(X).
true.

因此,对此类谓词进行推理非常复杂,以至于使用它们进行编程毫无乐趣可言。它使声明式调试变得不可能,并且很难声明任何保留的属性。例如,仅交换上述联合查询中子目标的顺序将使其失败:

?- my_pred(X), X = a.
false.

因此,我强烈建议留在 Prolog 的纯单调子集中,它允许沿着上面概述的行进行声明性推理。

CLP(FD) 约束、dif/2 等在这个意义上都是 :无论模式如何,您都不能欺骗这些谓词给出逻辑上无效的答案,订单等,你在其中使用它们。 if_/3也满足这个属性。另一方面,var/1nonvar/1integer/1!/0、带有副作用的谓词等都在逻辑上引用了声明世界之外的东西描述,因此不能被认为是纯粹的。

编辑:澄清一下:我在这里提到的不错的属性绝不是详尽无遗的。纯 Prolog 代码展示了许多其他极具价值的特性,通过这些特性您可以感受到逻辑编程的荣耀。例如,在纯 Prolog 代码中,添加一个子句最多可以 扩展 ,永远不会缩小解决方案的集合;添加一个目标最多可以缩小,永远不会扩展,等等

使用单个逻辑外原语可能而且通常会破坏其中的许多属性。因此,例如,每次使用 !/0 时,都将其视为 切入 清净之心,并为伤害这些特性而感到遗憾和羞愧。

一本好的Prolog书至少会开始介绍或包含很多提示来鼓励这种声明式的观点,引导你思考更一般的查询,保留的属性等。糟糕的Prolog书不会对此说太多并且通常最终会使用那些破坏语言最有价值和最美丽特性的不纯语言元素。

一个很棒的 Prolog 教学环境被称为 GUPU, I highly recommend to check out these ideas. Ulrich Neumerkel has generously made one core idea that is used in his environment partly available as library(diadem),它广泛使用这些属性来实现声明式调试。有关如何以声明方式调试意外失败的目标的良好示例,请参阅源文件:该库系统地构建 still 失败的查询的概括。这种推理当然可以完美地 与纯代码