Doopy
Doopy

Reputation: 706

Haskell No instance for ... arising

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

Answers (3)

Doopy
Doopy

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

Dan
Dan

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

Random Dev
Random Dev

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:

  • either you ran into a technicality: GHCi default n to Int here - you probably ran into the dreaded monomorphism restriction - which should not happen like this with newer GHC versions but well ...
  • or you use it in a context which constraints it to Int (which we do not see)

to be honest I'm not sure which it is here

Upvotes: 2

Related Questions