自述文件中引用的参考资料很好地概述了擦除问题。具体而言,本报告和本文都详细解释了 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 。