Coq 证明依赖类型实例之间的相等性

Coq 证明依赖类型实例之间的相等性,coq,Coq,当试图将对应于代数结构的类(例如所有幺半群的类)形式化时,自然的设计是创建一个类型幺半群(a:type),作为一个产品类型,对所有必需的字段进行建模(一个元素e:a,一个操作符app:a->a,证明满足幺半群定律等)。这样做,我们创建了一个映射monoid:Type->Type。这种方法的一个可能缺点是给定一个幺半群m:monoida(一个支持类型a的幺半群)和m':幺半群b(一个支持类型b的幺半群),我们甚至不能写出等式m=m'(更不用说证明它了)因为它是类型错误的。另一种设计是创建一个类型m

当试图将对应于代数结构的类(例如所有幺半群的类)形式化时,自然的设计是创建一个类型
幺半群(a:type)
,作为一个产品类型,对所有必需的字段进行建模(一个元素
e:a
,一个操作符
app:a->a
,证明满足幺半群定律等)。这样做,我们创建了一个映射
monoid:Type->Type
。这种方法的一个可能缺点是给定一个幺半群
m:monoida
(一个支持类型
a
的幺半群)和
m':幺半群b
(一个支持类型
b
的幺半群),我们甚至不能写出等式
m=m'
(更不用说证明它了)因为它是类型错误的。另一种设计是创建一个类型
monoid
,其中支持类型只是另一个字段
a:type
,因此给定
m:monoid
,询问
m=m'
,总是有意义的。不知何故,人们会认为如果
m
m'
具有相同的支持(
am=am
)并且运算符是相等的(
app m=app m'
,这可以通过一些扩展的相等公理来实现),并且证明字段不重要(因为我们有一些证明无关公理)等等,然后
m=m'
。不幸的是,我们不能用事件表示等式
app m=app m'
,因为它的类型不正确

为了简化问题,假设我们有:

Inductive myType : Type :=
| make : forall (a:Type), a -> myType.
.
我希望得到表格的结果:

forall (a b:Type) (x:a) (y:b), a = b -> x = y -> make a x = make b y.
这对账单打错了,所以我们无法收到


我可能有一些公理可以证明两种类型的
a
b
是相同的,我可能可以证明
x
y
确实是相同的,但我想有一个工具可以让我得出结论
make a x=make b y
。欢迎任何建议。

证明这一点的低技术方法是使用提供的等式插入手动类型转换。也就是说,您没有假设
x=y
,而是假设
(cast q x)=y
。下面我显式地将转换编写为匹配,但您也可以通过定义一个函数使其看起来更好

Inductive myType : Type :=
| make : forall (a:Type), a -> myType.

Lemma ex : forall (a b:Type) (x:a) (y:b) (q: a = b), (match q in _ = T return T with eq_refl => x end) = y -> make a x = make b y.
Proof.
  destruct q.
  intros q.
  congruence.
Qed.
有一种更好的方法可以通过使用“异构相等”(也称为JMeq)来隐藏大部分这种机制。我建议您进行详细介绍。您的示例变成

Require Import  Coq.Logic.JMeq.

Infix "==" := JMeq (at level 70, no associativity).

Inductive myType : Type :=
| make : forall (a:Type), a -> myType.

Lemma ex : forall (a b:Type) (x:a) (y:b), a = b -> x == y -> make a x = make b y.
Proof.
  intros.
  rewrite H0.
  reflexivity.
Qed.
一般来说,尽管这个特殊的定理可以在没有公理的情况下证明,如果你这样做形式化,你很可能会遇到没有关于平等的公理就无法在Coq中证明的目标。特别是,这种依赖记录的内射性是不可证明的。JMEq库将自动使用公理
JMeq_eq
关于异构等式,这使它非常方便