OK, so I'm attempting to write a Haskell function which efficiently detects all the factors of a given Int
. Based off of the solution given in this question, I've got the following:
-- returns a list of the factors of n
factors :: Int -> [Int]
factors n = sort . nub $ fs where
fs = foldr (++) [] [[m,n `div` m] | m <- [1..lim+1], n `mod` m == 0]
lim = sqrt . fromIntegral $ n
Sadly, GHCi informs me that there is No instance for (Floating Int)
in the line containing lim =
etc. etc.
I've read this answer, and the proposed solution works when typed into GHCi directly - it allows me to call sqrt
on an Int
. However, when what appears to be exactly the same code is placed in my function, it ceases to work.
I'm relatively new to Haskell, so I'd greatly appreciate the help!
When you check the type of sqrt
Prelude> :t sqrt
sqrt :: Floating a => a -> a
It requires a floating number. It doesn't work in ghci. You might have tried calling it on a number and ghci would have inferred the type as Float.
Prelude> let a = 1 :: Int
Prelude> sqrt a
<interactive>:5:1:
No instance for (Floating Int) arising from a use of `sqrt'
Possible fix: add an instance declaration for (Floating Int)
In the expression: sqrt a
In an equation for `it': it = sqrt a
Now coming back to your code. The problem is in the expression [1 .. lim + 1]
. Arithmetic sequences can only be applied on values of type Enum a => a
. Since lim
is of type Floating a => a
, you need to convert it back to Integral a => a
by either taking the ceiling
or floor
. Just for information, Integral
class instance constraints the type to have an Enum
instance too.