Prolog 中的一阶谓词逻辑:使用签名和算术项

First-order predicate logic in Prolog: Working with Signatures and Arithmetic Terms

我正在使用 Prolog 中的条款和签名(一阶谓词逻辑)。

我得到了签名 (∅, Z, {add(2), sub(2), mult(2)})。所以没有变量,常量是整数,函数是“add”、“sub”和“mult”。

目标是写谓词“calc/2”,它接受一个项(给定上面的签名)并根据通常的加法定义计算它,整数的减法和乘法。示例:

?- calc( add(sub(8,2), mult(4,-3)), N).
N = -6

(因为 ((8 − 2) + (4 ∗ −3)) = −6)

问题与 相似且相关,但一个很大的区别是我需要避免使用 =.. 运算符来查找职能。相反,我想利用 Prolog 在规则参数 上使用 模式匹配这一事实,这是我完全坚持的。另一件需要注意的事情是“add”、“sub”和“mult”不应该是谓词。

我使用 =.. 运算符的第一个解决方案是(借助上面链接的线程的答案):

op(+, add).
op(-, sub).
op(*, mult).

calc(Term, N) :-
    calc2(Term, Expr),
    N is Expr.

calc2(N,N) :- integer(N).
calc2(Term, Expr) :-
    Term =.. [Op_str, Comp1, Comp2],
    op(Op, Op_str),
    calc2(Comp1, Expr1),
    calc2(Comp2, Expr2),
    Expr =.. [Op, Expr1, Expr2].

但由于这^不是我正在寻找的解决方案类型,它对我的​​问题并没有多大帮助。

我可以非常轻松地执行单个计算(例如 calc(add(1,2), N)),但我很难处理比这更复杂的事情。

要使用模式匹配并避免使用 univ 运算符 =..,您可以这样重写 calc2/2:

calc2(add(Op1, Op2), Expr1 + Expr2) :- 
    calc2(Op1, Expr1),
    calc2(Op2, Expr2).
calc2(sub(Op1, Op2), Expr1 - Expr2) :-
    calc2(Op1, Expr1),
    calc2(Op2, Expr2).
calc2(mult(Op1, Op2), Expr1 * Expr2) :-
    calc2(Op1, Expr1),
    calc2(Op2, Expr2).

这使代码更加直观,其中额外的情况(例如电源)可以由单独的子句处理。此外,现代编译器可以优化生成的代码。