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 195 196 197 198 199 200 201 202 203 204 205 206 207
|
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="generator" content="AsciiDoc 8.6.8">
<title>TypeVariableScope</title>
<link rel="stylesheet" href="./asciidoc.css" type="text/css">
<link rel="stylesheet" href="./pygments.css" type="text/css">
<script type="text/javascript" src="./asciidoc.js"></script>
<script type="text/javascript">
/*<![CDATA[*/
asciidoc.install();
/*]]>*/
</script>
<link rel="stylesheet" href="./mlton.css" type="text/css"/>
</head>
<body class="article">
<div id="banner">
<div id="banner-home">
<a href="./Home">MLton 20130715</a>
</div>
</div>
<div id="header">
<h1>TypeVariableScope</h1>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph"><p>In <a href="StandardML">Standard ML</a>, every type variable is <em>scoped</em> (or
bound) at a particular point in the program. A type variable can be
either implicitly scoped or explicitly scoped. For example, <span class="monospaced">'a</span> is
implicitly scoped in</p></div>
<div class="listingblock">
<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">'a</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="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="n">x</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>and is implicitly scoped in</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">id</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="p">:</span><span class="w"> </span><span class="n">'a</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="n">x</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>On the other hand, <span class="monospaced">'a</span> is explicitly scoped in</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">'a</span><span class="w"> </span><span class="n">id</span><span class="p">:</span><span class="w"> </span><span class="n">'a</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="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="n">x</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>and is explicitly scoped in</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">'a</span><span class="w"> </span><span class="n">id</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="p">:</span><span class="w"> </span><span class="n">'a</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="n">x</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>A type variable can be scoped at a <span class="monospaced">val</span> or <span class="monospaced">fun</span> declaration. An SML
type checker performs scope inference on each top-level declaration to
determine the scope of each implicitly scoped type variable. After
scope inference, every type variable is scoped at exactly one
enclosing <span class="monospaced">val</span> or <span class="monospaced">fun</span> declaration. Scope inference shows that the
first and second example above are equivalent to the third and fourth
example, respectively.</p></div>
<div class="paragraph"><p>Section 4.6 of the <a href="DefinitionOfStandardML">Definition</a> specifies
precisely the scope of an implicitly scoped type variable. A free
occurrence of a type variable <span class="monospaced">'a</span> in a declaration <span class="monospaced">d</span> is said to be
<em>unguarded</em> in <span class="monospaced">d</span> if <span class="monospaced">'a</span> is not part of a smaller declaration. A
type variable <span class="monospaced">'a</span> is implicitly scoped at <span class="monospaced">d</span> if <span class="monospaced">'a</span> is unguarded in
<span class="monospaced">d</span> and <span class="monospaced">'a</span> does not occur unguarded in any declaration containing
<span class="monospaced">d</span>.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_scope_inference_examples">Scope inference examples</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
<p>
In this example,
</p>
<div class="listingblock">
<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">'a</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="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="n">x</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p><span class="monospaced">'a</span> is unguarded in <span class="monospaced">val id</span> and does not occur unguarded in any
containing declaration. Hence, <span class="monospaced">'a</span> is scoped at <span class="monospaced">val id</span> and the
declaration is equivalent to the following.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">'a</span><span class="w"> </span><span class="n">id</span><span class="p">:</span><span class="w"> </span><span class="n">'a</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="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="n">x</span><span class="w"></span>
</pre></div></div></div>
</li>
<li>
<p>
In this example,
</p>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="w"> </span><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">=></span><span class="w"> </span><span class="k">let</span><span class="w"> </span><span class="k">exception</span><span class="w"> </span><span class="n">E</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">'a</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">E</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="k">end</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p><span class="monospaced">'a</span> is unguarded in <span class="monospaced">val f</span> and does not occur unguarded in any
containing declaration. Hence, <span class="monospaced">'a</span> is scoped at <span class="monospaced">val f</span> and the
declaration is equivalent to the following.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">'a</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">=></span><span class="w"> </span><span class="k">let</span><span class="w"> </span><span class="k">exception</span><span class="w"> </span><span class="n">E</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">'a</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">E</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="k">end</span><span class="w"></span>
</pre></div></div></div>
</li>
<li>
<p>
In this example (taken from the <a href="DefinitionOfStandardML">Definition</a>),
</p>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><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">int</span><span class="w"> </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="k">let</span><span class="w"> </span><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">'a</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="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="k">end</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p><span class="monospaced">'a</span> occurs unguarded in <span class="monospaced">val id</span>, but not in <span class="monospaced">val x</span>. Hence, <span class="monospaced">'a</span> is
implicitly scoped at <span class="monospaced">val id</span>, and the declaration is equivalent to
the following.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><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">int</span><span class="w"> </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="k">let</span><span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">'a</span><span class="w"> </span><span class="n">id</span><span class="p">:</span><span class="w"> </span><span class="n">'a</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="w"> </span><span class="k">fn</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="k">end</span><span class="w"></span>
</pre></div></div></div>
</li>
<li>
<p>
In this example,
</p>
<div class="listingblock">
<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="p">(</span><span class="k">fn</span><span class="w"> </span><span class="n">x</span><span class="p">:</span><span class="w"> </span><span class="n">'a</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="k">fn</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">y</span><span class="p">)</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p><span class="monospaced">'a</span> occurs unguarded in <span class="monospaced">val f</span> and does not occur unguarded in any
containing declaration. Hence, <span class="monospaced">'a</span> is implicitly scoped at <span class="monospaced">val f</span>,
and the declaration is equivalent to the following.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">'a</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">(</span><span class="k">fn</span><span class="w"> </span><span class="n">x</span><span class="p">:</span><span class="w"> </span><span class="n">'a</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="k">fn</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">y</span><span class="p">)</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>This does not type check due to the <a href="ValueRestriction">ValueRestriction</a>.</p></div>
</li>
<li>
<p>
In this example,
</p>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="k">fun</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=</span><span class="w"></span>
<span class="w"> </span><span class="k">let</span><span class="w"></span>
<span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="p">(</span><span class="n">y</span><span class="p">:</span><span class="w"> </span><span class="n">'a</span><span class="p">)</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="n">x</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="n">y</span><span class="w"></span>
<span class="w"> </span><span class="k">in</span><span class="w"></span>
<span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="n">x</span><span class="w"></span>
<span class="w"> </span><span class="k">end</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p><span class="monospaced">'a</span> occurs unguarded in <span class="monospaced">fun g</span>, not in <span class="monospaced">fun f</span>. Hence, <span class="monospaced">'a</span> is
implicitly scoped at <span class="monospaced">fun g</span>, and the declaration is equivalent to</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="k">fun</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">=</span><span class="w"></span>
<span class="w"> </span><span class="k">let</span><span class="w"></span>
<span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">'a</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="p">(</span><span class="n">y</span><span class="p">:</span><span class="w"> </span><span class="n">'a</span><span class="p">)</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="n">x</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="n">y</span><span class="w"></span>
<span class="w"> </span><span class="k">in</span><span class="w"></span>
<span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="n">x</span><span class="w"></span>
<span class="w"> </span><span class="k">end</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>This fails to type check because <span class="monospaced">x</span> and <span class="monospaced">y</span> must have the same type,
and hence <span class="monospaced">'a</span> can not be generalized at <span class="monospaced">fun g</span>. MLton reports the
following error.</p></div>
<div class="listingblock">
<div class="content monospaced">
<pre>Error: scope.sml 3.7.
Unable to generalize 'a.
in: fun 'a g ((y): 'a) = (if true then x else y)</pre>
</div></div>
<div class="paragraph"><p>This problem could be fixed either by adding an explicit type
constraint, as in <span class="monospaced">fun f (x: 'a)</span>, or by explicitly scoping <span class="monospaced">'a</span>, as
in <span class="monospaced">fun 'a f x</span>.</p></div>
</li>
</ul></div>
</div>
</div>
<div class="sect1">
<h2 id="_restrictions_on_type_variable_scope">Restrictions on type variable scope</h2>
<div class="sectionbody">
<div class="paragraph"><p>It is not allowed to scope a type variable within a declaration in
which it is already in scope (see the last restriction listed on page
9 of the <a href="DefinitionOfStandardML">Definition</a>). For example, the
following program is invalid.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="k">fun</span><span class="w"> </span><span class="n">'a</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="p">:</span><span class="w"> </span><span class="n">'a</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"></span>
<span class="w"> </span><span class="k">let</span><span class="w"></span>
<span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">'a</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="p">(</span><span class="n">y</span><span class="p">:</span><span class="w"> </span><span class="n">'a</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">y</span><span class="w"></span>
<span class="w"> </span><span class="k">in</span><span class="w"></span>
<span class="w"> </span><span class="p">()</span><span class="w"></span>
<span class="w"> </span><span class="k">end</span><span class="w"></span>
</pre></div></div></div>
<div class="paragraph"><p>MLton reports the following error.</p></div>
<div class="listingblock">
<div class="content monospaced">
<pre>Error: z.sml 3.11.
Type variable 'a scoped at an outer declaration.</pre>
</div></div>
<div class="paragraph"><p>This is an error even if the scoping is implicit. That is, the
following program is invalid as well.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="k">fun</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="p">:</span><span class="w"> </span><span class="n">'a</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"></span>
<span class="w"> </span><span class="k">let</span><span class="w"></span>
<span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">'a</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="p">(</span><span class="n">y</span><span class="p">:</span><span class="w"> </span><span class="n">'a</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">y</span><span class="w"></span>
<span class="w"> </span><span class="k">in</span><span class="w"></span>
<span class="w"> </span><span class="p">()</span><span class="w"></span>
<span class="w"> </span><span class="k">end</span><span class="w"></span>
</pre></div></div></div>
</div>
</div>
</div>
<div id="footnotes"><hr></div>
<div id="footer">
<div id="footer-text">
</div>
<div id="footer-badges">
</div>
</div>
</body>
</html>
|