OCaml Cheat Sheet
Practical OCaml syntax covering let bindings, pattern matching, lists, and algebraic data types like records, variants, and options.
Bindings & Functions
let bindings and function definitions with type inference.
let x = 10let square x = x * xlet add a b = a + blet () = print_endline "Hello, World!"; Printf.printf "Square: %d\n" (square 5)(* explicit type annotations *)let divide (a : float) (b : float) : float = a /. b
Pattern Matching
match expressions and guards.
let describe n = match n with | 0 -> "zero" | n when n > 0 -> "positive" | _ -> "negative"let rec length = function | [] -> 0 | _ :: tail -> 1 + length tail
Lists & Common Functions
Building and transforming immutable lists.
- [1; 2; 3]- list literal syntax, elements separated by semicolons
- 1 :: [2; 3]- cons operator, prepends an element
- lst1 @ lst2- concatenates two lists
- List.map f lst- applies f to each element, returns a new list
- List.filter p lst- keeps elements where predicate p is true
- List.fold_left f acc lst- reduces the list to a single value
- List.length lst- number of elements in the list
- List.iter f lst- applies f to each element for side effects only
Records, Variants & Options
OCaml's algebraic data types.
type point = { x : float; y : float }let p = { x = 1.0; y = 2.0 }type shape = | Circle of float | Rectangle of float * floatlet area = function | Circle r -> 3.14159 *. r *. r | Rectangle (w, h) -> w *. hlet safe_div a b = if b = 0 then None else Some (a / b)match safe_div 10 2 with| Some v -> Printf.printf "%d\n" v| None -> print_endline "division by zero"
Modules & Functors
Signatures, module implementations, and parameterized modules.
module type ORDERED = sig type t val compare : t -> t -> intendmodule MakeSet (O : ORDERED) = struct type elt = O.t let contains x lst = List.exists (fun y -> O.compare x y = 0) lstendmodule IntSet = MakeSet (struct type t = int let compare = compareend)
Exceptions & Result
Idiomatic error handling with option, result, and exceptions.
let safe_div a b = if b = 0 then Error "divide by zero" else Ok (a / b)let () = match safe_div 10 2 with | Ok v -> Printf.printf "%d\n" v | Error e -> prerr_endline eexception Not_found_key of stringlet lookup k = try List.assoc k [("a", 1)] with Not_found -> raise (Not_found_key k)
Common Standard Library
Frequently used modules and functions from Stdlib.
- List.map / List.filter / List.fold_left- transform, select, and reduce lists
- Option.map / Option.value- work with 'a option without pattern matching
- Printf.printf / Printf.sprintf- type-checked formatted output and string building
- Hashtbl.create / add / find_opt- mutable hash tables with optional lookup
- Array.make / Array.iteri- fixed-size mutable arrays with indexed iteration
- String.concat / String.split_on_char- join and split strings
- |> and @@- pipe-forward and application operators for readable chains
Mutable State: refs, records, arrays
Controlled mutation with ref cells and mutable record fields.
let counter = ref 0incr counter; (* counter := !counter + 1 *)let n = !counter in (* dereference *)type account = { mutable balance : int }let a = { balance = 100 }a.balance <- a.balance - 30;let arr = Array.make 3 0 inarr.(0) <- 42;ignore (n, arr)
Let the type inferencer do the work — annotate only function signatures for public modules (in the .mli file), not every local let binding; over-annotating makes refactors noisier without adding safety.