如何从Integer转换为Fractional

Abr*_*m P 6 haskell types casting

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

divide_by_hundred :: Integer -> IO()
divide_by_hundred n = print(n/100)
Run Code Online (Sandbox Code Playgroud)

为什么当我尝试通过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)
Run Code Online (Sandbox Code Playgroud)

通过运行:t (/) 我得到:

(/) :: Fractional a => a -> a -> a
Run Code Online (Sandbox Code Playgroud)

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

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

lef*_*out 12

Haskell喜欢保持运算符的数学上可接受的含义./应该是乘法的倒数,但是例如5 / 4 * 4不可能5Fractional Integer实例1产生.

所以,如果你实际上意味着做截断的整数除法,语言的力量,你2通过使用做出明确divquot.OTOH,如果你真的希望结果作为一个分数,你可以使用/罚款,但你首先需要转换为具有Fractional实例的类型.例如,

Prelude> let x = 5
Prelude>:tx
x :: Integer
Prelude> let y = fromIntegral x/100
Prelude> y
5.0e-2
Prelude>:ty
y :: Double

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

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


1严格地说,Double由于浮点毛刺,这个反转的身份并不完全适用于实例,但它至少是近似的.

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

instance Fractional Integer where
  (/) = div
Run Code Online (Sandbox Code Playgroud)

你自己,那么你的原始代码就可以了.只是,这是一个坏主意!


Emi*_*röm 6

您可以使用div整数除法:

div :: Integral a => a -> a -> a
Run Code Online (Sandbox Code Playgroud)

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

fromIntegral :: (Integral a, Num b) => a -> b
Run Code Online (Sandbox Code Playgroud)

所以本质上:

divide_by_hundred :: Integer -> IO()
divide_by_hundred n = print $ fromIntegral n / 100
Run Code Online (Sandbox Code Playgroud)

整数不实现Fractional,您可以在手册中看到.