为什么FMapAVL在参数中的使用非严格为正,而列表是?

时间:2018-04-15 17:07:46

标签: coq

请考虑以下代码:

Require Import FMapAVL.
Require Import Coq.Structures.OrderedTypeEx.

Module NatMap := FMapAVL.Make(Nat_as_OT).

Inductive ttree (K : Type) (V : Type) :=
| tleaf : ttree K V
| tnode : ttree K V -> K -> V -> ttree K V -> nat -> ttree K V.

Inductive test :=
| test1 : test
| test2 : ttree nat test -> test   
| test3 : list test -> test
| test4 : NatMap.t test -> test.

在Coq 8.6中,我得到Error: Non strictly positive occurrence of "test" in "NatMap.t test -> test".没有test4我就没有错误。

为什么在我的NatMap.t归纳类型中应用FMapAVLnattest键)构造函数会在应用list构造函数时产生非严格的正面出现甚至ttree构造函数(就像FMapAVL的内部结构一样)好吗?

如果我想从我的示例中获取test4之类的内容,有哪些常见的解决方法,最好是不要求我像ttree那样制作自己的地图实现?

1 个答案:

答案 0 :(得分:1)

问题是Coq无法处理一些高阶归纳类型作为嵌套归纳 - 我不相信我完全理解这些局限性,但我调查了一下。

有助于解释行为的一个重要事实是Coq特别支持将归纳类型传递给类型构造函数。 CPDT's Inductive Types章节在嵌套归纳类型一节中对此进行了解释:Coq创建的listttree版本专门针对test并假装您正在定义tree和这些具有互感的专用电感。这通常可以正常工作(例如您的list甚至ttree定义)。它甚至适用于模块,只要它们使用“transparent ascription”(和FMapAVL.Make这样做)。但是,当类型是索引而不是参数时(例如,Type位于冒号右侧而不是左侧)时,它似乎会崩溃:

Module Type Transformer.
  Axiom T:Type -> Type.
End Transformer.

Module IdOpaque : Transformer.
  Definition T (t:Type) := t.
End IdOpaque.

Inductive transformer : Type -> Type :=
| MkT : forall t, t -> transformer t .

(* make the argument a parameter *)
Inductive transformer' (t:Type) : Type :=
| MkT' : t -> transformer' t.

Module IdInd <: Transformer.
  Definition T : Type -> Type := transformer.
End IdInd.

Module IdTransparent <: Transformer.
  Definition T (t:Type) : Type := t.
End IdTransparent.

(* works with a simple definition, even inside a module, as long as its
transparent *)
Inductive test1 :=
| mkTest1 (_:IdTransparent.T test1).

(* not strictly positive (Coq can't see definition) *)
Fail Inductive test2 :=
| mkTest2 (_:IdOpaque.T test2).

(* this is pretty much what happens with FMapAVL.Make *)
Fail Inductive test3 :=
| mkTest3 (_:IdInd.T test3).

(* even this fails *)
Fail Inductive test4 :=
| mkTest4 (_:transformer test4).

(* this finally works *)
Inductive test5 :=
| mkTest5 (_:transformer' test5).