ominug
ominug

Reputation: 1572

Haskell: No instance arising

Beginning with Haskell, I frequently encounter problems with types (and less helpful error messages of GHC). I defined following function:

ghci> let f x = floor x == x
ghci> :t f
f :: (Integral a, RealFrac a) => a -> Bool

which succeeds, but the invocation seams to be difficult:

ghci> let a = 1.1
ghci> f a

<interactive>:296:1:
    No instance for (Integral Double) arising from a use of `f'
    Possible fix: add an instance declaration for (Integral Double)
    In the expression: f a
    In an equation for `it': it = f a
ghci> let b = 2
ghci> f b

<interactive>:298:1:
    No instance for (RealFrac Integer) arising from a use of `f'
    Possible fix: add an instance declaration for (RealFrac Integer)
    In the expression: f b
    In an equation for `it': it = f b

How to define the function correctly?

Upvotes: 1

Views: 373

Answers (1)

shang
shang

Reputation: 24802

Haskell doesn't do any automatic coercion between different numeric types so if you e.g. compare x == y then x and y have to have the exact same type (e.g. both are ints or both are floats).

Now, if you look at the type of floor it's

floor :: (Integral b, RealFrac a) => a -> b

Which means that you can only call it for fractional types and result type must be an integral type.

When you call f 1.1 inside f you end up making the comparison

floor 1.1 == 1.1

But now you have a problem because floor can only return integral types and in order to make the comparison the result has to have the same type as 1.1 which is definitely not integral.

You need to define f as

let f x = fromIntegral (floor x) == x

The fromIntegral call coerces the integral floor value back into a fractional value so that it can be compared with the original x.

Upvotes: 4

Related Questions