我最近在 Mercury 中遇到了这个代码示例:
append(X,Y,Z) :-
X == [],
Z := Y.
append(X,Y,Z) :-
X => [H | T],
append(T,Y,NT),
Z <= [H | NT].
=
作为一名 Prolog 程序员,我想知道:正常的统一和这里使用的:=
or有什么区别?=>
在Mercury 参考文献中,这些运算符获得不同的优先级,但它们没有解释差异。
我最近在 Mercury 中遇到了这个代码示例:
append(X,Y,Z) :-
X == [],
Z := Y.
append(X,Y,Z) :-
X => [H | T],
append(T,Y,NT),
Z <= [H | NT].
=
作为一名 Prolog 程序员,我想知道:正常的统一和这里使用的:=
or有什么区别?=>
在Mercury 参考文献中,这些运算符获得不同的优先级,但它们没有解释差异。
首先让我们使用缩进重写代码:
append(X, Y, Z) :-
X == [],
Z := Y.
append(X, Y, Z) :-
X => [H | T],
append(T, Y, NT),
Z <= [H | NT].
您似乎必须将所有代码缩进四个空格,这在评论中似乎不起作用,我上面的评论应该被忽略(我无法删除它们)。
上面的代码不是真正的 Mercury 代码,而是伪代码。它作为真正的 Mercury 代码没有意义,因为<=
and=>
运算符用于类型类 (IIRC),而不是统一。另外,我以前没有见过:=
操作员,我不确定它是做什么的。
在这种伪代码风格(我相信)中,作者试图证明这:=
是一种统一的赋值类型,其中X
赋值为Y
. 类似地=>
显示的解构和显示X
的构造。还显示了和空列表之间的相等性测试。所有这些操作都是统一的类型。编译器知道谓词的每种模式应该使用哪种类型的统一。对于此代码,有意义的模式是<=
Z
==
X
append(in, in, out)
Mercury 在这方面与 Prolog 不同,它知道要使用哪种类型的统一,因此可以生成更高效的代码并确保程序是模式正确的。
还有一件事,这个伪代码的真正Mercury 代码是:
:- pred append(list(T)::in, list(T)::in, list(T)::out) is det.
append(X, Y, Z) :-
X = [],
Z = Y.
append(X, Y, Z) :-
X = [H | T],
append(T, Y, NT),
Z = [H | NT].
请注意,每个统一都是 a=
并且已添加谓词和模式声明。
在具体的 Mercury 语法中,运算符:=
用于字段更新。
也许我们在最近的 Mercury 版本中无法使用像 ':=' '<=' '=>' '==' 这样的运算符,但根据 Nancy Mazur 论文中的描述,这些运算符实际上是专门统一的。'=>' 代表解构,例如 X => f(Y1, Y2, ..., Yn) 其中 X 是输入,所有 Yn 都是输出。是半分。'<=' 恰恰相反,是 det。'==' 用在两边都磨的情况下,是semidet。':=' 就像任何其他语言中的常规分配运算符一样,它是 det。在旧论文中,我什至看到他们使用 '==' 而不是 '=>' 来执行解构。(我觉得我的英语很糟糕= x =)