Import Upstream version 20180207
[hcoop/debian/mlton.git] / doc / guide / localhost / Fixpoints
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
5 <meta name="generator" content="AsciiDoc 8.6.9">
6 <title>Fixpoints</title>
7 <link rel="stylesheet" href="./asciidoc.css" type="text/css">
8 <link rel="stylesheet" href="./pygments.css" type="text/css">
9
10
11 <script type="text/javascript" src="./asciidoc.js"></script>
12 <script type="text/javascript">
13 /*<![CDATA[*/
14 asciidoc.install();
15 /*]]>*/
16 </script>
17 <link rel="stylesheet" href="./mlton.css" type="text/css">
18 </head>
19 <body class="article">
20 <div id="banner">
21 <div id="banner-home">
22 <a href="./Home">MLton 20180207</a>
23 </div>
24 </div>
25 <div id="header">
26 <h1>Fixpoints</h1>
27 </div>
28 <div id="content">
29 <div id="preamble">
30 <div class="sectionbody">
31 <div class="paragraph"><p>This page discusses a framework that makes it possible to compute
32 fixpoints over arbitrary products of abstract types. The code is from
33 an Extended Basis library
34 (<a href="https://github.com/MLton/mltonlib/blob/master/com/ssh/extended-basis/unstable/README"><span class="monospaced">README</span></a>).</p></div>
35 <div class="paragraph"><p>First the signature of the framework
36 (<a href="https://github.com/MLton/mltonlib/blob/master/com/ssh/extended-basis/unstable/public/generic/tie.sig"><span class="monospaced">tie.sig</span></a>):</p></div>
37 <div class="listingblock">
38 <div class="content"><div class="highlight"><pre><span class="cm">(**</span>
39 <span class="cm"> * A framework for computing fixpoints.</span>
40 <span class="cm"> *</span>
41 <span class="cm"> * In a strict language you sometimes want to provide a fixpoint</span>
42 <span class="cm"> * combinator for an abstract type {t} to make it possible to write</span>
43 <span class="cm"> * recursive definitions. Unfortunately, a single combinator {fix} of the</span>
44 <span class="cm"> * type {(t -&gt; t) -&gt; t} does not support mutual recursion. To support</span>
45 <span class="cm"> * mutual recursion, you would need to provide a family of fixpoint</span>
46 <span class="cm"> * combinators having types of the form {(u -&gt; u) -&gt; u} where {u} is a</span>
47 <span class="cm"> * type of the form {t * ... * t}. Unfortunately, even such a family of</span>
48 <span class="cm"> * fixpoint combinators does not support mutual recursion over different</span>
49 <span class="cm"> * abstract types.</span>
50 <span class="cm"> *)</span><span class="w"></span>
51 <span class="k">signature</span><span class="w"> </span><span class="n">TIE</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">sig</span><span class="w"></span>
52 <span class="w"> </span><span class="k">include</span><span class="w"> </span><span class="n">ETAEXP&#39;</span><span class="w"></span>
53 <span class="w"> </span><span class="k">type</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">&#39;a</span><span class="w"> </span><span class="n">etaexp</span><span class="w"></span>
54 <span class="w"> </span><span class="cm">(** The type of fixpoint witnesses. *)</span><span class="w"></span>
55
56 <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">fix</span><span class="w"> </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">-&gt;</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">Fix</span><span class="p">.</span><span class="n">t</span><span class="w"></span>
57 <span class="w"> </span><span class="cm">(**</span>
58 <span class="cm"> * Produces a fixpoint combinator from the given witness. For example,</span>
59 <span class="cm"> * one can make a mutually recursive definition of functions:</span>
60 <span class="cm"> *</span>
61 <span class="cm"> *&gt; val isEven &amp; isOdd =</span>
62 <span class="cm"> *&gt; let open Tie in fix (function *` function) end</span>
63 <span class="cm"> *&gt; (fn isEven &amp; isOdd =&gt;</span>
64 <span class="cm"> *&gt; (fn 0 =&gt; true</span>
65 <span class="cm"> *&gt; | 1 =&gt; false</span>
66 <span class="cm"> *&gt; | n =&gt; isOdd (n-1)) &amp;</span>
67 <span class="cm"> *&gt; (fn 0 =&gt; false</span>
68 <span class="cm"> *&gt; | 1 =&gt; true</span>
69 <span class="cm"> *&gt; | n =&gt; isEven (n-1)))</span>
70 <span class="cm"> *)</span><span class="w"></span>
71
72 <span class="w"> </span><span class="cm">(** == Making New Witnesses == *)</span><span class="w"></span>
73
74 <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">pure</span><span class="w"> </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="n">*</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">UnOp</span><span class="p">.</span><span class="n">t</span><span class="p">)</span><span class="w"> </span><span class="n">Thunk</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">t</span><span class="w"></span>
75 <span class="w"> </span><span class="cm">(**</span>
76 <span class="cm"> * {pure} is a more general version of {tier}. It is mostly useful for</span>
77 <span class="cm"> * computing fixpoints in a non-imperative manner.</span>
78 <span class="cm"> *)</span><span class="w"></span>
79
80 <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">tier</span><span class="w"> </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="n">*</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">Effect</span><span class="p">.</span><span class="n">t</span><span class="p">)</span><span class="w"> </span><span class="n">Thunk</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">t</span><span class="w"></span>
81 <span class="w"> </span><span class="cm">(**</span>
82 <span class="cm"> * {tier} is used to define fixpoint witnesses for new abstract types</span>
83 <span class="cm"> * by providing a thunk whose instantiation allocates a mutable proxy</span>
84 <span class="cm"> * and a procedure for updating it with the result.</span>
85 <span class="cm"> *)</span><span class="w"></span>
86
87 <span class="w"> </span><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="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="n">t</span><span class="w"></span>
88 <span class="w"> </span><span class="cm">(** {id x} is equivalent to {pure (const (x, id))}. *)</span><span class="w"></span>
89
90 <span class="w"> </span><span class="cm">(** == Combining Existing Witnesses == *)</span><span class="w"></span>
91
92 <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">iso</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">&#39;b</span><span class="w"> </span><span class="n">t</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="p">,</span><span class="w"> </span><span class="n">&#39;b</span><span class="p">)</span><span class="w"> </span><span class="n">Iso</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">t</span><span class="w"></span>
93 <span class="w"> </span><span class="cm">(**</span>
94 <span class="cm"> * Given an isomorphism between {&#39;a} and {&#39;b} and a witness for {&#39;b},</span>
95 <span class="cm"> * produces a witness for {&#39;a}. This is useful when you have a new</span>
96 <span class="cm"> * type that is isomorphic to some old type for which you already have</span>
97 <span class="cm"> * a witness.</span>
98 <span class="cm"> *)</span><span class="w"></span>
99
100 <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">product</span><span class="w"> </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="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;b</span><span class="w"> </span><span class="n">t</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="p">,</span><span class="w"> </span><span class="n">&#39;b</span><span class="p">)</span><span class="w"> </span><span class="n">Product</span><span class="p">.</span><span class="n">t</span><span class="w"> </span><span class="n">t</span><span class="w"></span>
101 <span class="w"> </span><span class="cm">(**</span>
102 <span class="cm"> * Dependent product combinator. Given a witness for {&#39;a} and a</span>
103 <span class="cm"> * constructor from a {&#39;a} to witness for {&#39;b}, produces a witness for</span>
104 <span class="cm"> * the product {(&#39;a, &#39;b) Product.t}. The constructor for {&#39;b} should</span>
105 <span class="cm"> * not access the (proxy) value {&#39;a} before it has been fixed.</span>
106 <span class="cm"> *)</span><span class="w"></span>
107
108 <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">*`</span><span class="w"> </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="n">*</span><span class="w"> </span><span class="n">&#39;b</span><span class="w"> </span><span class="n">t</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="p">,</span><span class="w"> </span><span class="n">&#39;b</span><span class="p">)</span><span class="w"> </span><span class="n">Product</span><span class="p">.</span><span class="n">t</span><span class="w"> </span><span class="n">t</span><span class="w"></span>
109 <span class="w"> </span><span class="cm">(** {a *` b} is equivalent to {product (a, const b)}. *)</span><span class="w"></span>
110
111 <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">tuple2</span><span class="w"> </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="n">*</span><span class="w"> </span><span class="n">&#39;b</span><span class="w"> </span><span class="n">t</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="n">*</span><span class="w"> </span><span class="n">&#39;b</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"></span>
112 <span class="w"> </span><span class="cm">(**</span>
113 <span class="cm"> * Given witnesses for {&#39;a} and {&#39;b} produces a witness for the product</span>
114 <span class="cm"> * {&#39;a * &#39;b}.</span>
115 <span class="cm"> *)</span><span class="w"></span>
116
117 <span class="w"> </span><span class="cm">(** == Particular Witnesses == *)</span><span class="w"></span>
118
119 <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">function</span><span class="w"> </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;b</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"></span>
120 <span class="w"> </span><span class="cm">(** Witness for functions. *)</span><span class="w"></span>
121 <span class="k">end</span><span class="w"></span>
122 </pre></div></div></div>
123 <div class="paragraph"><p><span class="monospaced">fix</span> is a <a href="TypeIndexedValues">type-indexed</a> function. The type-index
124 parameter to <span class="monospaced">fix</span> is called a "witness". To compute fixpoints over
125 products, one uses the <span class="monospaced">*&grave;</span> operator to combine witnesses. To provide
126 a fixpoint combinator for an abstract type, one implements a witness
127 providing a thunk whose instantiation allocates a fresh, mutable proxy
128 and a procedure for updating the proxy with the solution. Naturally
129 this means that not all possible ways of computing a fixpoint of a
130 particular type are possible under the framework. The <span class="monospaced">pure</span>
131 combinator is a generalization of <span class="monospaced">tier</span>. The <span class="monospaced">iso</span> combinator is
132 provided for reusing existing witnesses.</p></div>
133 <div class="paragraph"><p>Note that instead of using an infix operator, we could alternatively
134 employ an interface using <a href="Fold">Fold</a>. Also, witnesses are eta-expanded
135 to work around the <a href="ValueRestriction">value restriction</a>, while
136 maintaining abstraction.</p></div>
137 <div class="paragraph"><p>Here is the implementation
138 (<a href="https://github.com/MLton/mltonlib/blob/master/com/ssh/extended-basis/unstable/detail/generic/tie.sml"><span class="monospaced">tie.sml</span></a>):</p></div>
139 <div class="listingblock">
140 <div class="content"><div class="highlight"><pre><span class="k">structure</span><span class="w"> </span><span class="n">Tie</span><span class="w"> </span><span class="p">:&gt;</span><span class="w"> </span><span class="n">TIE</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">struct</span><span class="w"></span>
141 <span class="w"> </span><span class="k">open</span><span class="w"> </span><span class="n">Product</span><span class="w"></span>
142 <span class="w"> </span><span class="k">infix</span><span class="w"> </span><span class="n">&amp;</span><span class="w"></span>
143 <span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">etaexp_dom</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">Unit</span><span class="p">.</span><span class="n">t</span><span class="w"></span>
144 <span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">etaexp_cod</span><span class="w"> </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="n">*</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">UnOp</span><span class="p">.</span><span class="n">t</span><span class="p">)</span><span class="w"> </span><span class="n">Thunk</span><span class="p">.</span><span class="n">t</span><span class="w"></span>
145 <span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">etaexp</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">etaexp_dom</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">etaexp_cod</span><span class="w"></span>
146 <span class="w"> </span><span class="k">type</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">&#39;a</span><span class="w"> </span><span class="n">etaexp</span><span class="w"></span>
147 <span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">fix</span><span class="w"> </span><span class="n">aT</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">val</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">ta</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">aT</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">ta</span><span class="w"> </span><span class="p">(</span><span class="n">f</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="k">end</span><span class="w"></span>
148 <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">Thunk</span><span class="p">.</span><span class="n">mk</span><span class="w"></span>
149 <span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">iso</span><span class="w"> </span><span class="n">bT</span><span class="w"> </span><span class="p">(</span><span class="n">iso</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="p">(_,</span><span class="w"> </span><span class="n">b2a</span><span class="p">))</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="w"> </span><span class="k">let</span><span class="w"></span>
150 <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="p">(</span><span class="n">b</span><span class="p">,</span><span class="w"> </span><span class="n">fB</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">bT</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">()</span><span class="w"></span>
151 <span class="w"> </span><span class="k">in</span><span class="w"></span>
152 <span class="w"> </span><span class="p">(</span><span class="n">b2a</span><span class="w"> </span><span class="n">b</span><span class="p">,</span><span class="w"> </span><span class="n">Fn</span><span class="p">.</span><span class="n">map</span><span class="w"> </span><span class="n">iso</span><span class="w"> </span><span class="n">fB</span><span class="p">)</span><span class="w"></span>
153 <span class="w"> </span><span class="k">end</span><span class="w"></span>
154 <span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">product</span><span class="w"> </span><span class="p">(</span><span class="n">aT</span><span class="p">,</span><span class="w"> </span><span class="n">a2bT</span><span class="p">)</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="w"> </span><span class="k">let</span><span class="w"></span>
155 <span class="w"> </span><span class="k">val</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">fA</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">aT</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">()</span><span class="w"></span>
156 <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="p">(</span><span class="n">b</span><span class="p">,</span><span class="w"> </span><span class="n">fB</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">a2bT</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">()</span><span class="w"></span>
157 <span class="w"> </span><span class="k">in</span><span class="w"></span>
158 <span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="n">&amp;</span><span class="w"> </span><span class="n">b</span><span class="p">,</span><span class="w"> </span><span class="n">Product</span><span class="p">.</span><span class="n">map</span><span class="w"> </span><span class="p">(</span><span class="n">fA</span><span class="p">,</span><span class="w"> </span><span class="n">fB</span><span class="p">))</span><span class="w"></span>
159 <span class="w"> </span><span class="k">end</span><span class="w"></span>
160 <span class="w"> </span><span class="cm">(* The rest are not primitive operations. *)</span><span class="w"></span>
161 <span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="k">op</span><span class="w"> </span><span class="n">*`</span><span class="w"> </span><span class="p">(</span><span class="n">aT</span><span class="p">,</span><span class="w"> </span><span class="n">bT</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">product</span><span class="w"> </span><span class="p">(</span><span class="n">aT</span><span class="p">,</span><span class="w"> </span><span class="n">Fn</span><span class="p">.</span><span class="n">const</span><span class="w"> </span><span class="n">bT</span><span class="p">)</span><span class="w"></span>
162 <span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">tuple2</span><span class="w"> </span><span class="n">ab</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">iso</span><span class="w"> </span><span class="p">(</span><span class="k">op</span><span class="w"> </span><span class="n">*`</span><span class="w"> </span><span class="n">ab</span><span class="p">)</span><span class="w"> </span><span class="n">Product</span><span class="p">.</span><span class="n">isoTuple2</span><span class="w"></span>
163 <span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">tier</span><span class="w"> </span><span class="n">th</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="p">((</span><span class="k">fn</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">ua</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">a</span><span class="p">,</span><span class="w"> </span><span class="n">Fn</span><span class="p">.</span><span class="n">const</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">o</span><span class="w"> </span><span class="n">ua</span><span class="p">))</span><span class="w"> </span><span class="n">o</span><span class="w"> </span><span class="n">th</span><span class="p">)</span><span class="w"></span>
164 <span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">id</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">pure</span><span class="w"> </span><span class="p">(</span><span class="n">Fn</span><span class="p">.</span><span class="n">const</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">Fn</span><span class="p">.</span><span class="n">id</span><span class="p">))</span><span class="w"></span>
165 <span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">function</span><span class="w"> </span><span class="n">?</span><span class="w"> </span><span class="p">=</span><span class="w"></span>
166 <span class="w"> </span><span class="n">pure</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="k">let</span><span class="w"></span>
167 <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="p">(</span><span class="n">Basic</span><span class="p">.</span><span class="n">raising</span><span class="w"> </span><span class="n">Fix</span><span class="p">.</span><span class="n">Fix</span><span class="p">)</span><span class="w"></span>
168 <span class="w"> </span><span class="k">in</span><span class="w"></span>
169 <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="n">!r</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="n">f</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="n">f</span><span class="w"> </span><span class="p">;</span><span class="w"> </span><span class="n">f</span><span class="p">))</span><span class="w"></span>
170 <span class="w"> </span><span class="k">end</span><span class="p">)</span><span class="w"> </span><span class="n">?</span><span class="w"></span>
171 <span class="k">end</span><span class="w"></span>
172 </pre></div></div></div>
173 <div class="paragraph"><p>Let&#8217;s then take a look at a couple of additional examples.</p></div>
174 <div class="paragraph"><p>Here is a naive implementation of lazy promises:</p></div>
175 <div class="listingblock">
176 <div class="content"><div class="highlight"><pre><span class="k">structure</span><span class="w"> </span><span class="n">Promise</span><span class="w"> </span><span class="p">:&gt;</span><span class="w"> </span><span class="k">sig</span><span class="w"></span>
177 <span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">t</span><span class="w"></span>
178 <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">lazy</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">Thunk</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">t</span><span class="w"></span>
179 <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">force</span><span class="w"> </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">-&gt;</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"></span>
180 <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">&#39;a</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="n">Tie</span><span class="p">.</span><span class="n">t</span><span class="w"></span>
181 <span class="k">end</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">struct</span><span class="w"></span>
182 <span class="w"> </span><span class="k">datatype</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">t&#39;</span><span class="w"> </span><span class="p">=</span><span class="w"></span>
183 <span class="w"> </span><span class="n">EXN</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">exn</span><span class="w"></span>
184 <span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">THUNK</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">Thunk</span><span class="p">.</span><span class="n">t</span><span class="w"></span>
185 <span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">VALUE</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"></span>
186 <span class="w"> </span><span class="k">type</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">&#39;a</span><span class="w"> </span><span class="n">t&#39;</span><span class="w"> </span><span class="n">Ref</span><span class="p">.</span><span class="n">t</span><span class="w"></span>
187 <span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">lazy</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">ref</span><span class="w"> </span><span class="p">(</span><span class="n">THUNK</span><span class="w"> </span><span class="n">f</span><span class="p">)</span><span class="w"></span>
188 <span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">force</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">=</span><span class="w"></span>
189 <span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="n">!t</span><span class="w"></span>
190 <span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="n">EXN</span><span class="w"> </span><span class="n">e</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="k">raise</span><span class="w"> </span><span class="n">e</span><span class="w"></span>
191 <span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">THUNK</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">(</span><span class="n">t</span><span class="w"> </span><span class="n">:=</span><span class="w"> </span><span class="n">VALUE</span><span class="w"> </span><span class="p">(</span><span class="n">f</span><span class="w"> </span><span class="p">())</span><span class="w"> </span><span class="k">handle</span><span class="w"> </span><span class="n">e</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="n">:=</span><span class="w"> </span><span class="n">EXN</span><span class="w"> </span><span class="n">e</span><span class="w"> </span><span class="p">;</span><span class="w"> </span><span class="n">force</span><span class="w"> </span><span class="n">t</span><span class="p">)</span><span class="w"></span>
192 <span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">VALUE</span><span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="n">v</span><span class="w"></span>
193 <span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">Y</span><span class="w"> </span><span class="n">?</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">Tie</span><span class="p">.</span><span class="n">tier</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="k">let</span><span class="w"></span>
194 <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">lazy</span><span class="w"> </span><span class="p">(</span><span class="n">raising</span><span class="w"> </span><span class="n">Fix</span><span class="p">.</span><span class="n">Fix</span><span class="p">)</span><span class="w"></span>
195 <span class="w"> </span><span class="k">in</span><span class="w"></span>
196 <span class="w"> </span><span class="p">(</span><span class="n">r</span><span class="p">,</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="n">&lt;\</span><span class="w"> </span><span class="k">op</span><span class="w"> </span><span class="n">:=</span><span class="w"> </span><span class="n">o</span><span class="w"> </span><span class="n">!</span><span class="p">)</span><span class="w"></span>
197 <span class="w"> </span><span class="k">end</span><span class="p">)</span><span class="w"> </span><span class="n">?</span><span class="w"></span>
198 <span class="k">end</span><span class="w"></span>
199 </pre></div></div></div>
200 <div class="paragraph"><p>An example use of our naive lazy promises is to implement equally naive
201 lazy streams:</p></div>
202 <div class="listingblock">
203 <div class="content"><div class="highlight"><pre><span class="k">structure</span><span class="w"> </span><span class="n">Stream</span><span class="w"> </span><span class="p">:&gt;</span><span class="w"> </span><span class="k">sig</span><span class="w"></span>
204 <span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">t</span><span class="w"></span>
205 <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">cons</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">*</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">-&gt;</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">t</span><span class="w"></span>
206 <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">get</span><span class="w"> </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">-&gt;</span><span class="w"> </span><span class="p">(</span><span class="n">&#39;a</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">t</span><span class="p">)</span><span class="w"> </span><span class="n">Option</span><span class="p">.</span><span class="n">t</span><span class="w"></span>
207 <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">&#39;a</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="n">Tie</span><span class="p">.</span><span class="n">t</span><span class="w"></span>
208 <span class="k">end</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">struct</span><span class="w"></span>
209 <span class="w"> </span><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">IN</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="p">(</span><span class="n">&#39;a</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">&#39;a</span><span class="w"> </span><span class="n">t</span><span class="p">)</span><span class="w"> </span><span class="n">Option</span><span class="p">.</span><span class="n">t</span><span class="w"> </span><span class="n">Promise</span><span class="p">.</span><span class="n">t</span><span class="w"></span>
210 <span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">cons</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">xs</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">IN</span><span class="w"> </span><span class="p">(</span><span class="n">Promise</span><span class="p">.</span><span class="n">lazy</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">SOME</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">xs</span><span class="p">)))</span><span class="w"></span>
211 <span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">get</span><span class="w"> </span><span class="p">(</span><span class="n">IN</span><span class="w"> </span><span class="n">p</span><span class="p">)</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">Promise</span><span class="p">.</span><span class="n">force</span><span class="w"> </span><span class="n">p</span><span class="w"></span>
212 <span class="w"> </span><span class="k">fun</span><span class="w"> </span><span class="n">Y</span><span class="w"> </span><span class="n">?</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">Tie</span><span class="p">.</span><span class="n">iso</span><span class="w"> </span><span class="n">Promise</span><span class="p">.</span><span class="n">Y</span><span class="w"> </span><span class="p">(</span><span class="k">fn</span><span class="w"> </span><span class="n">IN</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="n">p</span><span class="p">,</span><span class="w"> </span><span class="n">IN</span><span class="p">)</span><span class="w"> </span><span class="n">?</span><span class="w"></span>
213 <span class="k">end</span><span class="w"></span>
214 </pre></div></div></div>
215 <div class="paragraph"><p>Note that above we make use of the <span class="monospaced">iso</span> combinator. Here is a finite
216 representation of an infinite stream of ones:</p></div>
217 <div class="listingblock">
218 <div class="content"><div class="highlight"><pre><span class="k">val</span><span class="w"> </span><span class="n">ones</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="k">let</span><span class="w"></span>
219 <span class="w"> </span><span class="k">open</span><span class="w"> </span><span class="n">Tie</span><span class="w"> </span><span class="n">Stream</span><span class="w"></span>
220 <span class="k">in</span><span class="w"></span>
221 <span class="w"> </span><span class="n">fix</span><span class="w"> </span><span class="n">Y</span><span class="w"> </span><span class="p">(</span><span class="k">fn</span><span class="w"> </span><span class="n">ones</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="n">cons</span><span class="w"> </span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">ones</span><span class="p">))</span><span class="w"></span>
222 <span class="k">end</span><span class="w"></span>
223 </pre></div></div></div>
224 </div>
225 </div>
226 </div>
227 <div id="footnotes"><hr></div>
228 <div id="footer">
229 <div id="footer-text">
230 </div>
231 <div id="footer-badges">
232 </div>
233 </div>
234 </body>
235 </html>