我如何从整数转换为分数

假设我有以下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

对我来说,这表示(/)可以取任何可以表示为分数的数字(我的印象之下应该包括Integer,尽管我不确定如何验证这一点),只要输入到/属于同一类型。

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


Haskell喜欢遵守运营商在数学上接受的含义。 /应该是乘法的倒数,但例如5 / 4 * 4不可能为Fractional Integer实例1产生5

所以,如果你真的想要做截断整数除法,那么这种语言会强制你使用div或者quot ;来强制显示。 OTOH,如果你真的想把结果看作一个分数,你可以使用/ fine,但是你首先需要转换成一个带有Fractional实例的类型。 例如,

前奏>让x = 5
前奏>:tx
x :: Integer
前奏> let y = fromIntegral x / 100
前奏> y
5.0E-2
前奏>:ty
y ::双

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

Prelude> let y'= fromIntegral x / 100 :: Rational
前奏> y'
1%20


严格地说,这个反向标识对于Double实例来说并不完全适用,不是因为浮点小故障,而是至少大约是真的。

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

instance Fractional Integer where
  (/) = div

你自己,那么你的原代码将工作得很好。 只是,这是一个坏主意!


您可以使用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

整数不实现分数,你可以在手册中看到。

链接地址: http://www.djcxy.com/p/33153.html

上一篇: How do I cast from Integer to Fractional

下一篇: Cycle in type synonym declarations