Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type mysteries. Why does this code compile?

Tags:

haskell

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)?

like image 956
haskellHQ Avatar asked Jan 13 '16 20:01

haskellHQ


2 Answers

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.

like image 180
Ben Avatar answered Oct 12 '22 16:10

Ben


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).

like image 21
András Kovács Avatar answered Oct 12 '22 16:10

András Kovács