~ubuntu-branches/ubuntu/karmic/ocaml-doc/karmic

« back to all changes in this revision

Viewing changes to ocaml.html/manual004.html

  • Committer: Bazaar Package Importer
  • Author(s): Vanicat Rémi
  • Date: 2002-02-05 10:51:43 UTC
  • Revision ID: james.westby@ubuntu.com-20020205105143-a061tunf8tev07ne
Tags: 3.04-4
* New debian maintainer
* Split doc-base file
* Move to non-free
* Change the copyright file to the copyright of the documentation
* remove FAQs (their license prohibit their redistribution)
* corrected the examples

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
 
2
            "http://www.w3.org/TR/REC-html40/loose.dtd">
 
3
<HTML>
 
4
<HEAD>
 
5
 
 
6
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
 
7
<META name="GENERATOR" content="hevea 1.06-7 of 2001-11-14">
 
8
<TITLE>
 
9
 The module system
 
10
</TITLE>
 
11
</HEAD>
 
12
<BODY TEXT=black BGCOLOR=white>
 
13
<A HREF="manual003.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
 
14
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
 
15
<A HREF="manual005.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
 
16
<HR>
 
17
<TABLE CELLPADDING=0 CELLSPACING=0 WIDTH="100%">
 
18
<TR><TD BGCOLOR="#2de52d"><DIV ALIGN=center><TABLE>
 
19
<TR><TD><A NAME="htoc12"><B><FONT SIZE=6>Chapter&nbsp;2</FONT></B></A></TD>
 
20
<TD WIDTH="100%" ALIGN=center><B><FONT SIZE=6>The module system</FONT></B></TD>
 
21
</TR></TABLE></DIV></TD>
 
22
</TR></TABLE> <A NAME="c:moduleexamples"></A>
 
23
<BR>
 
24
This chapter introduces the module system of Objective Caml.<BR>
 
25
<BR>
 
26
<TABLE CELLPADDING=0 CELLSPACING=0 WIDTH="100%">
 
27
<TR><TD BGCOLOR="#66ff66"><DIV ALIGN=center><TABLE>
 
28
<TR><TD><A NAME="htoc13"><B><FONT SIZE=5>2.1</FONT></B></A></TD>
 
29
<TD WIDTH="100%" ALIGN=center><B><FONT SIZE=5>Structures</FONT></B></TD>
 
30
</TR></TABLE></DIV></TD>
 
31
</TR></TABLE>
 
32
<BR>
 
33
A primary motivation for modules is to package together related
 
34
definitions (such as the definitions of a data type and associated
 
35
operations over that type) and enforce a consistent naming scheme for
 
36
these definitions. This avoids running out of names or accidentally
 
37
confusing names. Such a package is called a <EM>structure</EM> and
 
38
is introduced by the <TT>struct</TT>...<TT>end</TT> construct, which contains an
 
39
arbitrary sequence of definitions. The structure is usually given a
 
40
name with the <TT>module</TT> binding. Here is for instance a structure
 
41
packaging together a type of priority queues and their operations:
 
42
<PRE><FONT COLOR=black>#<FONT COLOR=blue>module PrioQueue =
 
43
   struct
 
44
     type priority = int
 
45
     type 'a queue = Empty | Node of priority * 'a * 'a queue * 'a queue
 
46
     let empty = Empty
 
47
     let rec insert queue prio elt =
 
48
       match queue with
 
49
         Empty -&gt; Node(prio, elt, Empty, Empty)
 
50
       | Node(p, e, left, right) -&gt;
 
51
           if prio &lt;= p
 
52
           then Node(prio, elt, insert right p e, left)
 
53
           else Node(p, e, insert right prio elt, left)
 
54
     exception Queue_is_empty
 
55
     let rec remove_top = function
 
56
         Empty -&gt; raise Queue_is_empty
 
57
       | Node(prio, elt, left, Empty) -&gt; left
 
58
       | Node(prio, elt, Empty, right) -&gt; right
 
59
       | Node(prio, elt, (Node(lprio, lelt, _, _) as left),
 
60
                         (Node(rprio, relt, _, _) as right)) -&gt;
 
