繁体   English   中英

是否存在Haskell无法验证的类型签名?

[英]Are there type signatures which Haskell can't verify?

本文确定系统F中的类型推断(在本文中称为“可打字性”)是不可判定的。 我在其他地方从未听过的是该论文的第二个结果,即F中的“类型检查”也是不可判定的。 这里的“类型检查”问题意味着:给定一个术语t ,输入T和输入环境A ,判断A ⊢ t : T可推导? 这个问题是不可判定的(并且它相当于可打字性的问题)对我来说是令人惊讶的,因为它似乎直觉上应该是一个更容易回答的问题。

但无论如何,鉴于Haskell基于System F(或F-omega,偶数),关于类型检查的结果似乎表明存在Haskell项t和类型T ,因此编译器将无法决定t :: T是否有效。 如果是这样的话,我很好奇这样的术语和类型是什么......如果不是这样的话,我有什么误解?

据推测,理解这篇论文会得到一个建设性的答案,但我有点超出我的深度:)

通过适当地丰富语法,可以使类型检查成为可判定的。 例如,在论文中,我们将lambdas写为\\x -> e ; 要键入检查,你必须猜测 x的类型。 但是,使用适当丰富的语法,可以将其写为\\x :: t -> e ,它将猜测工作从流程中取出。 同样,在论文中,它们允许类型级lambda是隐含的; 也就是说,如果e :: t ,那么e :: forall a. t e :: forall a. t 做类型检查,你必须在猜测多少forall的增加,以及何时消除它们。 和以前一样,您可以通过添加语法使其更具确定性:我们添加两个新的表达式/\\a. e /\\a. ee [t]以及两个新的输入规则,如果e :: t ,那么/\\a. e :: forall a. t /\\a. e :: forall a. t /\\a. e :: forall a. t ,如果e :: forall a. t e :: forall a. t ,然后e [t'] :: t [t' / a] (其中t [t' / a]中的括号是替换括号)。 然后语法告诉我们何时以及添加多少个foralls,以及何时消除它们。

所以问题是:我们可以从Haskell转到充分注释的System F术语吗? 答案是肯定的,这要归功于Haskell类型系统的一些关键限制。 最关键的是所有类型都排名第一*。 没有太多细节,“排名”与你必须在->构造函数的左边找到一个forall

Int -> Bool -- rank 0?
forall a. (a -> a) -- rank 1
(forall a. a -> a) -> (forall a. a -> a) -- rank 2

特别是,这有点限制了多态性。 我们不能用一级类型输入这样的东西:

foo :: (forall a. a -> a) -> (String, Bool) -- a rank-2 type
foo polymorphicId = (polymorphicId "hey", polymorphicId True)

下一个最关键的限制是类型变量只能被单形类型替换。 (这包括其他类型变量,如a ,但不是像forall a. a这样的多态类型。)这确保了部分类型替换保留了一等级。

事实证明,如果你做出这两个限制,那么不仅类型推断是可判定的,而且你也得到最小的类型。

如果我们从Haskell转向GHC,那么我们不仅可以讨论什么是可打字的,而且可以讨论推理算法的外观。 特别是在GHC中,有一些扩展可以放宽上述两个限制; GHC如何在该环境中进行推理? 嗯,答案是它根本就没有尝试过。 如果您想使用这些功能编写术语,那么您必须在第一段中添加我们所讨论的键入注释:您必须明确注释引入和消除forall的位置。 那么,我们可以写一个GHC的类型检查器拒绝的术语吗? 是的,这很简单:只需使用未注释的二级(或更高级)类型或不可预测性。 例如,以下内容不进行类型检查,即使它具有显式类型注释并且可以使用rank-two类型:

{-# LANGUAGE Rank2Types #-}
foo :: (String, Bool)
foo = (\f -> (f "hey", f True)) id

*实际上,限制为二级足以使其可判定,但是一级类型的算法可以更有效。 排名三种类型已经给程序员足够的绳索使推理问题变得不可判定。 我不确定这些事实是否在委员会选择将Haskell限制为一级类型时已知。

以下是Scala中SKI演算的类型级实现的示例: http//michid.wordpress.com/2010/01/29/scala-type-level-encoding-of-the-ski-calculus/

最后一个示例显示了无界迭代。 如果你在Haskell中做同样的事情(我很确定你可以),你有一个“不可表达的表达式”的例子。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM