I am a little confused about weak polymorphism in OCaml.
Please see the following snippet, where I define a function remember
:
let remember x =
let cache = ref None in
match !cache with
| Some y -> y
| None -> cache := Some x; x
;;
The compiler can infer the polymorphic type 'a -> 'a
, and cache
is used locally.
But when I modify the above code into
let remember =
let cache = ref None in
(fun x -> match !cache with
| Some y -> y
| None -> cache := Some x; x)
;;
the compiler infers the weakly polymorphic type '_a -> '_a
, also, it seems that cache
is shared across invocations of remember
.
Why does the compiler infer a weakly polymorphic type here and why is cache
shared?
What is more, if I change the code again
let remember x =
let cache = ref None in
(fun z -> match !cache with
| Some y -> z
| None -> cache := Some x; x)
;;
the compiler infers the polymorphic type 'a -> 'a -> 'a
and cache
becomes locally used. Why is this the case?
Here
cache
is closed over by the returned function. But at the point where we declarecache
, we have no information on what the type will be; it'll be determined by whatever the type ofx
is andcache
is created whenremember
is defined.But since this is a closure we can do something like this:
Now it's clear that
cache : int option ref
since we've actually stored something in it. Since there's only ever onecache
,remember
can only ever store one type.In the next one, you close over 2 things,
x
andcache
. Since we create a newcache
ref with each invocation ofremember
the type can be fully polymorphic again. The reason the type isn't weakly polymorphic is because we know that we're going to storex
in it and we havex
s type at the time whencache
is created.