61
           if lprio &lt;= rprio
 
62
           then Node(lprio, lelt, remove_top left, right)
 
63
           else Node(rprio, relt, left, remove_top right)
 
64
     let extract = function
 
65
         Empty -&gt; raise Queue_is_empty
 
66
       | Node(prio, elt, _, _) as queue -&gt; (prio, elt, remove_top queue)
 
67
   end;;
 
68
<FONT COLOR=maroon>module PrioQueue :
 
69
  sig
 
70
    type priority = int
 
71
    and 'a queue = Empty | Node of priority * 'a * 'a queue * 'a queue
 
72
    val empty : 'a queue
 
73
    val insert : 'a queue -&gt; priority -&gt; 'a -&gt; 'a queue
 
74
    exception Queue_is_empty
 
75
    val remove_top : 'a queue -&gt; 'a queue
 
76
    val extract : 'a queue -&gt; priority * 'a * 'a queue
 
77
  end
 
78
</FONT></FONT></FONT></PRE>
 
79
Outside the structure, its components can be referred to using the
 
80
``dot notation'', that is, identifiers qualified by a structure name.
 
81
For instance, <TT>PrioQueue.insert</TT> in a value context is
 
82
the function <TT>insert</TT> defined inside the structure
 
83
<TT>PrioQueue</TT>. Similarly, <TT>PrioQueue.queue</TT> in a type context is the
 
84
type <TT>queue</TT> defined in <TT>PrioQueue</TT>. 
 
85
<PRE><FONT COLOR=black>#<FONT COLOR=blue>PrioQueue.insert PrioQueue.empty 1 "hello";;
 
86
<FONT COLOR=maroon>- : string PrioQueue.queue =
 
87
PrioQueue.Node (1, "hello", PrioQueue.Empty, PrioQueue.Empty)
 
88
</FONT></FONT></FONT></PRE>
 
89
<TABLE CELLPADDING=0 CELLSPACING=0 WIDTH="100%">
 
90
<TR><TD BGCOLOR="#66ff66"><DIV ALIGN=center><TABLE>
 
91
<TR><TD><A NAME="htoc14"><B><FONT SIZE=5>2.2</FONT></B></A></TD>
 
92
<TD WIDTH="100%" ALIGN=center><B><FONT SIZE=5>Signatures</FONT></B></TD>
 
93
</TR></TABLE></DIV></TD>
 
94
</TR></TABLE>
 
95
<BR>
 
96
Signatures are interfaces for structures. A signature specifies
 
97
which components of a structure are accessible from the outside, and
 
98
with which type. It can be used to hide some components of a structure 
 
99
(e.g. local function definitions) or export some components with a
 
100
restricted type. For instance, the signature below specifies the three
 
101
priority queue operations <TT>empty</TT>, <TT>insert</TT> and <TT>extract</TT>, but not the
 
102
auxiliary function <TT>remove_top</TT>. Similarly, it makes the <TT>queue</TT> type
 
103
abstract (by not providing its actual representation as a concrete type).
 
104
<PRE><FONT COLOR=black>#<FONT COLOR=blue>module type PRIOQUEUE =
 
105
   sig
 
106
     type priority = int         (* still concrete *)
 
107
     type 'a queue               (* now abstract *)
 
108
     val empty : 'a queue
 
109
     val insert : 'a queue -&gt; int -&gt; 'a -&gt; 'a queue
 
110
     val extract : 'a queue -&gt; int * 'a * 'a queue
 
111
     exception Queue_is_empty
 
112
   end;;
 
113
<FONT COLOR=maroon>module type PRIOQUEUE =
 
114
  sig
 
115
    type priority = int
 
116
    and 'a queue
 
117
    val empty : 'a queue
 
118
    val insert : 'a queue -&gt; int -&gt; 'a -&gt; 'a queue
 
119
    val extract : 'a queue -&gt; int * 'a * 'a queue
 
120
    exception Queue_is_empty
 
121
  end
 
122
</FONT></FONT></FONT></PRE>
 
