数据和功能 Data and Functions I

枚举类型 Enumerated Types

Inductive day

以下声明告诉 Coq,我们正在定义一组数据值 - a type。

Inductive day : Type :=
  | monday
  | tuesday
  | wednesday
  | thursday
  | friday
  | saturday
  | sunday.

新 type 称为 day ,其成员为 monday、tuesday 等。 定义了 day 后,我们可以编写在 day 上操作的 function 。

Definition next_weekday

Definition next_weekday (d:day) : day :=
  match d with
  | monday ⇒ tuesday
  | tuesday ⇒ wednesday
  | wednesday ⇒ thursday
  | thursday ⇒ friday
  | friday ⇒ monday
  | saturday ⇒ monday
  | sunday ⇒ monday
  end.

需要注意的一点是,明确声明此函数的参数和返回类型。与大多数功能性编程语言一样,Coq 经常可以在未明确给出这些类型时自行找出这些类型(即它可以进行类型推理)但通常我们会将其包括在内,以便于阅读。
定义了一个 function 后,我们接下来应该检查它是否适用于某些示例。
实际上,在 Coq 中,有三种不同的方法可以做这些例子。

计算 Compute

首先,我们可以使用命令 Compute 来评估涉及 next_weekday 的复合表达。

Compute (next_weekday friday).
(* ==> monday : day *)
Compute (next_weekday (next_weekday saturday)).
(* ==> tuesday : day *)

示例 Example

其次,我们可以以 Coq Example 的形式记录我们期望的结果:

Example test_next_weekday:
  (next_weekday (next_weekday saturday)) = tuesday.

此声明有两件事:它做出断言( Saturday 之后的第二个工作日是 Tuesday),并且它给断言起一个名字,以后可以用来参考它。在做出断言后,我们还可以要求 Coq 这样验证它:

Proof. simpl. reflexivity. Qed.

提取 Extract

第三,我们可以要求 Coq 从我们的定义中提取另一种更传统的编程语言(OCaml、计划或哈斯克尔)中的程序,并配备高性能编译器。

家庭作业提交指南

不要改变划分练习的"标记":练习头、练习名称、末尾的"空方括号"标记等。请留下这个标记。
不要删除练习。如果您跳过练习(例如,因为它被标记为"可选",或者因为无法解决它),请确定在您的.v文件中留下部分证据。这种情况下,请确保它以 Admitted 结束(而不是,例如 Abort)。
在解决方案中使用其他定义(帮助功能、有用的 Lemmas 等)是可以的。你可以把这些放在练习头和你被要求证明的定理之间。
如果你介绍一个帮手 Lemma ,你最终无法证明,因此用 Admitted 结束它,然后确保也用 Admitted 结束你使用它的主要定理,而不是Qed。

布尔值 Booleans

Inductive bool

以类似的方式,我们可以定义布尔值的标准类型 bool ,成员 true 和 false 。

Inductive bool : Type :=
  | true
  | false.

Definition negb

对 Booleans 的 Function 可以以与上述相同的方式定义:

Definition negb (b:bool) : bool :=
  match b with
  | true ⇒ false
  | false ⇒ true
  end.

Definition andb

Definition andb (b1:bool) (b2:bool) : bool :=
  match b1 with
  | true ⇒ b2
  | false ⇒ false
  end.

Definition orb

Definition orb (b1:bool) (b2:bool) : bool :=
  match b1 with
  | true ⇒ true
  | false ⇒ b2
  end.

(虽然我们在这里滚动我们自己的布尔值,以建立一切从零开始,Coq当然提供一个默认的布尔值的实施,以及许多有用的 Functions 和 Lemmas 。只要有可能,我们将命名我们自己的定义和定理,以便它们与标准库中的定义和定理完全一致。 最后两个说明了 Coq 的多参数函数定义语法。相应的多参数应用语法由以下"单位测试"说明,该测试构成了 orb 函数的完整规范 (真值表):

Example test_orb1: (orb true false) = true.
Proof. simpl. reflexivity. Qed.
Example test_orb2: (orb false false) = false.
Proof. simpl. reflexivity. Qed.
Example test_orb3: (orb false true) = true.
Proof. simpl. reflexivity. Qed.
Example test_orb4: (orb true true) = true.
Proof. simpl. reflexivity. Qed.

符号 Notation

我们还可以介绍一些熟悉的固定语法,我们刚刚定义的布尔值操作。 Notation 命令为现有定义定义了新的符号符号。

Notation "x && y" := (andb x y).
Notation "x || y" := (orb x y).
Example test_orb5: false || false || true = true.
Proof. simpl. reflexivity. Qed.

Notation 说明:在.v文件,我们使用方括号在注释中划定 Coq 代码的片段;此公约也由coqdoc文档工具使用,使其在视觉上与周围的文本保持独立。在 HTML 版本的文件中,这些文本以不同的字体显示。
这些示例也是引入 Coq 编程语言的又一个小功能的机会:有条件表达式。

有条件表达式 Conditional Expressions

Definition negb' (b:bool) : bool :=
  if b then false
  else true.
Definition andb' (b1:bool) (b2:bool) : bool :=
  if b1 then b2
  else false.
Definition orb' (b1:bool) (b2:bool) : bool :=
  if b1 then true
  else b2.

Coq 的条件与任何其他语言中的条件完全一样,具有一个小概括。由于bool类型不是内置的,Coq 实际上支持有条件的表达方式,而不是任何具有电感定义的类型,其定义中正好有两个子句。如果保护者对 Inductive 定义第一条款的"构造者"进行评估(在这种情况下恰好被称为 true ),则该护卫被视为 true ,如果对第二个条款进行评估则被视为 false 。

练习 Exercise

1: 1 star, standard (nandb)

命令 Admitted 可用作不完整证据的占位符。我们在练习中使用它来指示我们要留给你的部分 - 即, 你的工作是用真实的 Proofs 来取代 Admitted 。 删除" Admitted ",并完成以下功能的定义:然后确保以下 Examples 断言可以由 Coq 验证。(即,按照上面的 orb 测试模型填写每个证明,并确保 Coq 接受它。如果其中一项或两项输入都是 false 的,则该函数应返回 true 。

Definition nandb (b1:bool) (b2:bool) : bool
  (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
Example test_nandb1: (nandb true false) = true.
(* FILL IN HERE *) Admitted.
Example test_nandb2: (nandb false false) = true.
(* FILL IN HERE *) Admitted.
Example test_nandb3: (nandb false true) = true.
(* FILL IN HERE *) Admitted.
Example test_nandb4: (nandb true true) = false.
(* FILL IN HERE *) Admitted.

Coq代码

Definition nandb (b1:bool) (b2:bool) : bool 
:= 
if andb b1 b2 then false
else true.

Coq运行截图

2: 1 star, standard (andb3)

对下面的 andb3 功能也做同样的操作。当所有输入都是 true 的时候返回 true,否则这个功能应该会返回 false 。

Definition andb3 (b1:bool) (b2:bool) (b3:bool) : bool
  (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
Example test_andb31: (andb3 true true true) = true.
(* FILL IN HERE *) Admitted.
Example test_andb32: (andb3 false true true) = false.
(* FILL IN HERE *) Admitted.
Example test_andb33: (andb3 true false true) = false.
(* FILL IN HERE *) Admitted.
Example test_andb34: (andb3 true true false) = false.
(* FILL IN HERE *) Admitted.

Coq代码

Definition andb3 (b1:bool) (b2:bool) (b3:bool) : bool
:=
if andb(andb b1 b2) b3 then true
else false.

Coq运行截图
图片说明