Functors are "functions" on modules. It's a kind of function that takes in a module as input, and spits out a module as output.
module type X = sig
val x : int
end
module A : X = struct
let x = 0
end
module type X = sig val x : int end
module A : X
What if we wanted to create a module that is the same as A, but it's x is one bigger. We can use a functor for this:
module IncX = functor (M : X) -> struct
let x = M.x + 1
end
module IncX : functor (M : X) -> sig val x : int end
Let's go through this
module means we're using module-level syntax. The functor means that we're creating a functor! The module value that it takes in is locally called M, and has signature X. This yields (->) the struct where x is equal to M.x + 1.
A.x
- : int = 0
module B = IncX(A);;
module B : sig val x : int end
B.x
- : int = 1
Now we've defined B, where B.x is one bigger than A.x. There is also syntactic sugar for the keyword functor:
module IncX(M : X) = struct
let x = M.x + 1
end
module C = IncX(B);;
C.x;;
module IncX : functor (M : X) -> sig val x : int end
module C : sig val x : int end
- : int = 2
OCaml's type checker requires you to specify the : X in the function definition. It cannot infer this
Note that you also don't need to seal the module to use it with a functor.
(note that type annotations are required).
module F (M1 : S1) ... (Mn : Sn) = struct
...
end
module F =
functor (M1 : S1)
-> ...
-> functor (Mn : Sn)
-> struct
...
end