Opening of modules brings in too much into scope. In addition to the other proposals to create a lighter weight "import" mechanism for specific values (there's another issue for that), it would also be nice to have an "import fields" feature which brings in only the variant and record field labels of a module. You can try to achieve this by creating nested modules just for the type definitions, but it doesn't quite do what you want:
/* MyModule.re */
module Types = {
type layout = {
left: unitOfM,
top: unitOfM,
right: unitOfM,
bottom: unitOfM,
};
};
open Types;
let myValue = "hi";
/* YourModule.re */
open MyModule.Types;
/* Nice, we can see the labels and not `myValue` */
let x = {left: 0, right: 0, bottom: 0, top: 0};
/* Hmm, this sucks, we can see the type name */
type x = layout;
Feature:
Types module.One proposal:
/* MyModule.re */
type layout = {
left: unitOfM,
top: unitOfM,
right: unitOfM,
bottom: unitOfM,
};
let myValue = "hi";
/* YourModule.re */
import fields MyModule;
/* Nice, we can see the labels and not `myValue` */
let x = {left: 0, right: 0, bottom: 0, top: 0};
/* Awesome, not this will fail because we can't see the type definition either! */
/* type x = layout; */
Not yet answered: How this plays with .rei/.re files. Also, how does that change when we create a way for .re to pose as .rei.
In that proposal, you can in one shot bring in all the fields of all the records and variants defined in MyModule. But perhaps a better solution is more granular import of a single type's fields. It could be unified with a more general import syntax:
/* MyModule.re: */
type layout = {
left: unitOfM,
top: unitOfM,
right: unitOfM,
bottom: unitOfM,
};
let myValue = "hi";
/* YourModule.re: */
/* This would let you see the type name and its record fields */
import {type layout} from MyModule;
import {type layout, myValue} from MyModule;
/* Then you could import only the labels/fields if you wanted to,
* by saying you want to *import* the *import* of a type.
* This isn't quite that useful once we have full granularity of import */
import {import type layout} from MyModule;
/* Note: I'm using a destructing syntax for import */
https://github.com/whitequark/ppx_import is available for some inspiration if it helps.
Is this different than something like type layout = MyModule.layout? Just trying to understand, since I didn't see that called out here.
@Schmavery That creates an alias for the type but it doesn't bring the constructors for the type into scope.
In OCaml:
module Foo = struct
type t =
| A
| B
end
type foo = Foo.t
(* A and B are still not directly in scope, even though foo is an alias for Foo.t now *)
see also #627
Most helpful comment
@Schmavery That creates an alias for the type but it doesn't bring the constructors for the type into scope.
In OCaml: