8
6
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
9
<META name="GENERATOR" content="hevea 1.08">
7
<META name="GENERATOR" content="hevea 1.09">
10
8
<LINK rel="stylesheet" type="text/css" href="manual.css">
9
<TITLE>Labels and variants</TITLE>
16
<A HREF="manual005.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
17
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Up"></A>
18
<A HREF="manual007.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
12
<A HREF="manual005.html"><IMG SRC="previous_motif.gif" ALT="Previous"></A>
13
<A HREF="index.html"><IMG SRC="contents_motif.gif" ALT="Up"></A>
14
<A HREF="manual007.html"><IMG SRC="next_motif.gif" ALT="Next"></A>
21
<H1 CLASS="chapter"><A NAME="htoc36">Chapter 4</A> Labels and variants</H1> <A NAME="c:labl-examples"></A>
23
<I>(Chapter written by Jacques Garrigue)</I><BR>
29
This chapter gives an overview of the new features in
30
Objective Caml 3: labels, and polymorphic variants.<BR>
33
<H2 CLASS="section"><A NAME="htoc37">4.1</A> Labels</H2>
35
If you have a look at modules ending in <TT>Labels</TT> in the standard
16
<H1 CLASS="chapter"><A NAME="htoc36">Chapter�4</A>��Labels and variants</H1><P> <A NAME="c:labl-examples"></A>
17
</P><P><I>(Chapter written by Jacques Garrigue)</I></P><P><BR>
19
</P><P>This chapter gives an overview of the new features in
20
Objective Caml 3: labels, and polymorphic variants.</P><H2 CLASS="section"><A NAME="htoc37">4.1</A>��Labels</H2><P>If you have a look at modules ending in <TT>Labels</TT> in the standard
36
21
library, you will see that function types have annotations you did not
37
have in the functions you defined yourself.
38
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>ListLabels.map;;
22
have in the functions you defined yourself.</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>ListLabels.map;;
39
23
</FONT><FONT COLOR=maroon>- : f:('a -> 'b) -> 'a list -> 'b list = <fun>
41
25
<FONT COLOR=black>#</FONT><FONT COLOR=blue>StringLabels.sub;;
42
26
</FONT>- : string -> pos:int -> len:int -> string = <fun>
44
Such annotations of the form <TT>name:</TT> are called <EM>labels</EM>. They are
27
</FONT></PRE><P>Such annotations of the form <TT>name:</TT> are called <EM>labels</EM>. They are
45
28
meant to document the code, allow more checking, and give more
46
29
flexibility to function application.
47
30
You can give such names to arguments in your programs, by prefixing them
48
with a tilde <TT>~</TT>.
49
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let f ~x ~y = x - y;;
31
with a tilde <TT>~</TT>.</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let f ~x ~y = x - y;;
50
32
</FONT><FONT COLOR=maroon>val f : x:int -> y:int -> int = <fun>
52
34
<FONT COLOR=black>#</FONT><FONT COLOR=blue>let x = 3 and y = 2 in f ~x ~y;;
55
When you want to use distinct names for the variable and the label
36
</FONT></PRE><P>When you want to use distinct names for the variable and the label
56
37
appearing in the type, you can use a naming label of the form
57
<TT>~name:</TT>. This also applies when the argument is not a variable.
58
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let f ~x:x1 ~y:y1 = x1 - y1;;
38
<TT>~name:</TT>. This also applies when the argument is not a variable.</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let f ~x:x1 ~y:y1 = x1 - y1;;
59
39
</FONT><FONT COLOR=maroon>val f : x:int -> y:int -> int = <fun>
61
41
<FONT COLOR=black>#</FONT><FONT COLOR=blue>f ~x:3 ~y:2;;
64
Labels obey the same rules as other identifiers in Caml, that is you
65
cannot use a reserved keyword (like <TT>in</TT> or <TT>to</TT>) as label.<BR>
67
Formal parameters and arguments are matched according to their
43
</FONT></PRE><P>Labels obey the same rules as other identifiers in Caml, that is you
44
cannot use a reserved keyword (like <TT>in</TT> or <TT>to</TT>) as label.</P><P>Formal parameters and arguments are matched according to their
68
45
respective labels<SUP><A NAME="text1" HREF="#note1">1</A></SUP>, the absence of label
69
46
being interpreted as the empty label.
70
47
This allows commuting arguments in applications. One can also
71
48
partially apply a function on any argument, creating a new function of
72
the remaining parameters.
73
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let f ~x ~y = x - y;;
49
the remaining parameters.</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let f ~x ~y = x - y;;
74
50
</FONT><FONT COLOR=maroon>val f : x:int -> y:int -> int = <fun>
76
52
<FONT COLOR=black>#</FONT><FONT COLOR=blue>f ~y:2 ~x:3;;
79
55
<FONT COLOR=black>#</FONT><FONT COLOR=blue>ListLabels.fold_left;;
80
56
</FONT>- : f:('a -> 'b -> 'a) -> init:'a -> 'b list -> 'a = <fun>
82
58
<FONT COLOR=black>#</FONT><FONT COLOR=blue>ListLabels.fold_left [1;2;3] ~init:0 ~f:(+);;
85
61
<FONT COLOR=black>#</FONT><FONT COLOR=blue>ListLabels.fold_left ~init:0;;
86
62
</FONT>- : f:(int -> 'a -> int) -> 'a list -> int = <fun>
88
If in a function several arguments bear the same label (or no label),
63
</FONT></PRE><P>If in a function several arguments bear the same label (or no label),
89
64
they will not commute among themselves, and order matters. But they
90
can still commute with other arguments.
91
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let hline ~x:x1 ~x:x2 ~y = (x1, x2, y);;
65
can still commute with other arguments.</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let hline ~x:x1 ~x:x2 ~y = (x1, x2, y);;
92
66
</FONT><FONT COLOR=maroon>val hline : x:'a -> x:'b -> y:'c -> 'a * 'b * 'c = <fun>
94
68
<FONT COLOR=black>#</FONT><FONT COLOR=blue>hline ~x:3 ~y:2 ~x:5;;
95
69
</FONT>- : int * int * int = (3, 5, 2)
97
As an exception to the above parameter matching rules, if an
70
</FONT></PRE><P>As an exception to the above parameter matching rules, if an
98
71
application is total, labels may be omitted. In practice, most
99
72
applications are total, so that labels can be omitted in applications.
100
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>f 3 2;;
73
</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>f 3 2;;
101
74
</FONT><FONT COLOR=maroon>- : int = 1
103
76
<FONT COLOR=black>#</FONT><FONT COLOR=blue>ListLabels.map succ [1;2;3];;
104
77
</FONT>- : int list = [2; 3; 4]
106
79
But beware that functions like <TT>ListLabels.fold_left</TT> whose result
107
80
type is a type variable will never be considered as totally applied.
108
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>ListLabels.fold_left <U>(+)</U> 0 [1;2;3];;
81
</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>ListLabels.fold_left <U>(+)</U> 0 [1;2;3];;
109
82
</FONT><FONT COLOR=maroon>This expression has type int -> int -> int but is here used with type 'a list
111
When a function is passed as an argument to an higher-order function,
83
</FONT></PRE><P>When a function is passed as an argument to an higher-order function,
112
84
labels must match in both types. Neither adding nor removing labels
114
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let h g = g ~x:3 ~y:2;;
86
</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let h g = g ~x:3 ~y:2;;
115
87
</FONT><FONT COLOR=maroon>val h : (x:int -> y:int -> 'a) -> 'a = <fun>
117
89
<FONT COLOR=black>#</FONT><FONT COLOR=blue>h f;;
118
90
</FONT>- : int = 1
120
92
<FONT COLOR=black>#</FONT><FONT COLOR=blue>h <U>(+)</U>;;
121
93
</FONT>This expression has type int -> int -> int but is here used with type
122
94
x:int -> y:int -> 'a
125
<H3 CLASS="subsection"><A NAME="htoc38">4.1.1</A> Optional arguments</H3>
126
An interesting feature of labeled arguments is that they can be made
96
Note that when you don't need an argument, you can still use a wildcard
97
pattern, but you must prefix it with the label.
98
</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>h (fun ~x:_ ~y -> y+1);;
99
</FONT><FONT COLOR=maroon>- : int = 3
100
</FONT></PRE><H3 CLASS="subsection"><A NAME="htoc38">4.1.1</A>��Optional arguments</H3><P>An interesting feature of labeled arguments is that they can be made
127
101
optional. For optional parameters, the question mark <TT>?</TT> replaces the
128
102
tilde <TT>~</TT> of non-optional ones, and the label is also prefixed by <TT>?</TT>
129
103
in the function type.
130
Default values may be given for such optional parameters.
131
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let bump ?(step = 1) x = x + step;;
104
Default values may be given for such optional parameters.</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let bump ?(step = 1) x = x + step;;
132
105
</FONT><FONT COLOR=maroon>val bump : ?step:int -> int -> int = <fun>
134
107
<FONT COLOR=black>#</FONT><FONT COLOR=blue>bump 2;;
135
108
</FONT>- : int = 3
137
110
<FONT COLOR=black>#</FONT><FONT COLOR=blue>bump ~step:3 2;;
138
111
</FONT>- : int = 5
140
A function taking some optional arguments must also take at least one
112
</FONT></PRE><P>A function taking some optional arguments must also take at least one
141
113
non-labeled argument. This is because the criterion for deciding
142
114
whether an optional has been omitted is the application on a
143
115
non-labeled argument appearing after this optional argument in the
145
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let test ?(x = 0) ?(y = 0) () ?(z = 0) () = (x, y, z);;
116
function type.</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let test ?(x = 0) ?(y = 0) () ?(z = 0) () = (x, y, z);;
146
117
</FONT><FONT COLOR=maroon>val test : ?x:int -> ?y:int -> unit -> ?z:int -> unit -> int * int * int =
149
120
<FONT COLOR=black>#</FONT><FONT COLOR=blue>test ();;
150
121
</FONT>- : ?z:int -> unit -> int * int * int = <fun>
152
123
<FONT COLOR=black>#</FONT><FONT COLOR=blue>test ~x:2 () ~z:3 ();;
153
124
</FONT>- : int * int * int = (2, 0, 3)
155
Optional parameters may also commute with non-optional or unlabelled
125
</FONT></PRE><P>Optional parameters may also commute with non-optional or unlabelled
156
126
ones, as long as they are applied simultaneously. By nature, optional
157
127
arguments do not commute with unlabeled arguments applied
159
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>test ~y:2 ~x:3 () ();;
129
</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>test ~y:2 ~x:3 () ();;
160
130
</FONT><FONT COLOR=maroon>- : int * int * int = (3, 2, 0)
162
132
<FONT COLOR=black>#</FONT><FONT COLOR=blue>test () () ~z:1 ~y:2 ~x:3;;
163
133
</FONT>- : int * int * int = (3, 2, 1)
165
135
<FONT COLOR=black>#</FONT><FONT COLOR=blue><U>(test () ())</U> ~z:1;;
166
136
</FONT>This expression is not a function, it cannot be applied
168
138
Here <TT>(test () ())</TT> is already <TT>(0,0,0)</TT> and cannot be further
171
Optional arguments are actually implemented as option types. If
139
applied.</P><P>Optional arguments are actually implemented as option types. If
172
140
you do not give a default value, you have access to their internal
173
141
representation, <TT>type 'a option = None | Some of 'a</TT>. You can then
174
provide different behaviors when an argument is present or not.
175
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let bump ?step x =
142
provide different behaviors when an argument is present or not.</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let bump ?step x =
177
144
| None -> x * 2
178
145
| Some y -> x + y
180
147
</FONT><FONT COLOR=maroon>val bump : ?step:int -> int -> int = <fun>
182
It may also be useful to relay an optional argument from a function
148
</FONT></PRE><P>It may also be useful to relay an optional argument from a function
183
149
call to another. This can be done by prefixing the applied argument
184
150
with <TT>?</TT>. This question mark disables the wrapping of optional
185
argument in an option type.
186
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let test2 ?x ?y () = test ?x ?y () ();;
151
argument in an option type.</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let test2 ?x ?y () = test ?x ?y () ();;
187
152
</FONT><FONT COLOR=maroon>val test2 : ?x:int -> ?y:int -> unit -> int * int * int = <fun>
189
154
<FONT COLOR=black>#</FONT><FONT COLOR=blue>test2 ?x:None;;
190
155
</FONT>- : ?y:int -> unit -> int * int * int = <fun>
193
<H3 CLASS="subsection"><A NAME="htoc39">4.1.2</A> Labels and type inference</H3>
194
<A NAME="ss:label-inference"></A>
195
While they provide an increased comfort for writing function
156
</FONT></PRE><H3 CLASS="subsection"><A NAME="htoc39">4.1.2</A>��Labels and type inference</H3><P>
157
<A NAME="ss:label-inference"></A></P><P>While they provide an increased comfort for writing function
196
158
applications, labels and optional arguments have the pitfall that they
197
cannot be inferred as completely as the rest of the language.<BR>
199
You can see it in the following two examples.
200
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let h' g = g ~y:2 ~x:3;;
159
cannot be inferred as completely as the rest of the language.</P><P>You can see it in the following two examples.
160
</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let h' g = g ~y:2 ~x:3;;
201
161
</FONT><FONT COLOR=maroon>val h' : (y:int -> x:int -> 'a) -> 'a = <fun>
203
163
<FONT COLOR=black>#</FONT><FONT COLOR=blue>h' <U>f</U>;;
204
164
</FONT>This expression has type x:int -> y:int -> int but is here used with type
205
165
y:int -> x:int -> 'a
207
167
<FONT COLOR=black>#</FONT><FONT COLOR=blue>let bump_it bump x =
209
169
</FONT>val bump_it : (step:int -> 'a -> 'b) -> 'a -> 'b = <fun>
211
171
<FONT COLOR=black>#</FONT><FONT COLOR=blue>bump_it <U>bump</U> 1;;
212
172
</FONT>This expression has type ?step:int -> int -> int but is here used with type
213
173
step:int -> 'a -> 'b
215
175
The first case is simple: <TT>g</TT> is passed <TT>~y</TT> and then <TT>~x</TT>, but <TT>f</TT>
216
176
expects <TT>~x</TT> and then <TT>~y</TT>. This is correctly handled if we know the
217
177
type of <TT>g</TT> to be <TT>x:int -> y:int -> int</TT> in advance, but otherwise
218
178
this causes the above type clash. The simplest workaround is to apply
219
formal parameters in a standard order.<BR>
221
The second example is more subtle: while we intended the argument
179
formal parameters in a standard order.</P><P>The second example is more subtle: while we intended the argument
222
180
<TT>bump</TT> to be of type <TT>?step:int -> int -> int</TT>, it is inferred as
223
181
<TT>step:int -> int -> 'a</TT>.
224
182
These two types being incompatible (internally normal and optional
225
183
arguments are different), a type error occurs when applying <TT>bump_it</TT>
226
to the real <TT>bump</TT>.<BR>
228
We will not try here to explain in detail how type inference works.
184
to the real <TT>bump</TT>.</P><P>We will not try here to explain in detail how type inference works.
229
185
One must just understand that there is not enough information in the
230
186
above program to deduce the correct type of <TT>g</TT> or <TT>bump</TT>. That is,
231
187
there is no way to know whether an argument is optional or not, or
232
188
which is the correct order, by looking only at how a function is
233
189
applied. The strategy used by the compiler is to assume that there are
234
190
no optional arguments, and that applications are done in the right
237
The right way to solve this problem for optional parameters is to add
191
order.</P><P>The right way to solve this problem for optional parameters is to add
238
192
a type annotation to the argument <TT>bump</TT>.
239
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let bump_it (bump : ?step:int -> int -> int) x =
193
</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let bump_it (bump : ?step:int -> int -> int) x =
241
195
</FONT><FONT COLOR=maroon>val bump_it : (?step:int -> int -> int) -> int -> int = <fun>
243
197
<FONT COLOR=black>#</FONT><FONT COLOR=blue>bump_it bump 1;;
244
198
</FONT>- : int = 3
246
200
In practive, such problems appear mostly when using objects whose
247
201
methods have optional arguments, so that writing the type of object
248
arguments is often a good idea.<BR>
250
Normally the compiler generates a type error if you attempt to pass to
202
arguments is often a good idea.</P><P>Normally the compiler generates a type error if you attempt to pass to
251
203
a function a parameter whose type is different from the expected one.
252
204
However, in the specific case where the expected type is a non-labeled
253
205
function type, and the argument is a function expecting optional
254
206
parameters, the compiler will attempt to transform the argument to
255
207
have it match the expected type, by passing <TT>None</TT> for all optional
257
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let twice f (x : int) = f(f x);;
208
parameters.</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let twice f (x : int) = f(f x);;
258
209
</FONT><FONT COLOR=maroon>val twice : (int -> int) -> int -> int = <fun>
260
211
<FONT COLOR=black>#</FONT><FONT COLOR=blue>twice bump 2;;
261
212
</FONT>- : int = 8
263
This transformation is coherent with the intended semantics,
213
</FONT></PRE><P>This transformation is coherent with the intended semantics,
264
214
including side-effects. That is, if the application of optional
265
215
parameters shall produce side-effects, these are delayed until the
266
received function is really applied to an argument.<BR>
269
<H3 CLASS="subsection"><A NAME="htoc40">4.1.3</A> Suggestions for labeling</H3>
270
Like for names, choosing labels for functions is not an easy task. A
271
good labeling is a labeling which
272
<UL CLASS="itemize"><LI CLASS="li-itemize">
216
received function is really applied to an argument.</P><H3 CLASS="subsection"><A NAME="htoc40">4.1.3</A>��Suggestions for labeling</H3><P>Like for names, choosing labels for functions is not an easy task. A
217
good labeling is a labeling which</P><UL CLASS="itemize"><LI CLASS="li-itemize">
273
218
makes programs more readable,
274
<LI CLASS="li-itemize">is easy to remember,
275
<LI CLASS="li-itemize">when possible, allows useful partial applications.
277
We explain here the rules we applied when labeling Objective Caml
280
To speak in an “object-oriented” way, one can consider that each
219
</LI><LI CLASS="li-itemize">is easy to remember,
220
</LI><LI CLASS="li-itemize">when possible, allows useful partial applications.
221
</LI></UL><P>We explain here the rules we applied when labeling Objective Caml
222
libraries.</P><P>To speak in an “object-oriented” way, one can consider that each
281
223
function has a main argument, its <EM>object</EM>, and other arguments
282
224
related with its action, the <EM>parameters</EM>. To permit the
283
225
combination of functions through functionals in commuting label mode, the
287
229
role. When this is not possible the role is to prefer, since the nature will
288
230
often be given by the type itself. Obscure abbreviations should be
290
<PRE><FONT COLOR=maroon>ListLabels.map : f:('a -> 'b) -> 'a list -> 'b list
232
</P><PRE><FONT COLOR=maroon>ListLabels.map : f:('a -> 'b) -> 'a list -> 'b list
291
233
UnixLabels.write : file_descr -> buf:string -> pos:int -> len:int -> unit
293
When there are several objects of same nature and role, they are all
234
</FONT></PRE><P>When there are several objects of same nature and role, they are all
295
<PRE><FONT COLOR=maroon>ListLabels.iter2 : f:('a -> 'b -> 'c) -> 'a list -> 'b list -> unit
297
When there is no preferable object, all arguments are labeled.
298
<PRE><FONT COLOR=maroon>StringLabels.blit :
236
</P><PRE><FONT COLOR=maroon>ListLabels.iter2 : f:('a -> 'b -> 'c) -> 'a list -> 'b list -> unit
237
</FONT></PRE><P>When there is no preferable object, all arguments are labeled.
238
</P><PRE><FONT COLOR=maroon>StringLabels.blit :
299
239
src:string -> src_pos:int -> dst:string -> dst_pos:int -> len:int -> unit
301
However, when there is only one argument, it is often left unlabeled.
302
<PRE><FONT COLOR=maroon>StringLabels.create : int -> string
240
</FONT></PRE><P>However, when there is only one argument, it is often left unlabeled.
241
</P><PRE><FONT COLOR=maroon>StringLabels.create : int -> string
304
243
This principle also applies to functions of several arguments whose
305
244
return type is a type variable, as long as the role of each argument
306
245
is not ambiguous. Labeling such functions may lead to awkward error
307
246
messages when one attempts to omit labels in an application, as we
308
have seen with <TT>ListLabels.fold_left</TT>.<BR>
310
Here are some of the label names you will find throughout the
313
<DIV CLASS="center"><TABLE BORDER=1 CELLSPACING=0 CELLPADDING=1 WIDTH="80%">
314
<TR><TD ALIGN=center NOWRAP><B>Label</B></TD>
315
<TD ALIGN=center NOWRAP><B>Meaning</B></TD>
247
have seen with <TT>ListLabels.fold_left</TT>.</P><P>Here are some of the label names you will find throughout the
248
libraries.</P><DIV CLASS="center"><TABLE BORDER=1 CELLSPACING=0 CELLPADDING=1 WIDTH="80%"><TR><TD ALIGN=center NOWRAP><B>Label</B></TD><TD ALIGN=center NOWRAP><B>Meaning</B></TD></TR>
317
249
<TR><TD ALIGN=left NOWRAP>
319
<TD ALIGN=left NOWRAP>a function to be applied</TD>
321
<TR><TD ALIGN=left NOWRAP><TT>pos:</TT></TD>
322
<TD ALIGN=left NOWRAP>a position in a string or array</TD>
324
<TR><TD ALIGN=left NOWRAP><TT>len:</TT></TD>
325
<TD ALIGN=left NOWRAP>a length</TD>
327
<TR><TD ALIGN=left NOWRAP><TT>buf:</TT></TD>
328
<TD ALIGN=left NOWRAP>a string used as buffer</TD>
330
<TR><TD ALIGN=left NOWRAP><TT>src:</TT></TD>
331
<TD ALIGN=left NOWRAP>the source of an operation</TD>
333
<TR><TD ALIGN=left NOWRAP><TT>dst:</TT></TD>
334
<TD ALIGN=left NOWRAP>the destination of an operation</TD>
336
<TR><TD ALIGN=left NOWRAP><TT>init:</TT></TD>
337
<TD ALIGN=left NOWRAP>the initial value for an iterator</TD>
339
<TR><TD ALIGN=left NOWRAP><TT>cmp:</TT></TD>
340
<TD ALIGN=left NOWRAP>a comparison function, <I>e.g.</I> <TT>Pervasives.compare</TT></TD>
342
<TR><TD ALIGN=left NOWRAP><TT>mode:</TT></TD>
343
<TD ALIGN=left NOWRAP>an operation mode or a flag list</TD>
344
</TR></TABLE></DIV><BR>
346
All these are only suggestions, but one shall keep in mind that the
250
<TT>f:</TT></TD><TD ALIGN=left NOWRAP>a function to be applied</TD></TR>
251
<TR><TD ALIGN=left NOWRAP><TT>pos:</TT></TD><TD ALIGN=left NOWRAP>a position in a string or array</TD></TR>
252
<TR><TD ALIGN=left NOWRAP><TT>len:</TT></TD><TD ALIGN=left NOWRAP>a length</TD></TR>
253
<TR><TD ALIGN=left NOWRAP><TT>buf:</TT></TD><TD ALIGN=left NOWRAP>a string used as buffer</TD></TR>
254
<TR><TD ALIGN=left NOWRAP><TT>src:</TT></TD><TD ALIGN=left NOWRAP>the source of an operation</TD></TR>
255
<TR><TD ALIGN=left NOWRAP><TT>dst:</TT></TD><TD ALIGN=left NOWRAP>the destination of an operation</TD></TR>
256
<TR><TD ALIGN=left NOWRAP><TT>init:</TT></TD><TD ALIGN=left NOWRAP>the initial value for an iterator</TD></TR>
257
<TR><TD ALIGN=left NOWRAP><TT>cmp:</TT></TD><TD ALIGN=left NOWRAP>a comparison function, <I>e.g.</I> <TT>Pervasives.compare</TT></TD></TR>
258
<TR><TD ALIGN=left NOWRAP><TT>mode:</TT></TD><TD ALIGN=left NOWRAP>an operation mode or a flag list</TD></TR>
259
</TABLE></DIV><P>All these are only suggestions, but one shall keep in mind that the
347
260
choice of labels is essential for readability. Bizarre choices will
348
make the program harder to maintain.<BR>
350
In the ideal, the right function name with right labels shall be
261
make the program harder to maintain.</P><P>In the ideal, the right function name with right labels shall be
351
262
enough to understand the function's meaning. Since one can get this
352
263
information with OCamlBrowser or the <TT>ocaml</TT> toplevel, the documentation
353
is only used when a more detailed specification is needed.<BR>
356
<H2 CLASS="section"><A NAME="htoc41">4.2</A> Polymorphic variants</H2>
358
Variants as presented in section <A HREF="manual003.html#s:tut-recvariants">1.4</A> are a
264
is only used when a more detailed specification is needed.</P><H2 CLASS="section"><A NAME="htoc41">4.2</A>��Polymorphic variants</H2><P>Variants as presented in section�<A HREF="manual003.html#s:tut-recvariants">1.4</A> are a
359
265
powerful tool to build data structures and algorithms. However they
360
266
sometimes lack flexibility when used in modular programming. This is
361
267
due to the fact every constructor reserves a name to be used with a
362
268
unique type. One cannot use the same name in another type, or consider
363
269
a value of some type to belong to some other type with more
366
With polymorphic variants, this original assumption is removed. That
270
constructors.</P><P>With polymorphic variants, this original assumption is removed. That
367
271
is, a variant tag does not belong to any type in particular, the type
368
272
system will just check that it is an admissible value according to its
369
273
use. You need not define a type before using a variant tag. A variant
370
type will be inferred independently for each of its uses.<BR>
373
<H3 CLASS="subsection">Basic use</H3>
374
In programs, polymorphic variants work like usual ones. You just have
274
type will be inferred independently for each of its uses.</P><H3 CLASS="subsection">Basic use</H3><P>In programs, polymorphic variants work like usual ones. You just have
375
275
to prefix their names with a backquote character <TT>`</TT>.
376
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>[`On; `Off];;
276
</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>[`On; `Off];;
377
277
</FONT><FONT COLOR=maroon>- : [> `Off | `On ] list = [`On; `Off]
379
279
<FONT COLOR=black>#</FONT><FONT COLOR=blue>`Number 1;;
380
280
</FONT>- : [> `Number of int ] = `Number 1
382
282
<FONT COLOR=black>#</FONT><FONT COLOR=blue>let f = function `On -> 1 | `Off -> 0 | `Number n -> n;;
383
283
</FONT>val f : [< `Number of int | `Off | `On ] -> int = <fun>
385
285
<FONT COLOR=black>#</FONT><FONT COLOR=blue>List.map f [`On; `Off];;
386
286
</FONT>- : int list = [1; 0]
388
288
<TT>[>`Off|`On] list</TT> means that to match this list, you should at
389
289
least be able to match <TT>`Off</TT> and <TT>`On</TT>, without argument.
390
290
<TT>[<`On|`Off|`Number of int]</TT> means that <TT>f</TT> may be applied to <TT>`Off</TT>,
394
294
refined, either by defining more tags or allowing less. As such they
395
295
contain an implicit type variable. Both variant types appearing only
396
296
once in the type, the implicit type variables they constrain are not
399
The above variant types were polymorphic, allowing further refinement.
297
shown.</P><P>The above variant types were polymorphic, allowing further refinement.
400
298
When writing type annotations, one will most often describe fixed
401
299
variant types, that is types that can be no longer refined. This is
402
300
also the case for type abbreviations. Such types do not contain <TT><</TT> or
403
301
<TT>></TT>, but just an enumeration of the tags and their associated types,
404
302
just like in a normal datatype definition.
405
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>type 'a vlist = [`Nil | `Cons of 'a * 'a vlist];;
303
</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>type 'a vlist = [`Nil | `Cons of 'a * 'a vlist];;
406
304
</FONT><FONT COLOR=maroon>type 'a vlist = [ `Cons of 'a * 'a vlist | `Nil ]
408
306
<FONT COLOR=black>#</FONT><FONT COLOR=blue>let rec map f : 'a vlist -> 'b vlist = function
409
307
| `Nil -> `Nil
410
308
| `Cons(a, l) -> `Cons(f a, map f l)
412
310
</FONT>val map : ('a -> 'b) -> 'a vlist -> 'b vlist = <fun>
415
<H3 CLASS="subsection">Advanced use</H3>
416
Type-checking polymorphic variants is a subtle thing, and some
417
expressions may result in more complex type information.
418
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let f = function `A -> `C | `B -> `D | x -> x;;
311
</FONT></PRE><H3 CLASS="subsection">Advanced use</H3><P>Type-checking polymorphic variants is a subtle thing, and some
312
expressions may result in more complex type information.</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let f = function `A -> `C | `B -> `D | x -> x;;
419
313
</FONT><FONT COLOR=maroon>val f : ([> `A | `B | `C | `D ] as 'a) -> 'a = <fun>
421
315
<FONT COLOR=black>#</FONT><FONT COLOR=blue>f `E;;
422
316
</FONT>- : [> `A | `B | `C | `D | `E ] = `E
424
318
Here we are seeing two phenomena. First, since this matching is open
425
319
(the last case catches any tag), we obtain the type <TT>[> `A | `B]</TT>
426
320
rather than <TT>[< `A | `B]</TT> in a closed matching. Then, since <TT>x</TT> is
427
321
returned as is, input and return types are identical. The notation <TT>as 'a</TT> denotes such type sharing. If we apply <TT>f</TT> to yet another tag
428
<TT>`E</TT>, it gets added to the list.
429
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let f1 = function `A x -> x = 1 | `B -> true | `C -> false
322
<TT>`E</TT>, it gets added to the list.</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let f1 = function `A x -> x = 1 | `B -> true | `C -> false
430
323
let f2 = function `A x -> x = "a" | `B -> true ;;
431
324
</FONT><FONT COLOR=maroon>val f1 : [< `A of int | `B | `C ] -> bool = <fun>
432
325
val f2 : [< `A of string | `B ] -> bool = <fun>
434
327
<FONT COLOR=black>#</FONT><FONT COLOR=blue>let f x = f1 x && f2 x;;
435
328
</FONT>val f : [< `A of string & int | `B ] -> bool = <fun>
437
330
Here <TT>f1</TT> and <TT>f2</TT> both accept the variant tags <TT>`A</TT> and <TT>`B</TT>, but the
438
331
argument of <TT>`A</TT> is <TT>int</TT> for <TT>f1</TT> and <TT>string</TT> for <TT>f2</TT>. In <TT>f</TT>'s
439
332
type <TT>`C</TT>, only accepted by <TT>f1</TT>, disappears, but both argument types
440
333
appear for <TT>`A</TT> as <TT>int & string</TT>. This means that if we
441
334
pass the variant tag <TT>`A</TT> to <TT>f</TT>, its argument should be <EM>both</EM>
442
335
<TT>int</TT> and <TT>string</TT>. Since there is no such value, <TT>f</TT> cannot be
443
applied to <TT>`A</TT>, and <TT>`B</TT> is the only accepted input.<BR>
445
Even if a value has a fixed variant type, one can still give it a
336
applied to <TT>`A</TT>, and <TT>`B</TT> is the only accepted input.</P><P>Even if a value has a fixed variant type, one can still give it a
446
337
larger type through coercions. Coercions are normally written with
447
338
both the source type and the destination type, but in simple cases the
448
339
source type may be omitted.
449
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>type 'a wlist = [`Nil | `Cons of 'a * 'a wlist | `Snoc of 'a wlist * 'a];;
340
</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>type 'a wlist = [`Nil | `Cons of 'a * 'a wlist | `Snoc of 'a wlist * 'a];;
450
341
</FONT><FONT COLOR=maroon>type 'a wlist = [ `Cons of 'a * 'a wlist | `Nil | `Snoc of 'a wlist * 'a ]
452
343
<FONT COLOR=black>#</FONT><FONT COLOR=blue>let wlist_of_vlist l = (l : 'a vlist :> 'a wlist);;
453
344
</FONT>val wlist_of_vlist : 'a vlist -> 'a wlist = <fun>
455
346
<FONT COLOR=black>#</FONT><FONT COLOR=blue>let open_vlist l = (l : 'a vlist :> [> 'a vlist]);;
456
347
</FONT>val open_vlist : 'a vlist -> [> 'a vlist ] = <fun>
458
349
<FONT COLOR=black>#</FONT><FONT COLOR=blue>fun x -> (x :> [`A|`B|`C]);;
459
350
</FONT>- : [< `A | `B | `C ] -> [ `A | `B | `C ] = <fun>
461
You may also selectively coerce values through pattern matching.
462
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let split_cases = function
351
</FONT></PRE><P>You may also selectively coerce values through pattern matching.
352
</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let split_cases = function
463
353
| `Nil | `Cons _ as x -> `A x
464
354
| `Snoc _ as x -> `B x
466
356
</FONT><FONT COLOR=maroon>val split_cases :
467
357
[< `Cons of 'a | `Nil | `Snoc of 'b ] ->
468
358
[> `A of [> `Cons of 'a | `Nil ] | `B of [> `Snoc of 'b ] ] = <fun>
470
360
When an or-pattern composed of variant tags is wrapped inside an
471
361
alias-pattern, the alias is given a type containing only the tags
472
362
enumerated in the or-pattern. This allows for many useful idioms, like
473
incremental definition of functions.
474
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let num x = `Num x
363
incremental definition of functions.</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let num x = `Num x
475
364
let eval1 eval (`Num x) = x
476
365
let rec eval x = eval1 eval x ;;
477
366
</FONT><FONT COLOR=maroon>val num : 'a -> [> `Num of 'a ] = <fun>
478
367
val eval1 : 'a -> [< `Num of 'b ] -> 'b = <fun>
479
368
val eval : [< `Num of 'a ] -> 'a = <fun>
481
370
<FONT COLOR=black>#</FONT><FONT COLOR=blue>let plus x y = `Plus(x,y)
482
371
let eval2 eval = function
483
372
| `Plus(x,y) -> eval x + eval y
486
375
</FONT>val plus : 'a -> 'b -> [> `Plus of 'a * 'b ] = <fun>
487
376
val eval2 : ('a -> int) -> [< `Num of int | `Plus of 'a * 'a ] -> int = <fun>
488
377
val eval : ([< `Num of int | `Plus of 'a * 'a ] as 'a) -> int = <fun>
490
To make this even more confortable, you may use type definitions as
378
</FONT></PRE><P>To make this even more confortable, you may use type definitions as
491
379
abbreviations for or-patterns. That is, if you have defined <TT>type myvariant = [`Tag1 int | `Tag2 bool]</TT>, then the pattern <TT>#myvariant</TT> is
492
equivalent to writing <TT>(`Tag1(_ : int) | `Tag2(_ : bool))</TT>.<BR>
494
Such abbreviations may be used alone,
495
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let f = function
380
equivalent to writing <TT>(`Tag1(_ : int) | `Tag2(_ : bool))</TT>.</P><P>Such abbreviations may be used alone,
381
</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let f = function
496
382
| #myvariant -> "myvariant"
497
383
| `Tag3 -> "Tag3";;
498
384
</FONT><FONT COLOR=maroon>val f : [< `Tag1 of int | `Tag2 of bool | `Tag3 ] -> string = <fun>
500
386
or combined with with aliases.
501
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let g1 = function `Tag1 _ -> "Tag1" | `Tag2 _ -> "Tag2";;
387
</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let g1 = function `Tag1 _ -> "Tag1" | `Tag2 _ -> "Tag2";;
502
388
</FONT><FONT COLOR=maroon>val g1 : [< `Tag1 of 'a | `Tag2 of 'b ] -> string = <fun>
504
390
<FONT COLOR=black>#</FONT><FONT COLOR=blue>let g = function
505
391
| #myvariant as x -> g1 x
506
392
| `Tag3 -> "Tag3";;
507
393
</FONT>val g : [< `Tag1 of int | `Tag2 of bool | `Tag3 ] -> string = <fun>
510
<H3 CLASS="subsection"><A NAME="htoc42">4.2.1</A> Weaknesses of polymorphic variants</H3>
511
After seeing the power of polymorphic variants, one may wonder why
512
they were added to core language variants, rather than replacing them.<BR>
514
The answer is two fold. One first aspect is that while being pretty
394
</FONT></PRE><H3 CLASS="subsection"><A NAME="htoc42">4.2.1</A>��Weaknesses of polymorphic variants</H3><P>After seeing the power of polymorphic variants, one may wonder why
395
they were added to core language variants, rather than replacing them.</P><P>The answer is two fold. One first aspect is that while being pretty
515
396
efficient, the lack of static type information allows for less
516
397
optimizations, and makes polymorphic variants slightly heavier than
517
398
core language ones. However noticeable differences would only
518
appear on huge data structures.<BR>
520
More important is the fact that polymorphic variants, while being
399
appear on huge data structures.</P><P>More important is the fact that polymorphic variants, while being
521
400
type-safe, result in a weaker type discipline. That is, core language
522
401
variants do actually much more than ensuring type-safety, they also
523
402
check that you use only declared constructors, that all constructors
524
403
present in a data-structure are compatible, and they enforce typing
525
constraints to their parameters.<BR>
527
For this reason, you must be more careful about making types explicit
404
constraints to their parameters.</P><P>For this reason, you must be more careful about making types explicit
528
405
when you use polymorphic variants. When you write a library, this is
529
406
easy since you can describe exact types in interfaces, but for simple
530
programs you are probably better off with core language variants.<BR>
532
Beware also that certain idioms make trivial errors very hard to find.
407
programs you are probably better off with core language variants.</P><P>Beware also that some idioms make trivial errors very hard to find.
533
408
For instance, the following code is probably wrong but the compiler
534
409
has no way to see it.
535
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>type abc = [`A | `B | `C] ;;
410
</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>type abc = [`A | `B | `C] ;;
536
411
</FONT><FONT COLOR=maroon>type abc = [ `A | `B | `C ]
538
413
<FONT COLOR=black>#</FONT><FONT COLOR=blue>let f = function
540
415
| #abc -> "other" ;;
541
416
</FONT>val f : [< `A | `As | `B | `C ] -> string = <fun>
543
418
<FONT COLOR=black>#</FONT><FONT COLOR=blue>let f : abc -> string = f ;;
544
419
</FONT>val f : abc -> string = <fun>
546
421
You can avoid such risks by annotating the definition itself.
547
<PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let f : abc -> string = function
422
</P><PRE><FONT COLOR=black>#</FONT><FONT COLOR=blue>let f : abc -> string = function
548
423
| <U>`As</U> -> "A"
549
424
| #abc -> "other" ;;
550
425
</FONT><FONT COLOR=maroon>Warning U: this match case is unused.
551
426
val f : abc -> string = <fun>
555
<HR WIDTH="50%" SIZE=1><DL CLASS="list"><DT CLASS="dt-list"><FONT SIZE=5><A NAME="note1" HREF="#text1">1</A></FONT><DD CLASS="dd-list">This correspond to the commuting label mode
427
</FONT></PRE><HR CLASS="ffootnoterule"><DL CLASS="thefootnotes"><DT CLASS="dt-thefootnotes">
428
<A NAME="note1" HREF="#text1">1</A></DT><DD CLASS="dd-thefootnotes">This correspond to the commuting label mode
556
429
of Objective Caml 3.00 through 3.02, with some additional flexibility
557
430
on total applications. The so-called classic mode (<TT>-nolabels</TT>
558
431
options) is now deprecated for normal use.
561
<A HREF="manual005.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
562
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Up"></A>
563
<A HREF="manual007.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
434
<A HREF="manual005.html"><IMG SRC="previous_motif.gif" ALT="Previous"></A>
435
<A HREF="index.html"><IMG SRC="contents_motif.gif" ALT="Up"></A>
436
<A HREF="manual007.html"><IMG SRC="next_motif.gif" ALT="Next"></A>