为什么这种不同的行为会出现 `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 中的任何类型 Showa 的选择可能很重要,因为原则上,print (Nothing :: Maybe [Int]) 可以打印出与 print (Nothing :: Maybe [Bool]) 不同的内容。在这种情况下,打印输出将是相同的,但这只是因为我们很幸运。

例如 print ([] :: [Int])print ([] :: [Char]) 将打印不同的消息,因此 print [] 是不明确的。因此,GHC 拒绝它,并需要一个明确的类型注释(或类型应用程序 @ type,使用扩展名)。

那么,为什么 GHCi 接受这种模糊性?好吧,GHCi 旨在用于快速实验,因此,作为一个方便的功能,它会尽力默认这些模棱两可的 a。这是使用 extended defaulting rules 完成的,(我猜)原则上也可以通过打开该扩展在 GHC 中打开它。 但是,不建议这样做,因为有时默认规则会选择一些意外的类型,使代码编译但具有不需要的运行时行为。

此问题的常见解决方案是使用注释(或 @ type),因为它为程序员提供了更多控制权,使代码更易于阅读,并避免了意外。