I guess this is limited to functor-heavy code, which I’d venture most OCaml programmers don’t use, but it would become pervasive with modular implicits!
The problem is that you never know how your library is used. Your library may not contain any functors and just provide a single module
M. Now suppose that there is a user, that decided to parametrize his own library with the interfaces of yours, e.g.,
module type S = module type of M
module Make (Backend : S) : sig
This essentially makes
S a non-variant interface, as adding new fields to it will impose new requirements on Backends, and the downstream user needs to update their implementations. And removing a field will obviously break the API.
Thus my personal approach is to ignore the presence of the
module type of construct. If a module type is explicit, i.e., declared as a part of the interface with the
module type construct, then assume that it is non-variant and bump the version on any change. If the module interface is implicit (is not bound to a name) then I any subtype of it will have the same major version (i.e., I can add functions, data constructors, etc)