The value restriction

匆匆过客 提交于 2019-11-26 08:29:50

问题


In OCaml you can\'t generalize a partially-applied curried function (the \"value restriction\").

What is the purpose of the value restriction? What unpleasant would happen if it did not exist?


回答1:


Without the value restriction or other mechanisms to restrict generalization, this program would be accepted by the type system:

let r = (fun x -> ref x) [];; (* this is the line where the value restriction would trigger *)

> r : 'a list ref

r := [ 1 ];;

let cond = (!r = [ "foo" ]);;

The variable r would have type 'a list ref, meaning that its contents could be compared to [ "foo" ] although it contained a list of integers.

See Xavier Leroy's PhD thesis for more motivation (ref is not the only construct one may want to add to pure lambda-calculus that introduces the problem) and a survey of the systems that existed at the time of his thesis (including his).




回答2:


Here is the answer I gave some time ago about F#; the issue is exactly the same with OCaml. The problem is that without it, we would be able to create references that point to the wrong type of data:

let f : 'a -> 'a option =
    let r = ref None in
    fun x ->
        let old = !r in
        r := Some x;
        old

f 3           // r := Some 3; returns None : int option
f "t"         // r := Some "t"; returns Some 3 : string option!!!



回答3:


There is a nice description of weakly polymorphism here(side-effects-and-weak-polymorphism).

Basically, let's take a look at the function below (caching the first ever value it sees):

# let remember =
    let cache = ref None in
    (fun x ->
       match !cache with
       | Some y -> y
       | None -> cache := Some x; x)
  ;;
val remember : '_a -> '_a = <fun>

As it involves imperative, value restriction is applied.


However, let's assume there was no value restriction.

Then its type becomes val remember : 'a -> 'a = <fun>.


If I now do let () = remember 1, 1 is recorded inside cache, right?

If I call for 2nd time, let x = 3 + remember 2, this should work, because 3 is integer, remember returns the same type as its argument. I am giving 2 here, so remember returns integer too (but value is 1 as we already remembered once). This should pass the type check.


What if I call for 3rd time as let y = 3.0 + remember 2.0? Will it work again?

According to remember's type and the reason behind my 2nd call, it also should work, because I am giving float to remember, and it should return float.

But because the first time it already stored 1 (integer) inside, it will return 1 which is an integer. So the type check will fail, right?


We can see that without value restriction or weakly polymorphism, due to the mutability is allowed, the whole type check will have trouble. In the silly case above, you need constantly manually check or keep track of what's the initial type remember stored.



来源:https://stackoverflow.com/questions/22507448/the-value-restriction

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!