首页 > 解决方案 > Prolog if-then-else 结构:-> vs *-> vs. if_/3

问题描述

正如我似乎再也找不到的另一个 StackOverflow 答案中所述,这种模式经常出现在实际的 Prolog 代码中:

pred(X) :-
    guard(X),
    ...
pred(X) :-
    \+ guard(X),
    ...

许多人试图将其浓缩为

pred(X) :-
    (guard(X) ->
    ...
    ;
    ...).

然而众所周知,箭头结构破坏了选择点并且不合逻辑。

在 Ulrich Neumerkel 和 Stefan Kral 的Indexing dif/2中,提出了一个单调且合乎逻辑的谓词if_/3,但是在论文中他们提到了另一个引起我注意的构造:*->.

*->构造函数的功能与上面的未加糖保护子句示例完全相同,因此它似乎非常适合我的使用,因为我不想拥有所需的具体条件,if_/3而且我不太关心额外的选择点。如果我没记错的话(编辑:我是),它提供了与条件谓词相同的语义,if_/3但不需要将“具体化”添加到条件谓词中。

然而,在它的 SWI 文档中,它声称“这种结构很少使用”,这对我来说似乎很奇怪。在我看来,这比您尝试进行纯逻辑编程时要*->好得多。->是否有任何理由避免这种结构,或者是否有更好的替代整个保护条款/否定保护条款模式?

标签: if-statementprologcontrol-structurelogical-purityimplication

解决方案


让我们试试吧!你给的模式是:

预测(X):-
    (守卫(X)->
         ...
    ; ...
    )。

我现在使用(*->)/2并填写“...”如下:

预测(X):-
        (守卫(X)*->
            
        )。

此外,作为guard/1,我定义了明显的谓词:

后卫(一)。

现在,让我们问pred/1一个最普遍的问题有什么解决方案吗?

?- pred(X)。
错误的。

所以,根据谓词,没有X这样的词pred(X)是真的

但这是错误的,因为实际上有这样一个术语:

?- pred(b)。
真的。

事实上,pred/1无穷多的解。在这种情况下,谓词状态根本没有是可以接受的吗?当然,因为答案的计算效率非常高,不是吗?

我们得出的结论是,它(*->)/2有一个重要的缺点:如果仅进一步实例化条件中出现的变量,则在适用不同(->)/2分支的情况下,它可能会错误地提交到其中一个分支。以这种方式依赖于其参数的实例化的谓词永远不可能是纯的,因为它抵消了我们期望适用于纯逻辑程序的单调推理。特别是,从逻辑的角度来看,既然成立,我们期望是 的概括一定不能失败pred(b)pred(X)pred(b). 一旦这个属性被破坏,你就不能再应用声明式调试和其他让你更容易理解、推理和管理 Prolog 程序的重要方法,而这首先构成了声明式编程的主要吸引力。

您提到的问题可能是What uses does if_3/have ? .


推荐阅读