Import Upstream version 20180207
[hcoop/debian/mlton.git] / doc / guide / localhost / UniversalType
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>UniversalType</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();\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>UniversalType</h1>\r
27</div>\r
28<div id="content">\r
29<div id="preamble">\r
30<div class="sectionbody">\r
31<div class="paragraph"><p>A universal type is a type into which all other types can be embedded.\r
32Here&#8217;s a <a href="StandardML">Standard ML</a> signature for a universal type.</p></div>\r
33<div class="listingblock">\r
34<div class="content"><div class="highlight"><pre><span class="k">signature</span><span class="w"> </span><span class="n">UNIVERSAL_TYPE</span><span class="w"> </span><span class="p">=</span><span class="w"></span>\r
35<span class="w"> </span><span class="k">sig</span><span class="w"></span>\r
36<span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="n">t</span><span class="w"></span>\r
37\r
38<span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">embed</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="p">(</span><span class="n">&#39;a</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">t</span><span class="p">)</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="p">(</span><span class="n">t</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="p">)</span><span class="w"></span>\r
39<span class="w"> </span><span class="k">end</span><span class="w"></span>\r
40</pre></div></div></div>\r
41<div class="paragraph"><p>The idea is that <span class="monospaced">type t</span> is the universal type and that each call to\r
42<span class="monospaced">embed</span> returns a new pair of functions <span class="monospaced">(inject, project)</span>, where\r
43<span class="monospaced">inject</span> embeds a value into the universal type and <span class="monospaced">project</span> extracts\r
44the value from the universal type. A pair <span class="monospaced">(inject, project)</span>\r
45returned by <span class="monospaced">embed</span> works together in that <span class="monospaced">project u</span> will return\r
46<span class="monospaced">SOME v</span> if and only if <span class="monospaced">u</span> was created by <span class="monospaced">inject v</span>. If <span class="monospaced">u</span> was\r
47created by a different function <span class="monospaced">inject'</span>, then <span class="monospaced">project</span> returns\r
48<span class="monospaced">NONE</span>.</p></div>\r
49<div class="paragraph"><p>Here&#8217;s an example embedding integers and reals into a universal type.</p></div>\r
50<div class="listingblock">\r
51<div class="content"><div class="highlight"><pre><span class="k">functor</span><span class="w"> </span><span class="n">Test</span><span class="w"> </span><span class="p">(</span><span class="n">U</span><span class="p">:</span><span class="w"> </span><span class="n">UNIVERSAL_TYPE</span><span class="p">):</span><span class="w"> </span><span class="k">sig</span><span class="w"> </span><span class="k">end</span><span class="w"> </span><span class="p">=</span><span class="w"></span>\r
52<span class="w"> </span><span class="k">struct</span><span class="w"></span>\r
53<span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="p">(</span><span class="n">intIn</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">U</span><span class="p">.</span><span class="n">t</span><span class="p">,</span><span class="w"> </span><span class="n">intOut</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">U</span><span class="p">.</span><span class="n">embed</span><span class="w"> </span><span class="p">()</span><span class="w"></span>\r
54<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">U</span><span class="p">.</span><span class="n">t</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="p">(</span><span class="n">intIn</span><span class="w"> </span><span class="mi">13</span><span class="p">)</span><span class="w"></span>\r
55<span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">s1</span><span class="w"> </span><span class="p">=</span><span class="w"></span>\r
56<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="n">intOut</span><span class="w"> </span><span class="p">(</span><span class="n">!r</span><span class="p">)</span><span class="w"> </span><span class="k">of</span><span class="w"></span>\r
57<span class="w"> </span><span class="n">NONE</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="s">&quot;NONE&quot;</span><span class="w"></span>\r
58<span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">SOME</span><span class="w"> </span><span class="n">i</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="n">toString</span><span class="w"> </span><span class="n">i</span><span class="w"></span>\r
59<span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="p">(</span><span class="n">realIn</span><span class="p">:</span><span class="w"> </span><span class="n">real</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">U</span><span class="p">.</span><span class="n">t</span><span class="p">,</span><span class="w"> </span><span class="n">realOut</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">U</span><span class="p">.</span><span class="n">embed</span><span class="w"> </span><span class="p">()</span><span class="w"></span>\r
60<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">realIn</span><span class="w"> </span><span class="mf">13.0</span><span class="w"></span>\r
61<span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">s2</span><span class="w"> </span><span class="p">=</span><span class="w"></span>\r
62<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="n">intOut</span><span class="w"> </span><span class="p">(</span><span class="n">!r</span><span class="p">)</span><span class="w"> </span><span class="k">of</span><span class="w"></span>\r
63<span class="w"> </span><span class="n">NONE</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="s">&quot;NONE&quot;</span><span class="w"></span>\r
64<span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">SOME</span><span class="w"> </span><span class="n">i</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="n">toString</span><span class="w"> </span><span class="n">i</span><span class="w"></span>\r
65<span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">s3</span><span class="w"> </span><span class="p">=</span><span class="w"></span>\r
66<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="n">realOut</span><span class="w"> </span><span class="p">(</span><span class="n">!r</span><span class="p">)</span><span class="w"> </span><span class="k">of</span><span class="w"></span>\r
67<span class="w"> </span><span class="n">NONE</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="s">&quot;NONE&quot;</span><span class="w"></span>\r
68<span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">SOME</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">Real</span><span class="p">.</span><span class="n">toString</span><span class="w"> </span><span class="n">x</span><span class="w"></span>\r
69<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">print</span><span class="w"> </span><span class="p">(</span><span class="n">concat</span><span class="w"> </span><span class="p">[</span><span class="n">s1</span><span class="p">,</span><span class="w"> </span><span class="s">&quot; &quot;</span><span class="p">,</span><span class="w"> </span><span class="n">s2</span><span class="p">,</span><span class="w"> </span><span class="s">&quot; &quot;</span><span class="p">,</span><span class="w"> </span><span class="n">s3</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">])</span><span class="w"></span>\r
70<span class="w"> </span><span class="k">end</span><span class="w"></span>\r
71</pre></div></div></div>\r
72<div class="paragraph"><p>Applying <span class="monospaced">Test</span> to an appropriate implementation will print</p></div>\r
73<div class="listingblock">\r
74<div class="content monospaced">\r
75<pre>13 NONE 13.0</pre>\r
76</div></div>\r
77<div class="paragraph"><p>Note that two different calls to embed on the same type return\r
78different embeddings.</p></div>\r
79<div class="paragraph"><p>Standard ML does not have explicit support for universal types;\r
80however, there are at least two ways to implement them.</p></div>\r
81</div>\r
82</div>\r
83<div class="sect1">\r
84<h2 id="_implementation_using_exceptions">Implementation Using Exceptions</h2>\r
85<div class="sectionbody">\r
86<div class="paragraph"><p>While the intended use of SML exceptions is for exception handling, an\r
87accidental feature of their design is that the <span class="monospaced">exn</span> type is a\r
88universal type. The implementation relies on being able to declare\r
89exceptions locally to a function and on the fact that exceptions are\r
90<a href="GenerativeException">generative</a>.</p></div>\r
91<div class="listingblock">\r
92<div class="content"><div class="highlight"><pre><span class="k">structure</span><span class="w"> </span><span class="n">U</span><span class="p">:&gt;</span><span class="w"> </span><span class="n">UNIVERSAL_TYPE</span><span class="w"> </span><span class="p">=</span><span class="w"></span>\r
93<span class="w"> </span><span class="k">struct</span><span class="w"></span>\r
94<span class="w"> </span><span class="k">type</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">exn</span><span class="w"></span>\r
95\r
96<span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">embed</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=</span><span class="w"></span>\r
97<span class="w"> </span><span class="k">let</span><span class="w"></span>\r
98<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">&#39;a</span><span class="w"></span>\r
99<span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">project</span><span class="w"> </span><span class="p">(</span><span class="n">e</span><span class="p">:</span><span class="w"> </span><span class="n">t</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="p">=</span><span class="w"></span>\r
100<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="n">e</span><span class="w"> </span><span class="k">of</span><span class="w"></span>\r
101<span class="w"> </span><span class="n">E</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="n">SOME</span><span class="w"> </span><span class="n">a</span><span class="w"></span>\r
102<span class="w"> </span><span class="p">|</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">NONE</span><span class="w"></span>\r
103<span class="w"> </span><span class="k">in</span><span class="w"></span>\r
104<span class="w"> </span><span class="p">(</span><span class="n">E</span><span class="p">,</span><span class="w"> </span><span class="n">project</span><span class="p">)</span><span class="w"></span>\r
105<span class="w"> </span><span class="k">end</span><span class="w"></span>\r
106<span class="w"> </span><span class="k">end</span><span class="w"></span>\r
107</pre></div></div></div>\r
108</div>\r
109</div>\r
110<div class="sect1">\r
111<h2 id="_implementation_using_functions_and_references">Implementation Using Functions and References</h2>\r
112<div class="sectionbody">\r
113<div class="listingblock">\r
114<div class="content"><div class="highlight"><pre><span class="k">structure</span><span class="w"> </span><span class="n">U</span><span class="p">:&gt;</span><span class="w"> </span><span class="n">UNIVERSAL_TYPE</span><span class="w"> </span><span class="p">=</span><span class="w"></span>\r
115<span class="w"> </span><span class="k">struct</span><span class="w"></span>\r
116<span class="w"> </span><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="p">{</span><span class="n">clear</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">unit</span><span class="p">,</span><span class="w"></span>\r
117<span class="w"> </span><span class="n">store</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">unit</span><span class="p">}</span><span class="w"></span>\r
118\r
119<span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">embed</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=</span><span class="w"></span>\r
120<span class="w"> </span><span class="k">let</span><span class="w"></span>\r
121<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
122<span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">inject</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="p">):</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"></span>\r
123<span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="p">{</span><span class="n">clear</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">r</span><span class="w"> </span><span class="n">:=</span><span class="w"> </span><span class="n">NONE</span><span class="p">,</span><span class="w"></span>\r
124<span class="w"> </span><span class="n">store</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">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">a</span><span class="p">}</span><span class="w"></span>\r
125<span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">project</span><span class="w"> </span><span class="p">(</span><span class="n">T</span><span class="w"> </span><span class="p">{</span><span class="n">clear</span><span class="p">,</span><span class="w"> </span><span class="n">store</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="p">=</span><span class="w"></span>\r
126<span class="w"> </span><span class="k">let</span><span class="w"></span>\r
127<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">store</span><span class="w"> </span><span class="p">()</span><span class="w"></span>\r
128<span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">res</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">!r</span><span class="w"></span>\r
129<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">clear</span><span class="w"> </span><span class="p">()</span><span class="w"></span>\r
130<span class="w"> </span><span class="k">in</span><span class="w"></span>\r
131<span class="w"> </span><span class="n">res</span><span class="w"></span>\r
132<span class="w"> </span><span class="k">end</span><span class="w"></span>\r
133<span class="w"> </span><span class="k">in</span><span class="w"></span>\r
134<span class="w"> </span><span class="p">(</span><span class="n">inject</span><span class="p">,</span><span class="w"> </span><span class="n">project</span><span class="p">)</span><span class="w"></span>\r
135<span class="w"> </span><span class="k">end</span><span class="w"></span>\r
136<span class="w"> </span><span class="k">end</span><span class="w"></span>\r
137</pre></div></div></div>\r
138<div class="paragraph"><p>Note that due to the use of a shared ref cell, the above\r
139implementation is not thread safe.</p></div>\r
140<div class="paragraph"><p>One could try to simplify the above implementation by eliminating the\r
141<span class="monospaced">clear</span> function, making <span class="monospaced">type t = unit -&gt; unit</span>.</p></div>\r
142<div class="listingblock">\r
143<div class="content"><div class="highlight"><pre><span class="k">structure</span><span class="w"> </span><span class="n">U</span><span class="p">:&gt;</span><span class="w"> </span><span class="n">UNIVERSAL_TYPE</span><span class="w"> </span><span class="p">=</span><span class="w"></span>\r
144<span class="w"> </span><span class="k">struct</span><span class="w"></span>\r
145<span class="w"> </span><span class="k">type</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">unit</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="n">unit</span><span class="w"></span>\r
146\r
147<span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">embed</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=</span><span class="w"></span>\r
148<span class="w"> </span><span class="k">let</span><span class="w"></span>\r
149<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
150<span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">inject</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="p">):</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">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">a</span><span class="w"></span>\r
151<span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">project</span><span class="w"> </span><span class="p">(</span><span class="n">f</span><span class="p">:</span><span class="w"> </span><span class="n">t</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="p">=</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="n">NONE</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><span class="n">!r</span><span class="p">)</span><span class="w"></span>\r
152<span class="w"> </span><span class="k">in</span><span class="w"></span>\r
153<span class="w"> </span><span class="p">(</span><span class="n">inject</span><span class="p">,</span><span class="w"> </span><span class="n">project</span><span class="p">)</span><span class="w"></span>\r
154<span class="w"> </span><span class="k">end</span><span class="w"></span>\r
155<span class="w"> </span><span class="k">end</span><span class="w"></span>\r
156</pre></div></div></div>\r
157<div class="paragraph"><p>While correct, this approach keeps the contents of the ref cell alive\r
158longer than necessary, which could cause a space leak. The problem is\r
159in <span class="monospaced">project</span>, where the call to <span class="monospaced">f</span> stores some value in some ref cell\r
160<span class="monospaced">r'</span>. Perhaps <span class="monospaced">r'</span> is the same ref cell as <span class="monospaced">r</span>, but perhaps not. If\r
161we do not clear <span class="monospaced">r'</span> before returning from <span class="monospaced">project</span>, then <span class="monospaced">r'</span> will\r
162keep the value alive, even though it is useless.</p></div>\r
163</div>\r
164</div>\r
165<div class="sect1">\r
166<h2 id="_also_see">Also see</h2>\r
167<div class="sectionbody">\r
168<div class="ulist"><ul>\r
169<li>\r
170<p>\r
171<a href="PropertyList">PropertyList</a>: Lisp-style property lists implemented with a universal type\r
172</p>\r
173</li>\r
174</ul></div>\r
175</div>\r
176</div>\r
177</div>\r
178<div id="footnotes"><hr></div>\r
179<div id="footer">\r
180<div id="footer-text">\r
181</div>\r
182<div id="footer-badges">\r
183</div>\r
184</div>\r
185</body>\r
186</html>\r