Ch.11 Separate compilation in SML#

§ 11.4. Opaque types

The principle underlying interface declaration are the following.

  1. Define compile-time resources (static entities) such as datatype and exception themselves just the same way as they will be defined in a source file.

  2. Declare only the types of runtime resources such as functions and variables.

They are necessary and sufficient information to compile other source file that uses this interface file. However, this principle alone cannot support ML's information hiding through opaque signatures. For example, in the previous interface file queue.smi, the 'a queue type is explicitly defined to be Q of 'a list * 'a list and this information is open to the user of this interface file, but we often want to hide this implementation details.

To solve this problem, the interface language introduces the following opaque type declarations.

type tyvars tyid (= typeRep)    (* describe paranthesis as they are *)
eqtype tyvars tyid (= typeRep)    (* describe paranthesis as they are *)

These declaration reveals to the compiler that the internal representation of tyid is typeRep but this information is not available to the code that uses this interface file through _require declaration. As in signature, type declaration defines a type on which equality operation is not defined and eqtype declaration defines a type with on which equality operation is define. Possible internal representations typeRep include the following.

  • Atomic data representations, such as word, int, word8, char, real, real32.

  • contag. The internal representation of a datatype consisting only of constructors with no argument.

  • boxed. Heap allocated objects. Records, arrays, functions, and any datatype that is not compliant with contag have this representation.

For example,instead of datatype 'a queue declaration in queue.smi, one can write the following.

type 'a queue (= boxed)

Note that an internal representation is not a type.

Furthermore, as in signature, interface file need not exhaustively list all the resources the implementation may define. Only those resources defined in the interface file become visible to the code that use it through _require declaration.