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不可能5为Fractional Integer实例1产生.
所以,如果你实际上意味着做截断的整数除法,语言的力量,你2通过使用做出明确div或quot.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)
你自己,那么你的原始代码就可以了.只是,这是一个坏主意!
您可以使用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,您可以在手册中看到.