关于 Prolog 中的平等和统一,我缺少什么?

What am I missing about equality and unification in Prolog?

我正在通过 Clocksin 和 Mellish 努力尝试并最终超越仅仅涉足 Prolog。 FWIW,我是 运行 SWI-Prolog:

SWI-Prolog version 7.2.3 for x86_64-linux

无论如何,我在练习 1.4 中实现了一个 diff/2 谓词。谓词很简单:

diff(X,Y) :- X \== Y.

它在 sister_of 谓词中使用时有效,如下所示:

sister_of(X,Y) :- 
    female(X),
    diff(X,Y),
    parents(X, Mum, Dad ),
    parents(Y, Mum, Dad ).

其中,假设必要的额外事实,这样做:

?- sister_of(alice,alice).

returns 如预期的那样错误。但这就是问题所在。如果我这样做:

?- sister_of(alice, Who).

(同样,考虑到必要的额外事实) 我得到

Who = edward ;

Who = alice;

false

尽管如前所述,sister_of 谓词并未将 alice 视为自己的姐妹。

另一方面,如果我使用 SWI 提供的 dif/2 谓词,那么一切都会按照我天真地期望的方式进行。

任何人都可以解释为什么会这样,以及为什么我的 diff 实现没有按照我期望的方式工作,如果我从该查询中请求额外的统一?

可以找到我正在使用的整个源文件here

非常感谢任何帮助。

如您所见,问题源于平等(或更确切地说,不平等)与统一之间的相互作用。请注意,在 sister_of 的定义中,您首先找到 X 的候选值,然后 尝试约束 Y 不同,但是 Y 仍然是一个未实例化的逻辑变量,并且检查总是会成功,就像 diff(alice, Y) 一样。以下约束,包括最后一个为 Y 赋予具体值的约束,来得太晚了。

一般来说,您需要做的是确保在您到达不等式时检查所有变量都已实例化。否定是 Prolog 的非逻辑特征,因此具有潜在危险,但检查两个 ground terms 是否不相等是安全的。