14.5 Treatment of signatures
In Standard ML, in addition to resources explained in Section 14.3, signatures are also named resources. For example,one should be able to provide QUEUE signature as well as Queue structure. In require declaration in an interface file, signature files can be specified in the following syntax.
_require
is a path to a signature file. To understand this mechanism, let us review some properties of Standard ML signatures.
-
•
A signature may reference some types define in some other structures.
-
•
A signature itself does not define any type.
To deal with this situation properly, SML# compiler treats _require declaration as follows.
-
•
Evaluate the signature in the file in the context generated by all the other Require declarations.
-
•
The signature declaration is inserted at the beginning of the source file that use this interface file through _require.
Figure 14.3 shows an interface file containing an opaque signature.
queue-sig.sml file:
signature Queue =
sig datatype ’a queue = Q of ’a list * ’a list exception Dequeue val empty : ’a queue val isEmpty : ’a queue -> bool val enqueue : ’a queue * ’a -> ’a queue val dequeue : ’a queue -> ’a queue * ’a end queue.smi file: _require "basis.smi" _require "queue-sig.sml" structure Queue = struct type ’a queue (= boxed) exception Dequeue val empty : ’a queue val isEmpty : ’a queue -> bool val enqueue : ’a queue * ’a -> ’a queue val dequeue : ’a queue -> ’a queue * ’a end queue.sml file: structure Queue : QUEUE = struct datatype ’a queue = Q of ’a list * ’a list exception Dequeue val empty = Q ([],[]) fun isEmpty (Q ([],[])) = true | isEmpty _ = false fun enqueue (Q(Old,New),x) = Q (Old,x::New)} fun dequeue (Q (hd::tl,New)) = (Q (tl,New), hd) | dequeue (Q ([],_) = raise Dequeue | dequeue (Q(Old,New) = dequeue (Q(rev New,[])) end |