I wonder if any of the style guides supports using CamelCase for modules, to distinguish them from variant constructors? (If not, I’ll adapt.)
In case someone does use CamelCase for modules, do you name your files camelCase.ml, or CamelCase.ml? (Long ago, the latter was not allowed by the toolchain, but then it became allowed.)
I hope it is okay I bump this old thread. I have been confused about capitalization regarding modules and module types in OCaml. As far as I understand, they both must begin with a capital letter. However, there seems to be dissent about
whether modules should use CamelCase or Uppercase_with_underscores,
whether module types should use ALLCAPS_WITH_UNDERSCORES, CamelCase, or Uppercase_with_underscores.
Is it idiomatic to make my own style decisions in this matter?
I did some searches and found contradictory recommendations. Here are a few voices:
The official(?) OCaml Programming Guidelines at https://ocaml.org/docs/guidelines recommend in subsection How to Choose Identifiers to separate words by underscores(without explicitly mentioning whether this also applies to modules or module types):
“Separate words by underscores: […] capitalised words are reserved for constructors and module names. […] regular variables (functions or identifiers) must start with a lowercase letter. Those rules prevent proper usage of case modification for word separation in identifiers.”
“Module names […] idiomatically […] use CamelCase rather than Snake_case.”
By convention, module type names are usually CamelCase, like module names. So why did we use ALL_CAPS above […]? […] it’s perfectly valid to have a module named ListStack and a module type named ListStack. The compiler will not get confused […] But as a human you might well get confused […]."
The use of ALL_CAPS for module types was at one point common, and you might see it still. It’s an older convention from Standard ML. But the social conventions of all caps have changed since those days."
The OCaml Style Guide from the “CIS 3410/7000: Compilers” course (Spring 2024) of Penn Engineering (University of Pennsylvania) also recommends to use CamelCase (“embedded caps”) both for modules and module types, claiming that these are also followed by the OCaml library, and not mentioning the all-uppercase variant for module types:
“Module Types: Initial upper case. Use embedded caps for multiword names. [Example:] PriorityQueue”
“Modules: Same as module type convention. [Example:] PriorityQueue”
“[These] are the naming guidelines that are followed by the OCaml library”
OCaml Best Practices for Developers in the Xen Project wiki (last page revision from July 2013) recommends to use underscores in module and module type names (except when representing abbreviations/acronyms) and to use all uppercase for module types only if it does not hinder readability:
“Module identifiers require an initial capital letter and may use further capital letters to represent abbreviations/acronyms and underscores to separate words”
“Module type identifiers may be in upper-case, with underscores to separate words, but this is not mandatory. This style should only be used where it does not hinder readability”
The OCaml Guidelines from Hammerlab (last update January 2015) demand underscores and specifically state: “No CamelCase, ever”.
OCaml Towards Clarity and Grace (last update November 2023) contains some recommends in section Naming and Declarations, which are confusing to me. They seem to recommend camel case for module names (which they name “UpperCase”) and they distinguish between “signatures” and “module types” (which I thought are the same?) such that signatures should be camel case (referred to as “UpperCase”) and module types should be completely capitalized (ALLCAPS), not mentioning underscores.
“Modules: UpperCase”
“Signatures: UpperCase” (?)
“Module Types: ALLCAPS”
Looking into OCaml’s standard library (manual of version 5.4.0), I see both CamelCase and Uppercase_with_underscore for modules and CamelCase for module types, but I did not find any example of ALL_CAPSUppercase_with_underscore for module types:
The take away is that you want something predictable. My own strategy for that is to always downcase everything, acronyms included, separate words by _ and capitalize if mandated by the language (module name, constructor name) or uppercase for module types. That way I don’t need to think about capitalization when I devise a name or need to remember it.
Regarding the uppercase module types, some people think it screams too much (screaming examples here) I expect we are going to have style fights when module implicit/explicits quick in :–) Though if we use the M.S strategy (which to add confusion I sometimes write M.T, to mirror M.t) that may resolve by itself.
Not sure if I understand what the recommendation is here. Make a decision by myself and then stick to it in my own projects?
I.e. yes?
To me there doesn’t seem to be a consensus what to use, so I guess I’m free to do what I like.
I did notice, however, that file naming conventions become a bit odd with camel case, i.e. SomeModule will be expected in a someModule.ml file. Not sure how this behaves on systems with case-insensitive file systems, e.g. if you have two modules: NoBody and Nobody. On Windows, would these both be expected in a file named NOBODY.ML (case insensitive)?
Not at all! The compiler will look for a file named SomeModule.ml first, then try someModule.ml.
The support for file names starting with a lowercase letter was introduced in the very early days of OCaml (when it was called Caml Special Light, actually), to ease transition from Caml Light, and stuck around because many users are lazy with the Shift key. But I think it makes more sense to use SomeModule.ml file names that match the capitalization of the module name.
Oh, I somehow missed that. Thanks for letting me know. Interestingly, looking into the OCaml stdlib source code here, I do see the use of lowercase filenames. I guess it can be handy to have ALLCAPS files such as GUIDELINES.md or other capitalized file names like Makefile to appear at the beginning of a listing, followed by all regular modules.
But this is still not clear to me:
Do I have to avoid distinguishing module names only by capitalization? This would (in theory) be an argument against CamelCase because NoBody and Nobody couldn’t coexist (when using modules in seperate files on a case-insensitive file system), but No_body and Nobody could.