假设我有以下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?
答案 0 :(得分:12)
Haskell喜欢保持运算符在数学上被接受的含义。 /
应该是乘法的倒数,但例如对于5 / 4 * 4
实例 1 ,5
无法获得Fractional Integer
。
因此,如果你实际上是指截断整数除法,那么语言会强迫你 2 使用div
或quot
来明确表示。 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中看到。