Ambiguous type variable `a0' arising from a use of `it'

This has to do with the fact numeric literals are overloaded in Haskell. When you type map(\x -> (x, div 18 x)) [y | y <- [1..(ceiling $ sqrt 18)], 18 `rem` y == 0] into ghci, the 18 that is an argument to sqrt defaults to a Double and the others to Integers.

However, when you write

factorPairs:: (RealFrac a, Floating a, Integral a) => a -> [(a, a)]
factorPairs n = map(\x -> (x, div n x)) [y | y <- [1..(ceiling $ sqrt n)], n `rem` y == 0]

you force all instances of n to have only one type. Then, the problem becomes that there simply are no default number types (in fact number types in general I think) that satisfy all of these constraints, hence GHC telling you about "possible instances" it tries. The solution is to add fromIntegral and loosen the constraints:

factorPairs:: Integral a => a -> [(a, a)]
factorPairs n = map(\x -> (x, div n x)) [y | y <- [1..(ceiling $ sqrt $ fromIntegral n)], n `rem` y == 0]

Another way to get rid of the type error is to eliminate the use of sqrt. Since Haskell is lazy, you can simply iterate over [1..n], stopping when your divisor is greater than your quotient.

factorPairs :: Integral a => a -> [(a, a)]
factorPairs n = takeWhile (uncurry (>=)) [ (n `div` d, d) | d <- [1..n], n `mod` d == 0]

uncurry (>=) is just a fancy way of writing \(q, d) -> q >= d.

If you write this in monadic form, you can use divMod to get the quotient and the remainder with a single function all.

factorPairs n = takeWhile (uncurry (>=)) $ do
                d <- [1..n]
                let (q, r) = n `divMod` d
                guard $ r == 0
                return (q, d)