In other languages, I prefer to arrange source files so that simpler and more widely useful concepts are introduced before implementation details, and I try where possible to make complex implementation details top-level functions so that I can separate them out and let the main function read like a high-level algorithm description.
OCaml obviously has an interface/source distinction, but even with a sparse well-documented interface like
type t
(** Blah blah blah *)
val important_operator : t -> t -> t
(** Blah blah blah *)
I've been tempted to do things like
let rec important_operator a b =
let a', b' = foo a b in
let a', b' = iterate_until_convergence (=)
(fun (a, b) -> bar (baz a b))
(a', b') in
merge a', b'
(* Implementation details *)
and foo a b = ...
and bar x = ...
and baz a b = ...
and merge a b = ...
Is this poor style? Does it affect the ability of IDE-users to navigate source files?