我是 Coq 的新手,目前在Software FoundationsIndProp
章节。我很想学习编写自己的简单策略来自动化某些类型的推理,但不幸的是,作为初学者,官方文档对我来说有点难以理解。
我想写一个适用于以下场景的策略:
- 目前的目标是
False
- 有一个形式的假设
P \/ False
基于以下引理,我们应该能够~P
在这种情况下将当前目标替换为:
Lemma orfalse_lemma : forall P : Prop,
P \/ False -> ~P -> False.
Proof.
intros P [H|H] HP.
- apply HP. apply H.
- apply H.
Qed.
我们可以手动使用引理来达到预期的效果:
Example ex_orfalse_1 :
(1 <> 2) \/ False -> (False).
Proof.
intros H. apply (orfalse_lemma (1 <> 2)). apply H.
(* goal: ~ (1 <> 2) *)
Admitted.
我想自动化这个,所以我写了一个简单的策略来在目标和上下文匹配这个场景时应用引理:
Ltac orfalse :=
match goal with
| [H : ?P \/ False |- False ] => apply (orfalse_lemma P) ; [> apply H | ]
| _ => fail "expected goal to be False"
end.
它按预期工作。但是,当有多个假设与模式匹配时,我们无法在它们之间进行选择:
Example ex_orfalse_1 :
(1 <> 2) \/ False -> (False).
Proof.
intros H. orfalse.
(* goal: ~ (1 <> 2) *)
Admitted.
Example ex_orfalse_2 :
(false <> true) \/ False -> (1 <> 2) \/ False -> (False).
Proof.
intros H1 H2. orfalse.
(* goal: ~ (1 <> 2) *)
(* what if we want the goal to be ~ (false <> true) instead? *)
Admitted.
我假设解决这个问题就像将所需的假设orfalse
作为参数传递给策略一样简单:
Ltac orfalse H :=
match goal with
| [|- False ] => match H with
| ?P \/ False => apply (orfalse_lemma ?P) ; [> apply H | ]
| _ => fail "expected disjunction with false"
end
| _ => fail "expected goal to be False"
end.
但是,在证明中使用它失败了:
Example ex_orfalse_2 :
(false <> true) \/ False -> (1 <> 2) \/ False -> (False).
Proof.
intros H1 H2. orfalse H1.
(* Tactic failure: expected goal to be False. *)
Admitted.
?P
如果我用 just和 return替换嵌套匹配的第一种情况idtac ?P
,它只会打印我传入的假设的名称(例如H1
or H2
),所以我的猜测是匹配发生在标识符本身而不是假设上。
所以,我的问题是: 如果我将假设的名称传递给策略,我如何正确匹配该假设的结构? 谢谢!