为什么这种不同的行为会出现 `Ambiguous type..` 错误(在 ghci 中)?
Why such different behaviour with `Ambiguous type..` error (in ghci)?
此示例使用 ghci,加载此文件:
import Safe
t1 = tailMay []
并输入 ghci:
> print t1
Nothing
但是如果我们在之前的文件中添加类似的定义,它就不起作用:
import Safe
t1 = tailMay []
t2 = print $ tailMay []
出现这样的错误:
* Ambiguous type variable `a0' arising from a use of `print'
prevents the constraint `(Show a0)' from being solved.
Probable fix: use a type annotation to specify what `a0' should be.
These potential instances exist:
instance Show Ordering -- Defined in `GHC.Show'
instance Show Integer -- Defined in `GHC.Show'
instance Show a => Show (Maybe a) -- Defined in `GHC.Show'
...plus 22 others
这是 ghc 的第三个样本,错误相同:
import Safe
t1 = tailMay
main = do
print $ t1 []
print $ t1 [1,2,3]
为什么?以及如何在没有显式类型注释的情况下修复第二个示例?
这里的问题是 tailMay []
可以为任何 a
生成类型 Maybe [a]
的输出,而 print
可以接受类型 Maybe [a]
的输入] 对于任何 a
(在 class Show
中)。
当你组合一个“通用生产者”和一个“通用消费者”时,编译器不知道要选择哪种类型 a
—— 可以是 class 中的任何类型 Show
。 a
的选择可能很重要,因为原则上,print (Nothing :: Maybe [Int])
可以打印出与 print (Nothing :: Maybe [Bool])
不同的内容。在这种情况下,打印输出将是相同的,但这只是因为我们很幸运。
例如 print ([] :: [Int])
和 print ([] :: [Char])
将打印不同的消息,因此 print []
是不明确的。因此,GHC 拒绝它,并需要一个明确的类型注释(或类型应用程序 @ type
,使用扩展名)。
那么,为什么 GHCi 接受这种模糊性?好吧,GHCi 旨在用于快速实验,因此,作为一个方便的功能,它会尽力默认这些模棱两可的 a
。这是使用 extended defaulting rules 完成的,(我猜)原则上也可以通过打开该扩展在 GHC 中打开它。
但是,不建议这样做,因为有时默认规则会选择一些意外的类型,使代码编译但具有不需要的运行时行为。
此问题的常见解决方案是使用注释(或 @ type
),因为它为程序员提供了更多控制权,使代码更易于阅读,并避免了意外。
此示例使用 ghci,加载此文件:
import Safe
t1 = tailMay []
并输入 ghci:
> print t1
Nothing
但是如果我们在之前的文件中添加类似的定义,它就不起作用:
import Safe
t1 = tailMay []
t2 = print $ tailMay []
出现这样的错误:
* Ambiguous type variable `a0' arising from a use of `print'
prevents the constraint `(Show a0)' from being solved.
Probable fix: use a type annotation to specify what `a0' should be.
These potential instances exist:
instance Show Ordering -- Defined in `GHC.Show'
instance Show Integer -- Defined in `GHC.Show'
instance Show a => Show (Maybe a) -- Defined in `GHC.Show'
...plus 22 others
这是 ghc 的第三个样本,错误相同:
import Safe
t1 = tailMay
main = do
print $ t1 []
print $ t1 [1,2,3]
为什么?以及如何在没有显式类型注释的情况下修复第二个示例?
这里的问题是 tailMay []
可以为任何 a
生成类型 Maybe [a]
的输出,而 print
可以接受类型 Maybe [a]
的输入] 对于任何 a
(在 class Show
中)。
当你组合一个“通用生产者”和一个“通用消费者”时,编译器不知道要选择哪种类型 a
—— 可以是 class 中的任何类型 Show
。 a
的选择可能很重要,因为原则上,print (Nothing :: Maybe [Int])
可以打印出与 print (Nothing :: Maybe [Bool])
不同的内容。在这种情况下,打印输出将是相同的,但这只是因为我们很幸运。
例如 print ([] :: [Int])
和 print ([] :: [Char])
将打印不同的消息,因此 print []
是不明确的。因此,GHC 拒绝它,并需要一个明确的类型注释(或类型应用程序 @ type
,使用扩展名)。
那么,为什么 GHCi 接受这种模糊性?好吧,GHCi 旨在用于快速实验,因此,作为一个方便的功能,它会尽力默认这些模棱两可的 a
。这是使用 extended defaulting rules 完成的,(我猜)原则上也可以通过打开该扩展在 GHC 中打开它。
但是,不建议这样做,因为有时默认规则会选择一些意外的类型,使代码编译但具有不需要的运行时行为。
此问题的常见解决方案是使用注释(或 @ type
),因为它为程序员提供了更多控制权,使代码更易于阅读,并避免了意外。