Consider the following program (in Haskell, but could be any HM-inferred language):
x = []
y = x!!0
Using HM (or by running the compiler), we infer:
x :: forall t. [t]
y :: forall a. a
I understand how this happens, playing by the usual generalization/instantiation rules, but I'm not sure it's desirable to have something like forall a. a
.
One question is: since we have an out-of-bounds access here, one can rule out the program as a valid example. Instead, can we say the universal type we inferred is a sign of something wrong in the program? If yes, can we use this "fact" to deliberately fail checking of invalid programs in other cases as well?
The next program gets even stranger types:
c = []
d = (c!!0) + (1 :: Int)
Inferred types:
c :: forall t. [t]
d :: Int
...although d
was drawn from c
!
Can we augment HM to do a better job here without ruling out valid programs?
EDIT: I suspected this is an artifact of using partial functions (!!0
in this case). But see:
c = []
d = case c of [] -> 0; (x:_) -> x + (1 :: Int)
There are now no partial functions in use. And yet, c :: forall t. [t]
and d :: Int
.