我们如何为依赖类型定义“eqType”?
How can we define `eqType` for dependent types?
我想将依赖类型定义为 eqType
。
例如,假设我们定义了以下依赖类型 Tn
:
From mathcomp Require Import all_ssreflect.
Variable T: nat -> eqType.
Inductive Tn: Type := BuildT: forall n, T n -> Tn.
为了实现 eqType
,我为 Tn
:
定义了一个等式函数 Tn_eq
Definition Tn_eq: rel Tn :=
fun '(BuildT n1 t1) '(BuildT n2 t2) =>
(if n1 == n2 as b return (n1==n2) = b -> bool
then fun E => t1 == eq_rect_r T t2 (elimTF eqP E)
else fun _ => false) (erefl (n1 == n2)).
然后我试图证明 Tn_eq
的等式公理但是失败了。
Lemma Tn_eqP: Equality.axiom Tn_eq.
Proof.
case=>n1 t1; case=>n2 t2//=.
case_eq(n1==n2).
我这里有一个错误:
Illegal application:
The term "elimTF" of type
"forall (P : Prop) (b c : bool), reflect P b -> b = c -> if c then P else ~ P"
cannot be applied to the terms
"n1 = n2" : "Prop"
"b" : "bool"
"true" : "bool"
"eqP" : "reflect (n1 = n2) (n1 == n2)"
"E" : "b = true"
The 4th term has type "reflect (n1 = n2) (n1 == n2)" which should be coercible to
"reflect (n1 = n2) b".
我该如何证明这个引理?
开始吧:
From Coq Require Import EqdepFacts.
From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat.
Variable T: nat -> eqType.
Inductive Tn: Type := BuildT: forall n, T n -> Tn.
Definition Tn_eq: rel Tn :=
fun '(BuildT n1 t1) '(BuildT n2 t2) =>
(if n1 == n2 as b return (n1==n2) = b -> bool
then fun E => t1 == eq_rect_r T t2 (elimTF eqP E)
else fun _ => false) (erefl (n1 == n2)).
Lemma Tn_eqP: Equality.axiom Tn_eq.
Proof.
case=> n1 t1; case=> n2 t2 /=.
case: eqP => [eq1 | neq1]; last by constructor; case.
case: eqP.
- move=> ->; constructor; move: t2; rewrite [elimTF _ _]eq_irrelevance.
by case: _ / eq1.
move=> neq2; constructor.
case=> _ exT; move: (eq_sigT_snd exT) => Cast; apply: neq2.
rewrite -Cast.
rewrite [eq_sigT_fst _]eq_irrelevance [elimTF _ _]eq_irrelevance.
by case: _ / eq1.
Qed.
在没有额外帮助的情况下,目前在 mathcomp 中执行此操作的最佳方法(参见下文)是使用(部分)双射,而不是手动定义等式及其正确性证明:
Definition encode x := let: BuildT _ tn := x in Tagged T tn.
Definition decode (x : sigT T) := BuildT (tagged x).
Lemma encodeK : cancel encode decode. Proof. by case. Qed.
Definition Tn_eqMixin := CanEqMixin encodeK.
Canonical Tn_eqType := EqType Tn Tn_eqMixin.
自动化方法是:
PS:如果你真的需要,你总是可以相对容易地证明与自己的相等:
Lemma Tn_eqE : Tn_eq =2 eq_op.
Proof.
case=> [n tn] [m tm]; rewrite [RHS]/eq_op/= -tag_eqE/= /tag_eq/= /tagged_as/=.
by case: eqP => //= p; rewrite [elimTF _ _](eq_irrelevance _ p).
Qed.
(有时候证明程序等式确实比从头证明正确性更容易。)
我想将依赖类型定义为 eqType
。
例如,假设我们定义了以下依赖类型 Tn
:
From mathcomp Require Import all_ssreflect.
Variable T: nat -> eqType.
Inductive Tn: Type := BuildT: forall n, T n -> Tn.
为了实现 eqType
,我为 Tn
:
Tn_eq
Definition Tn_eq: rel Tn :=
fun '(BuildT n1 t1) '(BuildT n2 t2) =>
(if n1 == n2 as b return (n1==n2) = b -> bool
then fun E => t1 == eq_rect_r T t2 (elimTF eqP E)
else fun _ => false) (erefl (n1 == n2)).
然后我试图证明 Tn_eq
的等式公理但是失败了。
Lemma Tn_eqP: Equality.axiom Tn_eq.
Proof.
case=>n1 t1; case=>n2 t2//=.
case_eq(n1==n2).
我这里有一个错误:
Illegal application:
The term "elimTF" of type
"forall (P : Prop) (b c : bool), reflect P b -> b = c -> if c then P else ~ P"
cannot be applied to the terms
"n1 = n2" : "Prop"
"b" : "bool"
"true" : "bool"
"eqP" : "reflect (n1 = n2) (n1 == n2)"
"E" : "b = true"
The 4th term has type "reflect (n1 = n2) (n1 == n2)" which should be coercible to
"reflect (n1 = n2) b".
我该如何证明这个引理?
开始吧:
From Coq Require Import EqdepFacts.
From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat.
Variable T: nat -> eqType.
Inductive Tn: Type := BuildT: forall n, T n -> Tn.
Definition Tn_eq: rel Tn :=
fun '(BuildT n1 t1) '(BuildT n2 t2) =>
(if n1 == n2 as b return (n1==n2) = b -> bool
then fun E => t1 == eq_rect_r T t2 (elimTF eqP E)
else fun _ => false) (erefl (n1 == n2)).
Lemma Tn_eqP: Equality.axiom Tn_eq.
Proof.
case=> n1 t1; case=> n2 t2 /=.
case: eqP => [eq1 | neq1]; last by constructor; case.
case: eqP.
- move=> ->; constructor; move: t2; rewrite [elimTF _ _]eq_irrelevance.
by case: _ / eq1.
move=> neq2; constructor.
case=> _ exT; move: (eq_sigT_snd exT) => Cast; apply: neq2.
rewrite -Cast.
rewrite [eq_sigT_fst _]eq_irrelevance [elimTF _ _]eq_irrelevance.
by case: _ / eq1.
Qed.
在没有额外帮助的情况下,目前在 mathcomp 中执行此操作的最佳方法(参见下文)是使用(部分)双射,而不是手动定义等式及其正确性证明:
Definition encode x := let: BuildT _ tn := x in Tagged T tn.
Definition decode (x : sigT T) := BuildT (tagged x).
Lemma encodeK : cancel encode decode. Proof. by case. Qed.
Definition Tn_eqMixin := CanEqMixin encodeK.
Canonical Tn_eqType := EqType Tn Tn_eqMixin.
自动化方法是:
PS:如果你真的需要,你总是可以相对容易地证明与自己的相等:
Lemma Tn_eqE : Tn_eq =2 eq_op.
Proof.
case=> [n tn] [m tm]; rewrite [RHS]/eq_op/= -tag_eqE/= /tag_eq/= /tagged_as/=.
by case: eqP => //= p; rewrite [elimTF _ _](eq_irrelevance _ p).
Qed.
(有时候证明程序等式确实比从头证明正确性更容易。)