What's the difference (if any) between Standard ML's module system and OCaml module system?
There are some differences feature-wise, as well as semantically.
Features SML supports but not OCaml:
- transparent signature ascription
- module-level
let
- symmetric sharing constraints
- syntactic sugar for functors over types and values
Features OCaml 4 has but not SML:
- higher-order functors
- recursive modules
- local modules
- nested signatures
- modules as first-class values
- general module sharing (
sig with module A = M
) module type of
Several SML implementations provide some of these as extensions, however: e.g. higher-order functors (SML/NJ, Moscow ML, Alice ML), local and first-class modules (Moscow ML, Alice ML), module sharing (SML/NJ, Alice ML), nested signatures (Moscow ML, Alice ML), and recursive modules (Moscow ML).
Semantics-wise, the biggest difference is in the treatment of type equivalence, especially with respect to functors:
In SML, functors are generative, which means that applying the same functor twice to the same argument always yields fresh types.
In OCaml, functors are applicative, which means that applying the same functor twice to the exact same argument (plus additional syntactic restrictions) reproduces equivalent types. This semantics is more flexible, but can also break abstraction (see e.g. the examples we give in this paper, Section 8).
Edit: OCaml 4 added the ability to optionally make functors generative.
OCaml has a purely syntactic notion of signatures, which means that certain type equivalences cannot be expressed by the type system, and are silently dropped.
Edit: Consider this example:
module F (X : sig type t end) = struct type u = X.t -> unit type v = X.t end module M = F (struct type t = int end : sig type t end)
The type of
M
is simplysig type u type v end
and has thus lost any information about the relation between its typesu
andv
, because that cannot generally be expressed in the surface syntax.
Another notable difference is that OCaml's module type system is undecidable (i.e, type checking may not terminate), due to its permission of abstract signatures, which SML does not allow.
As for semantics, a much better and elaborate answer is given by Andreas Rossberg above. However, concerning syntax this site might be what you are looking for.