Something that comes up early on when learning OCaml is the topic of
abstract types. Comparable to "encapsulation" in object-oriented
programming, one purpose of abstract types is to protect the programmer
from misusing a module's types. By abstracting the type, for example,
Number.t instead of a plain
int type, the underlying
implementation can be swapped out, without affecting code using the
module. Only by using the module can the user create a value of that
type, because only the module knows that
Number.t = int, and has
ability to create that type.
Abstract types guarantee that the user can never access the concrete type directly This is known as "enforcing invariants", preserving certain properties about the type, so that you can now assume they will always be true, i.e., invariant. Placing this restriction on library users increases the level of type safety significantly.
On the other hand, sometimes you do want to have concrete types in your interface, and that's okay too. It gives more flexibility to the user, since they can construct those types by hand, and have more detail about the internals of the module.