There is a way to define a namespace in SML: define an "structure" that creates a module.
Example:
structure MyMath =
struct
val pi = 3.141529
fun double(x) =
x + x
end
To access the bindings, you need to prepend the namespace:
MyMath.double(2)
=> 4
It is possible to provide a kind of "interface" to our modules, saying that only some val
s and function bindings will be available to the external world.
signature MY_SIGNATURE
sig
val add : int * int -> int
end
Every module that implements MY_SIGNATURE
will only have the things defined in the signature as public. This way, it is easy to encapsulate things. It also enables to make "types" abstract.
Eg.:
structure MyStructure :> MY_SIGNATURE
struct
fun add(a, b) =
a + b
val pi = 3.1415 (* This will not be available to the outside world *)
end
Even if a module shares the same signature, it is not equivalent in types. Every signature defines its own types. You can't mix implementations that are equivalent, but does not share the same signature. This is because signature a has types that are diffent than signature b.