123
Restricting the <TT>PrioQueue</TT> structure by this signature results in
 
124
another view of the <TT>PrioQueue</TT> structure where the <TT>remove_top</TT>
 
125
function is not accessible and the actual representation of priority
 
126
queues is hidden:
 
127
<PRE><FONT COLOR=black>#<FONT COLOR=blue>module AbstractPrioQueue = (PrioQueue : PRIOQUEUE);;
 
128
<FONT COLOR=maroon>module AbstractPrioQueue : PRIOQUEUE
 
129
&nbsp;
 
130
<FONT COLOR=black>#<FONT COLOR=blue><U>AbstractPrioQueue.remove_top</U>;;
 
131
<FONT COLOR=maroon>Unbound value AbstractPrioQueue.remove_top
 
132
&nbsp;
 
133
<FONT COLOR=black>#<FONT COLOR=blue>AbstractPrioQueue.insert AbstractPrioQueue.empty 1 "hello";;
 
134
<FONT COLOR=maroon>- : string AbstractPrioQueue.queue = &lt;abstr&gt;
 
135
</FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></PRE>
 
136
The restriction can also be performed during the definition of the
 
137
structure, as in
 
138
<PRE>
 
139
module PrioQueue = (struct ... end : PRIOQUEUE);;
 
140
</PRE>An alternate syntax is provided for the above:
 
141
<PRE>
 
142
module PrioQueue : PRIOQUEUE = struct ... end;;
 
143
</PRE>
 
144
<TABLE CELLPADDING=0 CELLSPACING=0 WIDTH="100%">
 
145
<TR><TD BGCOLOR="#66ff66"><DIV ALIGN=center><TABLE>
 
146
<TR><TD><A NAME="htoc15"><B><FONT SIZE=5>2.3</FONT></B></A></TD>
 
147
<TD WIDTH="100%" ALIGN=center><B><FONT SIZE=5>Functors</FONT></B></TD>
 
148
</TR></TABLE></DIV></TD>
 
149
</TR></TABLE>
 
150
<BR>
 
151
Functors are ``functions'' from structures to structures. They are used to
 
152
express parameterized structures: a structure <I>A</I> parameterized by a
 
153
structure <I>B</I> is simply a functor <I>F</I> with a formal parameter
 
154
<I>B</I> (along with the expected signature for <I>B</I>) which returns
 
155
the actual structure <I>A</I> itself. The functor <I>F</I> can then be
 
156
applied to one or several implementations <I>B</I><SUB><FONT SIZE=2>1</FONT></SUB> ...<I>B</I><SUB><FONT SIZE=2><I>n</I></FONT></SUB>
 
157
of <I>B</I>, yielding the corresponding structures
 
158
<I>A</I><SUB><FONT SIZE=2>1</FONT></SUB> ...<I>A</I><SUB><FONT SIZE=2><I>n</I></FONT></SUB>.<BR>
 
159
<BR>
 
160
For instance, here is a structure implementing sets as sorted lists,
 
161
parameterized by a structure providing the type of the set elements
 
162
and an ordering function over this type (used to keep the sets
 
163
sorted):
 
164
<PRE><FONT COLOR=black>#<FONT COLOR=blue>type comparison = Less | Equal | Greater;;
 
165
<FONT COLOR=maroon>type comparison = Less | Equal | Greater
 
166
&nbsp;
 
167
<FONT COLOR=black>#<FONT COLOR=blue>module type ORDERED_TYPE =
 
168
   sig
 
169
     type t
 
170
     val compare: t -&gt; t -&gt; comparison
 
171
   end;;
 
172
<FONT COLOR=maroon>module type ORDERED_TYPE = sig type t val compare : t -&gt; t -&gt; comparison end
 
173
&nbsp;
 
174
<FONT COLOR=black>#<FONT COLOR=blue>module Set =
 
175
   functor (Elt: ORDERED_TYPE) -&gt;
 
176
     struct
 
177
       type element = Elt.t
 
178
       type set = element list
 
179
       let empty = []
 
180
       let rec add x s =
 
181
         match s with
 
182
           [] -&gt; [x]
 
