Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0005955OCamlOCaml typingpublic2013-03-17 17:202014-12-20 04:38
Assigned Togasche 
PlatformOSOS Version
Product Version 
Target VersionFixed in Version 
Summary0005955: support "let module rec ... in ..."
DescriptionI 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 = ()
TagsNo tags attached.
Attached Files

- Relationships
related to 0002720closedgarrigue Local, recursive modules 

-  Notes
xleroy (administrator)
2013-03-24 15:29

"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.
frisch (developer)
2013-04-10 22:35

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.
gasche (developer)
2013-04-11 09:30

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
frisch (developer)
2013-04-11 11:57

What's the issue with:

let class x = object end
    and y = object end

gasche (developer)
2013-04-16 11:59


(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.)
garrigue (manager)
2014-12-20 04:38

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.

- Issue History
Date Modified Username Field Change
2013-03-17 17:20 gasche New Issue
2013-03-24 15:29 xleroy Note Added: 0009006
2013-03-24 15:29 xleroy Status new => feedback
2013-04-10 22:35 frisch Note Added: 0009078
2013-04-11 09:30 gasche Note Added: 0009080
2013-04-11 09:30 gasche Status feedback => new
2013-04-11 11:57 frisch Note Added: 0009082
2013-04-16 11:59 gasche Note Added: 0009133
2013-04-16 11:59 gasche Status new => resolved
2013-04-16 11:59 gasche Resolution open => suspended
2013-04-16 11:59 gasche Assigned To => gasche
2013-07-27 07:47 gasche Relationship added related to 0002720
2014-12-19 15:19 whitequark Relationship added related to 0006728
2014-12-19 15:20 whitequark Relationship deleted related to 0006728
2014-12-20 04:38 garrigue Note Added: 0012896

Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker