此示例适用于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]为什么?如何在没有显式类型注释的情况下修复第二个样本?
发布于 2020-08-30 14:46:20
这里的问题是,tailMay []可以为任何a生成Maybe [a]类型的输出,而print可以为任何a (在Show类中)接受Maybe [a]类型的输入。
当您组合一个“通用生产者”和一个“通用消费者”时,编译器并不知道应该选择哪种类型的a --它可以是类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),因为它为程序员提供了更多的控制,使代码更容易阅读,并避免了意外。
https://stackoverflow.com/questions/63653952
复制相似问题