【问题标题】:Why it is impossible to divide Integer number in Haskell?为什么不能在 Haskell 中除整数?
【发布时间】:2016-06-27 07:27:48
【问题描述】:

这段代码

(4 :: Integer) / 2

会导致错误:

  No instance for (Fractional Integer) arising from a use of ‘/’
    In the expression: (4 :: Integer) / 2
    In an equation for ‘it’: it = (4 :: Integer) / 2

为什么?

我需要指定

fromIntegral(4 :: Integer) / 2

得到结果。但是如果我需要一个实数而不是2.0,该怎么办?

【问题讨论】:

  • IMO,一个更自然的问题是“为什么在这么多其他编程语言中可以除整数?”看到大多数整数不能被彼此整除,因此 整数除法 与(分数)除法有很大不同。

标签: haskell


【解决方案1】:

因为整数的除法运算符有两个结果(商和余数):

divMod :: Integer -> Integer -> (Integer, Integer)

您也可以使用div 运算符:

n `div` m

它只返回除法结果的一个分量(商),但这与n / m 不同。 / 适用于除法运算符只有一个结果,将“商”和“余数”组合在一个分数中的类型。

等式,如果(q, r) = n `divMod` m,那么

n = m * q + r

如果q = x / y,那么

x = y * q

(直到关于浮点数和近似值的常见警告)。

div 替换为/ 会破坏这种关系,因为它会丢弃一些您需要复制n 的信息。

【讨论】:

    【解决方案2】:

    在 Haskell 中,Fractional 类包含所有能够除法的类型。确实,这就是划分的定义;因此,每当 Haskell 遇到 / 时,它都会为正在操作的类型查找 Fractional 的实例。因为Integer 没有类Fractional 的实例,所以Haskell 在Integer 上没有/ 的定义。

    Haskell 有几个 Num 类的子类,它们值得熟悉,以便以最合适的方式键入您的类。

    【讨论】:

      【解决方案3】:

      因为Integer 类型没有Fractional 实例。

      (/) 的类型是 Fractional a => a -> a -> a。考虑a = Integer 时会发生什么。你会有Integer -> Integer -> Integer。但是1/2 不是一个整数,它是0.5。因此,适合除法运算符的唯一方法是 round 结果。但是没有一种单一的舍入方法,最佳选择取决于应用程序,因此决定提供该实例。

      如果您想执行整数除法,请使用divquot 函数(它们使用不同的舍入)。 否则转换为支持定义明确的除法运算的东西,例如Rational(这就是fromIntegral 正在做的事情)。

      【讨论】:

      • 可以用Integer代替Int进行整数除法吗?
      • @MarkNeu 函数divquot 的类型为Integral a => a -> a -> aInteger 确实有一个 Integral 实例,因此是的。
      猜你喜欢
      • 2014-08-02
      • 2013-11-24
      • 2014-12-16
      • 1970-01-01
      • 2013-12-09
      • 1970-01-01
      • 1970-01-01
      • 2015-03-01
      • 2021-04-26
      相关资源
      最近更新 更多