Prolog:缺少功能?

时间:2015-05-22 08:35:44

标签: prolog

任何在Prolog有一定经验的程序员都知道使用一元符号表示数字的优点。例如,如果我们将数字表示为1“(”4“是列表”[1,1,1,1]“等等)的列表,我们可以定义:

unary_succ(X,[1|X]).

以下查询执行预期的操作:

?- X=[1,1],unary_succ(X,Y).
X = [1, 1],
Y = [1, 1, 1].

?- unary_succ(X,Y),X=[1,1].
X = [1, 1],
Y = [1, 1, 1].

?- unary_succ(X,Y),Y=[1,1].
X = [1],
Y = [1, 1].

通过这种方式,语句unary_succ(X,Y)以一种方式“绑定”X和Y,如果在声明事实之后,其中一个变量绑定到一个值,另一个变量绑定到。

但是,如果我们使用内部数字表示,则无法执行此操作:

?- X=2,succ(X,Y).
X = 2,
Y = 3.

?- succ(X,Y),X=2.
ERROR: succ/2: Arguments are not sufficiently instantiated

?- succ(X,Y),Y=2.
ERROR: succ/2: Arguments are not sufficiently instantiated

在我看来,先前的陈述和类似的陈述能够达到预期目标是非常有用的。也就是说,我们需要链接两个变量,当其中一个变量绑定到一个值时,另一个变量遵循先前建立的规则。

我的问题是:

a)在Prolog中做一些简单的方法。

b)如果不可能,任何其他支持此功能的编程语言?

欢迎任何评论。

感谢大家。

*附录I *

另一个例子是:

user_id(john,1234).
user_id(tom,5678).

和查询:

X=john,user_id(X,Y).
user_id(X,Y),X=john

目前通过回溯来解决。

2 个答案:

答案 0 :(得分:4)

只要Prolog系统的答案仅限于(句法)答案替换,您描述的问题就存在。在您的示例中,目标succ(X, Y)将需要无限多个答案来描述整套解决方案。因此,会发出instantiation_error

要解决这个问题,我们需要扩展答案。所以答案不仅包括答案替换,还包括一些更精细的方式来描述一些集合。

library(clpfd) 提供对Z(以及最显着的有限域)的约束。

?- use_module(library(clpfd)).
?- Y #= X+1.
X+1#=Y.

请注意,对于一般情况,此类解算器不是很强大:

?- Y #= X+1, X #= Y+1.
Y+1#=X,
X+1#=Y.

您可能希望系统失败,但它会产生一个基本上重述查询的答案。至少答案是不正确的,因为它只是说明:是的,有一个解决方案提供这种关系成立(它没有,类似于保险合同或担保证书中的细则)。 / p>

when/2 也称为coroutining,在许多情况下比clpfd更弱。但是,在少数情况下,clpfd的某些实现更强。考虑dif/2,可以表示为when(?=(X,Y), X \== Y)

| ?- dif(X, Y), X = Y.
no

...而(在SICStus中)

| ?- X #\= Y, X #= Y.
Y #= X,
Y #\= X,
Y in inf..sup,
X in inf..sup ? ;
no

library(clpq) 提供的解算器在许多情况下更强,但缺少整数特定约束,如mod/2。在许多情况下,使用它仍然很有趣,如SICStus中所示:

| ?- use_module(library(clpq)).
yes
| ?- {Y=X+1}.
{X = -1+Y} ?
yes
| ?- {Y=X+1}, {X=Y+1}.
no

答案 1 :(得分:3)

这个主题被称为coroutining,并且要以相当一般的方式解决 - afaik - 需要扩展到基本的Prolog计算模型。幸运的是,大多数Prolog都有这样的扩展......所以,让我们尝试in SWISH来构建你自己的“反应性”'扩展:

my_succ(X, Y) :- when((nonvar(X);nonvar(Y)), succ(X, Y)).

编辑并非完全没有意义,但Jan在SWI-Prolog邮件列表上发布了一个关于协同应用程序的简单示例:

?- freeze(X, writeln(X)), findall(X, between(1,3,X), Xs).
1
2
3
Xs = [1, 2, 3],
freeze(X, writeln(X)).