Prolog如何模式匹配带参数的类型

时间:2017-05-24 08:33:46

标签: prolog

我正在努力学习Prolog,我是一个初学者。为了理解它,我尝试编写一个函数。我有一种以这种方式定义的类型:

a(X,Y,Z). 

让我们说,我的知识库是:

a(M,2,3) .
a(S,4,7) .

这里X是操作,Y,Z是将进行此操作的数字。我有一个函数f,它将执行此操作,然后如果此操作通过f的第二个参数得到结果,它将返回true。否则它将返回操作的结果。

例如,

g(M,4) 

应该屈服于

6.

由于M代表乘法而6不等于4.我们假设S代表求和运算,那么

g(S,11)
由于4 + 7 = 11,

应该为真。

所以,我尝试的是:

g([],0) .
g(a(M,X,Y),Z, true :- (Z =:= (X*Y) ) ) .
g(a(S,X,Y),Z, true :- (Z =:= (X+Y) ) ) .
g(a(M,X,Y),Z, (X*Y) ) .
g(a(S,X,Y),Z, (X+Y) ) .

但是当我打电话的时候     g(S,11)

我得到了

false.

虽然它应该评估为11。

当我打电话

g(S,45)

我应该得到11,但我仍然得到

false.

我非常非常初学,所以如果我错过了一些明显的事情,请不要过于苛刻,提前谢谢。

2 个答案:

答案 0 :(得分:2)

您发布的代码存在很多问题。特别是,它不是用于定义Prolog谓词的正确语法,它使用变量(以大写字母开头)而不是我认为的原则。

例如,您的代码:

g(a(M,X,Y),Z, true :- (Z =:= (X*Y) ) ) . 

简单地断言一个看起来像这样的术语,写成"规范":

g(a(M,X,Y), Z, :-(true, =:=(Z, *(X, Y))).

它是一个有效的Prolog术语,但不是用于断言谓词的Prolog语法。对于谓词,顶级仿函数必须为:-(通常为head :- body,或标准编写,:-(head, body))。在您的代码中,顶级函子g对Prolog没有特殊意义。

您可以使用运算符本身作为操作的描述,而不是定义其他原子来表示这些操作。所以你的知识库可能是这样的:

a(*, 2, 3).
a(*, 4, 5).
a(+, 2, 4).
a(+, 4, 7).

查询可能如下所示:

g(+, 11).

然后谓词将是:

g(Operation, Result) :-
    a(Operation, Operand1, Operand2),
    Expression =.. [Operation, Operand1, Operand2] ,
    Result #= Expression.

这里,我们查询具有可接受操作数的操作。然后,我们使用=../2将操作和操作数统一到一个Prolog term ,它由一个仿函数(列表的第一个元素)和参数(列表的其余部分)组成。然后我们使用CLP(FD)#=操作来正确推理整数,因为它提供了最通用的解决方案,并且评估了Expression中术语给出的表达式。根据以上事实,这得到以下结果:

| ?- g(+, 11).

yes
| ?- g(+, R).

R = 6 ? ;

R = 11

(1 ms) yes
| ?- g(Op, 11).

Op = (+)

yes
| ?- g(Op, 6).

Op = (*) ? ;

Op = (+) ? ;

no

<小时/> 如果您确实需要为运算符使用不同的符号表示,则可以定义别名映射:

alias(add, +).
alias(mul, *).

你的事实将是:

a(mul, 2, 3).
a(mul, 4, 5).
a(add, 2, 4).
a(add, 4, 7).

然后定义:

g(Operation, Result) :-
    a(Operation, Operand1, Operand2),
    alias(Operation, Op),
    Expression =.. [Op, Operand1, Operand2] ,
    Result #= Expression.

答案 1 :(得分:1)

不幸的是,您需要了解有关Prolog的更多信息,然后才能接近您在此处尝试的操作。首先,Prolog没有函数,只有谓词。这不仅仅是一个有趣的名称,它是一个根本不同的概念。

Prolog谓词不会按照您期望的方式评估值。它们要么失败要么成功,并且在成功的情况下,它们可以将一些变量绑定到值。这看起来像是“返回”其他语言中的值,但它不一样。

让我们看一下这个版本的程序:

a(mul, 2, 3).
a(add, 4, 7).

g(mul, Z) :-
    a(mul, X, Y),
    Z is X * Y.
g(add, Z) :-
    a(add, X, Y),
    Z is X + Y.

我可以问一下,11是否是添加存储在数据库中的操作数的正确结果:

?- g(add, 11).
true.

我也可以问问它的结果是什么,没有提出我的猜测:

?- g(add, Result).
Result = 11.

但你可以让它以错误的猜测“返回”正确的解决方案:

?- g(add, 45).
false.

这是因为任何“返回”值都会通过查询中的绑定变量来实现。但是这个查询不包含任何变量!你永远不能从看起来像这样的查询中“获取”一个值。

无论您的目标是什么,都可以在Prolog中完成,但您目前尚未走上正轨。您应该首先尝试更多地理解逻辑变量等概念,以及在程序中出现像a(mul, X, Y)这样的术语与作为谓词参数出现的同一术语的区别。