Let's say I have the following Haskell type description:
divide_by_hundred :: Integer -> IO()
divide_by_hundred n = print(n/100)
Why is it that when I attempt to run this through ghc I get:
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)
By running :t (/)
I get:
(/) :: Fractional a => a -> a -> a
which, to me, suggests that the (/) can take any Num that can be expressed as fractional (which I was under the impression should include Integer, though I am unsure as how to verify this), as long as both inputs to /
are of the same type.
This is clearly not accurate. Why? And how would I write a simple function to divide an Integer by 100?
Haskell likes to keep to the mathematically accepted meaning of operators. /
should be the inverse of multiplication, but e.g. 5 / 4 * 4
couldn't possibly yield 5
for a Fractional Integer
instance1.
So if you actually mean to do truncated integer division, the language forces you2 to make that explicit by using div
or quot
. OTOH, if you actually want the result as a fraction, you can use /
fine, but you first need to convert to a type with a Fractional
instance. For instance,
Prelude> let x = 5
Prelude> :t x
x :: Integer
Prelude> let y = fromIntegral x / 100
Prelude> y
5.0e-2
Prelude> :t y
y :: Double
Note that GHCi has selected the Double
instance here because that's the simples default; you could also do
Prelude> let y' = fromIntegral x / 100 :: Rational
Prelude> y'
1 % 20
1Strictly speaking, this inverse identity doesn't quite hold for the Double
instance either because of floating-point glitches, but there it's true at least approximately.
2Actually, not the language but the standard libraries. You could define
instance Fractional Integer where
(/) = div
yourself, then your original code would work just fine. Only, it's a bad idea!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With