-
Notifications
You must be signed in to change notification settings - Fork 32
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
Having types as possible module arguments #40
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The RFC is lacking the part where you argue why this feature is desirable/useful. Do you have compelling examples? (I know from private communication that there are some examples coming from modular implicits, and I think that it would be interesting to explain them, but maybe there are also compelling examples without them today?)
One way to look for examples would be to look for uses of sig type t end
in OCaml codebases in the wild. Here is for example a Github search URL, I have not looked at the results much.
rfcs/type_arguments_for_modules.md
Outdated
This RFC proposes to extend a bit the module language by adding the possibility | ||
of giving types arguments to modules. | ||
|
||
The goal of this feature is to simplify replace cases where the user might want |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: to simplify cases
rfcs/type_arguments_for_modules.md
Outdated
``` | ||
|
||
|
||
## Important restraints |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
restrictions
rfcs/type_arguments_for_modules.md
Outdated
Only type paths should be authorized when doing an application inside | ||
a type path. | ||
|
||
In other words, `M(type <m: int>).t` should be rejected. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find the wording of this paragraph obscure. I'm not fully sure what you mean by "type path", and "inside a type path" is also not clear. I believe that you are talking about type-functor applications that show up inside type expressions: M(type foo).t
; but can you give more details on the restriction on foo
, for example by listing the allowed constructions?
(cc @yallop who may be interested in this feature) |
You can look at example also via this sherlocode search |
The counter example
is indeed a counter example if the compilation would not be compiled as a function.
|
I asume that the encoding is :
stand for
where |
This isn't clear to me. Have you considered the alternative of using a value restriction? In current OCaml, type arguments to functions, like this let f (type a) = ... don't have run-time representations, and type arguments to constructors, like this let f (T (type a) (x : a)) = ... don't have run-time representations, so it's a bit non-uniform for type arguments to modules to have run-time representations. Type arguments to functions don't delay evaluation let f (type a) = begin print_endline "ok" end (* prints "ok" *) so it's rather surprising if type arguments to modules do delay evaluation: module M (type a) = struct print_endline "ok" end (* prints nothing *) For type arguments to functions, the usual value restriction applies, so in the following, let f (type a) =
let r : a option ref = ref None in
... Could a similar approach work for type arguments to modules? Continuing the analogy, type arguments to functions don't need to be supplied explicitly (though perhaps it'd be useful to have the option to do so). Could a similar approach work for type arguments to modules? |
Side-note: I find it surprising that |
I was actually wondering the same as Jeremy. I understand that the proposal is just syntactic sugar for the encoding I proposed, hence the actual semantics. However, it might be more interesting to not make it syntactic sugar and restric the body to be a value form. If we chose this sematics and restriction, the actual behavior when the body is not a value form can be recovered by passing an extra empty structure |
In the case where we we want to keep the descripted semantic with explicit application by the user, we can remove the application if the functor is pure. Because all applications will give the same result thus it can be pre-computed. I think the proposal from @diremy of not handling this as syntactic sugar and restricting the body to be a value seems to be a good idea. The biggest argument being that we can still obtain the actual behavior by adding the argument that is currently added at runtime in the proposal.
I think we might have cases where being able to explicitly give the type argument is still beneficial. I agree that sometimes not writing that argument could increase concision (such as |
I don't think that handling this as an optional argument works well. Consider the case where you abstract over several type arguments in sequence, there is no way at application time to indicate which of the arguments you have in mind on explicit application. I'm of two minds regarding application expliciteness:
|
The propose syntax was to write |
I think that this is a question that is weighting on @diremy's mind. Note: Coq/Rocq allows the application syntax |
A proposed design for having types as module arguments.
Rendered version
In summary :