Hi ! I’m wondering how can i forbid the creation of a module value implementing a certain module type ?
Lets say i have this module :
module type Admin = sig end
And an another module B which contain a function which take an Admin module in argument. I want that an Admin module can only be created inside the B module
If you describe a module type, then any module which has access to this description can implement modules satisfying the description.
But just like you can export a type as abstract and prevent users from creating new values of this type, you can export a module type as abstract and prevent other modules from actually creating new implementations.
Here is a concrete example:
(* lib.ml *)
(* Concrete definition *)
module type Admin = sig end
module B = struct
...
(* The signature of Admin is available *)
module Admin1 : Admin = struct end
end
(* lib.mli *)
(* Abstract type: impossible to instantiate from outside *)
module type Admin
module B : sig
(* Can still export existing implementations *)
module Admin1 : Admin
end
Note that if you want to allow B to instantiate Admin but forbid other modules at the same level as B from doing the same, you will have to move the declaration of the module type Admin inside B.
In particular, if you want B to be in its own .ml file and restrict other files from instantiating the Admin type then you need to either move Admin inside B or add an extra wrapper around both B and the module that defines Admin that makes Admin abstract.