I am new to Haskell from a C++ and Java background. Occassionally, I have trouble with Haskell's type system. My current error is with this piece of code:
countIf :: (Integral b) => [a] -> (a -> Bool) -> b
countIf [] p = 0
countIf (x:xs) p
| p x = 1 + countIf xs p
| otherwise = countIf xs p
isRelativelyPrime :: (Integral a) => a -> a -> Bool
isRelativelyPrime m n = gcd m n == 1
phi :: (Integral a, Integral b) => a -> b
phi n = countIf [1..(n - 1)] (isRelativelyPrime n)
main = print [(n, phi n, ratio) | n <- [1..10], let ratio = (fromIntegral (phi n)) / n]
The error message is
prog.hs:13:60:
Ambiguous type variable `b' in the constraints:
`Fractional b' arising from a use of `/' at prog.hs:13:60-85
`Integral b' arising from a use of `phi' at prog.hs:13:75-79
Probable fix: add a type signature that fixes these type variable(s)
13:60 is just before the usage of fromIntegral in the let binding in my list comprehension in main. I'm still trying to get used to ghc's error messages. I am unable to decipher this particular one in order to figure out what I need to change to get my code to compile. Any help will be greatly appreciated. Thanks.
This is an example of a common beginner mistake: excessively polymorphic code.
You've made your code as general as possible, e.g.
phi :: (Integral a, Integral b) => a -> b
this will take any integral type to any other integral type, via the phi transformation.
Such polymorphic code is great for libraries, but not so great for type inference. I'd put money that you just want this to work on Integers, so we can go ahead an give a more accurate type,
countIf :: [Integer] -> (Integer -> Bool) -> Integer
countIf [] p = 0
countIf (x:xs) p
| p x = 1 + countIf xs p
| otherwise = countIf xs p
isRelativelyPrime :: Integer -> Integer -> Bool
isRelativelyPrime m n = gcd m n == 1
phi :: Integer -> Integer
phi n = countIf [1..(n - 1)] (isRelativelyPrime n)
main = print [ (n, phi n, ratio)
| n <- [1..10], let ratio = (fromIntegral (phi n)) ]
and the type error just goes away.
You may even see performance improvements (particularly if you specialize to Int).
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