Here is the "summary of SML modules" slide I drew during lecture 6 of Concepts in Programming Languages. Introduce and name a structure (note not all structs need to be named and as we see in N2, N3 below, not all structures need to be literal structures, just like not all int expressions need to be integer constants): structure N = struct type T = int * bool type U = string * int val f = fn x => e val g = ... // could also have datatype or exception here end // We could have written "fun f x = e" instead. Introduce and name a signature (note not all sigs need to be named): signature S sig type T = int * bool // concrete, transparent type U // opaque val f = -> // we don't declare g here. end We have that N : S Motto: "structures are to signatures what values are to types". If I write structure N2 = N : S; then N2.U is equal to string*int. However, if I write structure N3 = N :> S; then N3.U is not equal to any other type than itself. But of course N2.T = N3.T because S exposes this. So we have two forms of restricting a structure, one to a signature treated transparently (:) and one to a signature treated opaquely (:>). Note also that both N2 and N3 have an f member, but neither has a g member. Summary of rest of the lecture "big ideas": Functors are structures which take other structures as arguments. We write, e.g. functor F (P1:S1, P2:S2) = We can then write, e.g. structure N57 = F(N2,N3) Generativity/Applicativity: The big question is, if we define structure N58 = F(N2,N3) whether N58 and N57 are equal. SML says not in general, OCaml says yes.