1

所以我试图定义自然数到目前为止我这样做了:

 1 nat(0).                        % 0 zero is a natural, can be a stoping case
 2 nat(X):- 0>X , !,fail.         %if is less then zero then its not a natural.
 3 nat(X):- nat(Z), X is Z+1.     %if its bigger than zero do recursively for the number-1   

当我这样做时,它给了我“(>)/2 的参数 2 中的实例化错误”,因此他无法在第 2 行中实例化 X,但如果取出失败,他会执行比较 (>) 并且实例化没有问题X,那他为什么抱怨我失败了?

4

1 回答 1

2

如果你想生成自然数,你可以不使用切割或fail/0控制结构来做到这一点。例如:

nat(Nat) :-
    next_integer(0, Nat).

next_integer(I, I).
next_integer(I, K) :-
    J is I + 1,
    next_integer(J, K).

示例调用:

| ?- nat(Nat).

Nat = 0 ? ;
Nat = 1 ? ;
Nat = 2 ? ;
Nat = 3 ?
...

但是,如果您想测试一个术语是否为自然数,则此谓词将不起作用。例如,以下调用将导致大多数 Prolog 系统中的堆栈溢出(因为我们不能通过从零递增来生成负整数):

| ?- nat(-3). 

如果您使用的是提供 CLP(FD) 库的 Prolog 系统,则可以使用更好的定义:

nat(Nat) :-
    Nat #>= 0,
    next_integer(0, Nat).

next_integer(I, I).
next_integer(I, K) :-
    J is I + 1,
    next_integer(J, K).

然后使用相同的谓词进行生成和测试。例如,使用 SWI-Prolog 和library(clpfd)

?- nat(Nat).
Nat = 0 ;
Nat = 1 ;
Nat = 2 ;
Nat = 3 
...

?- nat(-3).
false.

如果不使用约束库,您将需要编写如下内容:

nat(Nat) :-
    (   var(Nat) ->
        next_integer(0, Nat)
    ;   integer(Nat), Nat >= 0
    ).
于 2020-03-11T10:19:53.667 回答