试图在不创建错误术语的情况下使用证明无关性

时间:2017-12-17 09:36:25

标签: coq

为了说明我面临的问题,让我们假设我们在nat上有一个谓词:

Parameter pred : nat -> Prop

让我们进一步假设我们有一个封装数据的类型,以及封装数据满足某个属性的证明。例如:

Inductive obj : Type :=
  | c : forall (n:nat), pred n -> obj
  .

现在,我们希望将两个对象c n pc 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的类型理论中应该是正确的(鉴于证明不相关公理)但可能涉及一些初学者未知的技巧。任何建议都非常感谢。

1 个答案:

答案 0 :(得分:4)

TL; DR

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"

这意味着此时npred n之间的链接已丢失,我们可以通过明确说明xp必须遵守每个链接来恢复它另外通过概括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.对此特定情况的影响。