Haskell中-Wtype-defaults警告含义解析及代码问题咨询
代码中-Wtype-defaults警告的含义解析
触发警告的代码
truncate' :: Maybe Double -> Int -> Maybe Double truncate' Nothing _ = Nothing truncate' (Just x) n = Just $ fromIntegral (round (x * t)) / t where t = 10 ^ n
收到的警告信息
test/Spec.hs:9:31: warning: [-Wtype-defaults] • Defaulting the following constraint to type ‘Integer’ Integral a0 arising from a use of ‘fromIntegral’ • In the first argument of ‘(/)’, namely ‘fromIntegral (round (x * t))’ In the second argument of ‘($)’, namely ‘fromIntegral (round (x * t)) / t’ In the expression: Just $ fromIntegral (round (x * t)) / t
警告含义拆解
这个警告属于-Wtype-defaults类型,是Haskell编译器在遇到类型不明确,但可通过默认规则补全时发出的提示——核心问题是代码里存在未明确约束的类型,编译器自动选了Integer作为默认类型,但它不确定这是否符合你的预期,因此发出提醒。
具体到代码细节:
- 先看
where块里的t = 10 ^ n:^操作符的类型是(Num a, Integral b) => a -> b -> a,这里n是Int(符合Integral约束),但10的类型可以是任意Num实例(比如Int、Double等),编译器暂时无法确定t的具体类型。 - 再看
round (x * t):round的类型是(RealFrac a, Integral b) => a -> b,x是Double,所以x*t的类型依赖t,而round的返回值可以是任意Integral类型(比如Int、Integer),这里也没有明确约束。 - 最后是
fromIntegral (round ...):fromIntegral需要把Integral类型转成Num类型(最终要转成Double,因为要和t做除法,结果是Double),但round的返回类型不明确,编译器只能触发默认规则,选择Integer补全这个模糊类型,于是触发了警告。
解决思路
给t明确指定类型即可消除警告,比如把t的定义改成:
t = 10 ^ n :: Double
这样t的类型固定为Double,x*t就是Double,round的返回类型会被推导为Int(你也可以显式指定round (x*t) :: Int),整个类型链条清晰后,编译器就不会再触发默认类型补全的警告。
内容的提问来源于stack exchange,提问作者student422
相关产品推荐
相关产品推荐

