当试图形成与代数结构相对应的类(例如所有幺半群的类)时,自然设计是创建一个类型monoid (a:Type)
作为产品类型,它模拟所有必需的字段(元素e:a
,一个运算符app : a -> a -> a
,证明幺半群定律得到满足等等。在这样做时,我们正在创建地图monoid: Type -> Type
。这种方法的一个可能的缺点是给定一个幺半群m:monoid a
(一个支持类型a
的幺半群)和m':monoid b
(一个支持类型为b
的幺半群),我们甚至不能写等式m = m'
(更不用说证明它)因为它是错误的类型。另一种设计是创建一个类型monoid
,其中支持类型只是另一个字段a:Type
,因此给定m m':monoid
,询问m = m'
是否总是有意义的。不知何故,有人想说如果m
和m'
具有相同的支持(a m = a m
)并且运算符等于(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
。任何建议都是受欢迎的。
答案 0 :(得分:3)
证明这一点的低技术方法是使用提供的相等性来插入手动类型转换。也就是说,您没有假设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),可以更好地隐藏大部分机器。我建议the Equality chapter of CPDT进行详细介绍。你的例子变成了
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
,这使得它非常方便。