(* module types are the module-level analogy of types *)
module type Eq = sig
type t
val eq : t -> t -> bool
end
(* struct is a module literal *)
module IntEq = struct
type t = int
let eq x y = x = y (* OCaml's (=) operator isn't parametric, hence Eq modules are useful for type-safety *)
end
(* module that takes a module! *)
module ListEq (ElementEq : Eq) = struct
type t = ElementEq.t list
let rec eq xs ys =
match (xs, ys) with
| ([], []) -> true
| (x :: xs', y :: ys') -> ElementEq.eq x y && eq xs' ys'
| (_, _) -> false
end
(* module application *)
module IntListEq = ListEq (IntEq)
let () =
print_endline (if IntListEq.eq [1; 2; 3] [1; 2; 4] then "true" else "false")