fromIntegral
的类型为(Num b, Integral a) => a -> b
。我想了解这是怎么可能的,代码是什么,可以根据需要将任何积分号转换为任何数字类型。
fromIntegral
的{{3}}列为
fromIntegral = fromInteger . toInteger
fromInteger
actual code位于instance Num Int
和instance Num Integer
下,分别为:
instance Num Int where
...
fromInteger i = I# (integerToInt i)
和
instance Num Integer where
...
fromInteger x = x
假设I#
调用了一个将Integer
转换为Int
的C程序,我不知道其中任何一个生成的结果可能会添加到Float
。他们如何从Int
或Integer
转到其他地方?
fromInteger
将嵌入到一个表达式中,该表达式要求它生成某种类型。它无法知道所需的类型是什么?那会发生什么?
感谢。
答案 0 :(得分:11)
因为fromInteger
是Num
类的一部分,所以每个实例都有自己的实现。 两个实现(Int
和Integer
)中的都不知道如何制作Float
,但是当你'时,它们不会被调用。重新使用fromInteger
(或fromIntegral
)制作Float
;那是Float
Num
实例的用途。
等等所有其他类型。没有一个地方知道如何将整数转换为任何Num
类型;这是不可能的,因为它必须支持尚未存在的用户定义的Num
实例。相反,当每个单独的类型被声明为Num
的实例时,必须提供的特定类型的(通过实现fromInteger
)。
fromInteger
将嵌入到一个表达式中,该表达式要求它生成某种类型。它无法知道所需的类型是什么?那会发生什么?
实际上,知道它希望从嵌入调用的表达式返回的类型是完全它是如何工作的。
Haskell中的类型检查/推理在两个"方向上工作"立刻。它自上而下,弄清楚每个表达式应该具有什么类型,以便适应它所使用的更大的表达。它还可以自下而上"自下而上& #34;,确定每个表达式应该从它构建的较小子表达式中具有什么类型。当它找到一个不匹配的地方时,就会出现类型错误(确切地说"预期类型""实际类型"你看到的输入错误消息来自)。
但是因为编译器对每个表达式都有自上而下的知识("期望的类型"),所以它完全能够发现fromInteger
的调用正在进行在需要Float
的位置使用,因此在该调用中使用Float
Num
实例。
答案 1 :(得分:3)
将类型类与OOP接口区分开来的一个方面是类型类可以在方法的 result 类型上调度,而不仅仅是在其参数的类型上。典型的例子是read :: Read a => String -> a
函数。
fromInteger
的类型为fromInteger :: Num a => Integer -> a
。根据{{1}}的类型选择实现。如果类型检查员知道a
是a
,则会使用Float
的{{1}}实例,而不是Num
或Float
的实例