Is this use of (let ... and ...) in OCaml poor style? 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 -&gt; t -&gt; 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) -&gt; 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?
It's not idiomatic OCaml indeed.


"and" is an effective way to say "watch out for mutual recursion".
OCaml encourages you to use nested functions instead! As The Structure of OCaml programs says: "Nested functions are, however, very useful and very heavily used in OCaml."


You would write this code as follows:

let important_operator a b =
  let foo a b = ... in
  let bar x = ... in
  let baz a b = ... in
  let merge a b = ... in
  let a', b' = foo a b in
  let a', b' = iterate_until_convergence (=)
                 (fun (a, b) -&gt; bar (baz a b))
                 (a', b') in
  merge a', b'


Of course, you don't need to only use nested functions, you can also define bar or baz before defining important_operator. OCaml tends to only use functions that were defined "earlier", so using and for this is abusing the system.