【发布时间】:2011-10-05 07:09:23
【问题描述】:
以 Haskell 中不起眼的恒等函数为例,
id :: forall a. a -> a
鉴于 Haskell 据称支持隐含多态性,我应该能够通过类型归属将 id“限制”为 (forall a. a -> a) -> (forall b. b -> b) 类型似乎是合理的。但这不起作用:
Prelude> id :: (forall a. a -> a) -> (forall b. b -> b)
<interactive>:1:1:
Couldn't match expected type `b -> b'
with actual type `forall a. a -> a'
Expected type: (forall a. a -> a) -> b -> b
Actual type: (forall a. a -> a) -> forall a. a -> a
In the expression: id :: (forall a. a -> a) -> (forall b. b -> b)
In an equation for `it':
it = id :: (forall a. a -> a) -> (forall b. b -> b)
当然可以使用所需的签名定义新的受限形式的身份函数:
restrictedId :: (forall a. a -> a) -> (forall b. b -> b)
restrictedId x = x
但是用一般的id 定义它是行不通的:
restrictedId :: (forall a. a -> a) -> (forall b. b -> b)
restrictedId = id -- Similar error to above
那么这里发生了什么?似乎这可能与不可预测性的困难有关,但启用-XImpredicativeTypes 没有任何区别。
【问题讨论】:
-
我知道这有点晚了,但是......对于它的价值,在现代 GHC 中,
id :: (forall a. a -> a) -> (forall b. b -> b)确实会进行类型检查。使用TypeApplications,您可以使用id @(forall a. a -> a)(可能)避免ImpredicativeTypes类型检查的脆弱版本特定行为。 (不过,您仍然需要ImpredicativeTypes扩展。)
标签: haskell polymorphism impredicativetypes ascription