2012-04-12 110 views
8

我不是那么熟悉forall,但最近看了这样的疑问:What does the `forall` keyword in Haskell/GHC do?默认情况下为什么不应用(RankNTypes使用)?

在其中一个答案是这样的例子:

{-# LANGUAGE RankNTypes #-} 
liftTup :: (forall x. x -> f x) -> (a, b) -> (f a, f b) 
liftTup liftFunc (t, v) = (liftFunc t, liftFunc v) 

的解释是好的,我明白了什么forall是在这里做。但我想知道,为什么这不是默认行为,是否有一个特别的原因。有没有一段时间它会是不利的?

编辑:我的意思是,有没有原因为什么不能默认插入forall的?

+3

你是问为什么扩展没有在默认情况下或为什么'(x - > fx) - >(a,b) - >(fa,fb)'不同于'(forall x。x - > fx) - >(a,b) - >(fa,fb)'?如果是后者,你可以指定你建议编译器决定在哪里插入''forall''的逻辑吗? – sepp2k 2012-04-12 18:05:02

+0

后者,我不知道从哪里开始就这个问题提出任何建议! – 2012-04-12 18:23:11

+0

注意类型'(x - > f x) - >(a,b) - >(f a,f b)'是相当无用的。该函数不能将第一个参数应用于元组的任一元素,因此其结果必须是“⊥”或“(⊥,⊥)”。 – hammar 2012-04-13 00:42:34

回答

16

好吧,它不是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(对于任何fx)形式的任何函数,但对于前者,您传入的函数必须适用于全部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) 
+0

我想我需要消化这一些:) – 2012-04-12 18:37:23

+0

此外,对于二阶和更高阶的多态性,没有最普通的类型''∀b。 (∀a。a→b)→(b,b)'不比'∀c d更普遍。 (∀a b。a→b)→(c,d)'也不反过来。虽然类型推断对于一阶和二阶多态可确定,但它不适用于三阶和更高阶。 – Vitus 2012-04-12 21:12:45

+0

@vitus - 你能提供一个二阶多态性可判定性的参考吗?我不熟悉它。 – 2012-04-12 23:31:42

7

我怀疑更高级别类型默认情况下不因为they make type inference undecidable启用。这也是为什么,即使启用了扩展功能,您也需要使用关键字forall以获得更高级别的类型--GHC假定所有类型都是1级,除非明确告知否则为了推断尽可能多的类型信息。

换言之,没有通用的方法来推断更高级的类型(forall x. x -> f x) -> (a,b) -> (f a, f b),因此获得该类型的唯一方法是通过显式类型签名。

编辑:根据Vitus上面的评论,rank-2类型推断是可判定的,但是高级多态性不是。所以这种类型签名在技术上是可以推断的(尽管算法更复杂)。是否值得争取2级多态类型推断的额外复杂性是值得商榷的...

相关问题