如何在 Coq 中定义具有命名参数的依赖类型而不导致构造函数中出现统一问题?
我想定义一个长列表,但我喜欢在归纳定义顶部带有名称的参数。每当我尝试这样做时,我都会遇到我希望起作用的东西的统一错误,并且被迫做一个显然有错误的定义,例如允许一个列表,其中所有内容的长度都是 0 但有 1 个元素。我该如何解决这个问题?
Inductive Vector {A : Type} (n : nat) : Type :=
| vnil (* not quite right...*)
| vcons (hd : A) (tail: Vector (n-1)).
Check vnil 0.
Check vcons 1 true (vnil 0).
(* Inductive Vector' (n : nat) : Type :=
| vnil': Vector' 0
| vcons': A -> Vector' n -> Vector' (S n). *)
Inductive Vector' {A: Type} : nat -> Type :=
| vnil': Vector' 0
| vcons': forall n : nat, A -> Vector' n -> Vector' (S n).
Check vnil'.
Check vcons' 0 true (vnil').
Inductive Vector'' {A : Type} (n : nat) : Type :=
| vnil'': Vector'' n (* seems weird, wants to unify with n, argh! *)
| vcons'': A -> Vector'' (n-1) -> Vector'' n.
Check vnil'' 0.
Check vcons'' 1 true (vnil'' 0).
(* Check vcons'' 0 true (vnil'' 0). *) (* it also worked! nooooo! hope the -1 did the trick but not *)
I want to defined a lenghted list but I like arguments with names at the top of the inductive definition. Whenever I try that I get unification errors with things I hoped worked and was forced to do a definition that obviously has bugs e.g. allows a list where everything is length 0 but has 1 element. How do I fix this?
Inductive Vector {A : Type} (n : nat) : Type :=
| vnil (* not quite right...*)
| vcons (hd : A) (tail: Vector (n-1)).
Check vnil 0.
Check vcons 1 true (vnil 0).
(* Inductive Vector' (n : nat) : Type :=
| vnil': Vector' 0
| vcons': A -> Vector' n -> Vector' (S n). *)
Inductive Vector' {A: Type} : nat -> Type :=
| vnil': Vector' 0
| vcons': forall n : nat, A -> Vector' n -> Vector' (S n).
Check vnil'.
Check vcons' 0 true (vnil').
Inductive Vector'' {A : Type} (n : nat) : Type :=
| vnil'': Vector'' n (* seems weird, wants to unify with n, argh! *)
| vcons'': A -> Vector'' (n-1) -> Vector'' n.
Check vnil'' 0.
Check vcons'' 1 true (vnil'' 0).
(* Check vcons'' 0 true (vnil'' 0). *) (* it also worked! nooooo! hope the -1 did the trick but not *)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
:
左侧的命名参数(它们称为参数)在每个构造函数中隐式forall
',并且必须在每个构造函数的返回类型中显示为相同的变量。右侧的参数(它们称为索引)不是隐式地forall
的,并且可以显示为任何内容。您的定义的部分问题在于,在编写每个构造函数的类型时已经引入了n
,因此您不能完全将其限制为Z
或S m
此时。这个想法是参数应该是整个归纳定义的参数。
向量 A n
和向量 B m
彼此不依赖;将Vector A
和Vector B
视为不同的归纳定义,并将Vector
视为由参数化的归纳系列是有意义的>输入。另一方面,
Vector A (S n)
指Vector A n
;如果不首先构造Vector A n
,则无法构造类型Vector A (S n)
,因此它们应被视为归纳构造Vector A : nat - 的一部分>输入
。这种解释并没有严格执行——你可以用 Intropic E (n : nat) : Set := | 在其中戳一个洞。 mk_E:E(Sn)→ E n.-但是关于构造函数返回类型中的参数与索引的规则是强制执行的。 Coq 的设计意图是定义
Vector
的“最自然”方式是如果你想澄清
nat
是什么 评论这样做,您可以留下类似或的
如果您真的想要
Inducing Vector (A : Type) (n : nat) : Type
,那么您必须诉诸某些东西就像这让一切变得混乱。
Named arguments to the left of
:
(they are called parameters) are implicitlyforall
'd in each constructor and must appear as the same variable in the return type of each constructor. Arguments to the right (they are called indices) are not implicitlyforall
'd and may appear as anything. Part of the issue with your definitions is thatn
is already introduced by the time you're writing the type of each constructor, so you can't quite restrict it to beZ
orS m
at that point.The idea is that parameters are supposed to be parameters to the whole inductive definition.
Vector A n
andVector B m
do not depend on each other; it would make sense to considerVector A
andVector B
to be different inductive definitions, andVector
as a family of inductives parameterized by aType
. On the other hand,Vector A (S n)
refers toVector A n
; you cannot construct the typeVector A (S n)
without first constructingVector A n
, so they should be considered parts of one inductive constructionVector A : nat -> Type
.This interpretation is not strictly enforced—you can poke a hole in it with
Inductive E (n : nat) : Set := | mk_E : E (S n) -> E n.
—but the rule about parameters vs. indices in constructor return types is enforced. It is the intent of the design of Coq that the "most natural" way to defineVector
isIf you want to clarify what the
nat
is doing, you could just leave a comment likeor
If you really want
Inductive Vector (A : Type) (n : nat) : Type
, then you have to resort to something likeWhich makes everything messy.