从自然数创建后继数

Create successor numbers from natural numbers

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

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

输出应该是这样的:

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

实际上这是一个不定式循环。我不知道如何在结果不为真的情况下结束循环。

我建议使用一种稍微不同的方法,即使用库 (clpfd)。首先让我们为谓词选择一个更具声明性的名称。因为在你的 post 中,自然数和 s(X)-notation 中的数字分别是第一个和第二个参数,我们称它为 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).

这会在您的 post:

中产生预期的结果
   ?- 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最一般的query在第一个解法后出现实例化错误的原因...

   ?- 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)) ? ;
...