从自然数创建后继数
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)) ? ;
...
我想在 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)) ? ;
...