Wil*_*ess 14 logic prolog logical-purity
什么是"逻辑纯度"(在Prolog编程的背景下)?该逻辑纯度标记信息说,"使用程序只喇叭条款",但随后又怎么会谓词喜欢if_/3出线,使用因为它切为多,和各种元逻辑(什么是适当的术语?var/1和这样)谓词,即低级别的东西.
我明白它实现了一些"纯粹"的效果,但这究竟是什么意思呢?
mat*_*mat 10
让我们首先习惯逻辑程序的声明性读取.
声明地说,Prolog程序说明了什么是真的.
例如
natural_number(0).
natural_number(s(X)) :-
natural_number(X).
Run Code Online (Sandbox Code Playgroud)
第一个条款规定:0是一个自然数.
第二个条款规定:如果 X是自然数,则 s(X)是自然数.
现在让我们考虑一下这项计划变更的影响.例如,当我们改变这两个条款的顺序时会发生什么变化?
natural_number(s(X)) :-
natural_number(X).
natural_number(0).
Run Code Online (Sandbox Code Playgroud)
声明地说,交换条款的顺序并不会以任何方式改变程序的预期含义(分离是可交换的).
在操作上,也就是说,考虑到Prolog的实际执行策略,不同的子句命令显然经常会产生显着的差异.
但是,无论选择的子句排序如何,都会保留纯Prolog代码的一个非常好的属性:
如果查询在子句排序方面
Q成功O1,则Q不会因不同的顺序而失败O2.
请注意,我并不是说Q总是以不同的顺序成功:这是因为查询也可能循环或产生具有不同排序的错误.
对于两个查询Q1和Q2,我们说G1是更普遍的当且仅当它涵括G2相对于语法统一.例如,查询?- parent_child(P, C).是更普遍比查询?- parent_child(0, s(0))..
现在,通过纯Prolog程序,另一个非常好的属性成立:
如果查询
Q1成功,则每个更通用的查询Q2都不会失败.
请注意,这Q2可能会循环而不是成功.
现在考虑var/1你提到的情况,并考虑相关的谓词nonvar/1.假设我们有:
my_pred(V) :-
nonvar(V).
Run Code Online (Sandbox Code Playgroud)
什么时候举行?显然,如果参数不是变量,它就成立.
正如所料,我们得到:
?- my_pred(a).
true.
Run Code Online (Sandbox Code Playgroud)
但是,对于更一般的查询?- my_pred(X).,我们得到:
?- my_pred(X).
false.
Run Code Online (Sandbox Code Playgroud)
这样的断言被称为非单调,你不能把它当作一个真正的关系,因为这个属性:这是因为答案false以上逻辑意味着,有没有解决方案的任何,但紧接着前面的例子中,我们看到有是一个办法.因此,不合逻辑地,通过添加约束构建的更具体的查询使查询成功:
?- X = a, my_pred(X).
true.
Run Code Online (Sandbox Code Playgroud)
因此,对这种谓词的推理是非常复杂的,以至于与它们一起编程完全没有意义.它使声明性调试变得不可能,并且难以声明保留的任何属性.例如,只是在上面的联合查询中交换子目标的顺序将使它失败:
?- my_pred(X), X = a.
false.
Run Code Online (Sandbox Code Playgroud)
因此,我强烈建议保留在Prolog的纯粹单调子集中,这允许沿着上面概述的线进行声明性推理.
CLP(FD)约束dif/2等在这个意义上都是纯粹的:你不能欺骗这些谓词给出逻辑上无效的答案,无论你使用它们的模式,命令等.if_/3也满足这个属性.在另一方面,var/1,nonvar/1,integer/1,!/0,谓词与副作用等,都是被描述声明世界之外的所有额外逻辑引用东西,因此不能认为是纯粹的.
编辑:澄清:我在这里提到的不错的属性绝不是详尽无遗的.Pure Prolog代码展示了许多其他非常有价值的属性,通过它们可以感知逻辑编程的荣耀.例如,在纯Prolog代码中,添加一个子句最多可以扩展,而不是缩小解决方案集; 添加目标最多可以缩小,永不延伸,等等.
使用单个额外逻辑原语可能并且通常会破坏许多这些属性.因此,例如,每次使用时!/0,都认为它是切入纯洁心脏的切口,并试图为伤害这些属性而感到后悔和羞耻.
一本好的Prolog书至少会开始介绍或包含许多提示来鼓励这样的声明性观点,引导你思考更一般的查询,保留的属性等等.Pre Prolog书籍不会对此有太多了解并且通常最终会使用正是那些不纯的语言元素破坏了语言最有价值和最美丽的属性.
一个令人敬畏的Prolog教学环境,广泛使用这些属性来实现声明性调试称为GUPU,我强烈建议您查看这些想法.Ulrich Neumerkel慷慨地提出了一个核心思想,在他的环境中使用,部分可用作图书馆(王冠).请参阅源文件以获取有关如何以声明方式调试意外失败的目标的良好示例:库系统地构建仍然失败的查询的泛化.这种推理当然与纯代码完美配合.