| Anonymous | Login | Signup for a new account | 2013-06-20 12:23 CEST | ![]() |
| Main | My View | View Issues | Change Log | Roadmap |
| View Issue Details [ Jump to Notes ] | [ Issue History ] [ Print ] | ||||||||||
| ID | Project | Category | View Status | Date Submitted | Last Update | ||||||
| 0005480 | OCaml | OCaml general | public | 2012-01-17 10:00 | 2012-01-23 11:48 | ||||||
| Reporter | frisch | ||||||||||
| Assigned To | |||||||||||
| Priority | normal | Severity | feature | Reproducibility | have not tried | ||||||
| Status | acknowledged | Resolution | open | ||||||||
| Platform | OS | OS Version | |||||||||
| Product Version | |||||||||||
| Target Version | Fixed in Version | ||||||||||
| Summary | 0005480: Compilation units as recursive modules | ||||||||||
| Description | A compilation unit X with an implementation x.ml and an interface x.mli is morally interpreted as the following declaration: module X : sig [content of x.mli] end = struct [content of x.ml] end What about interpreting it instead as a recursive module declaration: module rec X : sig [content of x.mli] end = struct [content of x.ml] end This would make it possible to refer, in x.ml, to components defined further down in the same file and even to structural types (and class types, module types) defined in x.mli to avoid code duplication. | ||||||||||
| Tags | No tags attached. | ||||||||||
| Attached Files | |||||||||||
Notes |
|
|
(0006700) hcarty (reporter) 2012-01-17 19:05 |
This is an interesting proposal. What effect would this have on redefined values? For example: x.mli: val f : int -> int val g : int -> int x.ml: let g x = x + 1 let f x = g x let g x = x + 2 Which g is f using in your proposed case? Should one expect it to be the g exposed in the .mli or the g defined prior to f? Would "include X" be required at the top of x.ml to see types only defined in x.mli, or types/values defined later in the module? |
|
(0006701) frisch (developer) 2012-01-17 21:11 |
Scoping rules would be the same as for the "module rec" expansion. To refer to a definition further down in the module, you need to prefix with the module name explicitly. In your example, "f" uses the first "g". To use the second one, you would write "X.g". |
|
(0006712) hcarty (reporter) 2012-01-17 23:49 |
Under 3.12.1: module rec X : sig type t = A | B | C val f : t -> string val g : t -> string end = struct type t = A | B | C let f = X.g let g = function A -> "a" | B -> "b" | C -> "c" end X.(f A) raises an Undefined_recursive_module exception. Would this still be the case under your proposal if X is split into x.ml and x.mli? If t is not included fully in both the sig and struct sections then g fails with a compilation error. Would this duplication requirement change under your proposal? |
|
(0006713) gasche (developer) 2012-01-17 23:56 edited on: 2012-01-17 23:57 |
Note that you can remove the exception by eta-expanding f: let f x = X.g x The idea is that, under a backpatching semantics, "let f = X.g" would force X at definition time, which results in an undefined function `f`, while "let f x = X.g" only accesses X.g at `f` application time, which is after the X module has been fully built. See the manual for more details: http://caml.inria.fr/pub/docs/manual-ocaml/manual021.html#toc75 [^] |
|
(0006714) frisch (developer) 2012-01-18 07:24 |
It could be useful to improve the compilation strategy for recursive modules so as to cover more cases, but this is rather independent from the proposal. Concerning the duplication of type declarations: currently, recursive modules makes it possible to avoid duplication of structural type elements. For instance, your example with polymorphic variants. Or the following: module rec X : sig module type S = sig type t = A | B | C end include S end = struct module type S = X.S module rec Y : S = Y include Y end One could also consider adding a "type-include" mechanism, that would allow to write: module rec X : sig type t = A | B | C end = struct include type X.t end |
|
(0006766) lefessan (developer) 2012-01-22 22:51 |
I submitted a patch a while ago to improve the compilation strategy for recursive modules (0005286). Without this patch, I think a lot of programs would not compile if all units were recursive by default. Have you tried to compile some non-trivial applications with this patch ? |
|
(0006768) frisch (developer) 2012-01-23 09:07 |
Fabrice, unfortunately, I haven't tried your patch. At LexiFi, we have used a simpler form of the proposal for some time; in our version, compilation units are type-checked as recursive modules (which allows nice type-level forward references and references from the implementation to the interface) but compiled as usual (compile-time error if we use module recursion to refer to a dynamic component). |
|
(0006770) xleroy (administrator) 2012-01-23 11:48 |
I know for a fact that recursive modules in OCaml are a bit of a hack, in that the typechecking is incomplete and the compilation can fail at run-time in rather mysterious ways. That's tolerable as long as recursive modules are clearly marked as an experimental language extension. But I'm extremely wary of putting them at the heart of OCaml, so to speak, namely in the processing of compilation units. That's just calling for major trouble. |
Issue History |
|||
| Date Modified | Username | Field | Change |
| 2012-01-17 10:00 | frisch | New Issue | |
| 2012-01-17 19:05 | hcarty | Note Added: 0006700 | |
| 2012-01-17 21:11 | frisch | Note Added: 0006701 | |
| 2012-01-17 23:49 | hcarty | Note Added: 0006712 | |
| 2012-01-17 23:56 | gasche | Note Added: 0006713 | |
| 2012-01-17 23:57 | gasche | Note Edited: 0006713 | View Revisions |
| 2012-01-18 07:24 | frisch | Note Added: 0006714 | |
| 2012-01-22 22:51 | lefessan | Note Added: 0006766 | |
| 2012-01-23 00:27 | gasche | Status | new => acknowledged |
| 2012-01-23 09:07 | frisch | Note Added: 0006768 | |
| 2012-01-23 11:48 | xleroy | Note Added: 0006770 | |
| Copyright © 2000 - 2011 MantisBT Group |