相对:le_antisymmetric 理解

Rel: le_antisymmetric comprehension

逻辑基础的相关章节。我得到了我试图理解的运动量的解决方案:

Definition antisymmetric {X: Type} (R: relation X) :=
  forall a b : X, (R a b) -> (R b a) -> a = b.

Theorem le_antisymmetric :
  antisymmetric le.
Proof.
  unfold antisymmetric. intros a b [| b' H1] H2.
  - reflexivity.
  - absurd (S b' <= b').
    + apply le_Sn_n.
    + etransitivity ; eassumption.

我不明白,介绍模式 [| b' H1] 是如何工作的?介绍后显示:

2 subgoals (ID 43)

  a, b : nat
  H2 : a <= a
  ============================
  a = a

subgoal 2 (ID 46) is:
 a = S b'

第二个子目标:

a, b, b' : nat
H1 : a <= b'
H2 : S b' <= a
============================
a = S b'

我知道它等同于destruct,但什么样的destruct?绝对不是简单的destruct b.

我也试图理解使用 absurd (S b' <= b') 战术背后的逻辑。这是否意味着如果我们在这种情况下证明a = S b',则意味着我们将H1中的a重写为S b'后,我们得到:S b' <= b',这是一个普遍错误的陈述(荒谬)?

intros a b [| b' H1] H2等同于

intros a b H H2.
destruct H as [| b' H1].

destruct 模式通常遵循以下规则:如果归纳类型具有单个构造函数(例如产品),那么对于该归纳类型中的 xdestruct x as [a b c...] 会(非递归) 归纳并将新变量重命名为 abc 等。当归纳类型具有多个构造函数时,存在多种情况。为此,您使用 destruct x as [a b c ... | d e f ... | ...]。如果需要,可以嵌套这些破坏模式,例如destruct x as [[a b] | [c [d | e]]]。请注意,如果构造函数不带参数,则无需重命名,因此您可以将模式留空。

特别是,像自然数这样的东西可以用destruct n as [ | n']来破坏。这分为 n 为零(并且构造函数没有参数,因此 | 左侧没有任何内容)或 nn' 的后继者的情况.类似地,一个列表可以被分解为 destruct li as [ | a li'] 以分为列表为 nil 和列表为 cons a li' 的情况。 | 左边的 space 是不必要的,所以你可以做 destruct li as [| a li'].

你的情况具体是 le 被定义为归纳类型,类似于

Inductive le (n : nat) : nat -> Prop :=
| le_n : le n n
| le_S : forall m : nat, le n m -> le n (S m).

所以有两种情况:一种是没有参数,另一种是参数为m: natH: le n m的后继情况。因此,破坏模式是 [| m H].


回答你的第二个问题,absurd (S b' <= b'). 意味着(我们认为)我们能够在当前上下文中证明 S b' <= b'。我们还可以证明(在相同的上下文中)S b' <= b' 是荒谬的,即导致 False 的见证(更准确地说,S b' <= b' -> False)。使用 False 的归纳原理,这允许我们为任何类型生成见证,特别是 a = S b'.

你可以看到什么样的证明项 absurd 用最少的实验产生。

Goal forall A B: Type, A.
Proof.
  intros A B.
  absurd B.
  Show Proof.

这应该打印 (fun A B : Type => False_rect A (?Goal ?Goal0))。第一个目标 (?Goal) 的类型为 ~B(即 B -> False)。第二个目标 (?Goal0) 的类型为 B。如果我们可以同时提供两者,那么 ?Goal ?Goal0 的类型为 False,因此 False_rect A (?Goal ?Goal0) 会生成 A.

类型的见证