183
         | hd::tl -&gt;
 
184
            match Elt.compare x hd with
 
185
              Equal   -&gt; s         (* x is already in s *)
 
186
            | Less    -&gt; x :: s    (* x is smaller than all elements of s *)
 
187
            | Greater -&gt; hd :: add x tl
 
188
       let rec member x s =
 
189
         match s with
 
190
           [] -&gt; false
 
191
         | hd::tl -&gt;
 
192
             match Elt.compare x hd with
 
193
               Equal   -&gt; true     (* x belongs to s *)
 
194
             | Less    -&gt; false    (* x is smaller than all elements of s *)
 
195
             | Greater -&gt; member x tl
 
196
     end;;
 
197
<FONT COLOR=maroon>module Set :
 
198
  functor (Elt : ORDERED_TYPE) -&gt;
 
199
    sig
 
200
      type element = Elt.t
 
201
      and set = element list
 
202
      val empty : 'a list
 
203
      val add : Elt.t -&gt; Elt.t list -&gt; Elt.t list
 
204
      val member : Elt.t -&gt; Elt.t list -&gt; bool
 
205
    end
 
206
</FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></PRE>
 
207
By applying the <TT>Set</TT> functor to a structure implementing an ordered
 
208
type, we obtain set operations for this type:
 
209
<PRE><FONT COLOR=black>#<FONT COLOR=blue>module OrderedString =
 
210
   struct
 
211
     type t = string
 
212
     let compare x y = if x = y then Equal else if x &lt; y then Less else Greater
 
213
   end;;
 
214
<FONT COLOR=maroon>module OrderedString :
 
215
  sig type t = string val compare : 'a -&gt; 'a -&gt; comparison end
 
216
&nbsp;
 
217
<FONT COLOR=black>#<FONT COLOR=blue>module StringSet = Set(OrderedString);;
 
218
<FONT COLOR=maroon>module StringSet :
 
219
  sig
 
220
    type element = OrderedString.t
 
221
    and set = element list
 
222
    val empty : 'a list
 
223
    val add : OrderedString.t -&gt; OrderedString.t list -&gt; OrderedString.t list
 
224
    val member : OrderedString.t -&gt; OrderedString.t list -&gt; bool
 
225
  end
 
226
&nbsp;
 
227
<FONT COLOR=black>#<FONT COLOR=blue>StringSet.member "bar" (StringSet.add "foo" StringSet.empty);;
 
228
<FONT COLOR=maroon>- : bool = false
 
229
</FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></PRE>
 
230
<TABLE CELLPADDING=0 CELLSPACING=0 WIDTH="100%">
 
231
<TR><TD BGCOLOR="#66ff66"><DIV ALIGN=center><TABLE>
 
232
<TR><TD><A NAME="htoc16"><B><FONT SIZE=5>2.4</FONT></B></A></TD>
 
233
<TD WIDTH="100%" ALIGN=center><B><FONT SIZE=5>Functors and type abstraction</FONT></B></TD>
 
234
</TR></TABLE></DIV></TD>
 
235
</TR></TABLE>
 
236
<BR>
 
237
As in the <TT>PrioQueue</TT> example, it would be good style to hide the
 
238
actual implementation of the type <TT>set</TT>, so that users of the
 
239
structure will not rely on sets being lists, and we can switch later
 
240
to another, more efficient representation of sets without breaking
 
241
their code. This can be achieved by restricting <TT>Set</TT> by a suitable
 
242
functor signature:
 
243
<PRE><FONT COLOR=black>#<FONT COLOR=blue>module type SETFUNCTOR =
 
244
   functor (Elt: ORDERED_TYPE) -&gt;
 
245
     sig
 
246
       type element = Elt.t      (* concrete *)
 
247
       type set                  (* abstract *)
 
248
       val empty : set
 
249
       val add : element -&gt; set -&gt; set
 
250
       val member : element -&gt; set -&gt; bool
 
251
     end;;
 
252
<FONT COLOR=maroon>module type SETFUNCTOR =
 
253
  functor (Elt : ORDERED_TYPE) -&gt;
 
254
    sig
 
