Packaging, Style & Best Practices

46.1 Publishing to opam

Fill in dune-project metadata; dune build generates *.opam.

Tag a release: git tag 1.0.0 && git push --tags.

Use dune-release: dune-release tag && dune-release distrib && dune-release publish && dune-release opam pkg && dune-release opam submit.

A PR is opened against ocaml/opam-repository; CI checks it across platforms.

46.2 Formatting with ocamlformat

dune fmt formats the whole project. Commit the config so the team shares one style.

profile = default
version = 0.27.0
margin = 90

46.3 Naming conventions

values, functions Not_found, Some modules, functors String_map, Make UPPER or S ORDERED, S main type of a module

46.4 Idioms & best practices

Make illegal states unrepresentable with variants.

One main type t per module, functions take t first (or last for piping — be consistent).

Write .mli files; keep types abstract unless needed.

Prefer option/result over exceptions in public APIs; name raising variants _exn (find_exn).

Avoid catch-all _ patterns on your own variants so the compiler flags new cases.

Turn warnings into errors in dev; keep code warning-free.

Don't use open at top level except for well-known "prelude" modules.

**Use Fun.protect / with_* functions** for resources.

Avoid polymorphic equality on abstract types — provide equal.

Keep mutation local and hidden behind pure interfaces.

Use labeled arguments when two arguments have the same type (~src ~dst).

Document with odoc, test with expect tests and QCheck.

46.5 Common warnings to know

missing record fields in pattern unused match case unused for-loop index open shadows identifier unused record field missing .mli

46.6 Alternative standard libraries

Base / Core / Core_unix (Jane Street) — comprehensive, consistent, labeled APIs.

Containers — extends stdlib compatibly (CCList, CCHashtbl, ...).

Batteries — older extended stdlib.

Stdlib has grown a lot; for many projects it's sufficient.

open Core
let () =
  [1; 2; 3]
  |> List.map ~f:(fun x -> x * 2)
  |> List.fold ~init:0 ~f:( + )
  |> printf "%d\n"

46.7 Key libraries by domain

menhir, angstrom, sedlex (Unicode lexing), mparser owl, lacaml, zarith (bignums), gsl mirage-crypto, digestif, cryptokit, ocaml-tls containers, iter, saturn (lock-free), psq, lru alcotest, qcheck, ppx_expect, crowbar (fuzzing), mdx (doc tests) lablgtk3, bogue, raylib-ocaml, tsdl ptime, timedesc, calendar uutf, uucp, uunf, uuseg