如何从Integer转换为Fractional

时间:2014-03-04 14:01:23

标签: haskell types casting

假设我有以下Haskell类型描述:

divide_by_hundred :: Integer -> IO()
divide_by_hundred n = print(n/100)

为什么当我尝试通过ghc运行时,我得到:

No instance for (Fractional Integer) arising from a use of `/'
Possible fix: add an instance declaration for (Fractional Integer)
In the first argument of `print', namely `(n / 100)'
In the expression: print (n / 100)
In an equation for `divide_by_hundred':
    divide_by_hundred n = print (n / 100)

运行:t (/) 我明白了:

(/) :: Fractional a => a -> a -> a

对我来说,这表明(/)可以取任何可以表示为小数的Num(我在印象中应该包括整数,但我不确定如何验证这一点),只要两者都/的输入属于同一类型。

这显然不准确。为什么?我怎么写一个简单的函数来将整数除以100?

2 个答案:

答案 0 :(得分:12)

Haskell喜欢保持运算符在数学上被接受的含义。 /应该是乘法的倒数,但例如对于5 / 4 * 4实例 1 5无法获得Fractional Integer

因此,如果你实际上是指截断整数除法,那么语言会强迫你 2 使用divquot来明确表示。 OTOH,如果你真的想要将结果作为分数,你可以使用/罚款,但首先需要转换为具有Fractional实例的类型。例如,

  

前奏>设x = 5
  前奏> :t x
  x ::整数
  前奏>设y = fromIntegral x / 100
  前奏> ÿ
  5.0E-2
  前奏> :t y
  y ::双重

请注意,GHCi在这里选择了Double实例,因为这是简单的默认值;你也可以做

  

前奏>让y'= fromIntegral x / 100 :: Rational
  前奏> Y'
  1%20


1 严格地说,由于浮点毛刺,这个反转同一性并不完全适用于Double实例,但至少大约是这样。

2 实际上,不是语言而是标准库。你可以定义

instance Fractional Integer where
  (/) = div

你自己,然后你的原始代码就可以了。只是,这是一个坏主意!

答案 1 :(得分:6)

您可以使用div进行整数除法:

div :: Integral a => a -> a -> a

或者您可以使用fromIntegral将整数转换为小数:

fromIntegral :: (Integral a, Num b) => a -> b

所以实质上:

divide_by_hundred :: Integer -> IO()
divide_by_hundred n = print $ fromIntegral n / 100

整数不实现Fractional,您可以在the manual中看到。