在这个例子中,Coq的类型系统是做什么的?

时间:2017-07-27 23:36:28

标签: coq

我对下面h定义中证明词的匹配部分的Coq类型系统的行为感到困惑:

Set Implicit Arguments.
Definition h := fun (a b : nat) (e : a = b) =>
(fun (x y : nat)(HC : b = y)(H : x = y) =>
(match H in (_ = y0) return (b = y0 -> b = x) with
| @eq_refl _ _ => fun HC0 : b = x => HC0
end HC)) a b (eq_refl b) e.

检查h告诉我们整体类型是" forall a b:nat,a = b - > b = a"。

由于H的类型是x = y,看起来匹配将返回类型为b = y的项 - >由于return子句,b = x。应用后面的各种术语后,我们得到h的预期类型。

但是,有趣的是HC0:b = x => HC0是b = x - >的类型的同一性函数。 b = x。我不相信有强迫b = x - >的任何强制行为。 b = x被识别为类型b = y - > b = x。

我最好的猜测是H的构造函数是x = x的@eq_refl nat x,它是唯一的。由于H也是x = y类型,因此名称x和y绑定到相同的术语。因此,类型系统决定b = x - > b = x的类型为b = y - > b = x。这很接近吗?这种行为是在某处解释或记录的吗?我看了iota减少,但我不认为这是正确的。

1 个答案:

答案 0 :(得分:5)

这就是它。记录了这种行为(在the manual中查找“匹配......与......结构”),虽然理解那里发生的事情可能有点令人生畏。

首先,回想一下在Coq中检查典型match的方法:

Inductive list (T : Type) :=
| nil : list T
| cons : T -> list T -> list T.

Definition tail (T : Type) (l : list T) : list T :=
  match l with 
  | nil       => nil
  | cons x l' => l'
  end.

Coq检查(1)list类型的每个构造函数在match中都有对应的分支,(2)每个分支具有相同的类型(在这种情况下,{{1假设每个分支中引入的构造函数参数具有适当的类型(这里假设list T具有类型xT在第二个分支中具有类型l' )。

在这种简单的情况下,用于检查每个分支的类型与整个匹配表达式的类型完全相同。但是, not 始终为true:有时,Coq根据从正在检查的分支中提取的信息使用更专业的类型。在对索引归纳类型进行案例分析时经常会发生这种情况,例如list T

eq

Inductive eq (T : Type) (x : T) : T -> Prop := | eq_refl : eq T x x. 表示法只是=的中缀语法糖。)

赋予冒号右侧的归纳类型的参数在Coq中是特殊的:它们被称为 indices 。出现在左侧的那些(在本例中为eqT)称为参数。参数在归纳类型的声明中必须全部不同,并且必须与所有构造函数的结果中使用的参数完全匹配。例如,请考虑以下非法代码段:

x

Coq拒绝此示例,因为它在Inductive eq' (T : Type) (x : T) : T -> Type := | eq_refl' : eq nat 4 3. 构造函数的结果中找到了nat而不是T

另一方面,

指数不具有此限制:出现在构造函数的返回类型上的索引可以是适当类型的任何表达式。此外,该表达式可能因我们所在的构造函数而异。因此,Coq允许每个分支的返回类型根据每个分支的索引的选择而变化。请考虑原始示例的以下略微简化版本。

eq_refl'

由于Definition h (a b : nat) (e : a = b) : b = a := match e in _ = x return x = a with | eq_refl => eq_refl : a = a end. 的第二个参数是索引,因此它原则上可以根据使用的构造函数而变化。由于我们只在查看使用的构造函数时才发现该索引实际是什么,因此Coq允许匹配的返回类型依赖于该索引:匹配的eq子句为所有索引提供名称一个归纳类型,这些名称成为可以在in子句中使用的绑定变量。

在键入分支时,Coq会找出索引的值,并将这些值替换为return子句中声明的变量。此匹配只有一个分支,该分支强制索引等于in类型中的第二个参数(在本例中为e)。因此,Coq尝试确保该分支的类型为a(即a = ax = a替换a)。因此,我们可以简单地提供x,我们就完成了。

现在Coq检查了所有分支都是正确的,它为整个匹配表达式分配了eq_refl : a = a子句的类型,其中return的索引替换为e。此变量x的类型为e,索引为a = b,因此结果类型为b(即b = a x = a取代b)。

This answer提供了有关参数和索引之间差异的更多解释,如果有帮助的话。