class Visible a where
toString :: a -> String
size :: a -> Int
intToString :: (Integral t) => t -> String
intToString 0 = "0"
intToString 1 = "1"
intToString 2 = "2"
intToString 3 = "3"
intToString 4 = "4"
intToString 5 = "5"
intToString 6 = "6"
intToString 7 = "7"
intToString 8 = "8"
intToString 9 = "9"
intToString n
| ((div n 10) == 0) = (intToString (mod n 10))
| otherwise = (intToString (div n 10)) ++ (intToString (mod n 10))
Now
instance Visible Int where
toString = intToString
size n = length (toString n)
gives me an error about an ambiguous type variable at the prompt if I type something like (toString 55)
but
instance Visible Integer where
toString = intToString
size n = length (toString n)
does not.
What gives?
There are two things going on here. Remember that numeric literals in Haskell are polymorphic. That is:
really means
This is true for all numbers anywhere you write them. This can be awkward to work with, so GHCi implements type defaulting: it assumes that bare numbers are
Integers
orDoubles
if the type is ambiguous.When you write
toString 55
at the GHCi prompt, GHCi infers the type(Visible a, Num a) => a
for the number 55. If you only haveVisible Int
in scope, the type default ofInteger
doesn't work because it doesn't fulfill the class constraint (there's noVisible Integer
), so GHCi complains about the ambiguous type variable because it doesn't know which type to instantiate for the expression. If you do haveVisible Integer
in scope, the type default of Integer works just fine.If you want to use a type other than Integer, you can use an explicit type as in
toString (55 :: Int)
I found at this link a possible explanation. I think the default interpretation of a literal is an Integer in ghci. But if that doesn't work out, ghci starts being confused about which interpretation of the literal he must make (Int, Double, Float, ...). Subsequently he gives the error about ambiguity. The command (
toString (55:Int)
) gives no error because GHCi knows he has to interprete the55
as anInt
.