警告:将类型变量a0默认为Integer类型

编程语言 2026-07-09

代码:

module Main where

main :: IO ()
main = topLevel


topLevel = putStrLn $ "Hello World!" ++ (show 3)

通常在网上他们写道,当你想把 Integer 转换为 String 时,应该使用 show。但这会产生如下警告:

/home/mark/haskell/h7/app/Main.hs:7:42: warning: [GHC-18042] [-Wtype-defaults]
    * Defaulting the type variable `a0' to type `Integer' in the following constraints
        (Show a0) arising from a use of `show' at app/Main.hs:7:42-45
        (Num a0) arising from the literal `3' at app/Main.hs:7:47
    * In the second argument of `(++)', namely `(show 3)'
      In the second argument of `($)', namely
        `"Hello World!" ++ (show 3)'
      In the expression: putStrLn $ "Hello World!" ++ (show 3)
  |
7 | topLevel = putStrLn $ "Hello World!" ++ (show 3)
  |                                          ^^^^

我不明白为什么编译器会对 show 的变量类型发出警告。它难道不应该直接接受 Integer 吗?请解释。

无论如何,还有更好的方法吗?

ghc: 9.6.7

解决方案

在Haskell中,当你写下字面量 3 时,它实际上可能表示几种不同的东西,例如任意精度的 Integer 类型,或者64位的 Int 类型,甚至是一个双精度浮点数 Double

通常从上下文可以明确你想要哪种类型,GHC也能够自行推断出来。然而,与 show 相似的情况也会发生。它也是一个重载函数,能够作用于多种不同的类型。函数 show 可以作用于 IntegerInt,甚至像 Bool 这样的东西也能工作。关键在于,3 可以同时表示一个 Int 和一个 Integer,并且 show 也能在这两种类型上工作,这意味着GHC实际上无法确定你指的是哪一种类型。

在这种情况下,你必须以某种方式指明你希望 3 拥有什么类型。你可以通过显式类型签名来实现:

topLevel = putStrLn $ "Hello World!" ++ show (3 :: Integer)

这是一直被支持的语法。如今也有一种更简洁的方式来指定你想要使用的 show 的类型,即通过类型应用(type applications):

topLevel = putStrLn $ "Hello World!" ++ show @Integer 3

有时这更好一些,尽管在这种情况下差别不大。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章