11. 转换策略模式
在策略块(tactic block)内,可以使用关键字 conv 进入
转换模式(conversion mode)。该模式允许在假设和
目标内部进行导航,即使在函数抽象和依值箭头内部,
也可以应用重写或化简步骤。
11.1. 基本导航与重写
作为第一个例子,让我们证明示例
(a b c : Nat) : a * (b * c) = a * (c * b)
(此文件中的示例有些人为设计,因为
其他策略可以立即完成它们)。最直接
的首次尝试是进入策略模式并尝试 rw [Nat.mul_comm]。但这会将目标变换为
b * c * a = a * (c * b),在交换了项中出现的
第一个乘法之后。有多种
方法可以解决此问题,其中一种方法是使用更精确的工具:
转换模式。以下代码块显示了每一行之后的当前目标。
#guard_msgs (drop all) in
example (a b c : Nat) : a * (b * c) = a * (c * b) := a:Natb:Natc:Nat⊢ a * (b * c) = a * (c * b)
a:Natb:Natc:Nat⊢ b * c * a = a * (c * b)
example (a b c : Nat) : a * (b * c) = a * (c * b) := a:Natb:Natc:Nat⊢ a * (b * c) = a * (c * b)
a:Natb:Natc:Nat| a * (b * c) = a * (c * b)
a:Natb:Natc:Nat| a * (b * c)
a:Natb:Natc:Nat| aa:Natb:Natc:Nat| b * c
a:Natb:Natc:Nat| b * c
a:Natb:Natc:Nat| c * b
以上代码片段展示了三个导航命令:
-
lhs导航到关系(此处为等式)的左侧。 还有rhs用于导航到右侧。 -
congr为当前头部函数创建与(非依值和显式)参数数量相同的目标 (此处头部函数是乘法)。 -
rfl使用自反性(reflexivity)关闭目标。
一旦到达相关目标,我们可以像在普通策略模式中一样使用 rw。
使用转换模式的第二个主要原因是重写绑定器(binder)内部。假设我们想要证明示例
(fun x : Nat => 0 + x) = (fun x => x)。
最直接的首次尝试是进入策略模式并尝试
rw [Nat.zero_add]。但这会失败,并出现令人沮丧的
error: tactic 'rewrite' failed, did not find instance of the pattern
in the target expression
0 + ?n
⊢ (fun x => 0 + x) = fun x => x
解决方案是:
example : (fun x : Nat => 0 + x) = (fun x => x) := ⊢ (fun x => 0 + x) = fun x => x
| (fun x => 0 + x) = fun x => x
| fun x => 0 + x
x:Nat| 0 + x
x:Nat| x
其中 intro x 是进入 fun 绑定器内部的导航命令。
请注意,此示例有些人为设计,我们也可以这样做:
example : (fun x : Nat => 0 + x) = (fun x => x) := ⊢ (fun x => 0 + x) = fun x => x
x:Nat⊢ 0 + x = x; All goals completed! 🐙
或者简单地
example : (fun x : Nat => 0 + x) = (fun x => x) := ⊢ (fun x => 0 + x) = fun x => x
All goals completed! 🐙
conv 也可以使用 conv at h 重写来自局部上下文(local context)的假设(hypothesis)h。
11.2. 模式匹配
使用上述命令进行导航可能很繁琐。可以通过模式匹配来简化,如下所示:
example (a b c : Nat) : a * (b * c) = a * (c * b) := a:Natb:Natc:Nat⊢ a * (b * c) = a * (c * b)
a:Natb:Natc:Nat| b * c
a:Natb:Natc:Nat| c * b
这只是以下内容的语法糖
example (a b c : Nat) : a * (b * c) = a * (c * b) := a:Natb:Natc:Nat⊢ a * (b * c) = a * (c * b)
a:Natb:Natc:Nat| a * (b * c) = a * (c * b)
a:Natb:Natc:Nat| b * c
a:Natb:Natc:Nat| c * b
当然,允许使用通配符(wildcard):
11.3. 结构化转换策略
花括号(curly bracket)和 . 也可以在 conv 模式中用于结构化策略:
11.4. 转换模式中的其他策略
-
argi进入某个应用的第i个非依值显式参数。 -
args是congr的替代名称。 -
simp将化简器(simplifier)应用于当前目标。它支持与普通策略模式中相同的选项。def f (x : Nat) := if x > 0 then x + 1 else x + 2example (g : Nat → Nat) (h₁ : g x = x + 1) (h₂ : x > 0) : g x = f x := x:Natg:Nat → Nath₁:g x = x + 1h₂:x > 0⊢ g x = f x x:Natg:Nat → Nath₁:g x = x + 1h₂:x > 0| g x = f x x:Natg:Nat → Nath₁:g x = x + 1h₂:x > 0| f x x:Natg:Nat → Nath₁:g x = x + 1h₂:x > 0| x + 1 All goals completed! 🐙 -
enter[1, x, 2, y]使用给定的参数迭代arg和intro。 -
done在存在未解决的目标时失败。 -
trace_state显示当前策略状态。 -
whnf将项置于弱头正规形式(weak head normal form)。 -
tactic=> <tactic sequence>返回常规策略模式。这 对于处理conv模式不支持的目标,以及 应用自定义的同余(congruence)和外延性(extensionality)引理非常有用。example (g : Nat → Nat → Nat) (h₁ : ∀ x, x ≠ 0 → g x x = 1) (h₂ : x ≠ 0) : g x x + x = 1 + x := x:Natg:Nat → Nat → Nath₁:∀ (x : Nat), x ≠ 0 → g x x = 1h₂:x ≠ 0⊢ g x x + x = 1 + x x:Natg:Nat → Nat → Nath₁:∀ (x : Nat), x ≠ 0 → g x x = 1h₂:x ≠ 0| g x x + x = 1 + x x:Natg:Nat → Nat → Nath₁:∀ (x : Nat), x ≠ 0 → g x x = 1h₂:x ≠ 0| g x x + x x:Natg:Nat → Nat → Nath₁:∀ (x : Nat), x ≠ 0 → g x x = 1h₂:x ≠ 0| g x x x:Natg:Nat → Nat → Nath₁:∀ (x : Nat), x ≠ 0 → g x x = 1h₂:x ≠ 0| 1x:Natg:Nat → Nat → Nath₁:∀ (x : Nat), x ≠ 0 → g x x = 1h₂:x ≠ 0⊢ x ≠ 0 . x:Natg:Nat → Nat → Nath₁:∀ (x : Nat), x ≠ 0 → g x x = 1h₂:x ≠ 0| 1 . x:Natg:Nat → Nat → Nath₁:∀ (x : Nat), x ≠ 0 → g x x = 1h₂:x ≠ 0⊢ x ≠ 0 All goals completed! 🐙 -
apply<term>是tactic=> apply <term>的语法糖。example (g : Nat → Nat → Nat) (h₁ : ∀ x, x ≠ 0 → g x x = 1) (h₂ : x ≠ 0) : g x x + x = 1 + x := x:Natg:Nat → Nat → Nath₁:∀ (x : Nat), x ≠ 0 → g x x = 1h₂:x ≠ 0⊢ g x x + x = 1 + x x:Natg:Nat → Nat → Nath₁:∀ (x : Nat), x ≠ 0 → g x x = 1h₂:x ≠ 0| g x x + x = 1 + x x:Natg:Nat → Nat → Nath₁:∀ (x : Nat), x ≠ 0 → g x x = 1h₂:x ≠ 0| g x x + x x:Natg:Nat → Nat → Nath₁:∀ (x : Nat), x ≠ 0 → g x x = 1h₂:x ≠ 0| g x x x:Natg:Nat → Nat → Nath₁:∀ (x : Nat), x ≠ 0 → g x x = 1h₂:x ≠ 0| 1x:Natg:Nat → Nat → Nath₁:∀ (x : Nat), x ≠ 0 → g x x = 1h₂:x ≠ 0⊢ x ≠ 0 . x:Natg:Nat → Nat → Nath₁:∀ (x : Nat), x ≠ 0 → g x x = 1h₂:x ≠ 0| 1 . All goals completed! 🐙