[英]Why can't one put type signatures in instance declarations in 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. e
和e [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.