Reputation: 706
I'm trying to write a function that tests if the square root of a number is whole or not. My function looks like this:
check :: [Int] -> [Int]
check xs = filter (\n -> n == round sqrt n) xs
And the error messages I'm receiving are these:
No instance for (Integral (Int -> Int))
(maybe you haven't applied enough arguments to a function?)
arising from a use of "round"
In the second argument of "(==)", namely "round sqrt n"
...
No instance for (Floating a0) arising from a use of `sqrt'
The type variable `a0' is ambiguous
Note: there are several potential instances:
instance Floating Double -- Defined in `GHC.Float'
instance Floating Float -- Defined in `GHC.Float'
In the first argument of `round', namely `sqrt'
Edit: I ended up rewriting the whole question, I hope thats not a problem!
Upvotes: 0
Views: 1440
Reputation: 706
So I found another solution by myself:
check :: [Int] -> [Int]
check xs = filter (\n -> (ceiling (sqrt (fromIntegral n))) == (floor (sqrt (fromIntegral n)))) xs
This is the only one that doesn't throw compiler errors (in my case).
Upvotes: 1
Reputation: 13160
It should be
check :: [Int] -> [Int]
check xs = filter (\n -> fromIntegral n == round (sqrt (fromIntegral n))) xs
The error message is telling you the problem:
(maybe you haven't applied enough arguments to a function?)
arising from a use of "round"
Because round sqrt n
calls round
with the arguments sqrt
and n
.
But that still doesn't do what you want. You need to sqrt
the other side as well
check :: [Int] -> [Int]
check xs = filter (\n -> sqrt (fromIntegral n) == round (sqrt (fromIntegral n))) xs
Upvotes: 2
Reputation: 52270
it will work if you remove the left fromIntegral
:
test n = n == fromIntegral (round n)
the reason is that as it is your n
has to be RealFrac
(round
) and Integral
(fromIntegral
) but there is no type in the prelude which is both (neither Integer
nor Double
for example)
if you remove the left fromIntegral
you only need n
to have a type which is an instance of RealFrac
- Double
for example
the right side is like this:
RealFrac -round-> Integral -fromIntegral-> RealFrac
if you are in doubt you can always ask GHCi:
Prelude> :i RealFrac
class (Real a, Fractional a) => RealFrac a where
properFraction :: Integral b => a -> (b, a)
truncate :: Integral b => a -> b
round :: Integral b => a -> b
ceiling :: Integral b => a -> b
floor :: Integral b => a -> b
-- Defined in ‘GHC.Real’
instance RealFrac Float -- Defined in ‘GHC.Float’
instance RealFrac Double -- Defined in ‘GHC.Float’
as you can see this type-class gives you ways to cut-back numbers to Integral
(ask for Integral
to see what it's about - hint: think something like Integers)
you also see the known instances
if you see RealFrac Int
it means it was looking to find a RealFrac
instance-definition for Int
(there is none)
Why there is an Int
is another matter:
n
to Int
here - you probably ran into the dreaded monomorphism restriction - which should not happen like this with newer GHC versions but well ...Int
(which we do not see)to be honest I'm not sure which it is here
Upvotes: 2