File: generalizedopens.html

package info (click to toggle)
ocaml-doc 4.11-2
  • links: PTS, VCS
  • area: non-free
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 20,580 kB
  • sloc: sh: 37; makefile: 11
file content (194 lines) | stat: -rw-r--r-- 10,529 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
<!DOCTYPE html>
<html>
<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="generator" content="hevea 2.32">

  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">
<link rel="stylesheet" type="text/css" href="manual.css">
<title>8.22  Generalized open statements</title>
</head>
<body>
<a href="alerts.html"><img src="previous_motif.svg" alt="Previous"></a>
<a href="extn.html"><img src="contents_motif.svg" alt="Up"></a>
<a href="bindingops.html"><img src="next_motif.svg" alt="Next"></a>
<hr>
<h2 class="section" id="s:generalized-open"><a class="section-anchor" href="#s:generalized-open" aria-hidden="true"></a>8.22  Generalized open statements</h2>
<p>(Introduced in 4.08)</p><div class="syntax"><table class="display dcenter"><tr class="c019"><td class="dcell"><table class="c001 cellpading0"><tr><td class="c018">
<a class="syntax" href="modules.html#definition"><span class="c010">definition</span></a></td><td class="c015">::=</td><td class="c017">
...
 </td></tr>
<tr><td class="c018">&nbsp;</td><td class="c015">∣</td><td class="c017">  <span class="c004">open</span>  <a class="syntax" href="modules.html#module-expr"><span class="c010">module-expr</span></a>
 </td></tr>
<tr><td class="c018">&nbsp;</td><td class="c015">∣</td><td class="c017">  <span class="c004">open!</span> <a class="syntax" href="modules.html#module-expr"><span class="c010">module-expr</span></a>
 </td></tr>
<tr><td class="c018">&nbsp;</td></tr>
<tr><td class="c018">
<a class="syntax" href="modtypes.html#specification"><span class="c010">specification</span></a></td><td class="c015">::=</td><td class="c017">
...
 </td></tr>
<tr><td class="c018">&nbsp;</td><td class="c015">∣</td><td class="c017">  <span class="c004">open</span>  <a class="syntax" href="names.html#extended-module-path"><span class="c010">extended-module-path</span></a>
 </td></tr>
<tr><td class="c018">&nbsp;</td><td class="c015">∣</td><td class="c017">  <span class="c004">open!</span> <a class="syntax" href="names.html#extended-module-path"><span class="c010">extended-module-path</span></a>
 </td></tr>
<tr><td class="c018">&nbsp;</td></tr>
<tr><td class="c018">
<a class="syntax" href="expr.html#expr"><span class="c010">expr</span></a></td><td class="c015">::=</td><td class="c017">
...
 </td></tr>
<tr><td class="c018">&nbsp;</td><td class="c015">∣</td><td class="c017"> <span class="c004">let</span> <span class="c004">open</span>  <a class="syntax" href="modules.html#module-expr"><span class="c010">module-expr</span></a> <span class="c004">in</span>  <a class="syntax" href="expr.html#expr"><span class="c010">expr</span></a>
 </td></tr>
<tr><td class="c018">&nbsp;</td><td class="c015">∣</td><td class="c017"> <span class="c004">let</span> <span class="c004">open!</span> <a class="syntax" href="modules.html#module-expr"><span class="c010">module-expr</span></a> <span class="c004">in</span>  <a class="syntax" href="expr.html#expr"><span class="c010">expr</span></a>
 </td></tr>
<tr><td class="c018">&nbsp;</td></tr>
</table></td></tr>
</table></div><p>This extension makes it possible to open any module expression in
module structures and expressions. A similar mechanism is also available
inside module types, but only for extended module paths (e.g. <span class="c003">F(X).G(Y)</span>).</p><p>For instance, a module can be constrained when opened with</p><div class="caml-example verbatim">

<div class="ocaml">



<div class="pre caml-input"> <span class="ocamlkeyword">module</span> M = <span class="ocamlkeyword">struct</span> <span class="ocamlkeyword">let</span> x = 0 <span class="ocamlkeyword">let</span> hidden = 1 <span class="ocamlkeyword">end</span>
 <span class="ocamlkeyword">open</span> (M:<span class="ocamlkeyword">sig</span> <span class="ocamlkeyword">val</span> x: int <span class="ocamlkeyword">end</span>)
 <span class="ocamlkeyword">let</span> y = <span class="ocamlhighlight">hidden</span></div>



<div class="pre caml-output error"><span class="ocamlerror">Error</span>: Unbound value hidden</div></div>

</div><p>Another possibility is to immediately open the result of a functor application</p><div class="caml-example verbatim">

<div class="ocaml">



<div class="pre caml-input">   <span class="ocamlkeyword">let</span> sort (<span class="ocamlkeyword">type</span> x) (x:x list) =
     <span class="ocamlkeyword">let</span> <span class="ocamlkeyword">open</span> Set.Make(<span class="ocamlkeyword">struct</span> <span class="ocamlkeyword">type</span> t = x <span class="ocamlkeyword">let</span> compare=compare <span class="ocamlkeyword">end</span>) <span class="ocamlkeyword">in</span>
     elements (of_list x)</div>



<div class="pre caml-output ok"><span class="ocamlkeyword">val</span> sort : 'x list -&gt; 'x list = &lt;<span class="ocamlkeyword">fun</span>&gt;</div></div>

</div><p>Going further, this construction can introduce local components inside a
structure,</p><div class="caml-example verbatim">

<div class="ocaml">



