tabs vs spaces

This commit is contained in:
Arya Irani 2019-02-06 15:00:22 -05:00
parent 72070d4984
commit f2572c6566
2 changed files with 219 additions and 3 deletions

View File

@ -0,0 +1,216 @@
<!DOCTYPE html>
<html>
<head>
<title>Distributed programming API v1 discussion</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="created" content="2019-02-05T15:35:17-0500"/>
<meta name="modified" content="2019-02-06T14:58:54-0500"/>
<meta name="tags" content="unison"/>
<meta name="last device" content="ndnd"/>
</head>
<body>
<div class="note-wrapper">
<h1>Distributed programming API v1 discussion</h1>
<p>Underlying the Unison distributed programming API is the desire to move computations to other Locations:</p>
<br>
<pre><code class='code-multiline' lang='haskell'><span class="sf_code_hvariable">Remote.forkAt</span> <span class="sf_code_operator">:</span> <span class="sf_code_constant">Loc</span> <span class="sf_code_punctuation">{</span><span class="sf_code_hvariable">e</span><span class="sf_code_punctuation">}</span> <span class="sf_code_operator">-&gt;</span>'<span class="sf_code_punctuation">({</span><span class="sf_code_hvariable">e</span><span class="sf_code_punctuation">}</span> <span class="sf_code_hvariable">a</span><span class="sf_code_punctuation">)</span> <span class="sf_code_operator">-&gt;</span><span class="sf_code_punctuation">{</span><span class="sf_code_constant">Remote</span><span class="sf_code_punctuation">}</span> <span class="sf_code_constant">Future</span> <span class="sf_code_hvariable">a</span>
<span class="sf_code_comment">-- example:</span>
<span class="sf_code_hvariable">f1</span> <span class="sf_code_operator">=</span> <span class="sf_code_hvariable">forkAt</span> <span class="sf_code_hvariable">a</span> '<span class="sf_code_keyword">let</span>
<span class="sf_code_hvariable">x</span> <span class="sf_code_operator">=</span> <span class="sf_code_hvariable">longRunningComputation</span> <span class="sf_code_number">101</span>
<span class="sf_code_hvariable">Email.send</span> <span class="sf_code_hvariable">x</span>
<span class="sf_code_hvariable">y</span> <span class="sf_code_operator">=</span> <span class="sf_code_hvariable">otherLongComputation</span>
<span class="sf_code_comment">-- x and y are computed in parallel</span></code></pre>
<p><br></p>
<blockquote>
<p>We decided that automatically cancelling a child computation when its parent terminates or delaying termination of of the parent until its children complete would break associativity in terms of parallelism when chaining computations, therefore <code class='code-inline'>forkAt</code> doesnt enforce any such conditions. See more about cancellation & termination below, in “Supervision and garbage-collection of Futures”</p>
</blockquote>
<br>
<h2>Locations</h2>
<p>A Location is simply a computing context on some hardware somewhere, having access to certain computational resources. Its runtime representation is essentially a collection of cryptographic tokens authorizing the use of these resources.</p>
<br>
<p>In Unison code, a Location is represented by a <code class='code-inline'>Loc {e}</code>. A Unison value of type <code class='code-inline'>Loc {}</code> supports only pure computations, whereas a <code class='code-inline'>Loc {Remote, GPU}</code> provides the <code class='code-inline'>Remote</code> and <code class='code-inline'>GPU</code> abilities.</p>
<br>
<h3>Locations have a composite runtime representation</h3>
<p>A <code class='code-inline'>Loc</code> is represented by one or more host / port / auth tokens, along with ability use tokens. The distributed runtime may use any algorithm in selecting a host to submit a task to, and the receiving host will run the computation provided the accompanying tokens are valid.</p>
<br>
<pre><code class='code-multiline' lang='haskell'><span class="sf_code_comment">-- Haskell runtime representation</span>
<span class="sf_code_comment">-- individual Tokens should be cryptographically unguessable.</span>
<span class="sf_code_comment">-- Tokens may correspond to or contain quota/other data.</span>
<span class="sf_code_keyword">data</span> <span class="sf_code_constant">Loc</span> <span class="sf_code_operator">=</span> <span class="sf_code_constant">Loc</span> <span class="sf_code_constant">Hosts</span> <span class="sf_code_constant">Abilities</span> <span class="sf_code_constant">Quota</span>
<span class="sf_code_keyword">type</span> <span class="sf_code_constant">Token</span> <span class="sf_code_operator">=</span> <span class="sf_code_constant">TBD</span> <span class="sf_code_comment">-- sufficient to prove authorization</span>
<span class="sf_code_keyword">type</span> <span class="sf_code_constant">Hosts</span> <span class="sf_code_operator">=</span> <span class="sf_code_constant">Map</span> <span class="sf_code_punctuation">(</span><span class="sf_code_constant">Hostname</span><span class="sf_code_punctuation">,</span><span class="sf_code_constant">Port</span><span class="sf_code_punctuation">)</span> <span class="sf_code_constant">Token</span>
<span class="sf_code_keyword">type</span> <span class="sf_code_constant">Abilities</span> <span class="sf_code_operator">=</span> <span class="sf_code_constant">Map</span> <span class="sf_code_constant">Reference</span> <span class="sf_code_constant">Token</span>
<span class="sf_code_keyword">type</span> <span class="sf_code_constant">Quota</span> <span class="sf_code_operator">=</span> <span class="sf_code_constant">Set</span> <span class="sf_code_constant">QUnit</span>
<span class="sf_code_keyword">data</span> <span class="sf_code_constant">QUnit</span> <span class="sf_code_operator">=</span> <span class="sf_code_constant">QDisk</span> <span class="sf_code_constant">QDiskUnit</span> <span class="sf_code_constant">Token</span> <span class="sf_code_operator">|</span> <span class="sf_code_constant">QCpu</span> <span class="sf_code_constant">QCpuUnit</span> <span class="sf_code_constant">Token</span> <span class="sf_code_operator">|</span> <span class="sf_code_constant">QNet</span> <span class="sf_code_constant">QNetUnit</span> <span class="sf_code_constant">Token</span> <span class="sf_code_operator">|</span> <span class="sf_code_operator">...</span>
</code></pre>alternatively, if disk / cpu / network tokens only come in one size:
<pre><code class='code-multiline' lang='haskell'><span class="sf_code_keyword">type</span> <span class="sf_code_constant">Quota</span> <span class="sf_code_operator">=</span> <span class="sf_code_constant">Map</span> <span class="sf_code_constant">QType</span> <span class="sf_code_punctuation">[</span><span class="sf_code_constant">Token</span><span class="sf_code_punctuation">]</span>
<span class="sf_code_keyword">data</span> <span class="sf_code_constant">QType</span> <span class="sf_code_operator">=</span> <span class="sf_code_constant">QDisk</span> <span class="sf_code_operator">|</span> <span class="sf_code_constant">QCpu</span> <span class="sf_code_operator">|</span> <span class="sf_code_constant">QNetwork</span> <span class="sf_code_operator">|</span> <span class="sf_code_operator">...</span> </code></pre>
<p><br></p>
<p>Thanks to the composite representation, a <code class='code-inline'>Loc</code> can be restricted if desired by simply dropping some ability tokens:</p>
<pre><code class='code-multiline' lang='haskell'><span class="sf_code_hvariable">Loc.restrict</span> <span class="sf_code_operator">:</span> <span class="sf_code_constant">Abilities</span> <span class="sf_code_punctuation">{</span><span class="sf_code_hvariable">e</span><span class="sf_code_punctuation">}</span> <span class="sf_code_operator">-&gt;</span> <span class="sf_code_constant">Loc</span> <span class="sf_code_punctuation">{</span><span class="sf_code_hvariable">e</span><span class="sf_code_punctuation">,</span><span class="sf_code_hvariable">e2</span><span class="sf_code_punctuation">}</span> <span class="sf_code_operator">-&gt;</span> <span class="sf_code_constant">Loc</span> <span class="sf_code_punctuation">{</span><span class="sf_code_hvariable">e</span><span class="sf_code_punctuation">}</span>
</code></pre>Similarly, disk/cpu quotas can be sub-allocated to various subtasks.
<pre><code class='code-multiline' lang='haskell'><span class="sf_code_constant">Loc</span><span class="sf_code_punctuation">.</span><span class="sf_code_builtin">take</span> <span class="sf_code_operator">:</span> <span class="sf_code_constant">QType</span> <span class="sf_code_operator">-&gt;</span> <span class="sf_code_constant">Nat</span> <span class="sf_code_operator">-&gt;</span> <span class="sf_code_constant">Loc</span> <span class="sf_code_punctuation">{</span><span class="sf_code_hvariable">e</span><span class="sf_code_punctuation">}</span> <span class="sf_code_operator">-&gt;</span> <span class="sf_code_punctuation">(</span><span class="sf_code_constant">Optional</span> <span class="sf_code_punctuation">(</span><span class="sf_code_constant">Loc</span> <span class="sf_code_punctuation">{</span><span class="sf_code_hvariable">e</span><span class="sf_code_punctuation">}),</span> <span class="sf_code_constant">Loc</span> <span class="sf_code_punctuation">{</span><span class="sf_code_hvariable">e</span><span class="sf_code_punctuation">})</span>
<span class="sf_code_comment">-- or</span>
<span class="sf_code_constant">Loc</span><span class="sf_code_punctuation">.</span><span class="sf_code_builtin">take</span> <span class="sf_code_operator">:</span> <span class="sf_code_constant">QUnit</span> <span class="sf_code_operator">-&gt;</span> <span class="sf_code_constant">Loc</span> <span class="sf_code_punctuation">{</span><span class="sf_code_hvariable">e</span><span class="sf_code_punctuation">}</span> <span class="sf_code_operator">-&gt;</span> <span class="sf_code_punctuation">(</span><span class="sf_code_constant">Optional</span> <span class="sf_code_punctuation">(</span><span class="sf_code_constant">Loc</span> <span class="sf_code_punctuation">{</span><span class="sf_code_hvariable">e</span><span class="sf_code_punctuation">}),</span> <span class="sf_code_constant">Loc</span> <span class="sf_code_punctuation">{</span><span class="sf_code_hvariable">e</span><span class="sf_code_punctuation">})</span>
</code></pre>However, I dont have a story for composing locations on the user side. This may call for another type parameter on <code class='code-inline'>Loc</code>, representing the provider. More on this, below.
<h3>Elastically producing new Locations</h3>
An elastic compute service “front-end” would expose:
<ol start="1"><li>a function to <code class='code-inline'>provision</code> new locations
</li><li>a Location at which the function could be run
</li></ol>
<br>
<ul><li>Can I have this <code class='code-inline'>provision</code> function in my namespace, without having its implementation in my codebase?
</li></ul>
<br>
<ul class='todo-list'><li><span class='todo-checkbox '><svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" fill="#FFF"/><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" stroke="#B4B4B4"/><path d="M12.526 4.615L6.636 9.58l-2.482-.836c-.19-.06-.408.003-.518.15-.116.15-.106.352.026.495l2.722 2.91c.086.09.21.144.34.144h.046c.12-.013.234-.07.307-.156l6.1-7.125c.143-.166.123-.407-.046-.548-.164-.138-.435-.14-.604 0z" id="check" fill="#555"/></g></svg>
</span><span class='todo-text'> The implementation of <code class='code-inline'>provision</code> would need some way to authenticate and validate the request.</span>
</li><li><span class='todo-checkbox '><svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" fill="#FFF"/><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" stroke="#B4B4B4"/><path d="M12.526 4.615L6.636 9.58l-2.482-.836c-.19-.06-.408.003-.518.15-.116.15-.106.352.026.495l2.722 2.91c.086.09.21.144.34.144h.046c.12-.013.234-.07.307-.156l6.1-7.125c.143-.166.123-.407-.046-.548-.164-.138-.435-.14-.604 0z" id="check" fill="#555"/></g></svg>
</span><span class='todo-text'> It would need some way to construct a Unison <code class='code-inline'>Loc</code> value (not yet discussed).</span>
</li><li><span class='todo-checkbox '><svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" fill="#FFF"/><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" stroke="#B4B4B4"/><path d="M12.526 4.615L6.636 9.58l-2.482-.836c-.19-.06-.408.003-.518.15-.116.15-.106.352.026.495l2.722 2.91c.086.09.21.144.34.144h.046c.12-.013.234-.07.307-.156l6.1-7.125c.143-.166.123-.407-.046-.548-.164-.138-.435-.14-.604 0z" id="check" fill="#555"/></g></svg>
</span><span class='todo-text'> It should provide a way for the front-end to monitor utilization and spin up or shut down physical resources as needed.</span>
</li></ul>
<br>
<p><u>Idea</u>: Maybe the <code class='code-inline'>Token</code> value provided by the front-end is structured in a provider-specific way, with whatever data is needed to make these decisions. Having a distinct <code class='code-inline'>Token</code> type for distinct providers means another type parameter on the <code class='code-inline'>Loc</code>, which could answer the question about consolidating <code class='code-inline'>Loc</code>s on the user side. If two Locations share the same provider type, they can be consolidated (hosts, quotas, abilities); otherwise they obviously couldnt be.</p>
<pre><code class='code-multiline' lang='haskell'><span class="sf_code_hvariable">Remote.forkAt</span> <span class="sf_code_operator">:</span> <span class="sf_code_constant">Loc</span> <span class="sf_code_punctuation">{</span><span class="sf_code_hvariable">e</span><span class="sf_code_punctuation">}</span> <span class="sf_code_hvariable">p</span> <span class="sf_code_operator">-&gt;</span>'<span class="sf_code_punctuation">({</span><span class="sf_code_hvariable">e</span><span class="sf_code_punctuation">}</span> <span class="sf_code_hvariable">a</span><span class="sf_code_punctuation">)</span> <span class="sf_code_operator">-&gt;</span><span class="sf_code_punctuation">{</span><span class="sf_code_constant">Remote</span><span class="sf_code_punctuation">}</span> <span class="sf_code_constant">Future</span> <span class="sf_code_hvariable">a</span>
<span class="sf_code_hvariable">Location.join</span> <span class="sf_code_operator">:</span> <span class="sf_code_constant">Loc</span> <span class="sf_code_punctuation">{</span><span class="sf_code_hvariable">e</span><span class="sf_code_punctuation">}</span> <span class="sf_code_hvariable">p</span> <span class="sf_code_operator">-&gt;</span> <span class="sf_code_constant">Loc</span> <span class="sf_code_punctuation">{</span><span class="sf_code_hvariable">e2</span><span class="sf_code_punctuation">}</span> <span class="sf_code_hvariable">p</span> <span class="sf_code_operator">-&gt;</span> <span class="sf_code_constant">Loc</span> <span class="sf_code_punctuation">{</span><span class="sf_code_hvariable">e</span><span class="sf_code_punctuation">,</span><span class="sf_code_hvariable">e2</span><span class="sf_code_punctuation">}</span> <span class="sf_code_hvariable">p</span></code></pre>
<p><br></p>
<h2>Futures</h2>
<p>A <code class='code-inline'>Future</code> represents an asynchronous computation. <code class='code-inline'>Remote.forkAt</code> takes a computation and returns immediately with a <code class='code-inline'>Future</code>. To wait for the computations output, use <code class='code-inline'>Future.force</code>.</p>
<pre><code class='code-multiline' lang='haskell'><span class="sf_code_hvariable">Remote.forkAt</span> <span class="sf_code_operator">:</span> <span class="sf_code_constant">Loc</span> <span class="sf_code_punctuation">{</span><span class="sf_code_hvariable">e</span><span class="sf_code_punctuation">}</span> <span class="sf_code_operator">-&gt;</span>'<span class="sf_code_punctuation">({</span><span class="sf_code_hvariable">e</span><span class="sf_code_punctuation">}</span> <span class="sf_code_hvariable">a</span><span class="sf_code_punctuation">)</span> <span class="sf_code_operator">-&gt;</span><span class="sf_code_punctuation">{</span><span class="sf_code_constant">Remote</span><span class="sf_code_punctuation">}</span> <span class="sf_code_constant">Future</span> <span class="sf_code_hvariable">a</span>
<span class="sf_code_hvariable">Future.force</span> <span class="sf_code_operator">:</span> <span class="sf_code_constant">Future</span> <span class="sf_code_hvariable">a</span> <span class="sf_code_operator">-&gt;</span><span class="sf_code_punctuation">{</span><span class="sf_code_constant">Remote</span><span class="sf_code_punctuation">}</span> <span class="sf_code_punctuation">(</span><span class="sf_code_constant">Either</span> <span class="sf_code_constant">Err</span> <span class="sf_code_hvariable">a</span><span class="sf_code_punctuation">)</span>
<span class="sf_code_keyword">type</span> <span class="sf_code_constant">Err</span> <span class="sf_code_operator">=</span> <span class="sf_code_constant">TBD</span>
<span class="sf_code_comment">-- example:</span>
<span class="sf_code_hvariable">f1</span> <span class="sf_code_operator">=</span> <span class="sf_code_hvariable">forkAt</span> <span class="sf_code_hvariable">a</span> '<span class="sf_code_keyword">let</span>
<span class="sf_code_hvariable">x</span> <span class="sf_code_operator">=</span> <span class="sf_code_hvariable">longRunningComputation</span> <span class="sf_code_number">101</span>
<span class="sf_code_hvariable">makeHistogram</span> <span class="sf_code_hvariable">x</span>
<span class="sf_code_hvariable">y</span> <span class="sf_code_operator">=</span> <span class="sf_code_hvariable">otherLongComputation</span>
<span class="sf_code_hvariable">x</span> <span class="sf_code_operator">=</span> <span class="sf_code_hvariable">Future.force</span> <span class="sf_code_hvariable">f1</span>
<span class="sf_code_hvariable">Database.save</span> <span class="sf_code_punctuation">(</span><span class="sf_code_hvariable">x</span><span class="sf_code_punctuation">,</span> <span class="sf_code_hvariable">y</span><span class="sf_code_punctuation">)</span></code></pre>
<p><br></p>
<ul><li>How many times can a future be successfully forced?
</li></ul>
<br>
<h3>Supervision and garbage-collection of Futures</h3>
<p>Unison Futures can be monitored or terminated using:</p>
<pre><code class='code-multiline' lang='haskell'><span class="sf_code_hvariable">Future.status</span> <span class="sf_code_operator">:</span> <span class="sf_code_constant">Future</span> <span class="sf_code_hvariable">a</span> <span class="sf_code_operator">-&gt;</span><span class="sf_code_punctuation">{</span><span class="sf_code_constant">Remote</span><span class="sf_code_punctuation">}</span> <span class="sf_code_constant">Future.Status</span>
<span class="sf_code_keyword">type</span> <span class="sf_code_constant">Future.Status</span>
<span class="sf_code_operator">=</span> <span class="sf_code_constant">Running</span> <span class="sf_code_constant">LastUpdate</span> <span class="sf_code_operator">|</span> <span class="sf_code_constant">Canceled</span> <span class="sf_code_operator">|</span> <span class="sf_code_constant">Finished</span>
<span class="sf_code_operator">|</span> <span class="sf_code_constant">Unreachable</span> <span class="sf_code_operator">|</span> <span class="sf_code_constant">Unresponsive</span>
<span class="sf_code_hvariable">Future.cancel</span> <span class="sf_code_operator">:</span> <span class="sf_code_constant">Future</span> <span class="sf_code_hvariable">a</span> <span class="sf_code_operator">-&gt;</span><span class="sf_code_punctuation">{</span><span class="sf_code_constant">Remote</span><span class="sf_code_punctuation">}</span> <span class="sf_code_punctuation">(</span><span class="sf_code_constant">Either</span> <span class="sf_code_constant">Err2</span> <span class="sf_code_punctuation">())</span>
<span class="sf_code_keyword">type</span> <span class="sf_code_constant">Err2</span> <span class="sf_code_operator">=</span> <span class="sf_code_constant">TBD</span></code></pre>
<p><br></p>
<p>To the extent that an async computation should be canceled if there is no other computation interested in its result, we need some way of determining whether or not this is the case. We discussed having a system of keep-alives, absent which a Future might be canceled by its host:</p>
<pre><code class='code-multiline' lang='haskell'><span class="sf_code_comment">-- these likely will just be handled by the interpreter </span>
<span class="sf_code_comment">-- of Remote, not by "user" code.</span>
<span class="sf_code_hvariable">Future.keepalive</span> <span class="sf_code_operator">:</span> <span class="sf_code_constant">Duration</span> <span class="sf_code_operator">-&gt;</span> <span class="sf_code_constant">Future</span> <span class="sf_code_hvariable">a</span> <span class="sf_code_operator">-&gt;</span><span class="sf_code_punctuation">{</span><span class="sf_code_constant">Remote</span><span class="sf_code_punctuation">}</span> <span class="sf_code_constant">Status</span>
<span class="sf_code_hvariable">Future.remaining</span> <span class="sf_code_operator">:</span> <span class="sf_code_constant">Future</span> <span class="sf_code_hvariable">a</span> <span class="sf_code_operator">-&gt;</span><span class="sf_code_punctuation">{</span><span class="sf_code_constant">Remote</span><span class="sf_code_punctuation">}</span> <span class="sf_code_constant">Duration</span></code></pre>
<p><br></p>
<p>Moreover, there will be cases where we want to transfer or delegate the keep-alive responsibility for a long-running tasks to a more available location. </p>
<pre><code class='code-multiline' lang='haskell'><span class="sf_code_hvariable">Remote.supervise</span> <span class="sf_code_operator">:</span> <span class="sf_code_constant">Loc</span> <span class="sf_code_punctuation">{</span><span class="sf_code_hvariable">e</span><span class="sf_code_punctuation">}</span> <span class="sf_code_operator">-&gt;</span> <span class="sf_code_constant">Future</span> <span class="sf_code_hvariable">a</span> <span class="sf_code_operator">-&gt;</span> <span class="sf_code_punctuation">{</span><span class="sf_code_constant">Remote</span><span class="sf_code_punctuation">}</span> <span class="sf_code_punctuation">()</span>
<span class="sf_code_hvariable">Remote.unsupervise</span> <span class="sf_code_operator">:</span> <span class="sf_code_constant">Loc</span> <span class="sf_code_punctuation">{</span><span class="sf_code_hvariable">e</span><span class="sf_code_punctuation">}</span> <span class="sf_code_operator">-&gt;</span> <span class="sf_code_constant">Future</span> <span class="sf_code_hvariable">a</span> <span class="sf_code_operator">-&gt;</span> <span class="sf_code_punctuation">{</span><span class="sf_code_constant">Remote</span><span class="sf_code_punctuation">}</span> <span class="sf_code_punctuation">()</span>
</code></pre>
<blockquote>
We discussed producing a <code class='code-inline'>Heartbeat</code> identifier along with any <code class='code-inline'>Future</code>, but decided there was no benefit to separating the two.
</blockquote>
We havent discussed how to prevent a delegate supervisor from accumulating and perpetuating many long-running Futures that will never actually be forced. With this in mind, have we gained anything from a GC perspective?
<h2>Stationary data</h2>
We will need some notion of data that doesn't just move automatically with the computation, even if the computation references it. We identified two reasons you might want to do this:
<ul><li> The data is big, and you don't want to copy it around willy-nilly.
</li><li> The data is secret, and you don't want to accidentally ship it to another location, you want to be very explicit about when this happens (for instance, secret keys, etc).
</li></ul>
<br>
<p>More generally, we want a way of being explicit about when certain data is moved between locations, rather than implicitly relocating anything in lexical scope (this could be an API thing, a type-system thing, a code-analysis tool).</p>
<hr>
<h2>Notes/Desiderata</h2>
<ul class='todo-list'><li><span class='todo-checkbox '><svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" fill="#FFF"/><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" stroke="#B4B4B4"/><path d="M12.526 4.615L6.636 9.58l-2.482-.836c-.19-.06-.408.003-.518.15-.116.15-.106.352.026.495l2.722 2.91c.086.09.21.144.34.144h.046c.12-.013.234-.07.307-.156l6.1-7.125c.143-.166.123-.407-.046-.548-.164-.138-.435-.14-.604 0z" id="check" fill="#555"/></g></svg>
</span><span class='todo-text'> Elastic computation - need to be able to talk about spawning new computing resources, and ideally this compute can be garbage collected as soon as you're done using it.</span>
</li><li><span class='todo-checkbox todo-checked'><svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" fill="#FFF"/><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" stroke="#B4B4B4"/><path d="M12.526 4.615L6.636 9.58l-2.482-.836c-.19-.06-.408.003-.518.15-.116.15-.106.352.026.495l2.722 2.91c.086.09.21.144.34.144h.046c.12-.013.234-.07.307-.156l6.1-7.125c.143-.166.123-.407-.046-.548-.164-.138-.435-.14-.604 0z" id="check" fill="#555"/></g></svg>
</span><span class='todo-text'> <code class='code-inline'>fork</code> a task to run on a separate thread or at another "location"</span>
</li><li><span class='todo-checkbox todo-checked'><svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" fill="#FFF"/><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" stroke="#B4B4B4"/><path d="M12.526 4.615L6.636 9.58l-2.482-.836c-.19-.06-.408.003-.518.15-.116.15-.106.352.026.495l2.722 2.91c.086.09.21.144.34.144h.046c.12-.013.234-.07.307-.156l6.1-7.125c.143-.166.123-.407-.046-.548-.164-.138-.435-.14-.604 0z" id="check" fill="#555"/></g></svg>
</span><span class='todo-text'> Different locations may have access to different abilities (just pure computation, <code class='code-inline'>IO</code>, <code class='code-inline'>GPU</code>, etc)</span>
</li><li><span class='todo-checkbox '><svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" fill="#FFF"/><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" stroke="#B4B4B4"/><path d="M12.526 4.615L6.636 9.58l-2.482-.836c-.19-.06-.408.003-.518.15-.116.15-.106.352.026.495l2.722 2.91c.086.09.21.144.34.144h.046c.12-.013.234-.07.307-.156l6.1-7.125c.143-.166.123-.407-.046-.548-.164-.138-.435-.14-.604 0z" id="check" fill="#555"/></g></svg>
</span><span class='todo-text'> Need to be able to respond to location failures, with maximal flexibility. Allow different ways of doing failure detection/recovery.</span>
</li></ul>
<ul><li>Locations are first-class, permissions, tasks, are first-class
</li></ul>
<ul class='todo-list'><li><span class='todo-checkbox todo-checked'><svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" fill="#FFF"/><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" stroke="#B4B4B4"/><path d="M12.526 4.615L6.636 9.58l-2.482-.836c-.19-.06-.408.003-.518.15-.116.15-.106.352.026.495l2.722 2.91c.086.09.21.144.34.144h.046c.12-.013.234-.07.307-.156l6.1-7.125c.143-.166.123-.407-.046-.548-.164-.138-.435-.14-.604 0z" id="check" fill="#555"/></g></svg>
</span><span class='todo-text'> locations</span>
</li><li><span class='todo-checkbox '><svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" fill="#FFF"/><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" stroke="#B4B4B4"/><path d="M12.526 4.615L6.636 9.58l-2.482-.836c-.19-.06-.408.003-.518.15-.116.15-.106.352.026.495l2.722 2.91c.086.09.21.144.34.144h.046c.12-.013.234-.07.307-.156l6.1-7.125c.143-.166.123-.407-.046-.548-.164-.138-.435-.14-.604 0z" id="check" fill="#555"/></g></svg>
</span><span class='todo-text'> permissions?</span>
</li><li><span class='todo-checkbox todo-checked'><svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" fill="#FFF"/><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" stroke="#B4B4B4"/><path d="M12.526 4.615L6.636 9.58l-2.482-.836c-.19-.06-.408.003-.518.15-.116.15-.106.352.026.495l2.722 2.91c.086.09.21.144.34.144h.046c.12-.013.234-.07.307-.156l6.1-7.125c.143-.166.123-.407-.046-.548-.164-.138-.435-.14-.604 0z" id="check" fill="#555"/></g></svg>
</span><span class='todo-text'> tasks (futures)</span>
</li><li><span class='todo-checkbox '><svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" fill="#FFF"/><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" stroke="#B4B4B4"/><path d="M12.526 4.615L6.636 9.58l-2.482-.836c-.19-.06-.408.003-.518.15-.116.15-.106.352.026.495l2.722 2.91c.086.09.21.144.34.144h.046c.12-.013.234-.07.307-.156l6.1-7.125c.143-.166.123-.407-.046-.548-.164-.138-.435-.14-.604 0z" id="check" fill="#555"/></g></svg>
</span><span class='todo-text'> Some notion of data that doesn't just move automatically with the computation, even if the computation references it.</span>
</li></ul>
<ul><li> e.g., The data is big, and you don't want to copy it around willy nilly.
</li><li> e.g., The data is secret, and you don't want to accidentally ship it to another location, you want to be very explicit about when this happens (for instance, secret keys, etc).
</li><li> Might more generally want a way of being explicit about when data is moved to a location rather than just implicitly relocating anything in lexical scope (could be an API thing, a type system thing, a tool).
</li></ul>
<ul class='todo-list'><li><span class='todo-checkbox todo-checked'><svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" fill="#FFF"/><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" stroke="#B4B4B4"/><path d="M12.526 4.615L6.636 9.58l-2.482-.836c-.19-.06-.408.003-.518.15-.116.15-.106.352.026.495l2.722 2.91c.086.09.21.144.34.144h.046c.12-.013.234-.07.307-.156l6.1-7.125c.143-.166.123-.407-.046-.548-.164-.138-.435-.14-.604 0z" id="check" fill="#555"/></g></svg>
</span><span class='todo-text'> Need to be able to launch a long-running computation and have it outlive the task / location / node that launches it. But then how do you interact with this computation later? (Say, to cancel it? Or to check if it's finished? Or more generally, how do you monitor it?)</span>
</li><li><span class='todo-checkbox '><svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" fill="#FFF"/><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" stroke="#B4B4B4"/><path d="M12.526 4.615L6.636 9.58l-2.482-.836c-.19-.06-.408.003-.518.15-.116.15-.106.352.026.495l2.722 2.91c.086.09.21.144.34.144h.046c.12-.013.234-.07.307-.156l6.1-7.125c.143-.166.123-.407-.046-.548-.164-.138-.435-.14-.604 0z" id="check" fill="#555"/></g></svg>
</span><span class='todo-text'> Need to be able to hash and serialize any Unison value, so that storage API(s) can be implemented in pure Unison.</span>
</li></ul>
<ul><li> Should the hash of a value know the type of the value? <code class='code-inline'>hash : a -&gt; Hash a</code>)
</li></ul>
<ul class='todo-list'><li><span class='todo-checkbox todo-checked'><svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" fill="#FFF"/><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" stroke="#B4B4B4"/><path d="M12.526 4.615L6.636 9.58l-2.482-.836c-.19-.06-.408.003-.518.15-.116.15-.106.352.026.495l2.722 2.91c.086.09.21.144.34.144h.046c.12-.013.234-.07.307-.156l6.1-7.125c.143-.166.123-.407-.046-.548-.164-.138-.435-.14-.604 0z" id="check" fill="#555"/></g></svg>
</span><span class='todo-text'> How do you represent <code class='code-inline'>Loc{e}</code> to be securely verified by the receiving node? The <code class='code-inline'>Loc{e}</code> must be unguessable and tamper-proof.</span>
</li></ul>
<ul><li> This is achieved by making the component <code class='code-inline'>Token</code>s unguessable and tamper-proof.
</li></ul>
<ul class='todo-list'><li><span class='todo-checkbox '><svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" fill="#FFF"/><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" stroke="#B4B4B4"/><path d="M12.526 4.615L6.636 9.58l-2.482-.836c-.19-.06-.408.003-.518.15-.116.15-.106.352.026.495l2.722 2.91c.086.09.21.144.34.144h.046c.12-.013.234-.07.307-.156l6.1-7.125c.143-.166.123-.407-.046-.548-.164-.138-.435-.14-.604 0z" id="check" fill="#555"/></g></svg>
</span><span class='todo-text'> Must be safe to say <code class='code-inline'>at loc1 loc2</code> without allowing nefarious loc1 to abuse loc2. (Needs clarification.)</span>
</li></ul>
<br>
<ul class='todo-list'><li><span class='todo-checkbox todo-checked'><svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" fill="#FFF"/><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" stroke="#B4B4B4"/><path d="M12.526 4.615L6.636 9.58l-2.482-.836c-.19-.06-.408.003-.518.15-.116.15-.106.352.026.495l2.722 2.91c.086.09.21.144.34.144h.046c.12-.013.234-.07.307-.156l6.1-7.125c.143-.166.123-.407-.046-.548-.164-.138-.435-.14-.604 0z" id="check" fill="#555"/></g></svg>
</span><span class='todo-text'> The runtime needs an unguessable way (crypto?) to represent Locations and their abilities.</span>
</li><li><span class='todo-checkbox '><svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" fill="#FFF"/><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" stroke="#B4B4B4"/><path d="M12.526 4.615L6.636 9.58l-2.482-.836c-.19-.06-.408.003-.518.15-.116.15-.106.352.026.495l2.722 2.91c.086.09.21.144.34.144h.046c.12-.013.234-.07.307-.156l6.1-7.125c.143-.166.123-.407-.046-.548-.164-.138-.435-.14-.604 0z" id="check" fill="#555"/></g></svg>
</span><span class='todo-text'> Not all computations should have access to all data.</span>
</li></ul>
<ul><li> file system
</li><li> individual durables
</li></ul>
<ul class='todo-list'><li><span class='todo-checkbox todo-checked'><svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" fill="#FFF"/><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" stroke="#B4B4B4"/><path d="M12.526 4.615L6.636 9.58l-2.482-.836c-.19-.06-.408.003-.518.15-.116.15-.106.352.026.495l2.722 2.91c.086.09.21.144.34.144h.046c.12-.013.234-.07.307-.156l6.1-7.125c.143-.166.123-.407-.046-.548-.164-.138-.435-.14-.604 0z" id="check" fill="#555"/></g></svg>
</span><span class='todo-text'> Not all Locations should provide unlimited resources to all users (arbitrary computation, time, storage, bandwidth, priority).</span>
</li><li><span class='todo-checkbox '><svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" fill="#FFF"/><path d="M.5 12.853c0 1.462 1.185 2.647 2.647 2.647h9.706c1.462 0 2.647-1.185 2.647-2.647V3.147C15.5 1.685 14.315.5 12.853.5H3.147C1.685.5.5 1.685.5 3.147v9.706z" stroke="#B4B4B4"/><path d="M12.526 4.615L6.636 9.58l-2.482-.836c-.19-.06-.408.003-.518.15-.116.15-.106.352.026.495l2.722 2.91c.086.09.21.144.34.144h.046c.12-.013.234-.07.307-.156l6.1-7.125c.143-.166.123-.407-.046-.548-.164-.138-.435-.14-.604 0z" id="check" fill="#555"/></g></svg>
</span><span class='todo-text'> Not all data should be portable to arbitrary locations (think secret keys, top secret clearance, hipaa).</span>
</li></ul>
<br>
<p><u>Misc?</u>:</p>
<ul><li>Mutable typed (durable if needed) state at each location
<ul><li> For v1, could not have this, just focus on batch computation
</li></ul></li><li>Dealing with weird networks? (nat-busting)
<ul><li> Maybe in implementation, but not explicit in v1 API
</li></ul></li><li>Well-defined semantics not just a bunch of implementation-defined gobbledygook
</li><li>Do we need globally-addressed mutable state? e.g. node <code class='code-inline'>a</code> can refer to mutable data on node <code class='code-inline'>b</code>; or node <code class='code-inline'>c</code> can mutate data on node <code class='code-inline'>d</code>. Yes, probably.
</li></ul>
<br>
<p><span class='hashtag'>#unison</span></p>
</div>
<script type="text/javascript">
(function() {
var doc_ols = document.getElementsByTagName("ol");
for ( i=0; i<doc_ols.length; i++) {
var ol_start = doc_ols[i].getAttribute("start") - 1;
doc_ols[i].setAttribute("style", "counter-reset:ol " + ol_start + ";");
}
})();
</script>
<style>
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{margin:0;padding:0;border:0;font:inherit;font-size:100%;vertical-align:baseline}html{line-height:1}ol,ul{list-style:none}table{border-collapse:collapse;border-spacing:0}caption,th,td{text-align:left;font-weight:normal;vertical-align:middle}q,blockquote{quotes:none}q:before,q:after,blockquote:before,blockquote:after{content:"";content:none}a img{border:none}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}*{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}html{font-size:87.5%;line-height:1.57143em}html{font-size:14px;line-height:1.6em;-webkit-text-size-adjust:100%}body{background:#fcfcfc;color:#545454;text-rendering:optimizeLegibility;font-family:"AvenirNext-Regular"}a{color:#de4c4f;text-decoration:none}h1{font-family:"AvenirNext-Medium";color:#333;font-size:1.6em;line-height:1.3em;margin-bottom:.78571em}h2{font-family:"AvenirNext-Medium";color:#333;font-size:1.3em;line-height:1em;margin-bottom:.62857em}h3{font-family:"AvenirNext-Medium";color:#333;font-size:1.15em;line-height:1em;margin-bottom:.47143em}p{margin-bottom:1.57143em;hyphens:auto}hr{height:1px;border:0;background-color:#dedede;margin:-1px auto 1.57143em auto}ul,ol{margin-bottom:.31429em}ul ul,ul ol,ol ul,ol ol{margin-bottom:0px}ol li:before{content:counter(ol) ".";counter-increment:ol;color:#e06e73;text-align:right;display:inline-block;min-width:1em;margin-right:0.5em}b,strong{font-family:"AvenirNext-Bold"}i,em{font-family:"AvenirNext-Italic"}code{font-family:"Menlo-Regular"}.text-overflow-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sf_code_string,.sf_code_selector,.sf_code_attr-name,.sf_code_char,.sf_code_builtin,.sf_code_inserted{color:#D33905}.sf_code_comment,.sf_code_prolog,.sf_code_doctype,.sf_code_cdata{color:#838383}.sf_code_number,.sf_code_boolean{color:#0E73A2}.sf_code_keyword,.sf_code_atrule,.sf_code_rule,.sf_code_attr-value,.sf_code_function,.sf_code_class-name,.sf_code_class,.sf_code_regex,.sf_code_important,.sf_code_variable,.sf_code_interpolation{color:#0E73A2}.sf_code_property,.sf_code_tag,.sf_code_constant,.sf_code_symbol,.sf_code_deleted{color:#1B00CE}.sf_code_macro,.sf_code_entity,.sf_code_operator,.sf_code_url{color:#920448}.note-wrapper{max-width:46em;margin:0px auto;padding:1.57143em 3.14286em}.note-wrapper.spotlight-preview{overflow-x:hidden}u{text-decoration:none;background-image:linear-gradient(to bottom, rgba(0,0,0,0) 50%,#e06e73 50%);background-repeat:repeat-x;background-size:2px 2px;background-position:0 1.05em}s{color:#878787}p{margin-bottom:0.1em}hr{margin-bottom:0.7em;margin-top:0.7em}ul li{text-indent:-0.35em}ul li:before{content:"•";color:#e06e73;display:inline-block;margin-right:0.3em}ul ul{margin-left:1.25714em}ol li{text-indent:-1.45em}ol ol{margin-left:1.25714em}blockquote{display:block;margin-left:-1em;padding-left:0.8em;border-left:0.2em solid #e06e73}.todo-list ul{margin-left:1.88571em}.todo-list li{text-indent:-1.75em}.todo-list li:before{content:"";display:static;margin-right:0px}.todo-checkbox{text-indent:-1.7em}.todo-checkbox svg{margin-right:0.3em;position:relative;top:0.2em}.todo-checkbox svg #check{display:none}.todo-checkbox.todo-checked #check{display:inline}.todo-checkbox.todo-checked .todo-text{text-decoration:line-through;color:#878787}.code-inline{display:inline;background:white;border:solid 1px #dedede;padding:0.2em 0.5em;font-size:0.9em}.code-multiline{display:block;background:white;border:solid 1px #dedede;padding:0.7em 1em;font-size:0.9em;overflow-x:auto}.hashtag{display:inline-block;color:white;background:#b8bfc2;padding:0.0em 0.5em;border-radius:1em;text-indent:0}.hashtag a{color:#fff}.address a{color:#545454;background-image:linear-gradient(to bottom, rgba(0,0,0,0) 50%,#0da35e 50%);background-repeat:repeat-x;background-size:2px 2px;background-position:0 1.05em}.address svg{position:relative;top:0.2em;display:inline-block;margin-right:0.2em}.color-preview{display:inline-block;width:1em;height:1em;border:solid 1px rgba(0,0,0,0.3);border-radius:50%;margin-right:0.1em;position:relative;top:0.2em;white-space:nowrap}.color-code{margin-right:0.2em;font-family:"Menlo-Regular";font-size:0.9em}.color-hash{opacity:0.4}.ordered-list-number{color:#e06e73;text-align:right;display:inline-block;min-width:1em}.arrow svg{position:relative;top:0.08em;display:inline-block;margin-right:0.15em;margin-left:0.15em}.arrow svg #rod{stroke:#545454}.arrow svg #point{fill:#545454}mark{color:inherit;display:inline;padding:0.2em 0.5em;background-color:#fcffc0}img{max-width:100%;height:auto}
</style>
</body>
</html>

View File

@ -6,7 +6,7 @@ Remote.forkAt : Loc {e} ->'({e} a) ->{Remote} Future a
-- example:
f1 = forkAt a 'let
x = longRunningComputation 101
x = longRunningComputation 101
Email.send x
y = otherLongComputation
-- x and y are computed in parallel
@ -77,7 +77,7 @@ type Err = TBD
-- example:
f1 = forkAt a 'let
x = longRunningComputation 101
x = longRunningComputation 101
makeHistogram x
y = otherLongComputation
x = Future.force f1
@ -91,7 +91,7 @@ Unison Futures can be monitored or terminated using:
```haskell
Future.status : Future a ->{Remote} Future.Status
type Future.Status
= Running LastUpdate | Canceled | Finished
= Running LastUpdate | Canceled | Finished
| Unreachable | Unresponsive
Future.cancel : Future a ->{Remote} (Either Err2 ())