Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0005460OCamlOCaml generalpublic2012-01-03 04:472013-11-29 13:00
Reporterhcarty 
Assigned Togarrigue 
PrioritynormalSeverityfeatureReproducibilityalways
StatusassignedResolutionopen 
PlatformOSOS Version
Product Version3.12.1 
Target VersionFixed in Version 
Summary0005460: Request: Replace/rename/remove module types
DescriptionAs of the 3.12.x releases, we can replace types (... with type t := t') and remove modules (... with module M := M) in module signatures. It would be useful to be able to do the same thing with module types.
Steps To Reproduce(* This works - module H will not have a Make module in it *)
module H = struct
  include (Hashtbl : module type of Hashtbl with module type S := Hashtbl.S)
end

(* In the toplevel (both 3.12.1 and 3.13.0+dev8) this fails with:
   "Syntax error: ')' expected, the highlighted '(' might be unmatched"
   on "type" in "... with module type S ..." *)
module type S' = sig type t end
module H = struct
  include (Hashtbl : module type of Hashtbl with module type S := S')
end
Additional InformationThis would be useful when extending modules, particularly ones which provide functors and matching signatures.
Tagspatch
Attached Fileslog file icon ocamlbrew.wrMNQO.log [^] (181,292 bytes) 2012-01-13 22:36
? file icon with-module-type.diffs [^] (21,675 bytes) 2013-07-29 10:16

- Relationships
has duplicate 0006209closedgasche Cannot override module types 
related to 0005514acknowledged "with module" semantics seem broken 

-  Notes
(0006586)
garrigue (manager)
2012-01-04 07:51

I'm not sure I understand the intended semantics.
The constructs with type t := ... and with module M := ... just replace t and M by the corresponding definitions, but you seem to imply that "with module type S := ..." should also remove modules and functors containing S in their signature.
I don't think this new approach would make sense: since module types are purely structural, there is no way to distinguish S from its definition.

Concerning the possibility to substitute a module type, I see no reason it wouldn't be possible.
Note however that this is actually two new constructs:
  with module type S = ...
  with module type S := ...
I don't see why we should have the second without the first.
(0006591)
hcarty (reporter)
2012-01-04 15:15

I would be quite happy with those two new "with module type" constructs. I don't see any reason why only one or the other should be added.

For some clarification on the original request - "with type t := t'" does replace t with t', but "with module M := M" (where both M modules are the same) removes that module from the signature:

module H = struct
  include (Hashtbl : module type of Hashtbl with module Make := Hashtbl.Make)
end

I apologize - looking back at the original post, this is the code I meant to include as the first example. The H module will now be just like Hashtbl, except that there is no H.Make module included.

I don't know if removal makes sense for a module type any more than it does for a normal type. There may be situations where it is useful, but being able to substitute a module type seems more useful.
(0006635)
garrigue (manager)
2012-01-10 05:24

I implemented the above features experimentally in trunk/experimental/garrigue/with-module-type.diffs
The two syntaxes are available (= and :=), and the right hand side may be any module type.

Your example goes through modulo an instantiation of "statistics":

module H = struct
  include (Hashtbl : module type of Hashtbl with
           type statistics = Hashtbl.statistics
           and module type S := Hashtbl.S)
end

Could you try it and verify that it does what you expect?
(0006639)
hcarty (reporter)
2012-01-10 15:09

I tried to build trunk with this patch applied but I received an error. I can attach the entire build log if that would be helpful.

cd tools; make all
make[2]: Entering directory `/home/hcarty/ocamlbrew/mod-diff/build/build/tools'
../boot/ocamlrun ../boot/ocamlc -strict-sequence -nostdlib -I ../boot -c -warn-error A -I ../utils -I ../parsing -I ../typing -I ../bytecomp -I ../asmcomp -I ../driver depend.mli
../boot/ocamlrun ../boot/ocamlc -strict-sequence -nostdlib -I ../boot -c -warn-error A -I ../utils -I ../parsing -I ../typing -I ../bytecomp -I ../asmcomp -I ../driver depend.ml
File "depend.ml", line 181, characters 8-261:
Warning 8: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
(_, (Pwith_modtype _|Pwith_modtypesubst _))
File "depend.ml", line 1:
Error: Error-enabled warnings (1 occurrences)
make[2]: *** [depend.cmo] Error 2
make[2]: Leaving directory `/home/hcarty/ocamlbrew/mod-diff/build/build/tools'
make[1]: *** [ocamltools] Error 2
make[1]: Leaving directory `/home/hcarty/ocamlbrew/mod-diff/build/build'
make: *** [world.opt] Error 2
(0009678)
hcarty (reporter)
2013-07-02 17:15

Is there any chance that this could be updated and applied to 4.01 before release? If not, is there an updated patch to test against trunk?
(0009974)
garrigue (manager)
2013-07-29 10:19

I have uploaded (and committed in trunk/experimental/garrigue) a new patch that applies to current trunk and 4.01.
Note that this is a patch for the compiler only, not other tools.
So you should just do "make ocamlc ocaml".

I want this included, I suppose that some lobbying is needed.
Are there other useful examples, where this is not only used to delete components?
(0009976)
hcarty (reporter)
2013-07-29 12:36

It would be useful any time you want to extend a module type. For example, a module type defining the output of a functor. Adding anything to a MyHashtbl.S module type without this patch requires either having duplicate signatures (module MyHashtbl = struct include Hashtbl module type S' = sig include S ... end ... end) or copying and pasting the contents of S to a new file and modifying the result.

In the first case the original S still exists in MyHashtbl which is confusing for someone using the module. In the second case there is a lot of code duplication which would be useful and safer to avoid.
(0009993)
gasche (developer)
2013-07-29 18:39

I suspect it a bit late to be applied to the release branch (at this point, it would be better if only fixes that do not break things are applied to parts as sensible as the type-checker). But Jacques, I don't see any reason *not* to apply it to trunk if this is a feature that you want -- you are, after all, the type-system maintainer. It seems to me that it adds regularity to the module/interface language, which is a very good thing.
(0010005)
garrigue (manager)
2013-07-30 01:43
edited on: 2013-07-30 01:48

There was a typo in my note: "I want" -> "If you want".
And to clarify things: as maintainer of the type checker, my job is to fix bugs, but not to add features without first discussing it with other maintainers.
Also, this is too late for 4.01 (but not for 4.02).

Now, on this specific one, my main concern is that the only application example seems to be Hashtbl.
Namely, when a module contains both a direct and a functorial interface, this is needed to fully discard the functor part. I agree that copying the signature by hand is a pain, but adding a feature only for making easier extending one specific module in the standard library seems far-fetched.
This would be more interesting if there were examples using abstract signatures; i.e. substitution, not only removal. Or just demonstrating that this pattern is common enough.

It is also useful to understand better the original role of "with". Namely, it was only intended to allow turning abstract types into type abbreviations. In particular the semantics of "with module" was just to do it for all types in the module (there was no module substitution involved). The introduction of ":=" changed that a bit, as the module is now substituted (in functor applications). However handling module types is another story, so adding it is really an extension, not just adding some "forgotten" case, albeit the code is almost trivial.

To be clear, I'm not at all opposed to this feature, and I do think that it makes sense, but I would like to see more examples before committing to it.

(0010010)
hcarty (reporter)
2013-07-30 19:06

BatMap and BatSet from Batteries are two more examples. It looks like the equivalent modules in Core are too.
(0010036)
garrigue (manager)
2013-07-31 07:01

Actually, the BatMap and BatSet modules have no such problem, since they define respectively a PMap and a PSet submodule, whose interface can be used for this purpose.

So an alternative proposal would be to add such a submodule in Hashtbl too.
I suppose it is useful for other things too.
(0010037)
garrigue (manager)
2013-07-31 07:06

Or maybe you meant that adding removal for module types would completely avoid the need for those extra submodules. But we need to be sure that removal is not too cumbersome, and that those submodules are not needed for anything else.
(0010519)
jpdeplaix (reporter)
2013-10-19 11:52

I've two more (similar) examples:
- I wanted to do a Exceptionless « pack » module for batteries. So for example, it's easy for BatArray as a:
  module Array = struct
    include BatArray
    include BatArray.Exceptionless
  end
But some modules contains module signature with an Exceptionless module (BatMap, BatSet, BatHashbtl, …) and I can't override this module type (easily) without this feature.

- The other example is similar: I have a library that provides exception monads and I want a wrapper for the stdlib. So there is the same problems with almost the same modules (Map, Set, …).

- Issue History
Date Modified Username Field Change
2012-01-03 04:47 hcarty New Issue
2012-01-04 07:39 garrigue Assigned To => garrigue
2012-01-04 07:39 garrigue Status new => assigned
2012-01-04 07:51 garrigue Note Added: 0006586
2012-01-04 07:51 garrigue Status assigned => feedback
2012-01-04 15:15 hcarty Note Added: 0006591
2012-01-04 15:15 hcarty Status feedback => assigned
2012-01-10 05:24 garrigue Note Added: 0006635
2012-01-10 05:24 garrigue Status assigned => feedback
2012-01-10 15:09 hcarty Note Added: 0006639
2012-01-10 15:09 hcarty Status feedback => assigned
2012-01-13 22:36 hcarty File Added: ocamlbrew.wrMNQO.log
2012-03-07 08:26 garrigue Relationship added related to 0005514
2013-07-02 17:15 hcarty Note Added: 0009678
2013-07-29 10:16 garrigue File Added: with-module-type.diffs
2013-07-29 10:19 garrigue Note Added: 0009974
2013-07-29 12:36 hcarty Note Added: 0009976
2013-07-29 18:39 gasche Note Added: 0009993
2013-07-30 01:43 garrigue Note Added: 0010005
2013-07-30 01:43 garrigue Status assigned => feedback
2013-07-30 01:48 garrigue Note Edited: 0010005 View Revisions
2013-07-30 19:06 hcarty Note Added: 0010010
2013-07-30 19:06 hcarty Status feedback => assigned
2013-07-31 07:01 garrigue Note Added: 0010036
2013-07-31 07:06 garrigue Note Added: 0010037
2013-10-19 11:00 lpw25 Relationship added has duplicate 0006209
2013-10-19 11:52 jpdeplaix Note Added: 0010519
2013-11-29 13:00 doligez Tag Attached: patch


Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker