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?
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With