为了说明我面临的问题,让我们假设我们在nat
上有一个谓词:
Parameter pred : nat -> Prop
让我们进一步假设我们有一个封装数据的类型,以及封装数据满足某个属性的证明。例如:
Inductive obj : Type :=
| c : forall (n:nat), pred n -> obj
.
现在,我们希望将两个对象c n p
和c m q
视为n = m
的相同对象,而不管构建它们所涉及的证明。因此,让我们介绍一个证明无关公理:
Axiom irrel : forall (P:Prop) (p q:P), p = q.
现在给出了这个公理,预计c n p = c m q
可以证明平等n = m
:
Theorem obvious : forall (n m:nat) (p: pred n) (q:pred m),
n = m -> c n p = c m q.
现在我已经玩了一段时间了,没有一个典型的重写'战术可以起作用,因为他们创造了错误的术语。我猜测定理在Coq的类型理论中应该是正确的(鉴于证明不相关公理)但可能涉及一些初学者未知的技巧。任何建议都非常感谢。
答案 0 :(得分:4)
Theorem obvious n m (p: pred n) (q: pred m) :
n = m -> c n p = c m q.
Proof.
intros ->.
rewrite (irrel _ p q).
reflexivity.
Qed.
让我展示如何使用包含在错误消息中的信息来提出解决方案:
Theorem obvious n m (p: pred n) (q: pred m) :
n = m -> c n p = c m q.
Proof.
intros E.
Fail rewrite E.
此时我们收到以下错误消息:
The command has indeed failed with message: Abstracting over the term "n" leads to a term fun n0 : nat => c n0 p = c m q which is ill-typed. Reason is: Illegal application: The term "c" of type "forall n : nat, pred n -> obj" cannot be applied to the terms "n0" : "nat" "p" : "pred n" The 2nd term has type "pred n" which should be coercible to "pred n0".
rewrite
策略尝试使用eq_ind_r
引理构建证明术语。让我们看一下它的类型:
eq_ind_r
: forall (A : Type) (x : A) (P : A -> Prop),
P x -> forall y : A, y = x -> P y
rewrite
尝试构建以下术语:
@eq_ind_r _ m (fun x => c x p = c m q) (subgoal : c m p = c m q) n E.
这是错误的类型:
Fail Check @eq_ind_r _ m (fun x => c x p = c m q).
术语
"p"
的类型为"pred n"
,而预期类型为"pred x"
。
这意味着此时n
和pred n
之间的链接已丢失,我们可以通过明确说明x
和p
必须遵守每个链接来恢复它另外通过概括p
:
Check @eq_ind_r _ m (fun x => forall (p : pred x), c x p = c m q).
以上意味着我们可以通过以下方式完成证明:
revert p.
rewrite H; intros p.
rewrite (irrel _ p q).
reflexivity.
Qed.
该代码的原始版本使用intro-pattern intros ->
来实现更长intros E; revert p; rewrite E; intros p.
对此特定情况的影响。