2

我有这个非常简单的代码作为数字的表示。问题是当我使用 add2 函数时。

示例:正确add2(s(0)+s(s(0)), s(s(0)), Z).返回s(s(s(s(s(0)))))。然而add2(0, s(0)+s(s(0)), Z).总是returns s(0)+s(s(0))。谁能明白为什么会这样?

numeral(0).
numeral(s(X)) :- numeral(X).
numeral(X+Y) :- numeral(X), numeral(Y).

add(0,X,X).
add(s(X),Y,s(Z)) :- add(X,Y,Z).

%%  exercise 1
add2(X,Y,R) :- add(X,Y,R).
add2(X+Y,Z,R) :- add(X,Y,A),add2(A,Z,R).
add2(X,Y+Z,R) :- add(Y,Z,A),add2(X,A,R).
4

3 回答 3

2

这是因为第一个add2子句和第一个add子句的结合而发生的。你的add2(0, ..., ...)意志触发add(0, ..., ...)总是统一第二个和第三个参数。

于 2011-10-27T00:42:49.097 回答
1

在 Prolog 函数中,中缀之类的符号+不会被计算。您似乎正在尝试评估所有出现的+. 但是,其中一些仍未评估,如果您尝试像在add2/3. 考虑 add2(0+0+0,0,R)哪个不符合您的定义。

你叫什么numeral/1最好叫expression/1

考虑定义一个辅助谓词eval/2以将表达式简化为 s(X)-数字。但是请注意,即使这样的定义对于像add2(0,0,0+0). 这是一个固有问题,只能使用约束或类似技术来解决......

于 2011-10-26T22:25:30.753 回答
-1

调用add2(0, s(0)+s(s(0)), Z)的时候会和 的第一个子句统一add2/3,因为这个第一个子句的头部只有三个变量,所以可以和 的任何调用统一add2/3。这反过来将在您的示例中导致调用 的第一个子句add/3,因此 Z 将绑定到s(0)+s(s(0))

您的代码的问题是更具体的子句add2/3放在一般子句之后。因此,要使您的代码正常工作,请放置add2/3last 的第一个子句,并在其他两个子句中添加剪辑,例如

add2(X+Y,Z,R) :- !,add(X,Y,A),add2(A,Z,R).

因为当该子句的头部与查询匹配时,您确定您正在执行正确的子句并且您不会在回溯时遇到麻烦。

于 2011-10-27T06:04:19.580 回答