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