1
votes

Haskell "No instance for" error

Haskell Error: "No instance for (Enum [Int])

Function definition problems (No instance for … arising from)

No instance for Num String arising from the literal `1'

I am very new to Haskell, and functional programming in general. In addition, I am aware that the questions above are very similar, but I have not been able to find a solution for my problem anywhere. The following code is meant to find the factors of a number input:

fc4 :: Double -> IO ()
check :: Double -> Double -> IO ()
fc4 a = check a (sqrt a)
check a b = if rem a b == 0 then print (b, div a b) else print () >> if b > 1 then check a (b-1) else putStrLn ("Done.")

I have attempted switching from Double to Integer and back with every possible combination, but every one fails with the same error:

No instance for (Integral Double) arising from a use of 'rem'

I have also tried explicitly using fromIntegral and toInteger on the arguments of rem, but no combination I have attempted has avoided this problem. I also see by the documentation that the type for rem is Integral a => a -> a -> a, and so it seems that using the same type for a and b would always work, whether it be Double or Integer.

Am I on to something? Have I made some terrible rookie mistakes? For reference, here is a C++ version of what I hope to achieve. Thanks in advance!

1

1 Answers

7
votes

You could simply replace Double with Integer in the type signatures, since you need to use a value whose type is an instance of the Integral type class, which defines div and rem. However, sqrt only returns values that are instances of the Floating type class, and there aren't any types that are instances of both.

The simple solution is to use ceiling to get an integral value that is just slightly larger than sqrt n, which will not affect the correctness of your algorithm.

 check :: Integer -> Integer -> IO ()
 check a b = ... -- same as before

 fc4 :: Integer -> IO ()
 --fc4 a = check a (ceiling (sqrt a))  -- because I didn't bother testing
 fc4 a = check a (floor (sqrt (fromIntegral a)))