New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generalization with function-constructors #6847
Comments
Comment author: @Drup Additional note: if I annotate this type to be covariant, it generalizes properly, but since my real type is not covariant, that doesn't help me much. |
Comment author: @gasche This is the value restriction. Covariance works because of the relaxed value restriction. For reference, see (This is not related to injectivity.) There is no general solution to this problem, except an effect system that can guarantee that some functions are pure (and doing that in a usable way is a research problem). |
Comment author: @lpw25
I think higher-rank types would also solve it in this case: let add (x : 'a. 'a t) : 'b. 'b t = Add x Of course then |
Comment author: @xavierleroy "Real World OCaml" contains a tutorial on the value restriction and why it is there in the first place: |
Comment author: @Drup @gasche: I know about the value restriction and the relaxation with covariance, but it's not helping, since my type is not covariant, but I still would like to instruct the type system that it can generalize. If it's really unsound to generalize in this case, why ? As you said in #6653:
|
Comment author: @gasche It is unsound to generalize expressions which may allocate and share fresh mutable memory. The value restriction approximates "safe" terms by the set of values (which do not compute and thus do not allocate), and everything that is not syntactically value-like is considered unsafe and not generalized. In "this case" it's of course sound to generalize, as inlining the Add function immediately shows. The problem is that this is not a general criterion as inlining is anti-modular and opens a can of worm of never-ending non-trivial refinements. The proper solution is effect-typing, which gives a modular interface to the "safe to generalize" idea. I think the history of the value restriction is very well explained in the first two sections of Jacques' article. (In particular, Leo's suggestion to use rank-1 polymorphism is mentioned page 3.) |
Original bug ID: 6847
Reporter: @Drup
Assigned to: @gasche
Status: closed (set by @xavierleroy on 2016-12-07T10:48:56Z)
Resolution: not a bug
Priority: normal
Severity: minor
Version: 4.02.1
Category: typing
Bug description
The following piece of code describes the issue:
type _ t =
| Base : 'a t
| Add : 'a t -> 'a t
let add x = Add x
(* val add : 'a t -> 'a t *)
let x = Add(Base)
(* val x : 'a t )
let x' = add Base
( val x' : '_a t *)
x has a general type but x' does not.
Why is that ?
Is there a solution ? I know you can workaround the issue by giving Base a fixed type, but this solution is not satisfactory for me.
Note that the problem also appears with formats. You can see it with the ^^ operator:
"" ^^ "" ;;
The text was updated successfully, but these errors were encountered: