Advanced Module System
Removes a type from a signature by replacing it:
30.1 Destructive substitution :=
Removes a type from a signature by replacing it:
module type S = sig type t val x : t end
module type S_int = S with type t := int (* sig val x : int end *)
module type S2 = sig include S with type t := string val y : int end30.2 module type of
module type LIST = module type of List
module MyList : sig
include module type of struct include List end
val sum : int list -> int
end = struct
include List
let sum = fold_left ( + ) 0
end30.3 Recursive modules
Classic use: a set of trees whose nodes contain sets of trees:
module rec Even : sig val check : int -> bool end = struct
let check n = n = 0 || Odd.check (n - 1)
end
and Odd : sig val check : int -> bool end = struct
let check n = n <> 0 && Even.check (n - 1)
endmodule rec Tree : sig type t = Node of string * TreeSet.t val compare : t -> t -> int end = struct
type t = Node of string * TreeSet.t
let compare = compare
end
and TreeSet : Set.S with type elt = Tree.t = Set.Make (Tree)30.4 Generative vs applicative functors
module F (X : sig end) = struct type t = int end (* applicative: F(A).t = F(A).t *)
module G () = struct type t end (* generative: each G () gives a fresh type *)
module Id1 = G ()
module Id2 = G ()
(* Id1.t and Id2.t are distinct types: useful for unique-token / capability patterns *)30.5 Higher-order functors
module Apply (F : functor (X : ORDERED) -> sig type t end) (X : ORDERED) = F (X)30.6 Module aliases & -no-alias-deps
module L = List costs nothing; dune uses aliases to implement library wrapping.
30.7 Signature design patterns
S / Make / Intf pattern: module type S = sig ... end plus module Make (X : Arg) : S with type t = X.t.
_intf.ml files (Jane Street style) for sharing signatures between .ml and .mli.
Comparable / Hashable mixins: functors adding compare, Map, Set to any type.
module type COMPARABLE = sig
type t
val compare : t -> t -> int
end
module Make_comparable (X : COMPARABLE) = struct
include X
let equal a b = compare a b = 0
let ( < ) a b = compare a b < 0
let max a b = if compare a b >= 0 then a else b
module Map = Map.Make (X)
module Set = Set.Make (X)
end30.8 Packing modules with type constraints
module type ID = sig type t val of_string : string -> t end
let m = (module struct type t = string let of_string s = s end : ID with type t = string)30.9 Modular implicits / type classes
OCaml has no type classes; emulate with explicit dictionary passing via first-class modules:
module type SHOW = sig type t val show : t -> string end
let show_list (type a) (module S : SHOW with type t = a) (l : a list) =
"[" ^ String.concat "; " (List.map S.show l) ^ "]"
let _ = show_list (module struct type t = int let show = string_of_int end) [1;2]