Coq 类型族的归纳定义

Coq 类型族的归纳定义,coq,Coq,我已经为此奋斗了一段时间了。我有一个感应型: Definition char := nat. Definition string := list char. Inductive Exp : Set := | Lit : char -> Exp | And : Exp -> Exp -> Exp | Or : Exp -> Exp -> Exp | Many: Exp -> Exp 从中我归纳地定义了一系列类型: Inductive La

我已经为此奋斗了一段时间了。我有一个感应型:

Definition char := nat.
Definition string := list char.


Inductive Exp : Set :=
  | Lit : char -> Exp
  | And : Exp -> Exp -> Exp
  | Or  : Exp -> Exp -> Exp
  | Many: Exp -> Exp
从中我归纳地定义了一系列类型:

Inductive Language : Exp -> Set :=                                                                                                                                          
  | LangLit     : forall c:char, Language (Lit c)
  | LangAnd     : forall r1 r2: Exp, Language(r1) -> Language(r2) -> Language(And r1 r2)
  | LangOrLeft  : forall r1 r2: Exp, Language(r1) -> Language(Or r1 r2)
  | LangOrRight : forall r1 r2: Exp, Language(r2) -> Language(Or r1 r2)
  | LangEmpty   : forall r: Exp, Language (Many r)
  | LangMany    : forall r: Exp, Language (Many r) -> Language r -> Language (Many r).
这里的理由是,给定一个正则表达式
r:Exp
,我试图将与
r
相关联的语言表示为一种类型
语言r
,并且我使用一个归纳定义

我想证明:

Lemma L1 : forall (c:char)(x:Language (Lit c)),
  x = LangLit c.
Lemma L2: forall (x: List 0),
  x = ListNil.
(换句话说,类型
语言(Lit c)
只有一个元素,即正则表达式
'c'
的语言是由单个字符串
“c”
构成的。当然,我需要定义一些将
语言r
转换为
字符串的语义元素。)

现在,这个问题的细节并不重要,只是用来激发我的问题:让我们使用
nat
而不是
Exp
,并定义一个类型
List n
,它表示长度
n
的列表:

Parameter A:Set.
Inductive List : nat -> Set :=
  | ListNil   : List 0
  | ListCons  : forall (n:nat), A -> List n -> List (S n).
这里我再次使用一个归纳定义来定义一系列类型
listn

我想证明:

Lemma L1 : forall (c:char)(x:Language (Lit c)),
  x = LangLit c.
Lemma L2: forall (x: List 0),
  x = ListNil.
(换句话说,类型
列表0
只有一个元素)

关于这一点我已经没有主意了


通常,当试图用归纳类型(或谓词)证明(否定)结果时,我会使用
elim
策略(确保所有相关假设都在我的目标范围内(
generalize
),并且类型构造函数中只出现变量)。但是
elim
在这种情况下是不好的。

如果你愿意接受的不仅仅是Coq的基本逻辑,你可以使用
依赖销毁
策略,可以在
程序
库中找到(我冒昧地用标准库向量重新表述了你的上一个示例):

如果你检查这个术语,你会发现这个策略依赖于
JMeq_eq
axiom来获得证据:

Print Assumptions l0.

Axioms:
JMeq_eq : forall (A : Type) (x y : A), x ~= y -> x = y
幸运的是,通过对前面引理的陈述做一点小小的修改,可以证明
l0
,而不必求助于Coq基本逻辑之外的特性

Lemma l0_gen A n (v : Vector.t A n) :
  match n return Vector.t A n -> Prop with
  | 0 => fun v => v = @Vector.nil A
  | _ => fun _ => True
  end v.
Proof.
now destruct v.
Qed.

Lemma l0' A (v : Vector.t A 0) : v = @Vector.nil A.
Proof.
exact (l0_gen A 0 v).
Qed.
我们可以看到,这个新证明不需要任何额外的公理:

Print Assumptions l0'.
Closed under the global context
这里发生了什么事?粗略地说,问题在于,在Coq中,我们无法直接对索引具有特定形状(例如,在您的案例中为0)的依赖类型执行案例分析。相反,我们必须证明一个更一般的说法,即用变量替换有问题的指数。这正是
l0\u gen
引理所做的。注意我们如何在
n
上进行匹配,并返回一个在
v
上进行抽象的函数。这是我们所知的另一个例子。我们写信了吗

match n with
| 0 => v = @Vector.nil A
| _ => True
end.
Coq将看到
0
分支中的
v
具有类型
Vector.tan
,使该分支类型错误


提出这样的泛化是在Coq中进行依赖类型编程的一大难题。其他系统,如Agda,使编写此类代码的工作量大大减少,但直到最近才可以在不依赖Coq希望避免包含在其基本理论中的额外公理的情况下完成。我们只能希望在未来的版本中简化这一点。

如果您愿意接受的不仅仅是Coq的基本逻辑,那么您可以使用
依赖销毁
策略,该策略可在
程序
库中找到(我已经冒昧地用标准库向量重新表述了上一个示例):

如果你检查这个术语,你会发现这个策略依赖于
JMeq_eq
axiom来获得证据:

Print Assumptions l0.

Axioms:
JMeq_eq : forall (A : Type) (x y : A), x ~= y -> x = y
幸运的是,通过对前面引理的陈述做一点小小的修改,可以证明
l0
,而不必求助于Coq基本逻辑之外的特性

Lemma l0_gen A n (v : Vector.t A n) :
  match n return Vector.t A n -> Prop with
  | 0 => fun v => v = @Vector.nil A
  | _ => fun _ => True
  end v.
Proof.
now destruct v.
Qed.

Lemma l0' A (v : Vector.t A 0) : v = @Vector.nil A.
Proof.
exact (l0_gen A 0 v).
Qed.
我们可以看到,这个新证明不需要任何额外的公理:

Print Assumptions l0'.
Closed under the global context
这里发生了什么事?粗略地说,问题在于,在Coq中,我们无法直接对索引具有特定形状(例如,在您的案例中为0)的依赖类型执行案例分析。相反,我们必须证明一个更一般的说法,即用变量替换有问题的指数。这正是
l0\u gen
引理所做的。注意我们如何在
n
上进行匹配,并返回一个在
v
上进行抽象的函数。这是我们所知的另一个例子。我们写信了吗

match n with
| 0 => v = @Vector.nil A
| _ => True
end.
Coq将看到
0
分支中的
v
具有类型
Vector.tan
,使该分支类型错误


提出这样的泛化是在Coq中进行依赖类型编程的一大难题。其他系统,如Agda,使编写此类代码的工作量大大减少,但直到最近才可以在不依赖Coq希望避免包含在其基本理论中的额外公理的情况下完成。我们只能希望在将来的版本中简化这一点。

我还发现了另一种证明
:eq_dep_eq;移动E:{12}0v=>izv;案例:iz/v E.
有时很有用。事实上,
eq_dep
和类似的技巧在处理依赖类型时非常有用。这非常好,谢谢!。在我看来,在定义更一般的谓词(使用“护航模式”)时,至少在这种情况下,您可以取消“return Vector.t A n->Prop”。@ejgallego值得一提的是,这些链接在我看来是空白的(即使启用了javascript)。对不起,collacoq确实需要最新的chrome或firefox。我们正在努力支持其他浏览器。同时看看这个:collacoq的好处是,你可以直接运行证明。我还通过apply找到了这个替代证明
:eq\u dep\u eq;移动E:{12}0v=>izv;案例:iz/v E.
有时有用