255
      type element = Elt.t
 
256
      and set
 
257
      val empty : set
 
258
      val add : element -&gt; set -&gt; set
 
259
      val member : element -&gt; set -&gt; bool
 
260
    end
 
261
&nbsp;
 
262
<FONT COLOR=black>#<FONT COLOR=blue>module AbstractSet = (Set : SETFUNCTOR);;
 
263
<FONT COLOR=maroon>module AbstractSet : SETFUNCTOR
 
264
&nbsp;
 
265
<FONT COLOR=black>#<FONT COLOR=blue>module AbstractStringSet = AbstractSet(OrderedString);;
 
266
<FONT COLOR=maroon>module AbstractStringSet :
 
267
  sig
 
268
    type element = OrderedString.t
 
269
    and set = AbstractSet(OrderedString).set
 
270
    val empty : set
 
271
    val add : element -&gt; set -&gt; set
 
272
    val member : element -&gt; set -&gt; bool
 
273
  end
 
274
&nbsp;
 
275
<FONT COLOR=black>#<FONT COLOR=blue>AbstractStringSet.add "gee" AbstractStringSet.empty;;
 
276
<FONT COLOR=maroon>- : AbstractStringSet.set = &lt;abstr&gt;
 
277
</FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></PRE>
 
278
In an attempt to write the type constraint above more elegantly,
 
279
one may wish to name the signature of the structure
 
280
returned by the functor, then use that signature in the constraint:
 
281
<PRE><FONT COLOR=black>#<FONT COLOR=blue>module type SET =
 
282
   sig
 
283
     type element
 
284
     type set
 
285
     val empty : set
 
286
     val add : element -&gt; set -&gt; set
 
287
     val member : element -&gt; set -&gt; bool
 
288
   end;;
 
289
<FONT COLOR=maroon>module type SET =
 
290
  sig
 
291
    type element
 
292
    and set
 
293
    val empty : set
 
294
    val add : element -&gt; set -&gt; set
 
295
    val member : element -&gt; set -&gt; bool
 
296
  end
 
297
&nbsp;
 
298
<FONT COLOR=black>#<FONT COLOR=blue>module WrongSet = (Set : functor(Elt: ORDERED_TYPE) -&gt; SET);;
 
299
<FONT COLOR=maroon>module WrongSet : functor (Elt : ORDERED_TYPE) -&gt; SET
 
300
&nbsp;
 
301
<FONT COLOR=black>#<FONT COLOR=blue>module WrongStringSet = WrongSet(OrderedString);;
 
302
<FONT COLOR=maroon>module WrongStringSet :
 
303
  sig
 
304
    type element = WrongSet(OrderedString).element
 
305
    and set = WrongSet(OrderedString).set
 
306
    val empty : set
 
307
    val add : element -&gt; set -&gt; set
 
308
    val member : element -&gt; set -&gt; bool
 
309
  end
 
310
&nbsp;
 
311
<FONT COLOR=black>#<FONT COLOR=blue>WrongStringSet.add <U>"gee"</U> WrongStringSet.empty;;
 
312
<FONT COLOR=maroon>This expression has type string but is here used with type
 
313
  WrongStringSet.element = WrongSet(OrderedString).element
 
314
</FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></PRE>
 
315
The problem here is that <TT>SET</TT> specifies the type <TT>element</TT>
 
316
abstractly, so that the type equality between <TT>element</TT> in the result
 
317
of the functor and <TT>t</TT> in its argument is forgotten. Consequently,
 
318
<TT>WrongStringSet.element</TT> is not the same type as <TT>string</TT>, and the
 
319
operations of <TT>WrongStringSet</TT> cannot be applied to strings.
 
320
As demonstrated above, it is important that the type <TT>element</TT> in the
 
321
signature <TT>SET</TT> be declared equal to <TT>Elt.t</TT>; unfortunately, this is
 
322
impossible above since <TT>SET</TT> is defined in a context where <TT>Elt</TT> does
 
323
not exist. To overcome this difficulty, Objective Caml provides a
 
324
<TT>with type</TT> construct over signatures that allows to enrich a signature
 
