关于sqrt和round的参数类型的问题

leo*_*nyu 1 haskell types

在签名之后:

sqrt :: Floating a => a -> a
Run Code Online (Sandbox Code Playgroud)

为什么是(sqrt 2)合法的?数字不是2绝对不满足浮动的整数吗?关于圆形的相同问题,round (sqrt 2)是合法的,sqrt 返回类型 Floating 但圆形需要 ReadFrac。

round :: (RealFrac a, Integral b) => a -> b
Run Code Online (Sandbox Code Playgroud)

Sil*_*olo 6

文字2的类型为Num a => a。也就是说,它可以是任何数字类型。具体来说,Haskell 将获取整数值2并调用fromInteger它(为 any 定义Num)。所以当你写

sqrt 2
Run Code Online (Sandbox Code Playgroud)

在内部,正在发生的事情是

sqrt (fromInteger 2) :: Floating a => a
Run Code Online (Sandbox Code Playgroud)

如果你强制值,如GHCI,你会得到一个Double,因为那是默认Floating

同样,类型round (sqrt 2)将是Integral b => b并且将要求sqrt 2类型是RealFrac a => a。存在既是RealFracand 的类型Floating,所以这并不矛盾。特别是,Double出于与以前相同的原因,GHC 很乐意默认使用此处。如果您强制打印该值,则整个结果 ( Integral b => b) 将默认为Integer

重要的是要记住,所有这些都是普遍量化的。Floating a => a并不意味着“这是某种浮动类型,这就是我所知道的”。这意味着“如果您有任何浮动类型,我可以生成该类型的值”。您可以选择要使用的浮动类型,因此如果稍后出现约束并表示值也是RealFrac a => a,那很好,因为我们只是将自己约束为既是Floating又是RealFrac。这与 Java 之类的语言相反,如果我有某种接口类型的值,例如Comparable,那么我只能得出结论,它是某种 Comparable类型,而不是适用于所有类型。