警告:将类型变量a0默认为Integer类型
代码:
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 可以作用于 Integer 和 Int,甚至像 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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。