Reputation: 1572
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
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