The code
default ()
h :: Bool
h = 1.0 == 1.0 --Error. Ambiguity.
does not compile. This is expected because there is ambiguity. It could be either Float
or Double
and Haskell doesn't know which one we want.
But the code
default ()
foo :: (Fractional a, Eq a) => a -> Bool
foo x = x == 1.0
compiles successfully. I don't fully understand why. Why isn't this also ambiguous?
I have the feeling that this is because whenever we call foo
, we are guaranteed to have picked a concrete type in place of a
, i.e., we are guaranteed to have fixed a
to either Float
or Double
(or our custom type that has instances of both Fractional
and Eq
) at compile-time and therefore there is no ambiguity.
But this is just a feeling and I don't know if it's 100% accurate.
The definition for ambiguity in this context is given in Section 4.3.4 of Haskell Report:
We say that an expression
e
has an ambiguous type if, in its typeforall us. cx => t
, there is a type variableu
inus
that occurs incx
but not int
. Such types are invalid.
In foo :: (Fractional a, Eq a) => a -> Bool
, there is no such variable (because a
occurs in a -> Bool
). In 1.0 == 1.0
the type is actually (Fractional a, Eq a) => Bool
, so there is such a variable.
The reason this kind of ambiguity is an error is because there is no way for compiler to choose between different instantiations of the variable a
, and the result of the program can depend on which one it chooses. In this case 1.0 == 1.0
should always be True
for any reasonable instantiation, but 1) the compiler doesn't know this; 2) not all instantiations are reasonable.