Prolog补充运动

时间:2011-10-26 22:05:43

标签: prolog successor-arithmetics

我有这个非常简单的代码作为数字的表示。问题是当我使用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).

3 个答案:

答案 0 :(得分:2)

在Prolog中,不评估像中缀+这样的函数符号。您似乎正在尝试评估+的所有事件。但是,其中一些仍然没有被评估,如果您尝试像add2/3中那样临时执行此操作,这可能会非常棘手。考虑 add2(0+0+0,0,R)因您的定义而失败。

您可以更好地将numeral/1称为expression/1

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

答案 1 :(得分:2)

由于第一个add2子句和第一个add子句的组合,它正在发生。您的add2(0, ..., ...)将触发add(0, ..., ...),它始终统一第二个和第三个参数。

答案 2 :(得分:-1)

当你调用add2(0, s(0)+s(s(0)), Z)时,它将与add2/3的第一个子句统一,因为这个第一个子句在头部只有三个变量,所以它可以与任何{{{}的调用统一1}}。在您的示例中,这将导致调用add2/3的第一个子句,因此Z将绑定到add/3

您的代码的问题在于s(0)+s(s(0))的更具体的子句放在general子句之后。因此,为了使您的代码有效,请将add2/3的第一个子句放在最后,并将剪切添加到其他两个,例如。

add2/3

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