Reading — step 1 of 5
Learn
In OCaml, functors are modules that take other modules as parameters. ML's type-class equivalent — but earlier and arguably more powerful.
module type COMPARABLE = sig
type t
val compare : t -> t -> int
end
module Make_set (Item : COMPARABLE) = struct
type elem = Item.t
type t = elem list
let empty = []
let add x s = if List.exists (fun y -> Item.compare x y = 0) s then s else x :: s
let mem x s = List.exists (fun y -> Item.compare x y = 0) s
let size = List.length
end
The Make_set is a functor — it takes a module satisfying COMPARABLE, returns a new module providing set operations.
Apply the functor:
module IntCompare = struct
type t = int
let compare = compare (* polymorphic compare *)
end
module IntSet = Make_set (IntCompare)
let s = IntSet.empty
let s = IntSet.add 5 s
let s = IntSet.add 3 s
let s = IntSet.add 5 s (* dup, ignored *)
IntSet.size s (* 2 *)
IntSet.mem 3 s (* true *)
The standard library's Map.Make and Set.Make are functors:
module StringMap = Map.Make (String)
module IntSet = Set.Make (Int)
String and Int already implement OrderedType (the type expected). The Map/Set is parameterized by HOW the type orders.
Functors give:
- Compile-time generic structures (no runtime polymorphism cost)
- Different orderings/comparisons per instantiation (case-insensitive vs case-sensitive strings)
- Modular design — algorithm vs data plumbing separated
Functor with multiple modules:
module type S = sig type t val zero : t val (+) : t -> t -> t end
module Sum_pair (A : S) (B : S) = struct
type t = A.t * B.t
let zero = (A.zero, B.zero)
let (+) (a1, b1) (a2, b2) = A.(a1 + a2), B.(b1 + b2)
end
Functors are how OCaml libraries scale — Jane Street's Core is built on a deep functor hierarchy (Comparable, Hashable, Sexpable, etc.).
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…