嗯,它不是 Haskell 2010 标准的一部分,所以默认情况下它不是打开的,而是作为语言扩展提供的。至于为什么它不在标准中,rank-n 类型比标准 Haskell 的普通 rank-1 类型更难实现;它们也不是那么频繁地需要,因此出于语言和实现简单的原因,委员会可能决定不打扰它们。
当然,这并不意味着 rank-n 类型没有用;它们确实如此,没有它们,我们就没有像ST
monad这样有价值的工具(它提供了高效的本地可变状态——就像IO
你所能做的就是使用IORef
s)。但它们确实给语言增加了相当多的复杂性,并且在应用看似良性的代码转换时可能会导致奇怪的行为。例如,一些 rank-n 类型检查器将允许runST (do { ... })
但拒绝runST $ do { ... }
,即使这两个表达式在没有 rank-n 类型的情况下总是等价的。有关它可能导致的意外(有时是令人讨厌的)行为的示例,请参阅此 SO 问题。
如果像 sepp2k 所问的那样,您是在问为什么forall
必须明确地将其添加到类型签名中以获得更高的通用性,那么问题在于它(forall x. x -> f x) -> (a, b) -> (f a, f b)
实际上是一个比(x -> f x) -> (a, b) -> (f a, f b)
. 使用后者,您可以传入任何形式的函数x -> f x
(对于任何f
and x
),但对于前者,您传入的函数必须适用于all x
。因此,例如,类型函数String -> IO String
将是第二个函数的允许参数,但不是第一个函数;它必须有类型a -> IO a
。如果后者自动转换为前者,那将是相当混乱的!他们是两种截然不同的类型。
forall
将隐含的 s 明确化可能更有意义:
forall f x a b. (x -> f x) -> (a, b) -> (f a, f b)
forall f a b. (forall x. x -> f x) -> (a, b) -> (f a, f b)