Skip to content
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

support "let module rec ... in ..." #5955

Closed
vicuna opened this issue Mar 17, 2013 · 6 comments
Closed

support "let module rec ... in ..." #5955

vicuna opened this issue Mar 17, 2013 · 6 comments

Comments

@vicuna
Copy link

vicuna commented Mar 17, 2013

Original bug ID: 5955
Reporter: @gasche
Assigned to: @gasche
Status: resolved (set by @gasche on 2013-04-16T09:59:17Z)
Resolution: suspended
Priority: low
Severity: feature
Category: typing
Related to: #2720

Bug description

I don't think there is any reason to support local module definition, but not local recursive module definitions.

Additional information

module M : sig type t end = struct type t = int end;;

module M : sig type t end

module rec M : sig type t end = struct type t = int end;;

module rec M : sig type t end

let module M : sig type t end = struct type t = int end in ();;

  • : unit = ()

let module rec M : sig type t end = struct type t = int end in ();;

Error: Syntax error

Partial workaround:

let module A = struct

module rec M : sig type t end = struct type t = int end

end in
let module M = A.M in ();;

  • : unit = ()
@vicuna
Copy link
Author

vicuna commented Mar 24, 2013

Comment author: @xavierleroy

"There is no reason not to" does not imply "there exists a reason to". What is your reason?

Also, recursive module bindings, esp. mutually recursive ones, are heavy beasts, in the concrete syntax (must put signatures on names), in the abstract syntax, and esp. in the module type-checker. So please no gratuitous complications here.

@vicuna
Copy link
Author

vicuna commented Apr 10, 2013

Comment author: @alainfrisch

We already have a local counterpart of several kinds of structure items: let bindings, module binding, open. It would actually be quite useful to have local exceptions as well, allowing a more direct and slightly more efficient version of the following useful pattern:

type univ = exn

let foo (type t) () =
let module M = struct exception X of t end in
...
(fun x -> M.X x), (function M.X x -> Some x | _ -> None)

or simply to make it clear that an exception is local to a function and simplify escape analysis (e.g. to support a different compilation scheme).

I can also imagine uses of local type declarations (abbreviation and data type definitions) and local external primitive declarations (to make it clear that a primitive is only used locally).

So what about allowing in general a local version of structure items?

let STR_ITEM in ...

which would generalize (with the same syntax) the existing local open and local module construction. (For the local let-binding, we could allow the "let let p = e in e" form for uniformity while of course keeping the form with a single let). We could then also write:

let include(struct
let x = 1
let y = 2
end) in
...

which gives a slightly lighter syntax for long sequential let-bindings.

I don't think all this is very important, but it might actually simplify both the Parsetree (a single case Pexp_stritem instead of currently three constructors), the parser, and maybe even the type-checker, while making the language more regular. IMO, local exceptions would be really nice and other items (types, recursive modules) cute side-effects.

@vicuna
Copy link
Author

vicuna commented Apr 11, 2013

Comment author: @gasche

I like the generality of the proposal (I'm not sure Xavier will find the justifications he was expecting, but I do find the argument for more lightweight local exceptions convincing), but there are some dangling cases to worry about:

let class x = object end
and y = object end

@vicuna
Copy link
Author

vicuna commented Apr 11, 2013

Comment author: @alainfrisch

What's the issue with:

let class x = object end
and y = object end
in
...

?

@vicuna
Copy link
Author

vicuna commented Apr 16, 2013

Comment author: @gasche

meh.

(Alain: I saw a potential for confusion between the "and" of the class declaration and the "and" of the "let x = ... and y = ... in" feature, but it now occurs to me that this is not formally an ambiguity, even if you supported "let str_item and str_item and str_item" (a good idea imho), as long as you don't allow "let str_item and usual_let and ..." which is clearly insane.)

@vicuna vicuna closed this as completed Apr 16, 2013
@vicuna
Copy link
Author

vicuna commented Dec 20, 2014

Comment author: @garrigue

There is a better workaround for all these cases:

let module A = struct
module rec M : sig type t end = struct type t = int end
end in
let open A in ();;

If you want to add all these as syntactic sugar for the above, why not.
Direct support would mean extra work in the type checker, which seems overkill for such a simple abbreviation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants