我正在尝试创建一个相当直接的类型层次结构。这是一个最小的工作示例:
Record R0 : Type := {
R0_S :> Type
}.
Record R1 : Type := {
R1_S : Type;
op1 : R1_S -> R1_S
}.
Record R2 : Type := {
R2_S : Type;
op2 : R2_S -> R2_S
}.
Record R12: Type := {
R12_S : Type;
R12_op1 : R12_S -> R12_S;
R12_op2 : R12_S -> R12_S
}.
Definition R1_0 (r1: R1) := (Build_R0 (R1_S r1)).
Coercion R1_0 : R1 >-> R0.
Definition R2_0 (r2: R2) := (Build_R0 (R2_S r2)).
Coercion R2_0 : R2 >-> R0.
Definition R12_1 (r12: R12) := (Build_R1 (R12_S r12) (R12_op1 r12)).
Coercion R12_1 : R12 >-> R1.
Definition R12_2 (r12: R12) := (Build_R2 (R12_S r12) (R12_op2 r12)).
Coercion R12_2 : R12 >-> R2. (* Warning *)
最后一次强制会产生以下警告:
Ambiguous paths:
[R12_2; R2_0] : R12 >-> R0
[R12_2; R2_0; R0_S] : R12 >-> Sortclass
R12_2 is now a coercion
事实上,从R12
到R0
(或Sortclass
)的强制可以采取两种不同的路径。而且我理解为什么Coq会在一般情况下不允许这样做。因为...会使用哪一个?
但是,在这种情况下,可以显示路径R1_0 (R12_1 r12)
和R2_0 (R12_2 r12)
的强制完全相同。但是我仍然无法添加以下看似有效的公理:
Parameter r12 : R12.
Parameter x : r12.
Axiom id1 : (op1 _ x) = x. (* OK *)
Axiom id2 : (op2 _ x) = x. (* Error *)
问题:那么有没有办法让Coq相信这没关系?
答案 0 :(得分:1)
我相信没有办法说服Coq这是可以的。但是,通过使用其他功能(例如规范结构或类型类)可以获得类似的效果。这就是人们可以用类型来翻译你的例子的方式,例如:
Class R1 T :=
{
op1 : T -> T
}.
Class R2 T :=
{
op2 : T -> T
}.
Class R12 T `{R1 T} `{R2 T} :=
{}.
Section S.
Context T `{R12 T}.
Variable x : T.
Hypothesis id1 : op1 x = x.
Hypothesis id2 : op2 x = x.
End S.
请注意,类R12
没有自己的任何方法,但要求类型T
成为R1
和R2
的实例,这会在道德上产生同样的事情。 Context
声明强制Coq根据这些要求自动假设R1
和R2
的实例。
编辑:
如果您尝试添加R0
类来完成图表,则可能会因类型类推断失败而导致奇怪的错误。一种解决方案是关闭R12
中的自动泛化(即删除后引号),并强制R1
和R2
基于相同的R0
实例:
Class R0 (T : Type) := {}.
Class R1 T `{R0 T} :=
{
op1 : T -> T
}.
Class R2 T `{R0 T} :=
{
op2 : T -> T
}.
Class R12 T `{R0 T} {r1:R1 T} {r2:R2 T} :=
{}.
Section S.
Context T `{R12 T}.
Variable x : T.
Hypothesis id1 : op1 x = x.
Hypothesis id2 : op2 x = x.
End S.
不幸的是,我并没有很好地解释为什么会出现错误,因为类型推断有点复杂。但是,我认为它与您先遇到的问题无关,因为实际上并没有像以前那样模糊的路径。