325
with extra type equalities:
 
326
<PRE><FONT COLOR=black>#<FONT COLOR=blue>module AbstractSet = 
 
327
   (Set : functor(Elt: ORDERED_TYPE) -&gt; (SET with type element = Elt.t));;
 
328
<FONT COLOR=maroon>module AbstractSet :
 
329
  functor (Elt : ORDERED_TYPE) -&gt;
 
330
    sig
 
331
      type element = Elt.t
 
332
      and set
 
333
      val empty : set
 
334
      val add : element -&gt; set -&gt; set
 
335
      val member : element -&gt; set -&gt; bool
 
336
    end
 
337
</FONT></FONT></FONT></PRE>
 
338
As in the case of simple structures, an alternate syntax is provided
 
339
for defining functors and restricting their result:
 
340
<PRE>
 
341
module AbstractSet(Elt: ORDERED_TYPE) : (SET with type element = Elt.t) =
 
342
  struct ... end;;
 
343
</PRE>
 
344
Abstracting a type component in a functor result is a powerful
 
345
technique that provides a high degree of type safety, as we now
 
346
illustrate. Consider an ordering over character strings that is
 
347
different from the standard ordering implemented in the
 
348
<TT>OrderedString</TT> structure. For instance, we compare strings without
 
349
distinguishing upper and lower case.
 
350
<PRE><FONT COLOR=black>#<FONT COLOR=blue>module NoCaseString =
 
351
   struct
 
352
     type t = string
 
353
     let compare s1 s2 =
 
354
       OrderedString.compare (String.lowercase s1) (String.lowercase s2)
 
355
   end;;
 
356
<FONT COLOR=maroon>module NoCaseString :
 
357
  sig type t = string val compare : string -&gt; string -&gt; comparison end
 
358
&nbsp;
 
359
<FONT COLOR=black>#<FONT COLOR=blue>module NoCaseStringSet = AbstractSet(NoCaseString);;
 
360
<FONT COLOR=maroon>module NoCaseStringSet :
 
361
  sig
 
362
    type element = NoCaseString.t
 
363
    and set = AbstractSet(NoCaseString).set
 
364
    val empty : set
 
365
    val add : element -&gt; set -&gt; set
 
366
    val member : element -&gt; set -&gt; bool
 
367
  end
 
368
&nbsp;
 
369
<FONT COLOR=black>#<FONT COLOR=blue>NoCaseStringSet.add "FOO" <U>AbstractStringSet.empty</U>;;
 
370
<FONT COLOR=maroon>This expression has type
 
371
  AbstractStringSet.set = AbstractSet(OrderedString).set
 
372
but is here used with type
 
373
  NoCaseStringSet.set = AbstractSet(NoCaseString).set
 
374
</FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></PRE>
 
375
Notice that the two types <TT>AbstractStringSet.set</TT> and 
 
376
<TT>NoCaseStringSet.set</TT> are not compatible, and values of these
 
377
two types do not match. This is the correct behavior: even though both
 
378
set types contain elements of the same type (strings), both are built
 
379
upon different orderings of that type, and different invariants need
 
380
to be maintained by the operations (being strictly increasing for the
 
381
standard ordering and for the case-insensitive ordering). Applying
 
382
operations from <TT>AbstractStringSet</TT> to values of type
 
383
<TT>NoCaseStringSet.set</TT> could give incorrect results, or build
 
384
lists that violate the invariants of <TT>NoCaseStringSet</TT>.<BR>
 
385
<BR>
 
386
<TABLE CELLPADDING=0 CELLSPACING=0 WIDTH="100%">
 
387
<TR><TD BGCOLOR="#66ff66"><DIV ALIGN=center><TABLE>
 
388
<TR><TD><A NAME="htoc17"><B><FONT SIZE=5>2.5</FONT></B></A></TD>
 
389
<TD WIDTH="100%" ALIGN=center><B><FONT SIZE=5>Modules and separate compilation</FONT></B></TD>
 
390
</TR></TABLE></DIV></TD>
 
391
</TR></TABLE>
 
392
<BR>
 
