Coq中sig类型元素的相等性

时间:2017-07-10 13:51:36

标签: coq subtype

使用sig类型定义:

Inductive A: Set := mkA : nat-> A.
Function getId (a: A) : nat := match a with mkA n => n end.
Function filter (a: A) : bool := if (beq_nat (getId a) 0) then true else false.
Coercion is_true : bool >-> Sortclass.
Definition subsetA : Set := { a : A | filter a }.

我试图证明它的投射是单射的:

Lemma projection_injective : 
  forall t1 t2: subsetA, proj1_sig t1 = proj1_sig t2 -> t1 = t2.
Proof.
 destruct t1.
 destruct t2.
 simpl.
 intros.
 rewrite -> H. (* <- stuck here *)
Abort.

此时,Coq知道:

x : A
i : is_true (filter x)
x0 : A
i0 : is_true (filter x0)
H : x = x0

我尝试了一些改写没有成功。例如,为什么我不能重写iH来给Coq一个i0?请问这里我想念的是什么?感谢。

1 个答案:

答案 0 :(得分:2)

当你遇到困难时,你的目标大致如下:

exist x i = exist x0 i0

如果您输入的重写成功,您将获得以下目标:

exist x0 i = exist x0 i0

在这里,你可以看到为什么Coq抱怨:重写可能会产生一个错误的术语。问题是子项exist x0 i使用i作为filter x0类型的术语,当它确实具有类型filter x时。为了让Coq相信这不是问题,你需要在重写之前按摩你的目标:

Lemma projection_injective : 
  forall t1 t2: subsetA, proj1_sig t1 = proj1_sig t2 -> t1 = t2.
Proof.
 destruct t1.
 destruct t2.
 simpl.
 intros.
 revert i. (* <- this is new *)
 rewrite -> H. (* and now the tactic succeeds *)
 intros i.
Abort.

或者,您可以使用subst策略,该策略尝试删除上下文中的所有冗余变量。以下是上述脚本的更紧凑版本:

Lemma projection_injective :
  forall t1 t2: subsetA, proj1_sig t1 = proj1_sig t2 -> t1 = t2.
Proof.
  intros [x1 i1] [x2 i2]; simpl; intros e.
  subst.
Abort.

之后您可能会遇到另一个问题:显示filter x0类型的任何两个术语都相同。一般来说,你需要证明不相关的公理才能表明这一点;但是,由于filter被定义为具有可判定等式的类型的两个项之间的相等,因此您可以将此属性证明为一个定理(Coq standard library已经为您做过)。

作为旁注,mathcomp库已经有一个generic lemma包含您的财产,名为val_inj。只是举个例子,这是人们可以使用它的方式:

From mathcomp Require Import ssreflect ssrfun ssrbool eqtype.

Inductive A: Set := mkA : nat-> A.
Function getId (a: A) : nat := match a with mkA n => n end.
Function filter (a: A) : bool := if (Nat.eqb (getId a) 0) then true else false.
Definition subsetA : Set := { a : A | filter a }.

Lemma projection_injective :
  forall t1 t2: subsetA, proj1_sig t1 = proj1_sig t2 -> t1 = t2.
Proof.
  intros t1 t2.
  apply val_inj.
Qed.