0

我想在 Prolog 中从自然数创建后继数。

nat2s(0, s(0)).
nat2s(NaturalNumber, SNumber) :-
            N is NaturalNumber - 1,
            nat2s(N, s(SNumber)).

输出应该是这样的:

nat2s(3, X).
X = s(s(s(0))).

实际上它是一个不定式循环。我不知道如何结束循环而不只是得到真实的结果。

4

1 回答 1

5

我建议一种稍微不同的方法,即使用库(clpfd)。首先让我们为谓词选择一个更具声明性的名称。由于在您的帖子中,自然数和 s(X) 表示法中的数字分别是第一个和第二个参数,我们称之为 nat_sx/2。那么谓词可以这样定义:

:- use_module(library(clpfd)).

nat_sx(0,0).
nat_sx(N,s(X)) :-
   N #> 0,
   N0 #= N-1,
   nat_sx(N0,X).

这会在您的帖子中产生所需的结果:

   ?- nat_sx(3,X).
X = s(s(s(0))) ? ;
no

要了解为什么使用 clpfd 是有益的,让我们将注释中的建议更正合并到您的代码中并比较两个版本。

nat2s(0, 0).
nat2s(NaturalNumber, s(SNumber)) :-
   NaturalNumber > 0,
   N is NaturalNumber - 1,
   nat2s(N, SNumber).

上面的查询也适用于这个版本:

   ?- nat2s(3,S).
S = s(s(s(0))) ? ;
no

但是,如果能够在另一个方向上使用谓词,那就太好了。所以让我们问哪个自然数对应于 s(s(0)):

   ?- nat_sx(N,s(s(0))).
N = 2 ? ;
no
   ?- nat2s(N,s(s(0))).
     ERROR at  clause 2 of user:nat2s/2 !!
     INSTANTIATION ERROR- =:=/2: expected bound value

实例化错误的原因是 is/2 期望右侧有一个无变量表达式:

   ?- X is 3-1.
X = 2
   ?- 2 is X-1.
     ERROR!!
     INSTANTIATION ERROR- in arithmetic: expected bound value
   ?- 2 is 3-X.
     ERROR!!
     INSTANTIATION ERROR- in arithmetic: expected bound value

这也是为什么最普遍的nat2s/2查询在第一次解决后出现实例化错误的原因……

   ?- nat2s(N,S).
N = S = 0 ? ;
     ERROR at  clause 2 of user:nat2s/2 !!
     INSTANTIATION ERROR- =:=/2: expected bound value

...而 nat_sx/2 不断生成解决方案:

   ?- nat_sx(N,S).
N = S = 0 ? ;
N = 1,
S = s(0) ? ;
N = 2,
S = s(s(0)) ? ;
...
于 2017-05-01T20:30:36.710 回答