I’ve started using more and more .ml-only modules, with the following
patterns:
(* as usual *)
module type FOO = sig … end
(** The docs go here *)
let some_public_fun (x:a) (y:b) : c = …
open struct
module Foo = Imported_foo
exception Oops
(** Doc here too for LSP hover *)
let private_fun x y = …
end
let other_public_fun x y : unit =
try private_fun x y
with Oops -> false
cuts down on repetition for modules that are either:
- a lot of type definitions + auxiliary stuff (everything public)
- just a few public things at the end, the rest in
open struct … end
clearly marked as implementation details.