【问题标题】:What does the fromIntegral type here actually do?这里的 fromIntegral 类型实际上做了什么?
【发布时间】:2022-12-03 09:11:33
【问题描述】:

我只是想澄清一下我对来自积分输入哈斯克尔。

这两个欧氏距离函数的输出是相同的,那么输入 fromIntegral 有什么意义呢?就像它们都给出欧氏距离的浮点值一样。

另外,对于使用 fromIntegral 类型的函数 distance2 的类型定义,为什么它是 (Floating a1, Integral a2) 然后 => (a2, a2) -> (a2, a2) -> a1? 我只是不太明白这里的解释。

distance2 :: (Floating a1, Integral a2) => (a2, a2) -> (a2, a2) -> a1
distance2 (x1, y1) (x2, y2) 
      = sqrt (fromIntegral ((x2-x1)^2 + (y2 - y1)^2))

distance3 :: Floating a => (a, a) -> (a, a) -> a
distance3 (x1, y1) (x2, y2) 
      = sqrt ((x2-x1)^2 + (y2 - y1)^2)

谁能帮忙解释一下,谢谢:)

【问题讨论】:

  • fromIntegral 不是类型;它是 (Integral a, Num b) => a -> b 类型的函数。
  • 输出不一样,试试distance2 (0,0) (9000,9011) - distance3 (0,0) (9000,9011) :: Float

标签: haskell


【解决方案1】:

这两个欧氏距离函数的输出是相同的,那么输入 fromIntegral 有什么意义呢?就像它们都给出欧氏距离的浮点值一样。

他们两个浮点值,但它们不是两者浮点值。

> distance3 (pi, 0) (0, 0)
3.141592653589793
> distance2 (pi, 0) (0, 0)
<interactive>:2:1: error:
    • Could not deduce (Integral a20) arising from a use of ‘distance2’
      from the context: Floating a1
        bound by the inferred type of it :: Floating a1 => a1
<snipped considerable additional error text>

另外,对于使用 fromIntegral 类型的函数 distance2 的类型定义,为什么它是 (Floating a1, Integral a2) 然后 => (a2, a2) -> (a2, a2) -> a1?

您的 distance2 函数接受数字并返回数字,但不是同一类型的数字。输入的数字必须是类似整数的东西,这样你就可以对它们应用fromIntegral;但是传出的数字必须是类似浮点数的东西,这样你就可以对它们应用sqrt。例如,这里有一些单态类型,distance2 可以专用于:

(Int, Int) -> (Int, Int) -> Double
(Integer, Integer) -> (Integer, Integer) -> Double
(Word, Word) -> (Word, Word) -> Float

这个英语描述是通过创建两个类型变量来捕获的,每个变量都有不同的约束。 distance2 的相同类型,但具有更多人类可读的变量名称,可能如下所示:

(Floating float, Integral int) => (int, int) -> (int, int) -> float

【讨论】:

  • 我有点困惑,就像括号 (Floating a1, Integral a2) 一样,这是否意味着像我所说的那样,(x1,y1) 和 (x2,y2),x1 是浮点数而 y1是积分?同样对于点(x2,y2)?对不起。
  • @LorenBeer 不,不完全是。这意味着在类型接下来,a1Floatinga2Integral。因为你在distance2 中的点类型是(a2, a2)——也就是说,都是a2——这意味着 x 和 y 坐标都必须是Integral
【解决方案2】:

fromIntegral 用于将您的平方和生成的Integral a =&gt; a 类型的值转换为sqrt 期望的Floating a =&gt; a 类型的值。

fromIntegral 的类型为 (Integral a, Num b) =&gt; a -&gt; b。这意味着,给定一个Integral a类型的值,它将返回一个值任何输入 b 有一个 Num 实例。由于FloatingNum 作为超类(通过Fractional),这意味着fromIntegral 可以生成Floating a =&gt; a 类型的值。

【讨论】:

    【解决方案3】:

    这里有两个相关的类型类:

    • Integral 是表示整数子集的类型的类型类
      • 每个Integral类型都有一个函数toInteger将其值转换为任意长度的整数类型Integer
    • Num 是包含整数作为子集的数字类型的类型类
      • 每个Num 类型都有一个函数fromInteger 将任意长度的Integer 值转换为该Num 类型的值

    前奏函数fromIntegral定义为:

    fromIntegral = fromInteger . toInteger
    

    它使用这两个函数将任何 Integral 类型转换为任何 Num 类型。

    这就是让您的第一个功能发挥作用的原因任何Integral类型作为输入:通过平方差和表达式推断输入类型作为fromIntegral的输入,并从该类型的Integral实例中选择toInteger,而Floating输出通过 sqrt 函数推断类型,要求与 fromIntegral 调用的结果相同的类型,并从输出类型的 Num 实例中选择 fromInteger

    【讨论】:

      猜你喜欢
      • 2023-01-26
      • 2013-06-02
      • 2020-11-21
      • 2015-02-26
      • 2017-06-29
      • 2013-06-13
      • 2021-10-25
      • 2011-08-12
      • 1970-01-01
      相关资源
      最近更新 更多