I deliberately added x to the end of this function
let myMax x y =
if x > y then x else y
x
I was expecting that x and y arguments are still of ‘a type, but I get this signature instead:
myMax : x:unit -> y:unit -> unit
Why these arguments inferred to have a unit type?
Edit: Thank you @gilles for the answer. Consider these two functions:
let foo x y =
0 // warning
x
val foo : x:'a -> y:'b -> 'a
let foo2 x y =
if x > y then x else y // no warning
x
val foo2 : x:unit -> y:unit -> unit
What makes the two signatures different? Seems like in the second function the compiler interpret the result of the comparison –either x or y- as unit
Let's write a simpler example:
In a compound expression, the expression before the semicolon/newline operator must have unit type. If you want to use an expression with a “real” value (i.e. anything of a type other than unit), you need to ignore it explicitly, or bind it to a variable-less pattern. The compiler reminds you if the expression's type can't be unified with
unit
:It would be possible to have a typing rule that allows any type before
;
— the value is ignored, after all, so its type doesn't matter — but that would make it easy to accidentally discard a return value that matters. So if you want to ignore the value, do so explicitly:or