米尔纳让多态性成为第2级特征吗?

时间:2011-11-28 13:45:06

标签: haskell polymorphism type-systems

let a = b in c可以被认为是(\a -> c) b的语法糖,但在一般的打字环境中,情况并非如此。例如,在米尔纳微积分中let a = \x -> x in (a True, a 1)是典型的,但看似等价的(\a -> (a True, a 1)) (\x -> x)不是。

然而,后者在系统F中是典型的,第一个lambda的等级为2。

我的问题是:

  • 是否让多态性成为在Milner演算的其他排名1世界中偷偷潜入的2级特征?

  • 拥有单独的let构造的目的似乎是指定哪些类型应该由类型检查器推广,哪些不是。它是否有任何其他用途?是否有任何理由扩展更强大的系统,例如系统F与单独的let不是糖?有没有关于米尔纳微积分设计背后理由的论文,这对我来说不再是显而易见的?

  • 系统F中\a -> (a True, a 1)是否有最常规的类型?

  • 在beta扩展下是否关闭了类型系统?即如果P是典型的且M N = P那么M是典型的吗?

一些澄清:

  • 通过等价,我指的是等价模数类型注释。 “System F a la Church”是正确的术语吗?

  • 我知道一般来说,主要的输入属性不能保存在F中,但是我的特定术语可能存在主体类型。

  • let我的意思是let的非递归风格。使用递归let扩展系统F显然很有用,因为它允许非终止。

5 个答案:

答案 0 :(得分:17)

W.r.t。问四个问题:

  • 这件事的关键见解是,而不仅仅是输入一个 我们可以使用具有潜在多态参数类型的lambda抽象 正在输入一个(加糖的)抽象,它是(1)只应用一次 而且,这是(2)应用于静态已知的论证。 也就是说,我们可以首先对“论证”(即...的定义)进行处理 本地定义)键入重建来找到它 (多态)类型;然后将找到的类型分配给“参数” (定义);然后,最后,在扩展中键入正文 类型上下文。

    请注意,这比一般的Rank-2类型要容易得多 推断。

  • 请注意,严格来说,如果你要求定义带有一个类型注释,那么.. :: .. in ..只是系统F中的语法糖:let ..:.. = .. in。 ..

  • 以下是系统F中的T in(\ a :: T - >(a True,a 1))的两个解决方案:forall b。 (forall a.a - > b) - > (b,b)和forall c d。 (forall a b.a - > b) - > (c,d)。请注意,它们中的任何一个都不比另一个更通用。通常,系统F不承认主要类型。

  • 我认为这适用于简单输入的lambda演算?

答案 1 :(得分:4)

在任何可以表达“死代码”概念的微积分中,类型不会在beta扩展下保留。你可以弄清楚如何用任何可用的语言写出类似的内容:

if True then something typable else utter nonsense

例如,允许M = (\x y -> x) (something typable)N = (utter nonsense)以及P = (something typable),以便M N = PP可以打字,但M N不是'吨。

...重读你的问题,我发现你只要求M可以打字,但这似乎是一种非常奇怪的意义,可以让“保留在β扩展下”给我。无论如何,我不明白为什么像上面这样的论点不适用:只需让M有一些不可分类的死代码。

答案 2 :(得分:3)

您可以键入(\a -> (a True, a 1)) (\x -> x)如果不是只概括let表达式,而是概括所有 lambda抽象。完成此操作后,还需要在每个使用点实例化类型模式,而不仅仅是在实际使用引用它们的绑定器的位置。我不认为这实际上有任何问题,除了效率低得多。我记得在TAPL中对此进行了一些讨论,实际上也提出了类似的观点。

答案 3 :(得分:2)

很多年前,我在一本关于lambda演算(可能是Barendregt)的书中看到了一个由β扩展保留的类型系统。它没有量化,但它有一个断言,表示一个术语需要同时不止一种类型,以及每个术语居住的特殊类型欧米茄。我记得,后者避免了Daniel Wagner的死代码异议。虽然每个表达都是很好的类型,但限制类型中的欧米茄的位置允许你描述哪些表达式(弱?)头部正常形式。

另外,如果我没记错的话,完全正常的表单表达式有主要类型,它们不包含omega。

例如\ f x - >的主要类型f(f x)(教会数字2)将类似于((A - > B)/ \(B - > C)) - > A - > ç

答案 4 :(得分:0)

无法回答所有非常专业的问题,但不是,它不是第2级功能。在您编写时,只是让定义被量化,产生完全多态的rank-1类型,除非定义依赖于nouter范围内的某些单态值。

请注意,Haskell let在其他语言中称为let rec,允许定义相互递归的函数和值。这是你不想用lambda表达式和Y-combinator手动编码的东西。