从Coq中提取的Ocaml代码包括(在某些情况下)类型__
和函数__
,其定义如下:
type __ = Obj.t
let __ = let rec f _ = Obj.repr f in Obj.repr f
文档说过去,这种类型被定义为unit
(因此__
可以被视为()
)但是存在(罕见)案例,其值为__
类型__
应用于__
类型的值。
Obj
使用来自OCaml的__
模块的未记录的函数,但似乎所定义的本质上是一个完全多态的函数,它会吃掉它的所有参数(无论它们的数量是多少)。
是否有一些关于{{1}}无法消除的情况的文档,这种类型的值适用于相同类型的值,无论是理论上的(构建Coq术语,其中消除是不可能的)和实际的(显示出现这种情况的现实情况)观点?
答案 0 :(得分:2)
README中引用的参考文献很好地概述了擦除问题。具体来说,this报告和this文章都详细说明了如何删除CIC术语的类型方案和逻辑部分,以及为什么必须有__ x = __
。问题不在于__
可能适用于自身,而是可以应用于任何。
不幸的是,如果在任何非病理情况下这种行为都很重要,那一点都不清楚。给出的动机是能够提取任何 Coq术语,并且文档没有提到任何从实际角度来看真正有趣的案例。 3上给出的示例是这样的:
Definition foo (X : Type) (f : nat -> X) (g : X -> nat) := g (f 0).
Definition bar := foo True (fun _ => I).
执行Recursive Extraction bar.
会得到以下结果:
type __ = Obj.t
let __ = let rec f _ = Obj.repr f in Obj.repr f
type nat =
| O
| S of nat
(** val foo : (nat -> 'a1) -> ('a1 -> nat) -> nat **)
let foo f g =
g (f O)
(** val bar : (__ -> nat) -> nat **)
let bar =
foo (Obj.magic __)
由于foo
在Type
上是多态的,因此无法简化其f O
应用程序,因为它可能具有计算内容。但是,由于Prop
是Type
的子类型,foo
也可以应用于True
,这是bar
中发生的情况。因此,当我们尝试缩减bar
时,我们会将__
应用于O
。
这个特殊情况不是很有趣,因为它可以完全内联foo
:
let bar g =
g __
由于True
无法应用于任何内容,如果g
对应于任何合法的Coq术语,则其__
参数也不会应用于任何内容,因此它会安全__ = ()
(我相信)。然而,存在这样的情况:不可能事先知道是否可以进一步应用已擦除的术语,这使得__
的一般定义成为必要。例如,请查看文件末尾附近的Fun
示例here。