如何在定理类型中引用类型类多态变量?

时间:2015-01-09 00:20:11

标签: typeclass coq

我编写了一个Haskell风格的Functor类型类:

Class Functor (f: Type -> Type) := {
  map {a b: Type}: (a -> b) -> (f a -> f b);
  map_id: forall (a: Type) (x: f a), map id x = x
}

id有明显的定义。

现在,我已经证实了Functor list和函数类型的实例。但我想证明关于任何仿函数的陈述。首先,我想证明什么是基本上是一个重言式:对map_id的任何仿函数进行重述。

Theorem map_id_restatement: forall (F: Type -> Type), 
  Functor F -> forall T (x: F T), map id x = x.

想要证明这个定理的想法我只是apply map_id。但是当我尝试开始证明这一点时,我收到了一个错误:

Toplevel input, characters 88-91:
Error:

Could not find an instance for "Functor F" in environment:

F : Type -> Type
T : Type
x : F T

但由于类型中的假设,Functor F实例应该已经在范围内。为什么不被认可?

编辑:

好的,我发现我可以通过量化Functor F

来实现它
Theorem map_id_restatement: forall (F: Type -> Type) (finst: Functor F),
  forall T (x: F T), map id x = x.
Proof. apply @map_id. Qed.

为什么这有必要?有趣的是,如果我没有明确地为仿函数实例命名(例如,如果我只是写(_: Functor F)),

1 个答案:

答案 0 :(得分:3)

我不知道这是不是一个bug,但请注意,当你写Functor F -> SomeType之类的内容时,你隐含地说SomeType不依赖于Functor实例,在你的情况下不正确:你的定理的完整类型,打印所有隐式参数,将是这样的:

Theorem map_id_restatement: forall (F: Type -> Type) (finst: Functor F),
  forall T (x: F T), @map F fints T T (@id T) x = x.

如果您将finst替换为_,则会获得

Theorem map_id_restatement: forall (F: Type -> Type) (_: Functor F),
  forall T (x: F T), @map F _ T T (@id T) x = x.

无法真正进行类型检查,因为_实际上并不是变量名。

请注意,如果您在冒号前匿名绑定Functor F,Coq会接受它:

Theorem map_id_restatement (F: Type -> Type) (_ : Functor F) :
  forall T (x: F T), map (@id T) x = x.
Proof. apply @map_id. Qed.

据推测,在这里,Coq以不同的方式处理_,并用自动生成的名称替换它,而不是实际将其保留为未命名。您还可以使用以下表单,该表单在forall下或冒号之前有效:

Theorem map_id_restatement (F: Type -> Type) : forall `(Functor F),
  forall T (x: F T), map (@id T) x = x.
Proof. apply @map_id. Qed.