<div class="pre caml-input"> <span class="ocamlkeyword">module</span> M = <span class="ocamlkeyword">struct</span>
   <span class="ocamlkeyword">let</span> x = 0
   <span class="ocamlkeyword">open</span>! <span class="ocamlkeyword">struct</span>
     <span class="ocamlkeyword">let</span> x = 0
     <span class="ocamlkeyword">let</span> y = 1
   <span class="ocamlkeyword">end</span>
   <span class="ocamlkeyword">let</span> w = x + y
 <span class="ocamlkeyword">end</span></div>



<div class="pre caml-output ok"><span class="ocamlkeyword">module</span> M : <span class="ocamlkeyword">sig</span> <span class="ocamlkeyword">val</span> x : int <span class="ocamlkeyword">val</span> w : int <span class="ocamlkeyword">end</span></div></div>

</div><p>One important restriction is that types introduced by <span class="c002"><span class="c003">open</span> <span class="c003">struct</span></span> ...
<span class="c004">end</span> cannot appear in the signature of the enclosing structure, unless they
are defined equal to some non-local type.
So:</p><div class="caml-example verbatim">

<div class="ocaml">



<div class="pre caml-input"> <span class="ocamlkeyword">module</span> M = <span class="ocamlkeyword">struct</span>
   <span class="ocamlkeyword">open</span> <span class="ocamlkeyword">struct</span> <span class="ocamlkeyword">type</span> 'a t = 'a option = None | Some <span class="ocamlkeyword">of</span> 'a <span class="ocamlkeyword">end</span>
   <span class="ocamlkeyword">let</span> x : int t = Some 1
 <span class="ocamlkeyword">end</span></div>



<div class="pre caml-output ok"><span class="ocamlkeyword">module</span> M : <span class="ocamlkeyword">sig</span> <span class="ocamlkeyword">val</span> x : int option <span class="ocamlkeyword">end</span></div></div>

</div><p>


is OK, but:</p><div class="caml-example verbatim">

<div class="ocaml">



<div class="pre caml-input"> <span class="ocamlkeyword">module</span> M = <span class="ocamlkeyword">struct</span>
   <span class="ocamlhighlight">open struct type t = A end</span>
   <span class="ocamlkeyword">let</span> x = A
 <span class="ocamlkeyword">end</span></div>



<div class="pre caml-output error"><span class="ocamlerror">Error</span>: The type t/4502 introduced by this open appears in the signature
       File "exten.etex", line 3, characters 6-7:
         The value x has no valid type if t/4502 is hidden</div></div>

</div><p>


is not because <span class="c003">x</span> cannot be given any type other than <span class="c003">t</span>, which only exists
locally. Although the above would be OK if <span class="c003">x</span> too was local:</p><div class="caml-example verbatim">

<div class="ocaml">



<div class="pre caml-input"> <span class="ocamlkeyword">module</span> M: <span class="ocamlkeyword">sig</span> <span class="ocamlkeyword">end</span> = <span class="ocamlkeyword">struct</span>
   <span class="ocamlkeyword">open</span> <span class="ocamlkeyword">struct</span>
   <span class="ocamlkeyword">type</span> t = A
   <span class="ocamlkeyword">end</span>
   <span class="ocamlkeyword">open</span> <span class="ocamlkeyword">struct</span> <span class="ocamlkeyword">let</span> x = A <span class="ocamlkeyword">end</span>
 <span class="ocamlkeyword">end</span></div>



<div class="pre caml-output ok"><span class="ocamlkeyword">module</span> M : <span class="ocamlkeyword">sig</span> <span class="ocamlkeyword">end</span></div></div>

</div><p>Inside signatures, extended opens are limited to extended module paths,


</p><div class="caml-example verbatim">

<div class="ocaml">



<div class="pre caml-input"> <span class="ocamlkeyword">module</span> <span class="ocamlkeyword">type</span> S = <span class="ocamlkeyword">sig</span>
   <span class="ocamlkeyword">module</span> F: <span class="ocamlkeyword">sig</span> <span class="ocamlkeyword">end</span> -&gt; <span class="ocamlkeyword">sig</span> <span class="ocamlkeyword">type</span> t <span class="ocamlkeyword">end</span>
   <span class="ocamlkeyword">module</span> X: <span class="ocamlkeyword">sig</span> <span class="ocamlkeyword">end</span>
   <span class="ocamlkeyword">open</span> F(X)
   <span class="ocamlkeyword">val</span> f: t
 <span class="ocamlkeyword">end</span></div>



<div class="pre caml-output ok"><span class="ocamlkeyword">module</span> <span class="ocamlkeyword">type</span> S =
  <span class="ocamlkeyword">sig</span>
    <span class="ocamlkeyword">module</span> F : <span class="ocamlkeyword">sig</span> <span class="ocamlkeyword">end</span> -&gt; <span class="ocamlkeyword">sig</span> <span class="ocamlkeyword">type</span> t <span class="ocamlkeyword">end</span>
    <span class="ocamlkeyword">module</span> X : <span class="ocamlkeyword">sig</span> <span class="ocamlkeyword">end</span>
    <span class="ocamlkeyword">val</span> f : F(X).t
  <span class="ocamlkeyword">end</span></div></div>

</div><p>and not</p><pre>  open struct type t = int end
</pre><p>
In those situations, local substitutions(see <a href="signaturesubstitution.html#ss%3Alocal-substitution">8.7.2</a>)
can be used instead.</p><p>Beware that this extension is not available inside class definitions:</p><pre>class c =
  let open Set.Make(Int) in
  ...
</pre>
<hr>
<a href="alerts.html"><img src="previous_motif.svg" alt="Previous"></a>
<a href="extn.html"><img src="contents_motif.svg" alt="Up"></a>
<a href="bindingops.html"><img src="next_motif.svg" alt="Next"></a>
</body>
</html>