I have the following function to return the Factor Pairs for a given number
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]
When I call the function in ghci factorPairs 18
I'm getting a run time error of
* Ambiguous type variable `a0' arising from a use of `it'
prevents the constraint `(Floating a0)' from being solved.
Probable fix: use a type annotation to specify what `a0' should be.
These potential instances exist:
instance Floating Double -- Defined in `GHC.Float'
instance Floating Float -- Defined in `GHC.Float'
* In the first argument of `print', namely `it'
In a stmt of an interactive GHCi command: print it
I can hard code the function in ghci
map(\x -> (x, div 18 x)) [y | y <- [1..(ceiling $ sqrt 18)], 18 `rem` y == 0]
and don't have any issues but I can't seem to figure out why my function is failing. I believe ghci is trying to tell me it can't figure out what type to call print
with but am struggling to find the solution.
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 Integer
s.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With