let 在与 -XRankNTypes 一起使用时不起作用
let doesn't work when used with -XRankNTypes
考虑以下最小示例:
{-# LANGUAGE RankNTypes #-}
module Test where
class C w
data A = A (forall u. C u => u)
x :: forall u. C u => u
x = undefined
a = A x
正如预期的那样,此类型检查正常。但是,如果 a
被重构为使用 let
语句:
{-# LANGUAGE RankNTypes #-}
module Test where
class C w
data A = A (forall u. C u => u)
x :: forall u. C u => u
x = undefined
a = let x' = x in A x'
它突然无法进行类型检查,并出现以下错误:
test.hs:12:14: error:
* No instance for (C u0) arising from a use of `x'
* In the expression: x
In an equation for x': x' = x
In the expression: let x' = x in A x'
|
12 | a = let x' = x in A x'
| ^
test.hs:12:21: error:
* Couldn't match expected type `u' with actual type `u0'
because type variable `u' would escape its scope
This (rigid, skolem) type variable is bound by
a type expected by the context:
forall u. C u => u
at test.hs:12:19-22
* In the first argument of `A', namely x'
In the expression: A x'
In the expression: let x' = x in A x'
* Relevant bindings include x' :: u0 (bound at test.hs:12:9)
|
12 | a = let x' = x in A x'
为什么会这样?这不违反等式推理吗?
这是可怕的单态限制的结果。启用 XNoMonomorphismRestriction
应该可以编译。
a = let x' = x in A x'
不等价于a = A x
,因为在单态限制下x'
in let x' = ...
是单态的,但是A需要多态参数。
考虑以下最小示例:
{-# LANGUAGE RankNTypes #-}
module Test where
class C w
data A = A (forall u. C u => u)
x :: forall u. C u => u
x = undefined
a = A x
正如预期的那样,此类型检查正常。但是,如果 a
被重构为使用 let
语句:
{-# LANGUAGE RankNTypes #-}
module Test where
class C w
data A = A (forall u. C u => u)
x :: forall u. C u => u
x = undefined
a = let x' = x in A x'
它突然无法进行类型检查,并出现以下错误:
test.hs:12:14: error:
* No instance for (C u0) arising from a use of `x'
* In the expression: x
In an equation for x': x' = x
In the expression: let x' = x in A x'
|
12 | a = let x' = x in A x'
| ^
test.hs:12:21: error:
* Couldn't match expected type `u' with actual type `u0'
because type variable `u' would escape its scope
This (rigid, skolem) type variable is bound by
a type expected by the context:
forall u. C u => u
at test.hs:12:19-22
* In the first argument of `A', namely x'
In the expression: A x'
In the expression: let x' = x in A x'
* Relevant bindings include x' :: u0 (bound at test.hs:12:9)
|
12 | a = let x' = x in A x'
为什么会这样?这不违反等式推理吗?
这是可怕的单态限制的结果。启用 XNoMonomorphismRestriction
应该可以编译。
a = let x' = x in A x'
不等价于a = A x
,因为在单态限制下x'
in let x' = ...
是单态的,但是A需要多态参数。