首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么‘`Ambiguous type..’错误(在ghci中)会有如此不同的行为?

为什么‘`Ambiguous type..’错误(在ghci中)会有如此不同的行为?
EN

Stack Overflow用户
提问于 2020-08-30 12:27:11
回答 1查看 39关注 0票数 0

此示例适用于ghci,请加载此文件:

代码语言:javascript
复制
import Safe

t1 = tailMay []

并放入ghci:

代码语言:javascript
复制
> print t1
Nothing

但如果我们将类似的定义添加到前面的文件中,它将不起作用:

代码语言:javascript
复制
import Safe

t1 = tailMay []
t2 = print $ tailMay []

有这样的错误:

代码语言:javascript
复制
    * 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的第三个示例:

代码语言:javascript
复制
import Safe

t1 = tailMay

main = do
  print $ t1 []
  print $ t1 [1,2,3]

为什么?如何在没有显式类型注释的情况下修复第二个样本?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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),因为它为程序员提供了更多的控制,使代码更容易阅读,并避免了意外。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63653952

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档