393
All examples of modules so far have been given in the context of the
 
394
interactive system. However, modules are most useful for large,
 
395
batch-compiled programs. For these programs, it is a practical
 
396
necessity to split the source into several files, called compilation
 
397
units, that can be compiled separately, thus minimizing recompilation
 
398
after changes.<BR>
 
399
<BR>
 
400
In Objective Caml, compilation units are special cases of structures
 
401
and signatures, and the relationship between the units can be
 
402
explained easily in terms of the module system. A compilation unit <I>a</I>
 
403
comprises two files:
 
404
<UL><LI>
 
405
the implementation file <I>a</I><TT>.ml</TT>, which contains a sequence
 
406
of definitions, analogous to the inside of a <TT>struct</TT>...<TT>end</TT>
 
407
construct;
 
408
<LI>the interface file <I>a</I><TT>.mli</TT>, which contains a sequence of
 
409
specifications, analogous to the inside of a <TT>sig</TT>...<TT>end</TT>
 
410
construct.
 
411
</UL>
 
412
Both files define a structure named <I>A</I> (same name as the base name
 
413
<I>a</I> of the two files, with the first letter capitalized), as if
 
414
the following definition was entered at top-level:
 
415
<PRE>
 
416
module <I>A</I>: sig (* contents of file <I>a</I>.mli *) end
 
417
        = struct (* contents of file <I>a</I>.ml *) end;;
 
418
</PRE>
 
419
The files defining the compilation units can be compiled separately
 
420
using the <TT>ocamlc -c</TT> command (the <TT>-c</TT> option means ``compile only, do
 
421
not try to link''); this produces compiled interface files (with
 
422
extension <TT>.cmi</TT>) and compiled object code files (with extension
 
423
<TT>.cmo</TT>). When all units have been compiled, their <TT>.cmo</TT> files are
 
424
linked together using the <TT>ocaml</TT> command. For instance, the following
 
425
commands compile and link a program composed of two compilation units
 
426
<TT>aux</TT> and <TT>main</TT>:
 
427
<PRE>
 
428
$ ocamlc -c aux.mli                     # produces aux.cmi
 
429
$ ocamlc -c aux.ml                      # produces aux.cmo
 
430
$ ocamlc -c main.mli                    # produces main.cmi
 
431
$ ocamlc -c main.ml                     # produces main.cmo
 
432
$ ocamlc -o theprogram aux.cmo main.cmo
 
433
</PRE>The program behaves exactly as if the following phrases were entered
 
434
at top-level:
 
435
<PRE>
 
436
module Aux: sig (* contents of aux.mli *) end
 
437
          = struct (* contents of aux.ml *) end;;
 
438
module Main: sig (* contents of main.mli *) end
 
439
           = struct (* contents of main.ml *) end;;
 
440
</PRE>
 
441
In particular, <TT>Main</TT> can refer to <TT>Aux</TT>: the definitions and
 
442
declarations contained in <TT>main.ml</TT> and <TT>main.mli</TT> can refer to
 
443
definition in <TT>aux.ml</TT>, using the <TT>Aux.</TT><I>ident</I> notation, provided
 
444
these definitions are exported in <TT>aux.mli</TT>.<BR>
 
445
<BR>
 
446
The order in which the <TT>.cmo</TT> files are given to <TT>ocaml</TT> during the
 
447
linking phase determines the order in which the module definitions
 
448
occur. Hence, in the example above, <TT>Aux</TT> appears first and <TT>Main</TT> can
 
449
refer to it, but <TT>Aux</TT> cannot refer to <TT>Main</TT>.<BR>
 
450
<BR>
 
451
Notice that only top-level structures can be mapped to
 
452
separately-compiled files, but not functors nor module types.
 
453
However, all module-class objects can appear as components of a
 
454
structure, so the solution is to put the functor or module type
 
455
inside a structure, which can then be mapped to a file.
 
456
 
 
457
<BR>
 
458
<BR>
 
459
<HR>
 
460
<A HREF="manual003.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
 
461
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
 
462
<A HREF="manual005.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
 
463
</BODY>
 
464
</HTML>