Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why these arguments inferred to have a unit type?

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

like image 936
ٍShagrouni Avatar asked May 07 '16 21:05

ٍShagrouni


1 Answers

Let's write a simpler example:

> fun x -> x; 0;;          
val it : unit -> int = <fun:clo@5>

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:

> fun x -> 0; x;;

  fun x -> 0; x;;
  ---------^

stdin(7,10): warning FS0020: This expression should have type 'unit', but has type 'int'. 
Use 'ignore' to discard the result of the expression, 
or 'let' to bind the result to a name.
val it : x:'a -> 'a = <fun:clo@7-1>

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:

let myMax x y =
  ignore (if x > y then x else y)
  x

or

let myMax x y =
  let _ = if x > y then x else y
  x
like image 70
Gilles 'SO- stop being evil' Avatar answered Nov 27 '22 05:11

Gilles 'SO- stop being evil'