为什么Num在haskell中可以被视为Floating



我定义了一个函数,用于计算sqrt并将参数从Integral类转换为CCD_2:

isqrt :: Integral i => i -> i
isqrt = floor . sqrt . fromIntegral

我不明白为什么会编译。如果我们写出我们得到的各个函数的签名:

fromIntegral :: (Num b, Integral a) => a -> b
sqrt :: Floating a => a -> a
floor :: (RealFrac a, Integral b) => a -> b

所以"CCD_ 3";采用Floating类型的东西,但是它被提供有Num。如果你看一看类的层次结构,你可以看到Floating"继承";而不是相反。如果CCD_ 8可以隐式地被视为CCD_;专用的";类型为什么这对编译器来说是可以的?

否,sqrt不是随任何Num提供的

其供应商fromIntegral能够根据需要生产任何Num,而sqrt需要Floating作为其输入。CCD_ 16是CCD_ 17的子类

所以fromIntegral愉快地答应了。既然它可以产生任何Num,那么它肯定可以在Num的任何子类中产生任何类型。因此,无论它最终是什么具体类型,它都在Floating中,因此必然在Num中。

因此fromIntegral提供它没有问题

edit:Floating不是类型。它是一类类型。具体类型可能在Floating类型类中。由于FloatingNum的一个子类,因此也保证该类型在Num中。这不是由于";"继承";你提到的。";"继承";即子类关系是对CCD_ 29的特定类型的要求也在CCD_ 30中,即实现CCD_ 31的方法以及来自CCD_ 32的方法。

因此,是的,(特定的、具体的(sqrt3类型也可以被视为Num类型。

另一方面,sqrt产生的类型与其输入类型相同,因此它将是相同的具体Floating类型。但是floor期望RealFrac类型。

观察

> :t floor            ----------
floor :: (Integral b, RealFrac a) => a -> b
> :t sqrt . fromIntegral            ----------
sqrt . fromIntegral :: (Integral a, Floating c) => a -> c
> :t floor . sqrt            ----------  ----------
floor . sqrt :: (Integral c, RealFrac b, Floating b) => b -> c
> :i Floating
class Fractional a => Floating a where
....
instance Floating Float
instance Floating Double
> :i RealFrac
class (Real a, Fractional a) => RealFrac a where
....
instance RealFrac Float
instance RealFrac Double

因此,sqrt调用产生(并因此接受(的具体类型必须是(在(RealFracFloating

由于没有从应用程序链外部观察到它,因此它可以是任何兼容类型,因此不明确;但类型defaulting会启动并选择Double,除非您更改了默认值。

因此sqrt采用Floating类型,但随Num一起提供。

fromIntegral保证它可以将类型为Integral类型类成员的任意数字转换为任何Num类型,而不是转换为一个Num类型。

由于sqrt需要一个作为Floating类型类成员的数字,因此对于该特定情况,fromIntegral将特别返回属于Floating类型类成员类型的东西。

相关内容

  • 没有找到相关文章

最新更新