【问题标题】:How does fromIntegral work?fromIntegral 是如何工作的?
【发布时间】:2016-11-22 21:14:28
【问题描述】:

fromIntegral 的类型是(Num b, Integral a) => a -> b。我想了解这是怎么可能的,可以根据需要将任何整数转换为任何数字类型的代码是什么。

fromIntegralactual code 被列为

fromIntegral = fromInteger . toInteger

fromIntegercodeinstance Num Intinstance Num Integer 下面分别是:

instance  Num Int  where
  ...
  fromInteger i = I# (integerToInt i)

instance  Num Integer  where
  ...
  fromInteger x  =  x

假设I# 调用了一个将Integer 转换为Int 的C 程序,我看不出其中任何一个如何生成可以添加到Float 的结果。他们如何从 IntInteger 转到其他位置?

fromInteger 将嵌入到一个表达式中,该表达式要求它产生某种类型。它不知道所需的类型是什么?那么会发生什么?

谢谢。

【问题讨论】:

    标签: haskell


    【解决方案1】:

    因为fromIntegerNum 类的一部分,所以每个实例都有自己的实现。 两种实现(IntInteger)都不知道如何创建Float,但是当您使用fromInteger(或fromIntegral)时不会调用它们) 制作一个Float;这就是 FloatNum 实例的用途。

    对于所有其他类型,依此类推。没有一个地方知道如何将整数转换为任何Num 类型;这是不可能的,因为它必须支持尚不存在的用户定义的Num 实例。相反,当每个单独的类型被声明为Num 的实例时,必须提供一种针对该特定类型的方法(通过实现fromInteger)。

    fromInteger 将嵌入到一个表达式中,该表达式要求它产生某种类型。它不知道所需的类型是什么?那么会发生什么?

    实际上,知道从调用嵌入的表达式返回的预期类型是确切它的工作原理。

    Haskell 中的类型检查/推理同时在两个“方向”上工作。它是自上而下的,找出每个表达式应该具有什么类型,以适应它所使用的更大的表达式。它也是“自下而上”的,找出每个表达式的类型表达式应该来自构建它的较小的子表达式。当它找到一个不匹配的地方时,你会得到一个类型错误(这正是你在类型错误消息中看到的“预期类型”和“实际类型”的锥体)。

    但是因为编译器对每个表达式都有自上而下的知识(“预期类型”),所以它完全能够找出在预期 Float 的地方使用了 fromInteger 的调用,因此在该调用中为Num 使用Float 实例。

    【讨论】:

      【解决方案2】:

      将类型类与 OOP 接口区分开来的一个方面是,类型类可以在方法的 result 类型上调度,而不仅仅是在其参数的类型上。经典的例子是read :: Read a => String -> a 函数。


      fromInteger 的类型为 fromInteger :: Num a => Integer -> a。根据a 的类型选择实现。如果类型检查器知道aFloat,则将使用FloatNum 实例,而不是IntInteger 之一。

      【讨论】:

        猜你喜欢
        • 2011-03-28
        • 2017-07-24
        • 2016-11-13
        • 2017-10-11
        • 2021-10-13
        • 2011-02-24
        • 2013-11-16
        • 2011-10-16
        • 2012-11-03
        相关资源
        最近更新 更多