我有这个非常简单的代码作为数字的表示。问题是当我使用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).
答案 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
因为当该子句的头部与查询匹配时,您确定您正在执行正确的子句,并且您不会遇到回溯问题。