-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Allow to define explicit "impure" (i.e. generative) functors #5905
Comments
Comment author: @alainfrisch I agree it would be very nice to have generative functors in addition to transparent ones. But why should this notion require a "dummy" argument? It is quite common to have functors taking a non-trivial argument, which should be generative (typical example: a hash-consing functor). I'd rather have a different kind of functors (unfortunately, this requires more innovation on the syntactic side than your proposal). Also, generative functors enable something very useful: unpacking of first-class modules within/as the functor body. This can be used, for instance, to choose at runtime between two implementations of the functor, based on some condition. With runtime types (or a manual version based on GADTs), it is even possible to customize the functor's behavior according to the structure of the abstract types in the argument (example: implement sets as Patricia trees if the elements are integers). Would your proposal make this possible for generator functors? |
Comment author: @garrigue The idea of using a "dummy" argument is that it requires no new syntax (or very little). The discussion should rather be: since generativeness is a property of functors, is it useful to mark it in functor applications. I believe that this is the case, as this is the application, not the functor, that behaves differently. I have also updated the patch so that it is now possible to unpack first class modules inside impure functors: module type S = sig val x : int end;; |
Comment author: @garrigue Fixed the patch: if we are to allow unpacking inside impure functors, then we should not allow applying them inside an applicative body... |
Comment author: @garrigue Fixed the patch again: one cannot coerce an impure functor into an applicative one. |
Comment author: @alainfrisch FWIW, I believe that extending the language with generative functors would indeed be very useful, especially if it allows to unpack first-class modules in their body. |
Comment author: @alainfrisch Now that 4.01 is branched, what about including the patch in the trunk? It seems nobody objects to it, and there are at least two supporters. |
Comment author: @alainfrisch Jacques: do you think your patch is ready for inclusion, or are you aware of some problems with it? |
Comment author: @garrigue I don't recall any problem, but of course I would check everything again before inclusion. |
Comment author: @lpw25 An example that should be prevented: module F () : sig type t end = struct module M = (val ...) type t = M.t end module G (X : struct end) : sig type t end = struct module N1 = G(X) where This would have N1.t equal to N2.t even though they may be different types (because they come from unpacking a first-class module). |
Comment author: @garrigue This is already taken care of: module type S = sig val x : int end module G (X : sig end) : S = F ();;Error: This kind of expression is only allowed inside impure functors. |
Comment author: @lpw25 This idea is only half-baked, but I was wondering if the same mechanism could be used to express functors that are only used for their side-effects. Something like: module F (X : sig ... end) : () = struct module () = F(Foo) so the functor is given module M = F(Foo) similarly, ignoring the result of a normal functor would be an error: module () = Map.Make(List) Note that since these side-effect only functors can not create any types, I think they can safely be used within an applicative functor even if they are "impure". |
Comment author: @garrigue I'm not sure we need new syntax for the return type part. |
Comment author: @garrigue Patch merged to trunk at revision 14365. |
Original bug ID: 5905
Reporter: @garrigue
Assigned to: @garrigue
Status: closed (set by @xavierleroy on 2016-12-07T10:47:25Z)
Resolution: fixed
Priority: normal
Severity: feature
Version: 4.01.0+dev
Target version: 4.01.1+dev
Fixed in version: 4.02.0+dev
Category: typing
Tags: patch
Related to: #6821
Monitored by: bobot @hcarty @mmottl
Bug description
For some applications, not having the possibility to declare a functor as generative is a problem.
For instance when you define a global map through a functor
module DB : functor (X : struct end) -> sig
type key
let new_key : unit -> key
let write : key -> string -> unit
let read : key -> string
end
module MyDB = DB(struct end)
The above works fine (i.e. keys are restricted to a single DB) as long as nobody writes the following code:
module DB1 = DB(String)
module DB2 = DB(String)
which makes DB1.key and DB2.key equal.
The problem is that to my best knowledge there is no workaround.
My proposal is a rather stupid one: add some syntax for impure functors,
that are not using their argument, but must be generative.
module DB () = ...
module DB = functor () -> ...
module M = DB ()
module DB : functor () -> ...
Simplest implementation: all this is just syntactic sugar for an argument of name "*" and of type "sig end", and forcing the functor application to be generative in that case.
Patch included.
The text was updated successfully, but these errors were encountered: