好吧,它不是Haskell 2010标准的一部分,所以默认情况下它不会被启用,而是作为语言扩展提供。至于为什么它不在标准中,rank-n类型比Haskell普通的rank-1类型标准实现起来要困难得多;他们也不是经常需要,所以委员会可能决定不因语言和实施简单的原因而烦恼他们。
当然,这并不意味着排名n型是没有用的;他们是,非常如此,没有他们,我们不会有像ST
monad这样的有价值的工具(它提供了高效的局部可变状态 - 比如IO
,你所能做的就是使用IORef
s)。但是它们确实增加了语言的相当复杂性,并且在应用看似良性的代码转换时会引起奇怪的行为。例如,一些rank-n型检查器将允许runST (do { ... })
但拒绝runST $ do { ... }
,即使这两个表达式总是等同于没有rank-n类型。请参阅this SO question了解它可能导致的意外(有时令人讨厌)行为的示例。
如果像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
和x
)形式的任何函数,但对于前者,您传入的函数必须适用于全部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)
你是问为什么扩展没有在默认情况下或为什么'(x - > fx) - >(a,b) - >(fa,fb)'不同于'(forall x。x - > fx) - >(a,b) - >(fa,fb)'?如果是后者,你可以指定你建议编译器决定在哪里插入''forall''的逻辑吗? – sepp2k 2012-04-12 18:05:02
后者,我不知道从哪里开始就这个问题提出任何建议! – 2012-04-12 18:23:11
注意类型'(x - > f x) - >(a,b) - >(f a,f b)'是相当无用的。该函数不能将第一个参数应用于元组的任一元素,因此其结果必须是“⊥”或“(⊥,⊥)”。 – hammar 2012-04-13 00:42:34