Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OCaml's rectype inference

Tags:

ocaml

While playing with -rectypes option of OCaml at some point I'm just lost.

This expression is pretty much typable:

# fun x -> x x;;
- : ('a -> 'b as 'a) -> 'b = <fun>

But here OCaml fell in infinite loop:

# (fun x -> x x) (fun x -> x x);;
  C-c C-cInterrupted.

Ok, I can understand, recursive type system is a quite difficult thing. But first of all, I really want to know the type of this expression and does it typable at all, and secondly, in this context, I don't understand how OCaml still can type this:

# fun _ -> (fun x -> x x) (fun x -> x x);;
- : 'a -> 'b = <fun>

So, can someone elaborate a bit on this topic?

like image 725
vonaka Avatar asked May 24 '18 13:05

vonaka


People also ask

Does OCaml have type inference?

Hindley–Milner type inference is one of the core algorithms that makes the OCaml language, and many other functional languages, possible. It is fundamentally based on traversing the source code to collect a system of equations, then solving that system to determine the types.

What is the type of inference?

Type inference refers to the automatic detection of the type of an expression in a formal language. These include programming languages and mathematical type systems, but also natural languages in some branches of computer science and linguistics.

What is type checking inference?

Type Inference. A Type Checker only verifies that the given declarations are consistent with their use. Examples: type checkers for Pascal, C. A Type Inference system generates consistent type declarations from information implicit in the program.

How does rust type inference work?

Type inference means that if you don't tell the compiler the type, but it can decide by itself, it will decide. The compiler always needs to know the type of the variables, but you don't always need to tell it. Actually, usually you don't need to tell it.


1 Answers

Let's first try to evaluate your expression.

# (fun x -> x x) (fun x -> x x);;
# let x = (fun x -> x x) in x x;; (* applying the function on the left *)
# (fun x -> x x) (fun x -> x x);; (* inlining the let-binding *)
(* We came back to our original state, infinite loop *)

So the infinite loop doesn't come from the typing system, but from the semantics of the expression you gave it to.

You can get the type of an expression without evaluating it using ocamlc -i

$ echo 'let x = (fun x -> x x) (fun x -> x x)' > rectypes.ml
$ ocamlc -i -rectypes rectypes.ml                                                                                                                                                                                                           
val x : 'a

So here it is, you created a value of type 'a (which usually means "this expression never returns").

Note that you can do the same kind of trick without using rectypes:

# let x =
   let rec f () = f () in
   f ();;

As you can understand now, your last bit of code takes any argument and never returns, hence the 'a -> 'b type.

like image 82
PatJ Avatar answered Sep 16 '22 15:09

PatJ