[英]Code unexpectedly accepted by GHC/GHCi
I don't understand why this code should pass type-checking: 我不明白为什么这段代码应该通过类型检查:
foo :: (Maybe a, Maybe b)
foo = let x = Nothing in (x,x)
Since each component is bound to the same variable x
, I would expect that the most general type for this expression to be (Maybe a, Maybe a)
. 由于每个组件都绑定到相同的变量
x
,所以我希望此表达式的最通用类型是(Maybe a, Maybe a)
。 I get the same results if I use a where
instead of a let
. 如果使用
where
而不是let
我将得到相同的结果。 Am I missing something? 我想念什么吗?
Briefly put, the type of x
gets generalized by let
. 简而言之,
x
的类型由let
推广。 This is a key step in the Hindley-Milner type inference algorithm. 这是Hindley-Milner类型推断算法中的关键步骤。
Concretely, let x = Nothing
initially assigns x
the type Maybe t
, where t
is a fresh type variable. 具体来说,
let x = Nothing
最初为x
分配类型Maybe t
,其中t
是新鲜的类型变量。 Then, the type gets generalized, universally quantifying all its type variables (technically: except those in use elsewhere, but here we only have t
). 然后,对类型进行泛化,通用地量化其所有类型变量(技术上:除了在其他地方使用的变量,但这里我们只有
t
)。 This causes x :: forall t. Maybe t
这导致
x :: forall t. Maybe t
x :: forall t. Maybe t
. x :: forall t. Maybe t
。 Note that this is exactly the same type as Nothing :: forall t. Maybe t
请注意,此类型与
Nothing :: forall t. Maybe t
完全相同Nothing :: forall t. Maybe t
Nothing :: forall t. Maybe t
. Nothing :: forall t. Maybe t
。
Hence, each time we use x
in our code, that refers to a potentially different type Maybe t
, much like Nothing
. 因此,每次我们在代码中使用
x
时,它都表示可能不同的类型Maybe t
,就像Nothing
一样。 Using (x, x)
gets the same type as (Nothing, Nothing)
for this reason. 因此,使用
(x, x)
与(Nothing, Nothing)
类型相同。
Instead, lambdas do not feature the same generalization step. 相反,lambda 不具有相同的概括步骤。 By comparison
(\\x -> (x, x)) Nothing
"only" has type forall t. (Maybe t, Maybe t)
相比之下
(\\x -> (x, x)) Nothing
“ only”的类型为forall t. (Maybe t, Maybe t)
forall t. (Maybe t, Maybe t)
, where both components are forced to be of the same type. forall t. (Maybe t, Maybe t)
,其中两个组件都被强制为相同类型。 Here x
is again assigned type Maybe t
, with t
fresh, but it is not generalized. 在这里
x
再次被赋予类型Maybe t
,其中t
fresh,但是没有被概括。 Then (x, x)
is assigned type (Maybe t, Maybe t)
. 然后
(x, x)
被分配类型(Maybe t, Maybe t)
。 Only at the top-level we generalize adding forall t
, but at that point is too late to obtain a heterogeneous pair. 仅在最高级别上,我们才一般性地加上了
forall t
,但是在这一点上太晚了,无法获得异构对。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.