为什么coq的typechecker拒绝我的地图定义?

时间:2019-05-03 11:34:36

标签: coq type-theory

我尝试试验列表的定义。 例如,让我们看一下这个定义:

Inductive list1 : Type -> Type := nil1 : forall (A : Type), list1 A
                               | cons1 : forall (A : Type), A -> list1 A -> list1 A.

您可能会认为上面的定义与此等效:

Inductive list0 (A : Type) : Type := nil0 : list0 A
                                   | cons0 : A -> list0 A -> list0 A.

为什么要这张地图:

Fixpoint map0 {A : Type} {B : Type} (f : A -> B) (xs : list0 A) : list0 B :=
  match xs with
    nil0 _ => nil0 B
  | cons0 _ v ys => cons0 B (f v) (map0 f ys)
  end.

被接受,但是这个不是:

Fail Fixpoint map1 {A : Type} {B : Type} (f : A -> B) (xs : list1 A) :=
  match xs with
    nil1 _ => nil1 B
  | cons1 _ v ys => cons1 B (f v) (map1 f ys)
  end.

2 个答案:

答案 0 :(得分:1)

这确实是数据类型定义的一个令人困惑的方面。问题在于,list1 等同于list0,因为在这些方法中如何处理 indices parameters 定义。在Coq术语中,“索引”表示在冒号右侧声明的参数,如list1中所示。相反,“参数”是在冒号左侧声明的参数,如A中的list0

使用索引时,match表达式的返回类型对于索引必须是通用的。可以从list1_rec的类型中看出这一点,它是用于在列表上编写递归定义的组合器:

Check list1_rec.

list1_rec
     : forall P : forall T : Type, list1 T -> Set,
       (forall A : Type, P A (nil1 A)) ->
       (forall (A : Type) (a : A) (l : list1 A), P A l -> P A (cons1 A a l)) ->
       forall (T : Type) (l : list1 T), P T l

此类型表示给定由列表和元素P索引的通用类型l : list1 A,您可以通过告诉Coq {{1}返回什么来产生P A l类型的结果}}和nil1。但是,cons1分支的类型(cons1的第三个参数)表明,该分支不仅必须适用于以list1类型出现的A,而且还适用于所有 other 类型l。将此与A'的类型进行比较:

list0_rec

Check list0_rec. list0_rec : forall (A : Type) (P : list0 A -> Set), P (nil0 A) -> (forall (a : A) (l : list0 A), P l -> P (cons0 A a l)) -> forall l : list0 A, P l 的分支没有cons0位,这意味着该分支只需要为forall A中的A类型工作。

这在编写诸如l : list0 A之类的函数时会有所不同。在map中,我们被允许应用map0,因为我们知道f : A -> B的参数类型为cons0。在A中,map1的参数具有不同的通用类型cons1,导致出现此错误消息:

A'

答案 1 :(得分:0)

为完整起见,您可以在map上定义函数list1

Fixpoint map1 {A : Type} {B : Type} (f : A -> B) (xs : list1 A) :=
  match xs with
  | nil1 A' => fun _ => nil1 B
  | cons1 A' v ys => fun f => cons1 B (f v) (map1 f ys)
  end f.

这是所谓的convoy pattern的示例。通常,需要在return构造中添加match子句,以便进行类型检查,但是Coq足够聪明来推断它。

但是,我当然不赞成使用列表的这种定义,因为在类似情况下使用起来很麻烦。