Coq严格的积极性令人费解
我正在开发一种包含术语、变量和nat文本的语言,其中语言的算术结构是预定义的:Coq严格的积极性令人费解,coq,Coq,我正在开发一种包含术语、变量和nat文本的语言,其中语言的算术结构是预定义的: Inductive sort : Set := TERM | VAR | NAT. Inductive termArity : list sort -> Set := | Var : termArity [VAR] | Let : termArity [VAR ; TERM ; TERM] | Lam : termArity [VAR ; TERM] | Ap : t
Inductive sort : Set := TERM | VAR | NAT.
Inductive termArity : list sort -> Set :=
| Var : termArity [VAR]
| Let : termArity [VAR ; TERM ; TERM]
| Lam : termArity [VAR ; TERM]
| Ap : termArity [TERM ; TERM]
| NumLit : termArity [NAT]
| Plus : termArity [TERM ; TERM]
.
我要使用的术语定义包含一个子项,该子项与arity规范hlist中的每种类型相匹配。hlist是CPDT中的异构列表:
Inductive t : Type :=
| Node : forall (sorts : list sort) (code : termArity sorts),
hlist (fun s : sort => match s with
| TERM => t
| VAR => String.string
| NAT => nat
end) sorts
-> t.
但coq以“t的非严格阳性发生率”拒绝了它
正如预期的那样,用nat替换定义中的t会让coq相信它是可以的:
Inductive t : Type :=
| Node : forall (sorts : list sort) (code : termArity sorts),
hlist (fun s : sort => match s with
| TERM => nat
| VAR => String.string
| NAT => nat
end
) sorts
-> t.
令人惊讶的是,它总是返回t
为什么我尝试的定义失败,而它通过了积极性检查?我如何修正我的定义
编辑:另一次放弃代码但由于宇宙不一致而失败的尝试:
Definition var : Set := String.string.
Inductive termArity : list Type -> Type :=
| Var : termArity [var]
| Let : termArity [t; t]
| Lam : termArity [var; t]
| Ap : termArity [t; t]
| NumLit : termArity [nat]
| Plus : termArity [t; t]
with t : Type :=
| Node : forall (sorts : list Type) (code : termArity sorts),
hlist (fun s : Type => s) sorts -> t.
整个文件:
Require Coq.Bool.Bool. Open Scope bool.
Require Coq.Strings.String. Open Scope string_scope.
Require Coq.Arith.EqNat.
Require Coq.Arith.PeanoNat.
Require Coq.Arith.Peano_dec. Open Scope nat_scope.
Require Coq.Lists.List. Open Scope list_scope.
Require Coq.Vectors.Vector. Open Scope vector_scope.
Require Fin.
Module Export LocalListNotations.
Notation " [ ] " := nil (format "[ ]") : list_scope.
Notation " [ x ; .. ; y ] " := (cons x .. (cons y nil) ..) : list_scope.
Notation " [ x ; y ; .. ; z ] " := (cons x (cons y .. (cons z nil) ..)) : list_scope.
End LocalListNotations.
Module Core.
Set Implicit Arguments.
(* cpdt heterogeneous lists *)
Section hlist.
Variable A : Type.
Variable B : A -> Type.
Inductive hlist : list A -> Type :=
| HNil : hlist nil
| HCons : forall (x : A) (ls : list A), B x -> hlist ls -> hlist (x :: ls).
Variable elm : A.
Inductive member : list A -> Type :=
| HFirst : forall ls, member (elm :: ls)
| HNext : forall x ls, member ls -> member (x :: ls).
Fixpoint hget ls (mls : hlist ls) : member ls -> B elm :=
match mls with
| HNil => fun mem =>
match mem in member ls' return (match ls' with
| nil => B elm
| _ :: _ => unit
end) with
| HFirst _ => tt
| HNext _ _ => tt
end
| HCons x mls' => fun mem =>
match mem in member ls' return (match ls' with
| nil => Empty_set
| x' :: ls'' =>
B x' -> (member ls'' -> B elm)
-> B elm
end) with
| HFirst _ => fun x _ => x
| HNext _ mem' => fun _ get_mls' => get_mls' mem'
end x (hget mls')
end.
End hlist.
Arguments HNil [A B].
Arguments HCons [A B x ls].
Arguments HFirst [A elm ls].
Arguments HNext [A elm x ls].
Module Exp.
Inductive sort : Set := TERM | VAR | NAT.
Inductive termArity : list sort -> Set :=
| Var : termArity [VAR]
| Let : termArity [VAR ; TERM ; TERM]
| Lam : termArity [VAR ; TERM]
| Ap : termArity [TERM ; TERM]
| NumLit : termArity [NAT]
| Plus : termArity [TERM ; TERM]
.
(* coq complains this is not strictly positive. *)
Inductive t : Type :=
| Node3 : forall (sorts : list sort) (code : termArity sorts),
hlist (fun s : sort => match s with
| TERM => t
| VAR => String.string
| NAT => nat
end) sorts
-> t.
(* exactly the same definition, but replacing t with nat, is
not flagged as non-strictly-positive. this makes sense to me. *)
Inductive t_not_quite_1 : Type :=
| Node1 : forall (sorts : list sort) (code : termArity sorts),
hlist (fun s : sort => match s with
| TERM => nat
| VAR => String.string
| NAT => nat
end
) sorts
-> t_not_quite_1.
(* this also (like the failed definition) returns t in the
hlist type, but surprisingly typechecks! I don't understand
how this is different *)
Inductive t_not_quite_2 : Type :=
| Node2 : forall (sorts : list sort) (code : termArity sorts),
hlist (fun s : sort => t_not_quite_2) sorts
-> t_not_quite_2.
End Exp.
End Core.
Coq未看穿积极性检查器中的匹配语句;这是一个长期存在的功能请求,请参阅和 我相信如果你把它变成一个感应式的
Inductive kind_of_sort t : sort -> Type :=
| term_kind : t -> kind_of_sort t TERM
| var_kind : String.string -> kind_of_sort VAR
| nat_kind : nat -> kind_of_sort NAT.
然后用它来代替匹配语句。Coq在积极性检查器中看不透匹配语句;这是一个长期存在的功能请求,请参阅和 我相信如果你把它变成一个感应式的
Inductive kind_of_sort t : sort -> Type :=
| term_kind : t -> kind_of_sort t TERM
| var_kind : String.string -> kind_of_sort VAR
| nat_kind : nat -> kind_of_sort NAT.
然后用它代替match语句。如果用var:Type替换var:Set,您的宇宙不一致性会消失吗?它会变成异常:'异常宇宙比较只能在变量之间发生。请在“您使用的是什么版本的Coq?”?在8.7.1中有这样的说法吗?如果是这样,这是一个应该在GitHubThank上报告的bug——从8.7.0升级到8.7.1修复了这个异常。现在它只报告了一个宇宙不一致性。如果你也替换[nat][nat:Type],你的宇宙不一致性会消失吗?如果你用var:Type替换var:Set,它会变成一个异常:'异常-宇宙比较只能在变量之间发生。请在“您使用的是什么版本的Coq?”?在8.7.1中有这样的说法吗?如果是这样,这是一个应该在GitHubThank上报告的bug——从8.7.0升级到8.7.1修复了这个异常。它现在只报告了一个宇宙不一致性。如果您还替换[nat][nat:Type],会怎么样?