Coq中Peano数的实现

Coq中Peano数的实现,coq,peano-numbers,Coq,Peano Numbers,我正在翻阅《软件基础》一书来学习Coq,结果我被卡住了。在这个类型定义中 Inductive nat : Type := | O : nat | S : nat -> nat. 当我们将O用于定义时,它如何变成0 Definition pred (n : nat) : nat := match n with | O => O | S n' => n' end. 我只知道,O表示自然数,S取一个自然数并返回另一个自然数。我不明白的是,当我们定义

我正在翻阅《软件基础》一书来学习Coq,结果我被卡住了。在这个类型定义中

Inductive nat : Type :=
  | O : nat
  | S : nat -> nat.
当我们将
O
用于定义时,它如何变成
0

Definition pred (n : nat) : nat :=
  match n with
    | O => O
    | S n' => n'
  end.
我只知道,
O
表示自然数,
S
取一个自然数并返回另一个自然数。我不明白的是,当我们定义的
nat
数据类型在
pred
定义中使用时,
O
如何表示
0
?而
sn'
模式匹配如何给我们提供了
n
的前身Peano数
nat
表示通过的自然数。
nat
类型的居民(值)为
O
so
S(so)
S(so))
,…,
S(S(S…O)…

我们将符号
O
解释为自然数零。
S
表示一元表示中的单个“勾号”,即我们将
S
解释为构造函数(与面向对象编程无关),它接受自然数并生成下一个自然数

前置函数 从某种意义上说,
pred
实际上不是一个性能很好的函数

首先,当我们谈论自然数时,没有零的前身。但是Coq中的所有函数都必须返回一个值,因此如果我们想保持
pred
(即
nat->nat
)的类型我们必须对
pred O
做些什么。返回
O
并完成它感觉很自然。这给了我们模式匹配表达式的第一个分支(
O=>O

接下来,当我们对表示1的数字调用
pred
时,我们返回什么?让我们回忆一下,我们在Coq中将1写成
so
。这很简单--
pred(so)
应该返回
O
。现在让我们尝试2:
pred(so))
应该返回
so
。你看到这里的模式了吗?如果我们在
O
前面有一堆
S
,我们去掉一个
S
,就这么简单。模式匹配表达式的第二个分支(
sn'=>n'
)就是这样做的:它取a(非零)表单的编号
sn'
,并将其转换为
n'
(当然,不更改原件)

让我举一个例子。让我们一步一步地计算数字3的前身:

pred (S (S (S O)))
展开
pred
的定义,用
S(S(so))
代替
n

match S (S (S O)) with
| O => O
| S n' => n'
end
S(S(so))
具有形式
sn'
(它以
S
开头),因此我们采用第二个分支,将
n'
绑定到
S(so)
。我们如何检查我们没有犯错误?如果我们将
n'
的定义替换为
sn'
,我们应该拿回原始的
n
sn'
=
S(so))
=
n

现在,我们只返回
n'

S (S O)
果然,我们得到了2分

符号 0、
0
O
之间有区别。第一个零(0)是自然数零的元级数字(这是我们在元语言中指定零的方式,例如本例中的英语).
0
O
的符号,换句话说,
0
O
的语法糖。正如Coq参考手册所说():

数字在微积分中没有明确的语义。它们只是可以通过符号机制绑定到对象上的符号(详见第12章)。最初,数字绑定到Peano对自然数的表示(见3.1.3)

很容易说明:

Check 0.                     (* 0 : nat *)
Check 5.                     (* 5 : nat *)
Unset Printing Notations.    (* Print terms as is, no syntactic sugar *)
Check 0.                     (* O : nat *)
Check 5.                     (* S (S (S (S (S O)))) : nat *)
您可以重载数字,下面是一个整数示例:

Set Printing Notations.
Require Import Coq.ZArith.ZArith.
Open Scope Z.
Check 0.                            (* 0 : Z *)
Check 5.                            (* 5 : Z *) 
Unset Printing Notations.
Check 0.                            (* Z0 : Z *)
Check 5.                            (* Zpos (xI (xO xH)) : Z *)
结果:相同的符号可以绑定到不同的术语。Coq定义了一些默认的符号,例如,对于数字等无处不在的事物


如果您想定义自己的类型来表示自然数(
my_nat
),而
O
S
的名称可能不同(如
stop
tick
),那么您必须编写一个插件,将Coq数字映射到
my_nat
的术语上(请参阅).

O
代表一个单一的自然数。@DanielSchepler,这是一个单一的数字
0
?是
S
O
是一些变量,我可以用任何东西来代替它们,或者它们在Coq中有特定的含义。因为书上说我们可以用
停止
勾选
来代替它们。我的编辑并回答您的问题?请毫不犹豫地提出后续问题。