module <name> =
struct
..
end;;
module type <name> =
struct (* should have been sig *)
..
end;;
views:
33answers:
3module type describe a module. It is the same as the difference between .ml and .mli
The first declares a module and the second declares a module type (aka a signature). A module type contains type
and val
declarations, whereas a module can contain definitions (e.g., let
bindings). You can use a signature to restrict the type of a module, much as you might for a function. For example,
module type T = sig
val f : int -> int
end
module M : T = struct
let f x = x + 1
let g x = 2 * x
end
Now, we have
# M.f 0 ;;
- : int = 1
# M.g 0 ;;
Error: Unbound value M.g
M.g
is unbound because it's hidden by the signature T
.
Another common way to use module types is as arguments to and return values of functors. For example, the Map.Make
functor in the standard library takes a module with signature Map.OrderedType
and creates a module with signature Map.S
P.S. Note that there's a mistake in the question. A module type is declared using
module type <name> = sig
...
end
A structure (written struct … end
) is a bunch of definitions. Any object in the language can be defined in a module: core values (let x = 2 + 2
), types (type t = int
), modules (module Empty = struct end
), signatures (module type EMPTY = sig end
), etc. Modules are a generalization of structures: a structure is a module, and so is a functor (think of it as a function that takes a module as argument and returns a new module). Modules are like core values, but live one level above: a module can contain anything, whereas a core value can only contain other core values¹.
A signature (written sig … end
) is a bunch of specifications (some languages use the term declaration). Any object in the language can be specified in a module: core values (val x : int
), types (type t = int
), modules (module Empty : sig end
), signatures (module type EMPTY = sig end
), etc. Module types generalize signatures: a module type specifies a module, and a module type that happens to specify a structure is called a signature. Module types are to modules what ordinary types are to core values.
Compilation units (.ml
files) are structures. Interfaces (.mli
files) are signatures.
So module Foo = struct … end
defines a module called Foo
, which happens to be a structure. This is analogous to let foo = (1, "a")
which defines a value called foo
which happens to be a pair. And module type FOO = sig … end
(note: sig
, not struct
) defines a module type called FOO
, which happens to be a signature. This is analogous to type foo = int * string
which defines a type called foo
which happens to be a product type.
¹ This is in fact no longer true since OCaml 3.12 introduced first-class modules, but it's close enough for an introductory presentation.