我编写了一个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)
), 。
答案 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.