Agda - 以交互方式构建证明 - 如何使用 hole 语法?
Agda - Building proofs interactively - How to use the hole syntax?
抱歉这个奇怪的标题,我不知道这些概念实际上是如何命名的。
我正在学习 Agda
教程,其中有一节解释了如何以归纳方式构建证明:https://plfa.github.io/Induction/#building-proofs-interactively
很酷,您可以逐步扩展您的证明并让漏洞(此 { }0
)更新其内容以告诉您发生了什么。但是,仅解释了在使用 rewrite
语法时如何执行此操作。
当我想 "manually" 在 begin
块内进行证明时,这是如何工作的,例如:
+-assoc : ∀ (m n p : ℕ) → (m + n) + p ≡ m + (n + p)
+-assoc zero n p =
begin
(zero + n) + p
≡⟨⟩ n + p
≡⟨⟩ zero + (n + p)
∎
+-assoc (suc m) n p =
begin
(suc m + n) + p
≡⟨⟩ suc (m + n) + p
≡⟨⟩ suc ((m + n) + p)
≡⟨ cong suc (+-assoc m n p) ⟩
suc (m + (n + p))
≡⟨⟩ suc m + (n + p)
∎
问题如下。先从命题说起,开始论证:
+-assoc : ∀ (m n p : ℕ) → (m + n) + p ≡ m + (n + p)
+-assoc m n p = ?
计算结果为:
+-assoc : ∀ (m n p : ℕ) → (m + n) + p ≡ m + (n + p)
+-assoc m n p = { }0
在这种情况下,我想通过归纳法进行证明,所以我使用 C-c C-c
使用变量 m
:
拆分它们
+-assoc : ∀ (m n p : ℕ) → (m + n) + p ≡ m + (n + p)
+-assoc zero n p = { }0
+-assoc (suc m) n p = { }1
基本情况很简单,在使用 C-c C-r
解析后用 refl
替换。然而,电感外壳(孔 1)需要做一些工作。如何把这个{ }1
洞变成下面的结构来做证明:
begin
-- my proof
∎
我的编辑器 (spacemacs) 说 { }1
是 read-only。我无法删除它,只能在大括号之间插入内容。我可以 force-delete 但这显然不是故意的。
你应该怎么做才能把洞扩大成 begin
方块?像这样
{ begin }1
不起作用并导致错误消息
谢谢!
编辑:
好的,以下似乎有效:
{ begin ? }1
这变成了这个:
+-assoc : ∀ (m n p : ℕ) → (m + n) + p ≡ m + (n + p)
+-assoc zero n p = refl
+-assoc (suc m) n p = begin { }0
这是一个进步 :D。但是现在我不知道把证明的实际步骤放在哪里:
...
+-assoc (suc m) n p = begin (suc m + n) + p { }0
-- or
+-assoc (suc m) n p = begin { (suc m + n) + p }0
似乎都不起作用
{ }1
is read-only
此消息在两种情况下显示:
- 您正在尝试使用退格键删除一个洞,但这是行不通的。不过,如果孔是空的,您可以使用 C-backspace
- 您正在尝试在 insert/overwrite 模式下编辑一个空洞,这也行不通
一条经验法则是,您始终使用 C-c C-SPC
使用与目标类型相同的表达式来细化孔。在您的情况下,这意味着从 begin ?
开始,然后给出 (suc m + n) + p ≡⟨⟩ ?
等等。
有两种细化孔的方法:
C-c C-r
:给定一个函数时为你创建新的洞。例如。使用此设置:
test : Bool
test = {!!}
如果你在洞里输入 not
test : Bool
test = {!not!}
再细化,你会得到
test : Bool
test = not {!!}
即新洞是自动为参数创建的。
通过这种方式或完善一个漏洞,Agda 还会按照它喜欢的方式重新格式化你的代码,我不喜欢这种方式,所以我通常不使用它。
C-c C-SPC
:不会为参数创建新的漏洞,也不会重新格式化您的代码
抱歉这个奇怪的标题,我不知道这些概念实际上是如何命名的。
我正在学习 Agda
教程,其中有一节解释了如何以归纳方式构建证明:https://plfa.github.io/Induction/#building-proofs-interactively
很酷,您可以逐步扩展您的证明并让漏洞(此 { }0
)更新其内容以告诉您发生了什么。但是,仅解释了在使用 rewrite
语法时如何执行此操作。
当我想 "manually" 在 begin
块内进行证明时,这是如何工作的,例如:
+-assoc : ∀ (m n p : ℕ) → (m + n) + p ≡ m + (n + p)
+-assoc zero n p =
begin
(zero + n) + p
≡⟨⟩ n + p
≡⟨⟩ zero + (n + p)
∎
+-assoc (suc m) n p =
begin
(suc m + n) + p
≡⟨⟩ suc (m + n) + p
≡⟨⟩ suc ((m + n) + p)
≡⟨ cong suc (+-assoc m n p) ⟩
suc (m + (n + p))
≡⟨⟩ suc m + (n + p)
∎
问题如下。先从命题说起,开始论证:
+-assoc : ∀ (m n p : ℕ) → (m + n) + p ≡ m + (n + p)
+-assoc m n p = ?
计算结果为:
+-assoc : ∀ (m n p : ℕ) → (m + n) + p ≡ m + (n + p)
+-assoc m n p = { }0
在这种情况下,我想通过归纳法进行证明,所以我使用 C-c C-c
使用变量 m
:
+-assoc : ∀ (m n p : ℕ) → (m + n) + p ≡ m + (n + p)
+-assoc zero n p = { }0
+-assoc (suc m) n p = { }1
基本情况很简单,在使用 C-c C-r
解析后用 refl
替换。然而,电感外壳(孔 1)需要做一些工作。如何把这个{ }1
洞变成下面的结构来做证明:
begin
-- my proof
∎
我的编辑器 (spacemacs) 说 { }1
是 read-only。我无法删除它,只能在大括号之间插入内容。我可以 force-delete 但这显然不是故意的。
你应该怎么做才能把洞扩大成 begin
方块?像这样
{ begin }1
不起作用并导致错误消息
谢谢!
编辑:
好的,以下似乎有效:
{ begin ? }1
这变成了这个:
+-assoc : ∀ (m n p : ℕ) → (m + n) + p ≡ m + (n + p)
+-assoc zero n p = refl
+-assoc (suc m) n p = begin { }0
这是一个进步 :D。但是现在我不知道把证明的实际步骤放在哪里:
...
+-assoc (suc m) n p = begin (suc m + n) + p { }0
-- or
+-assoc (suc m) n p = begin { (suc m + n) + p }0
似乎都不起作用
{ }1
is read-only
此消息在两种情况下显示:
- 您正在尝试使用退格键删除一个洞,但这是行不通的。不过,如果孔是空的,您可以使用 C-backspace
- 您正在尝试在 insert/overwrite 模式下编辑一个空洞,这也行不通
一条经验法则是,您始终使用 C-c C-SPC
使用与目标类型相同的表达式来细化孔。在您的情况下,这意味着从 begin ?
开始,然后给出 (suc m + n) + p ≡⟨⟩ ?
等等。
有两种细化孔的方法:
C-c C-r
:给定一个函数时为你创建新的洞。例如。使用此设置:test : Bool test = {!!}
如果你在洞里输入
not
test : Bool test = {!not!}
再细化,你会得到
test : Bool test = not {!!}
即新洞是自动为参数创建的。
通过这种方式或完善一个漏洞,Agda 还会按照它喜欢的方式重新格式化你的代码,我不喜欢这种方式,所以我通常不使用它。
C-c C-SPC
:不会为参数创建新的漏洞,也不会重新格式化您的代码