Option & Result

13.1 option — a value that may be absent

Option module:

type 'a option = None | Some of 'a

let safe_div a b = if b = 0 then None else Some (a / b)

let rec find p = function
  | [] -> None
  | x :: xs -> if p x then Some x else find p xs

match safe_div 10 2 with
| Some v -> Printf.printf "Result: %d\n" v
| None -> print_endline "Division by zero"
Option.map (fun x -> x * 2) (Some 3)       (* Some 6 *)
Option.bind (Some 3) (fun x -> safe_div 12 x)  (* Some 4 *)
Option.value ~default:0 None               (* 0 *)
Option.get (Some 1)                        (* 1 — raises on None *)
Option.is_some, Option.is_none
Option.iter print_endline (Some "x")
Option.fold ~none:0 ~some:succ (Some 1)    (* 2 *)
Option.to_list (Some 1)                    (* [1] *)
Option.join (Some (Some 1))                (* Some 1 *)

13.2 result — success or a typed error

Result module:

Chaining with bind:

(Better syntax with let* in §33.)

type ('a, 'e) result = Ok of 'a | Error of 'e

type parse_error = Empty | Not_a_number of string | Negative of int

let parse_age s : (int, parse_error) result =
  if s = "" then Error Empty
  else match int_of_string_opt s with
    | None -> Error (Not_a_number s)
    | Some n when n < 0 -> Error (Negative n)
    | Some n -> Ok n
Result.map, Result.bind, Result.map_error
Result.value ~default, Result.get_ok, Result.is_ok
Result.to_option, Result.join, Result.fold ~ok ~error
let ( >>= ) = Result.bind

let validate s =
  parse_age s >>= fun age ->
  if age > 150 then Error (Negative age) else Ok age

13.3 When to use what

"Not found" is normal Caller must handle a described failure Truly exceptional / programming error Fast local control flow exception (cheap in OCaml)