# OCaml implementation ## Source of truth - `.mli` files are the specification and outrank tests. - If an interface and a test disagree, fix the test. - Changing an interface is a deliberate design decision — raise it, don't drift into it. ## Style - Modern, idiomatic OCaml. Favour the principle of least surprise: a reader should not need to learn a local idiom to follow the code. - Prefer readable, shallow code. A flat sequence a reader can follow top to bottom beats a deeply nested tower of `match` arms. - Reach for `let*` when it flattens nested cases — chained `result` or `result Lwt.t` plumbing where each step short-circuits on error. Used this way, a bind improves flow and cuts indentation. - A single `match` is clearer than a monad; don't reach for one reflexively. - Two or three cascading `match ... with Error _ -> ... | Ok x -> ...` steps are the signal to switch to `let*`. - Abstract types with smart constructors for anything carrying an invariant. - Use `result` for expected, recoverable failure. - This includes converting untrusted external data and domain feedback a caller can present or recover from. - Each module defines its own errors; no shared catch-all error type or `string` errors. - Raise a module-specific exception for a violated authored-plan precondition after validation. - Do not use exceptions for normal domain outcomes or recorded deviations. - Prefer closed variants — they keep `match` exhaustiveness working for you. - Total functions where practical; make partiality visible in the type. ## Layering Three libraries, dependencies pointing inward only: - `hito.core` — pure domain. No framework, database, or serialization dependencies. Ever. - `hito.app` — `Repository` port, `Service`, adapters. Knows nothing of Dream. - `hito.web` — Dream application. The only place Dream and dream-html appear. Rules: - Ports are module types; adapters implement them. - Persistence identity is assigned in `hito.app`, not in the core.