barbara
barbara

Reputation: 3201

Why it is impossible to divide Integer number in Haskell?

This code

(4 :: Integer) / 2

will lead to error:

  No instance for (Fractional Integer) arising from a use of ‘/’
    In the expression: (4 :: Integer) / 2
    In an equation for ‘it’: it = (4 :: Integer) / 2

Why?

I need to specify

fromIntegral(4 :: Integer) / 2

to get a result. But what if I need a real number and not 2.0?

Upvotes: 26

Views: 47002

Answers (3)

Jonathan Cast
Jonathan Cast

Reputation: 4635

Because the division operator for integers has two results (quotient and remainder):

divMod :: Integer -> Integer -> (Integer, Integer)

You can also use the div operator:

n `div` m

which returns only one component of the division result (the quotient), but that's not the same thing as n / m. / is for types where the division operator has only one result which combines 'quotient' and 'remainder' in one fraction.

Equationally, if (q, r) = n `divMod` m, then

n = m * q + r

whereas if q = x / y, then

x = y * q

(up to the usual caveats about floating point numbers and approximations).

Substituting div for / breaks that relationship, because it throws away some of the information you need to reproduce n.

Upvotes: 9

noamchomsky
noamchomsky

Reputation: 11

In Haskell, the class Fractional contains all types which are capable of division. Indeed, this is how division is defined; accordingly, whenever Haskell encounters /, it looks for an instance of Fractional for the type being operated on. Because there is no instance of the class Fractional for Integer, Haskell does not have a definition for / on Integer.

Haskell has several subclasses of the Num class, and they are worth being familiar with in order to type your classes in the most appropriate way possible.

Upvotes: 1

Bakuriu
Bakuriu

Reputation: 101919

Because the Integer type has no Fractional instance.

The type for (/) is Fractional a => a -> a -> a. Consider what happens when a = Integer. You'd have Integer -> Integer -> Integer. But 1/2 is not an integer, it's 0.5. So the only way to fit the division operator would be to round the result. But there is not a single way to round, and the best choice depends on the application, hence it was decided to not provide that instance.

If you want to perform integer division use the div or quot functions (they use different rounding). Otherwise convert to something that supports a well-defined division operation like Rational (this is what the fromIntegral is doing).

Upvotes: 38

Related Questions