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