dopatraman
dopatraman

Reputation: 13908

Apply comparison between Integral and Fractional

I want to check if an Integral is a square:

isSquare :: Integral n => n -> Bool
isSquare n = (>1) $ length (filter (\x -> n / x == x) numList)
    where numList = reverse [1..n]

Apart from whether or not iterating through a list is the right approach here, when I try to compile this function I get the error:

No instance for (Fractional Int) arising from a use of ‘/’

My understanding of this is that since I am binding n to the Integral type, by dividing it I am breaking the function's rigid type construction. How can I fix my function so that it compiles?

Upvotes: 2

Views: 105

Answers (1)

Ry-
Ry-

Reputation: 225074

You could add fromIntegral to everything to get Fractionals:

filter (\x -> fromIntegral n / fromIntegral x == fromIntegral x) numList

Or just square the number instead:

filter (\x -> n == x ^ 2)

Also, your length check shouldn’t be >1. ==1 would make more sense, but you should use null to avoid having to try every number every time (besides using a faster algorithm in the first place).

isSquare :: Integral a => a -> Bool
isSquare n = not $ null $ filter (\x -> n == x ^ 2) numList
    where numList = [n,n-1..1]

Upvotes: 4

Related Questions