Import Upstream version 20180207
[hcoop/debian/mlton.git] / doc / guide / localhost / ValueRestriction
CommitLineData
7f918cf1
CE
1<!DOCTYPE html>\r
2<html lang="en">\r
3<head>\r
4<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">\r
5<meta name="generator" content="AsciiDoc 8.6.9">\r
6<title>ValueRestriction</title>\r
7<link rel="stylesheet" href="./asciidoc.css" type="text/css">\r
8<link rel="stylesheet" href="./pygments.css" type="text/css">\r
9\r
10\r
11<script type="text/javascript" src="./asciidoc.js"></script>\r
12<script type="text/javascript">\r
13/*<![CDATA[*/\r
14asciidoc.install(2);\r
15/*]]>*/\r
16</script>\r
17<link rel="stylesheet" href="./mlton.css" type="text/css">\r
18</head>\r
19<body class="article">\r
20<div id="banner">\r
21<div id="banner-home">\r
22<a href="./Home">MLton 20180207</a>\r
23</div>\r
24</div>\r
25<div id="header">\r
26<h1>ValueRestriction</h1>\r
27<div id="toc">
28 <div id="toctitle">Table of Contents</div>
29 <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
30</div>\r
31</div>\r
32<div id="content">\r
33<div id="preamble">\r
34<div class="sectionbody">\r
35<div class="paragraph"><p>The value restriction is a rule that governs when type inference is\r
36allowed to polymorphically generalize a value declaration. In short,\r
37the value restriction says that generalization can only occur if the\r
38right-hand side of an expression is syntactically a value. For\r
39example, in</p></div>\r
40<div class="listingblock">\r
41<div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="n">x</span><span class="w"></span>\r
42<span class="k">val</span><span class="w"> </span><span class="p">_</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">(</span><span class="n">f</span><span class="w"> </span><span class="s">&quot;foo&quot;</span><span class="p">;</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="mi">13</span><span class="p">)</span><span class="w"></span>\r
43</pre></div></div></div>\r
44<div class="paragraph"><p>the expression <span class="monospaced">fn x =&gt; x</span> is syntactically a value, so <span class="monospaced">f</span> has\r
45polymorphic type <span class="monospaced">'a -&gt; 'a</span> and both calls to <span class="monospaced">f</span> type check. On the\r
46other hand, in</p></div>\r
47<div class="listingblock">\r
48<div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">let</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="k">end</span><span class="w"></span>\r
49<span class="k">val</span><span class="w"> </span><span class="p">_</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">(</span><span class="n">f</span><span class="w"> </span><span class="s">&quot;foo&quot;</span><span class="p">;</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="mi">13</span><span class="p">)</span><span class="w"></span>\r
50</pre></div></div></div>\r
51<div class="paragraph"><p>the expression <span class="monospaced">let in fn x =&gt; end end</span> is not syntactically a value\r
52and so <span class="monospaced">f</span> can either have type <span class="monospaced">int -&gt; int</span> or <span class="monospaced">string -&gt; string</span>,\r
53but not <span class="monospaced">'a -&gt; 'a</span>. Hence, the program does not type check.</p></div>\r
54<div class="paragraph"><p><a href="DefinitionOfStandardML">The Definition of Standard ML</a> spells out\r
55precisely which expressions are syntactic values (it refers to such\r
56expressions as <em>non-expansive</em>). An expression is a value if it is of\r
57one of the following forms.</p></div>\r
58<div class="ulist"><ul>\r
59<li>\r
60<p>\r
61a constant (<span class="monospaced">13</span>, <span class="monospaced">"foo"</span>, <span class="monospaced">13.0</span>, &#8230;)\r
62</p>\r
63</li>\r
64<li>\r
65<p>\r
66a variable (<span class="monospaced">x</span>, <span class="monospaced">y</span>, &#8230;)\r
67</p>\r
68</li>\r
69<li>\r
70<p>\r
71a function (<span class="monospaced">fn x =&gt; e</span>)\r
72</p>\r
73</li>\r
74<li>\r
75<p>\r
76the application of a constructor other than <span class="monospaced">ref</span> to a value (<span class="monospaced">Foo v</span>)\r
77</p>\r
78</li>\r
79<li>\r
80<p>\r
81a type constrained value (<span class="monospaced">v: t</span>)\r
82</p>\r
83</li>\r
84<li>\r
85<p>\r
86a tuple in which each field is a value <span class="monospaced">(v1, v2, ...)</span>\r
87</p>\r
88</li>\r
89<li>\r
90<p>\r
91a record in which each field is a value <span class="monospaced">{l1 = v1, l2 = v2, ...}</span>\r
92</p>\r
93</li>\r
94<li>\r
95<p>\r
96a list in which each element is a value <span class="monospaced">[v1, v2, ...]</span>\r
97</p>\r
98</li>\r
99</ul></div>\r
100</div>\r
101</div>\r
102<div class="sect1">\r
103<h2 id="_why_the_value_restriction_exists">Why the value restriction exists</h2>\r
104<div class="sectionbody">\r
105<div class="paragraph"><p>The value restriction prevents a ref cell (or an array) from holding\r
106values of different types, which would allow a value of one type to be\r
107cast to another and hence would break type safety. If the restriction\r
108were not in place, the following program would type check.</p></div>\r
109<div class="listingblock">\r
110<div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">r</span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">option</span><span class="w"> </span><span class="n">ref</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">ref</span><span class="w"> </span><span class="n">NONE</span><span class="w"></span>\r
111<span class="k">val</span><span class="w"> </span><span class="n">r1</span><span class="p">:</span><span class="w"> </span><span class="n">string</span><span class="w"> </span><span class="n">option</span><span class="w"> </span><span class="n">ref</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">r</span><span class="w"></span>\r
112<span class="k">val</span><span class="w"> </span><span class="n">r2</span><span class="p">:</span><span class="w"> </span><span class="n">int</span><span class="w"> </span><span class="n">option</span><span class="w"> </span><span class="n">ref</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">r</span><span class="w"></span>\r
113<span class="k">val</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">r1</span><span class="w"> </span><span class="n">:=</span><span class="w"> </span><span class="n">SOME</span><span class="w"> </span><span class="s">&quot;foo&quot;</span><span class="w"></span>\r
114<span class="k">val</span><span class="w"> </span><span class="n">v</span><span class="p">:</span><span class="w"> </span><span class="n">int</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">valOf</span><span class="w"> </span><span class="p">(</span><span class="n">!r2</span><span class="p">)</span><span class="w"></span>\r
115</pre></div></div></div>\r
116<div class="paragraph"><p>The first line violates the value restriction because <span class="monospaced">ref NONE</span> is\r
117not a value. All other lines are type correct. By its last line, the\r
118program has cast the string <span class="monospaced">"foo"</span> to an integer. This breaks type\r
119safety, because now we can add a string to an integer with an\r
120expression like <span class="monospaced">v + 13</span>. We could even be more devious, by adding\r
121the following two lines, which allow us to threat the string <span class="monospaced">"foo"</span>\r
122as a function.</p></div>\r
123<div class="listingblock">\r
124<div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">r3</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">int</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">int</span><span class="p">)</span><span class="w"> </span><span class="n">option</span><span class="w"> </span><span class="n">ref</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">r</span><span class="w"></span>\r
125<span class="k">val</span><span class="w"> </span><span class="n">v</span><span class="p">:</span><span class="w"> </span><span class="n">int</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">int</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">valOf</span><span class="w"> </span><span class="p">(</span><span class="n">!r3</span><span class="p">)</span><span class="w"></span>\r
126</pre></div></div></div>\r
127<div class="paragraph"><p>Eliminating the explicit <span class="monospaced">ref</span> does nothing to fix the problem. For\r
128example, we could replace the declaration of <span class="monospaced">r</span> with the following.</p></div>\r
129<div class="listingblock">\r
130<div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">f</span><span class="p">:</span><span class="w"> </span><span class="n">unit</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">option</span><span class="w"> </span><span class="n">ref</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="n">ref</span><span class="w"> </span><span class="n">NONE</span><span class="w"></span>\r
131<span class="k">val</span><span class="w"> </span><span class="n">r</span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">option</span><span class="w"> </span><span class="n">ref</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">()</span><span class="w"></span>\r
132</pre></div></div></div>\r
133<div class="paragraph"><p>The declaration of <span class="monospaced">f</span> is well typed, while the declaration of <span class="monospaced">r</span>\r
134violates the value restriction because <span class="monospaced">f ()</span> is not a value.</p></div>\r
135</div>\r
136</div>\r
137<div class="sect1">\r
138<h2 id="_unnecessarily_rejected_programs">Unnecessarily rejected programs</h2>\r
139<div class="sectionbody">\r
140<div class="paragraph"><p>Unfortunately, the value restriction rejects some programs that could\r
141be accepted.</p></div>\r
142<div class="listingblock">\r
143<div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">id</span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="n">x</span><span class="w"></span>\r
144<span class="k">val</span><span class="w"> </span><span class="n">f</span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="n">id</span><span class="w"></span>\r
145</pre></div></div></div>\r
146<div class="paragraph"><p>The type constraint on <span class="monospaced">f</span> requires <span class="monospaced">f</span> to be polymorphic, which is\r
147disallowed because <span class="monospaced">id id</span> is not a value. MLton reports the\r
148following type error.</p></div>\r
149<div class="listingblock">\r
150<div class="content monospaced">\r
151<pre>Error: z.sml 2.5-2.5.\r
152 Type of variable cannot be generalized in expansive declaration: f.\r
153 type: ['a] -&gt; ['a]\r
154 in: val 'a f: ('a -&gt; 'a) = id id</pre>\r
155</div></div>\r
156<div class="paragraph"><p>MLton indicates the inability to make <span class="monospaced">f</span> polymorphic by saying that\r
157the type of <span class="monospaced">f</span> cannot be generalized (made polymorphic) its\r
158declaration is expansive (not a value). MLton doesn&#8217;t explicitly\r
159mention the value restriction, but that is the reason. If we leave\r
160the type constraint off of <span class="monospaced">f</span></p></div>\r
161<div class="listingblock">\r
162<div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">id</span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="n">x</span><span class="w"></span>\r
163<span class="k">val</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="n">id</span><span class="w"></span>\r
164</pre></div></div></div>\r
165<div class="paragraph"><p>then the program succeeds; however, MLton gives us the following\r
166warning.</p></div>\r
167<div class="listingblock">\r
168<div class="content monospaced">\r
169<pre>Warning: z.sml 2.5-2.5.\r
170 Type of variable was not inferred and could not be generalized: f.\r
171 type: ??? -&gt; ???\r
172 in: val f = id id</pre>\r
173</div></div>\r
174<div class="paragraph"><p>This warning indicates that MLton couldn&#8217;t polymorphically generalize\r
175<span class="monospaced">f</span>, nor was there enough context using <span class="monospaced">f</span> to determine its type.\r
176This in itself is not a type error, but it it is a hint that something\r
177is wrong with our program. Using <span class="monospaced">f</span> provides enough context to\r
178eliminate the warning.</p></div>\r
179<div class="listingblock">\r
180<div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">id</span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="n">x</span><span class="w"></span>\r
181<span class="k">val</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="n">id</span><span class="w"></span>\r
182<span class="k">val</span><span class="w"> </span><span class="p">_</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="mi">13</span><span class="w"></span>\r
183</pre></div></div></div>\r
184<div class="paragraph"><p>But attempting to use <span class="monospaced">f</span> as a polymorphic function will fail.</p></div>\r
185<div class="listingblock">\r
186<div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">id</span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="n">x</span><span class="w"></span>\r
187<span class="k">val</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="n">id</span><span class="w"></span>\r
188<span class="k">val</span><span class="w"> </span><span class="p">_</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="mi">13</span><span class="w"></span>\r
189<span class="k">val</span><span class="w"> </span><span class="p">_</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="s">&quot;foo&quot;</span><span class="w"></span>\r
190</pre></div></div></div>\r
191<div class="listingblock">\r
192<div class="content monospaced">\r
193<pre>Error: z.sml 4.9-4.15.\r
194 Function applied to incorrect argument.\r
195 expects: [int]\r
196 but got: [string]\r
197 in: f "foo"</pre>\r
198</div></div>\r
199</div>\r
200</div>\r
201<div class="sect1">\r
202<h2 id="_alternatives_to_the_value_restriction">Alternatives to the value restriction</h2>\r
203<div class="sectionbody">\r
204<div class="paragraph"><p>There would be nothing wrong with treating <span class="monospaced">f</span> as polymorphic in</p></div>\r
205<div class="listingblock">\r
206<div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">id</span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="n">x</span><span class="w"></span>\r
207<span class="k">val</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="n">id</span><span class="w"></span>\r
208</pre></div></div></div>\r
209<div class="paragraph"><p>One might think that the value restriction could be relaxed, and that\r
210only types involving <span class="monospaced">ref</span> should be disallowed. Unfortunately, the\r
211following example shows that even the type <span class="monospaced">'a -&gt; 'a</span> can cause\r
212problems. If this program were allowed, then we could cast an integer\r
213to a string (or any other type).</p></div>\r
214<div class="listingblock">\r
215<div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">f</span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">=</span><span class="w"></span>\r
216<span class="w"> </span><span class="k">let</span><span class="w"></span>\r
217<span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">r</span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">option</span><span class="w"> </span><span class="n">ref</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">ref</span><span class="w"> </span><span class="n">NONE</span><span class="w"></span>\r
218<span class="w"> </span><span class="k">in</span><span class="w"></span>\r
219<span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"></span>\r
220<span class="w"> </span><span class="k">let</span><span class="w"></span>\r
221<span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">!r</span><span class="w"></span>\r
222<span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="n">:=</span><span class="w"> </span><span class="n">SOME</span><span class="w"> </span><span class="n">x</span><span class="w"></span>\r
223<span class="w"> </span><span class="k">in</span><span class="w"></span>\r
224<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="k">of</span><span class="w"></span>\r
225<span class="w"> </span><span class="n">NONE</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="n">x</span><span class="w"></span>\r
226<span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">SOME</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="n">y</span><span class="w"></span>\r
227<span class="w"> </span><span class="k">end</span><span class="w"></span>\r
228<span class="w"> </span><span class="k">end</span><span class="w"></span>\r
229<span class="k">val</span><span class="w"> </span><span class="p">_</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="mi">13</span><span class="w"></span>\r
230<span class="k">val</span><span class="w"> </span><span class="p">_</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="s">&quot;foo&quot;</span><span class="w"></span>\r
231</pre></div></div></div>\r
232<div class="paragraph"><p>The previous version of Standard ML took a different approach\r
233(<a href="References#MilnerEtAl90">MilnerEtAl90</a>, <a href="References#Tofte90">Tofte90</a>, <a href="ImperativeTypeVariable">ImperativeTypeVariable</a>)\r
234than the value restriction. It encoded information in the type system\r
235about when ref cells would be created, and used this to prevent a ref\r
236cell from holding multiple types. Although it allowed more programs\r
237to be type checked, this approach had significant drawbacks. First,\r
238it was significantly more complex, both for implementers and for\r
239programmers. Second, it had an unfortunate interaction with the\r
240modularity, because information about ref usage was exposed in module\r
241signatures. This either prevented the use of references for\r
242implementing a signature, or required information that one would like\r
243to keep hidden to propagate across modules.</p></div>\r
244<div class="paragraph"><p>In the early nineties, Andrew Wright studied about 250,000 lines of\r
245existing SML code and discovered that it did not make significant use\r
246of the extended typing ability, and proposed the value restriction as\r
247a simpler alternative (<a href="References#Wright95">Wright95</a>). This was adopted in the\r
248revised <a href="DefinitionOfStandardML">Definition</a>.</p></div>\r
249</div>\r
250</div>\r
251<div class="sect1">\r
252<h2 id="_working_with_the_value_restriction">Working with the value restriction</h2>\r
253<div class="sectionbody">\r
254<div class="paragraph"><p>One technique that works with the value restriction is\r
255<a href="EtaExpansion">EtaExpansion</a>. We can use eta expansion to make our <span class="monospaced">id id</span>\r
256example type check follows.</p></div>\r
257<div class="listingblock">\r
258<div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">id</span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="n">x</span><span class="w"></span>\r
259<span class="k">val</span><span class="w"> </span><span class="n">f</span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">(</span><span class="n">id</span><span class="w"> </span><span class="n">id</span><span class="p">)</span><span class="w"> </span><span class="n">z</span><span class="w"></span>\r
260</pre></div></div></div>\r
261<div class="paragraph"><p>This solution means that the computation (in this case <span class="monospaced">id id</span>) will\r
262be performed each time <span class="monospaced">f</span> is applied, instead of just once when <span class="monospaced">f</span>\r
263is declared. In this case, that is not a problem, but it could be if\r
264the declaration of <span class="monospaced">f</span> performs substantial computation or creates a\r
265shared data structure.</p></div>\r
266<div class="paragraph"><p>Another technique that sometimes works is to move a monomorphic\r
267computation prior to a (would-be) polymorphic declaration so that the\r
268expression is a value. Consider the following program, which fails\r
269due to the value restriction.</p></div>\r
270<div class="listingblock">\r
271<div class="content"><div class="highlight"><pre><span class="k">datatype</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">string</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">B</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"></span>\r
272<span class="k">val</span><span class="w"> </span><span class="n">x</span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="p">(</span><span class="k">if</span><span class="w"> </span><span class="n">true</span><span class="w"> </span><span class="k">then</span><span class="w"> </span><span class="s">&quot;yes&quot;</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="s">&quot;no&quot;</span><span class="p">)</span><span class="w"></span>\r
273</pre></div></div></div>\r
274<div class="paragraph"><p>It is easy to rewrite this program as</p></div>\r
275<div class="listingblock">\r
276<div class="content"><div class="highlight"><pre><span class="k">datatype</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">string</span><span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">B</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"></span>\r
277<span class="k">local</span><span class="w"></span>\r
278<span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">true</span><span class="w"> </span><span class="k">then</span><span class="w"> </span><span class="s">&quot;yes&quot;</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="s">&quot;no&quot;</span><span class="w"></span>\r
279<span class="k">in</span><span class="w"></span>\r
280<span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">x</span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="n">s</span><span class="w"></span>\r
281<span class="k">end</span><span class="w"></span>\r
282</pre></div></div></div>\r
283<div class="paragraph"><p>The following example (taken from <a href="References#Wright95">Wright95</a>) creates a ref\r
284cell to count the number of times a function is called.</p></div>\r
285<div class="listingblock">\r
286<div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">count</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">&#39;a</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">&#39;a</span><span class="p">)</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="p">(</span><span class="n">&#39;a</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">&#39;a</span><span class="p">)</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="p">(</span><span class="n">unit</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">int</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"></span>\r
287<span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"></span>\r
288<span class="w"> </span><span class="k">let</span><span class="w"></span>\r
289<span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">ref</span><span class="w"> </span><span class="mi">0</span><span class="w"></span>\r
290<span class="w"> </span><span class="k">in</span><span class="w"></span>\r
291<span class="w"> </span><span class="p">(</span><span class="k">fn</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">(</span><span class="n">r</span><span class="w"> </span><span class="n">:=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">+</span><span class="w"> </span><span class="n">!r</span><span class="p">;</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">x</span><span class="p">),</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="n">!r</span><span class="p">)</span><span class="w"></span>\r
292<span class="w"> </span><span class="k">end</span><span class="w"></span>\r
293<span class="k">val</span><span class="w"> </span><span class="n">id</span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="n">x</span><span class="w"></span>\r
294<span class="k">val</span><span class="w"> </span><span class="p">(</span><span class="n">countId</span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">&#39;a</span><span class="p">,</span><span class="w"> </span><span class="n">numCalls</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">count</span><span class="w"> </span><span class="n">id</span><span class="w"></span>\r
295</pre></div></div></div>\r
296<div class="paragraph"><p>The example does not type check, due to the value restriction.\r
297However, it is easy to rewrite the program, staging the ref cell\r
298creation before the polymorphic code.</p></div>\r
299<div class="listingblock">\r
300<div class="content"><div class="highlight"><pre><span class="k">datatype</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">int</span><span class="w"> </span><span class="n">ref</span><span class="w"></span>\r
301<span class="k">val</span><span class="w"> </span><span class="n">count1</span><span class="p">:</span><span class="w"> </span><span class="n">unit</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="p">(</span><span class="n">ref</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"></span>\r
302<span class="k">val</span><span class="w"> </span><span class="n">count2</span><span class="p">:</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="p">(</span><span class="n">&#39;a</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">&#39;a</span><span class="p">)</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="p">(</span><span class="n">unit</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">int</span><span class="p">)</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="p">(</span><span class="n">&#39;a</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">&#39;a</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"></span>\r
303<span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="p">(</span><span class="n">T</span><span class="w"> </span><span class="n">r</span><span class="p">,</span><span class="w"> </span><span class="n">f</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">(</span><span class="k">fn</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="n">!r</span><span class="p">,</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">(</span><span class="n">r</span><span class="w"> </span><span class="n">:=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">+</span><span class="w"> </span><span class="n">!r</span><span class="p">;</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">x</span><span class="p">))</span><span class="w"></span>\r
304<span class="k">val</span><span class="w"> </span><span class="n">id</span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="n">x</span><span class="w"></span>\r
305<span class="k">val</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">count1</span><span class="w"> </span><span class="p">()</span><span class="w"></span>\r
306<span class="k">val</span><span class="w"> </span><span class="n">countId</span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">#</span><span class="mi">2</span><span class="w"> </span><span class="p">(</span><span class="n">count2</span><span class="w"> </span><span class="p">(</span><span class="n">t</span><span class="p">,</span><span class="w"> </span><span class="n">id</span><span class="p">))</span><span class="w"> </span><span class="n">z</span><span class="w"></span>\r
307<span class="k">val</span><span class="w"> </span><span class="n">numCalls</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">#</span><span class="mi">1</span><span class="w"> </span><span class="p">(</span><span class="n">count2</span><span class="w"> </span><span class="p">(</span><span class="n">t</span><span class="p">,</span><span class="w"> </span><span class="n">id</span><span class="p">))</span><span class="w"></span>\r
308</pre></div></div></div>\r
309<div class="paragraph"><p>Of course, one can hide the constructor <span class="monospaced">T</span> inside a <span class="monospaced">local</span> or behind\r
310a signature.</p></div>\r
311</div>\r
312</div>\r
313<div class="sect1">\r
314<h2 id="_also_see">Also see</h2>\r
315<div class="sectionbody">\r
316<div class="ulist"><ul>\r
317<li>\r
318<p>\r
319<a href="ImperativeTypeVariable">ImperativeTypeVariable</a>\r
320</p>\r
321</li>\r
322</ul></div>\r
323</div>\r
324</div>\r
325</div>\r
326<div id="footnotes"><hr></div>\r
327<div id="footer">\r
328<div id="footer-text">\r
329</div>\r
330<div id="footer-badges">\r
331</div>\r
332</div>\r
333</body>\r
334</html>\r