This code does not compile:
default ()
f :: RealFloat a => a
f = 1.0
g :: RealFloat a => a
g = 1.0
h :: Bool
h = f < g --Error. Ambiguous.
This is expected because it's ambiguous. The two possibilities are Float and Double and the compiler doesn't know which < to pick.
However, this code does compile:
default ()
f :: RealFloat a => a
f = 1.0
g :: RealFloat a => a
g = 1.0
h :: RealFloat a => a
h = f + g --Why does this compile?
Why? Why isn't Haskell confused here, in a similar manner as in the example above, about which + to pick (for Float or Double)?
In your second example h also has a polymorphic type. So the type at which + is used isn't ambiguous; it just hasn't been chosen yet.
The context where h is used will determine which type's + is chosen (and different use-sites can make different choices). The user of h can ask it to provide any RealFloat type they please; f and g can also provide any RealFloat type, so h will just ask them for exactly the type its user is asking for.
With h = f < g :: Bool, the type Bool doesn't contain the polymorphic a variable. To actually compute the Bool result, the a needs to be instantiated, and the resulting Bool value can depend on the choice of a (through the RealFloat instance), so instead of making an arbitrary choice GHC refuses to compile.
With h = f + g, the a parameter is in the type of the result, therefore there is no ambiguity. The choice for a has not yet been made, we can still instantiate a as we like (or more precisely, we re-generalized the type of f + g).
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