繁体   English   中英

GHC / GHCi意外接受的代码

[英]Code unexpectedly accepted by GHC/GHCi

我不明白为什么这段代码应该通过类型检查:

foo :: (Maybe a, Maybe b)
foo = let x = Nothing in (x,x)

由于每个组件都绑定到相同的变量x ,所以我希望此表达式的最通用类型是(Maybe a, Maybe a) 如果使用where而不是let我将得到相同的结果。 我想念什么吗?

简而言之, x的类型由let推广。 这是Hindley-Milner类型推断算法中的关键步骤。

具体来说, let x = Nothing最初为x分配类型Maybe t ,其中t是新鲜的类型变量。 然后,对类型进行泛化,通用地量化其所有类型变量(技术上:除了在其他地方使用的变量,但这里我们只有t )。 这导致x :: forall t. Maybe t x :: forall t. Maybe t 请注意,此类型与Nothing :: forall t. Maybe t完全相同Nothing :: forall t. Maybe t Nothing :: forall t. Maybe t

因此,每次我们在代码中使用x时,它都表示可能不同的类型Maybe t ,就像Nothing一样。 因此,使用(x, x)(Nothing, Nothing)类型相同。

相反,lambda 具有相同的概括步骤。 相比之下(\\x -> (x, x)) Nothing “ only”的类型为forall t. (Maybe t, Maybe t) forall t. (Maybe t, Maybe t) ,其中两个组件都被强制为相同类型。 在这里x再次被赋予类型Maybe t ,其中t fresh,但是没有被概括。 然后(x, x)被分配类型(Maybe t, Maybe t) 仅在最高级别上,我们才一般性地加上了forall t ,但是在这一点上太晚了,无法获得异构对。

暂无
暂无

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

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