Coq 为什么我在本例中定义强制的方法是错误的,正确的方法是什么?

Coq 为什么我在本例中定义强制的方法是错误的,正确的方法是什么?,coq,Coq,我的Coq代码如下: Inductive A (X: Type) := n1 : nat -> X -> (A X) . Arguments n1 {X} _ _. Inductive B := m1 : (A nat) -> B | m2 : B -> B -> B . Coercion m1 : A >-> B. Check m2 (m1 (n1 1

我的Coq代码如下:

    Inductive A (X: Type) :=
      n1 : nat -> X -> (A X)
    .

    Arguments n1 {X} _ _. 

    Inductive B :=
      m1 : (A nat) -> B |
      m2 : B -> B -> B
    .

    Coercion m1 : A >-> B.

    Check m2 (m1 (n1 1 2)) (m1 (n1 2 2)). (* 1st Check *)
    Check m2 (n1 1 2) (n1 2 2). (* 2nd Check *)
我定义了类型A和B(A是多态类型)。当写下由操作符'm2'连接的B的表达式(如'1st Check')时,我希望省略构造函数'm1'(如'2nd Check'),因此我如上所述定义了强制。但是,只有“第一次检查”有效,“第二次检查”无效


这里使用胁迫的正确方式是什么?为什么我的定义是错误的?

我不认为有任何方便的方法可以通过当前的强制引擎获得您想要的东西。当您输入
m1
作为强制时,Coq表示它不遵守统一继承条件。当您声明类型族之间的强制以修复某些参数时,就会发生这种情况;在这里,您将
X
固定为
nat
。当此条件被打破时,Coq的类型检查器拒绝应用强制

一种局部解决方案是引入一种中间类型:

Inductive A (X: Type) :=
      n1 : nat -> X -> (A X)
    .

    Arguments n1 {X} _ _.

Definition Anat := A nat.
Identity Coercion Anat_of_A : Anat >-> A.

Inductive B :=
  m1 : Anat -> B |
  m2 : B -> B -> B
.

Coercion m1 : Anat >-> B.

Check m2 (m1 (n1 1 2)) (m1 (n1 2 2)). (* 1st Check *)
Check m2 (n1 1 2 : Anat) (n1 2 2 : Anat). (* 2nd Check *)

问题是,
n1
最后仍然产生
A
类型的东西,而不是
Anat
。因此,您需要显式强制转换来说服Coq触发强制。当然,您也可以定义一个专门用于
X
n1
版本,但这会破坏使
a
多态的目的。

问题是我不能在这里预先定义Anat,例如,如果m1:(a B)->B,我该怎么做?使用类型类来伪造强制是否可以?您可以定义一个类型类
isbt:=toB:T->B
,并在
m1
周围定义一个包装器,该包装器假定一个实现该类型类的参数:
m1'x:=m1(tobx)
。问题是,这种“强制”不会自动应用于每个函数;您需要一个重载版本的每个函数,您希望使用这个强制。我可能需要一些时间来理解您所说的。无论如何,谢谢你的回答。