OSDN Git Service

Infencer/Interpreter hybrid and Kleene Star types.
authorSimon Forman <sforman@hushmail.com>
Sun, 24 Jun 2018 23:33:07 +0000 (16:33 -0700)
committerSimon Forman <sforman@hushmail.com>
Sun, 24 Jun 2018 23:33:07 +0000 (16:33 -0700)
Still draft but it works.  Gotta clean it up and supply defs for basis
functions.

docs/Types.html
docs/Types.ipynb
docs/Types.md
docs/Types.rst
docs/sphinx_docs/_build/html/notebooks/index.html
docs/sphinx_docs/_build/html/searchindex.js
docs/sphinx_docs/notebooks/Types.rst
joy/utils/polytypes.py [new file with mode: 0644]
joy/utils/types.py

index 8add8a5..a6f1526 100644 (file)
@@ -11775,7 +11775,8 @@ div#notebook {
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<h1 id="Type-Inference">Type Inference<a class="anchor-link" href="#Type-Inference">&#182;</a></h1>
+<h1 id="Type-Inference">Type Inference<a class="anchor-link" href="#Type-Inference">&#182;</a></h1><p>Cf. <a href="http://prl.ccs.neu.edu/blog/2017/03/10/type-inference-in-stack-based-programming-languages/">"Type Inference in Stack-Based Programming Languages"</a> by Rob Kleffner, 2017-03-10.</p>
+
 </div>
 </div>
 </div>
@@ -11783,7 +11784,7 @@ div#notebook {
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<h2 id="P&#246;ial's-Rules">P&#246;ial's Rules<a class="anchor-link" href="#P&#246;ial's-Rules">&#182;</a></h2><p><a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.212.6026">"Typing Tools for Typeless Stack Languages" by Jaanus Pöial</a></p>
+<h2 id="Part-I:-P&#246;ial's-Rules">Part I: P&#246;ial's Rules<a class="anchor-link" href="#Part-I:-P&#246;ial's-Rules">&#182;</a></h2><p><a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.212.6026">"Typing Tools for Typeless Stack Languages" by Jaanus Pöial</a></p>
 
 <pre><code>@INPROCEEDINGS{Pöial06typingtools,
     author = {Jaanus Pöial},
@@ -11826,7 +11827,7 @@ div#notebook {
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<h3 id="Third-Rule">Third Rule<a class="anchor-link" href="#Third-Rule">&#182;</a></h3><p>The third rule is actually two rules.  These two rules deal with composing functions when the second one will consume one of items the first one produces.  The two types must be <em>unified</em> or a type conflict declared.</p>
+<h3 id="Third-Rule">Third Rule<a class="anchor-link" href="#Third-Rule">&#182;</a></h3><p>The third rule is actually two rules.  These two rules deal with composing functions when the second one will consume one of items the first one produces.  The two types must be <a href="https://en.wikipedia.org/wiki/Robinson&#39;s_unification_algorithm"><em>unified</em></a> or a type conflict declared.</p>
 
 <pre><code>   (a -- b t[i])∘(c u[j] -- d)   t &lt;= u (t is subtype of u)
 -------------------------------
@@ -11844,7 +11845,7 @@ div#notebook {
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<h2 id="Examples">Examples<a class="anchor-link" href="#Examples">&#182;</a></h2><p>Let's work through some examples by hand to develop an intuition for the algorithm.</p>
+<p>Let's work through some examples by hand to develop an intuition for the algorithm.</p>
 
 </div>
 </div>
@@ -12229,7 +12230,7 @@ cons ( 1 [...] -- [1 ...] )</code></pre>
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<h2 id="Implementation">Implementation<a class="anchor-link" href="#Implementation">&#182;</a></h2>
+<h2 id="Part-II:-Implementation">Part II: Implementation<a class="anchor-link" href="#Part-II:-Implementation">&#182;</a></h2>
 </div>
 </div>
 </div>
@@ -12687,7 +12688,7 @@ cons ( 1 [...] -- [1 ...] )</code></pre>
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<h3 id="List-Functions">List Functions<a class="anchor-link" href="#List-Functions">&#182;</a></h3><p>Here's that trick to represent functions like <code>rest</code> and <code>cons</code> that manipulate lists.  We use a cons-list of tuples and give the tails their own numbers.  Then everything above already works.</p>
+<h3 id="Stack-Functions">Stack Functions<a class="anchor-link" href="#Stack-Functions">&#182;</a></h3><p>Here's that trick to represent functions like <code>rest</code> and <code>cons</code> that manipulate stacks.  We use a cons-list of tuples and give the tails their own numbers.  Then everything above already works.</p>
 
 </div>
 </div>
@@ -12804,7 +12805,8 @@ cons ( 1 [...] -- [1 ...] )</code></pre>
 <div class="text_cell_render border-box-sizing rendered_html">
 <p>Compare with the stack effect comment and you can see it works fine:</p>
 
-<pre><code>([4 5 ...] 2 3 1 -- [3 2 ...])</code></pre>
+<pre><code>([4 5 ...] 2 3 1 -- [3 2 ...])
+  3 4  5   1 2 0     2 1  5</code></pre>
 
 </div>
 </div>
@@ -12882,7 +12884,7 @@ cons ( 1 [...] -- [1 ...] )</code></pre>
 <div class=" highlight hl-ipython2"><pre><span></span><span class="k">def</span> <span class="nf">unify</span><span class="p">(</span><span class="n">u</span><span class="p">,</span> <span class="n">v</span><span class="p">,</span> <span class="n">s</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
     <span class="k">if</span> <span class="n">s</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
         <span class="n">s</span> <span class="o">=</span> <span class="p">{}</span>
-    <span class="k">else</span><span class="p">:</span>
+    <span class="k">elif</span> <span class="n">s</span><span class="p">:</span>
         <span class="n">u</span> <span class="o">=</span> <span class="n">update</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">u</span><span class="p">)</span>
         <span class="n">v</span> <span class="o">=</span> <span class="n">update</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span>
 
@@ -12951,7 +12953,7 @@ cons ( 1 [...] -- [1 ...] )</code></pre>
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<h2 id="Compiling">Compiling<a class="anchor-link" href="#Compiling">&#182;</a></h2><p>Now consider the Python function we would like to derive:</p>
+<h2 id="Part-III:-Compiling-Stack-Functions">Part III: Compiling Stack Functions<a class="anchor-link" href="#Part-III:-Compiling-Stack-Functions">&#182;</a></h2><p>Now consider the Python function we would like to derive:</p>
 
 </div>
 </div>
@@ -13541,7 +13543,7 @@ def uncons(stack):
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<h2 id="Types-and-Subtypes-of-Arguments">Types and Subtypes of Arguments<a class="anchor-link" href="#Types-and-Subtypes-of-Arguments">&#182;</a></h2><p>So far we have dealt with types of functions, those dealing with simple stack manipulation.  Let's extend our machinery to deal with types of arguments.</p>
+<h2 id="Part-IV:-Types-and-Subtypes-of-Arguments">Part IV: Types and Subtypes of Arguments<a class="anchor-link" href="#Part-IV:-Types-and-Subtypes-of-Arguments">&#182;</a></h2><p>So far we have dealt with types of functions, those dealing with simple stack manipulation.  Let's extend our machinery to deal with types of arguments.</p>
 
 </div>
 </div>
@@ -14028,7 +14030,7 @@ i0 &gt;= f0 -&gt; False
 <div class=" highlight hl-ipython2"><pre><span></span><span class="k">def</span> <span class="nf">unify</span><span class="p">(</span><span class="n">u</span><span class="p">,</span> <span class="n">v</span><span class="p">,</span> <span class="n">s</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
     <span class="k">if</span> <span class="n">s</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
         <span class="n">s</span> <span class="o">=</span> <span class="p">{}</span>
-    <span class="k">else</span><span class="p">:</span>
+    <span class="k">elif</span> <span class="n">s</span><span class="p">:</span>
         <span class="n">u</span> <span class="o">=</span> <span class="n">update</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">u</span><span class="p">)</span>
         <span class="n">v</span> <span class="o">=</span> <span class="n">update</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span>
 
@@ -14659,7 +14661,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<h2 id="Functions-that-use-the-Stack">Functions that use the Stack<a class="anchor-link" href="#Functions-that-use-the-Stack">&#182;</a></h2><p>Consider the <code>stack</code> function which grabs the whole stack, quotes it, and puts it on itself:</p>
+<h2 id="Part-V:-Functions-that-use-the-Stack">Part V: Functions that use the Stack<a class="anchor-link" href="#Part-V:-Functions-that-use-the-Stack">&#182;</a></h2><p>Consider the <code>stack</code> function which grabs the whole stack, quotes it, and puts it on itself:</p>
 
 <pre><code>stack (...     -- ... [...]        )
 stack (... a   -- ... a [a ...]    )
@@ -14752,7 +14754,7 @@ uncons = ((a, Z), S) -- (Z, (a, S))</code></pre>
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<h4 id="compose()-version-2"><code>compose()</code> version 2<a class="anchor-link" href="#compose()-version-2">&#182;</a></h4><p>This function has to be modified to use the new datastructures and it is no longer recursive, instead recursion happens as part of unification.</p>
+<h4 id="compose()-version-2"><code>compose()</code> version 2<a class="anchor-link" href="#compose()-version-2">&#182;</a></h4><p>This function has to be modified to use the new datastructures and it is no longer recursive, instead recursion happens as part of unification.  Further, the first and second of Pöial's rules are now handled automatically by the unification algorithm.</p>
 
 </div>
 </div>
@@ -14763,28 +14765,11 @@ uncons = ((a, Z), S) -- (Z, (a, S))</code></pre>
 <div class="inner_cell">
     <div class="input_area">
 <div class=" highlight hl-ipython2"><pre><span></span><span class="k">def</span> <span class="nf">compose</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">g</span><span class="p">):</span>
-
     <span class="p">(</span><span class="n">f_in</span><span class="p">,</span> <span class="n">f_out</span><span class="p">),</span> <span class="p">(</span><span class="n">g_in</span><span class="p">,</span> <span class="n">g_out</span><span class="p">)</span> <span class="o">=</span> <span class="n">f</span><span class="p">,</span> <span class="n">g</span>
-
-    <span class="k">if</span> <span class="ow">not</span> <span class="n">g_in</span><span class="p">:</span>
-        <span class="n">fg_in</span><span class="p">,</span> <span class="n">fg_out</span> <span class="o">=</span> <span class="n">f_in</span><span class="p">,</span> <span class="n">stack_concat</span><span class="p">(</span><span class="n">g_out</span><span class="p">,</span> <span class="n">f_out</span><span class="p">)</span>
-
-    <span class="k">elif</span> <span class="ow">not</span> <span class="n">f_out</span><span class="p">:</span>
-        <span class="n">fg_in</span><span class="p">,</span> <span class="n">fg_out</span> <span class="o">=</span> <span class="n">stack_concat</span><span class="p">(</span><span class="n">f_in</span><span class="p">,</span> <span class="n">g_in</span><span class="p">),</span> <span class="n">g_out</span>
-
-    <span class="k">else</span><span class="p">:</span> <span class="c1"># Unify and update.</span>
-
-        <span class="n">s</span> <span class="o">=</span> <span class="n">unify</span><span class="p">(</span><span class="n">g_in</span><span class="p">,</span> <span class="n">f_out</span><span class="p">)</span>
-
-        <span class="k">if</span> <span class="n">s</span> <span class="o">==</span> <span class="bp">False</span><span class="p">:</span>  <span class="c1"># s can also be the empty dict, which is ok.</span>
-            <span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s1">&#39;Cannot unify </span><span class="si">%r</span><span class="s1"> and </span><span class="si">%r</span><span class="s1">.&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">fo</span><span class="p">,</span> <span class="n">gi</span><span class="p">))</span>
-
-        <span class="n">fg_in</span><span class="p">,</span> <span class="n">fg_out</span> <span class="o">=</span> <span class="n">update</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="p">(</span><span class="n">f_in</span><span class="p">,</span> <span class="n">g_out</span><span class="p">))</span>
-
-    <span class="k">return</span> <span class="n">fg_in</span><span class="p">,</span> <span class="n">fg_out</span>
-
-
-<span class="n">stack_concat</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">q</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="p">(</span><span class="n">q</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">stack_concat</span><span class="p">(</span><span class="n">q</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">e</span><span class="p">))</span> <span class="k">if</span> <span class="n">q</span> <span class="k">else</span> <span class="n">e</span>
+    <span class="n">s</span> <span class="o">=</span> <span class="n">unify</span><span class="p">(</span><span class="n">g_in</span><span class="p">,</span> <span class="n">f_out</span><span class="p">)</span>
+    <span class="k">if</span> <span class="n">s</span> <span class="o">==</span> <span class="bp">False</span><span class="p">:</span>  <span class="c1"># s can also be the empty dict, which is ok.</span>
+        <span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s1">&#39;Cannot unify </span><span class="si">%r</span><span class="s1"> and </span><span class="si">%r</span><span class="s1">.&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">f_out</span><span class="p">,</span> <span class="n">g_in</span><span class="p">))</span>
+    <span class="k">return</span> <span class="n">update</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="p">(</span><span class="n">f_in</span><span class="p">,</span> <span class="n">g_out</span><span class="p">))</span>
 </pre></div>
 
 </div>
@@ -15379,7 +15364,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<h2 id="Multiple-Stack-Effects">Multiple Stack Effects<a class="anchor-link" href="#Multiple-Stack-Effects">&#182;</a></h2><p>...</p>
+<h2 id="Part-VI:-Multiple-Stack-Effects">Part VI: Multiple Stack Effects<a class="anchor-link" href="#Part-VI:-Multiple-Stack-Effects">&#182;</a></h2><p>...</p>
 
 </div>
 </div>
@@ -15585,79 +15570,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<h2 id="concat"><code>concat</code><a class="anchor-link" href="#concat">&#182;</a></h2><p>How to deal with <code>concat</code>?</p>
-
-<pre><code>concat ([.0.] [.1.] -- [.0. .1.])
-
-</code></pre>
-<p>We would like to represent this in Python somehow...</p>
-
-</div>
-</div>
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[89]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">concat</span> <span class="o">=</span> <span class="p">(</span><span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span> <span class="p">((</span><span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">1</span><span class="p">]),)</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
-</div>
-<div class="inner_cell">
-<div class="text_cell_render border-box-sizing rendered_html">
-<p>But this is actually <code>cons</code> with the first argument restricted to be a stack:</p>
-
-<pre><code>([.0.] [.1.] -- [[.0.] .1.])
-
-</code></pre>
-<p>What we have implemented so far would actually only permit:</p>
-
-<pre><code>([.0.] [.1.] -- [.2.])</code></pre>
-
-</div>
-</div>
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[90]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">concat</span> <span class="o">=</span> <span class="p">(</span><span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span> <span class="p">(</span><span class="n">S</span><span class="p">[</span><span class="mi">2</span><span class="p">],)</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
-</div>
-<div class="inner_cell">
-<div class="text_cell_render border-box-sizing rendered_html">
-<p>Which works but can lose information.  Consider <code>cons concat</code>, this is how much information we <em>could</em> retain:</p>
-
-<pre><code>(1 [.0.] [.1.] -- [1 .0. .1.])
-
-</code></pre>
-<p>As opposed to just:</p>
-
-<pre><code>(1 [.0.] [.1.] -- [.2.])</code></pre>
-
-</div>
-</div>
-</div>
-<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
-</div>
-<div class="inner_cell">
-<div class="text_cell_render border-box-sizing rendered_html">
-<h3 id="Brzo...'s-Derivitives-of-Regular-Expressions">Brzo...'s Derivitives of Regular Expressions<a class="anchor-link" href="#Brzo...'s-Derivitives-of-Regular-Expressions">&#182;</a></h3><p>We can invent a new type of type variable, a "sequence type" (I think this is what they mean in the literature by that term...) or "Kleene Star" type.  I'm going to represent it as a type letter and the asterix, so a sequence of zero or more <code>AnyJoyType</code> variables would be:</p>
+<h3 id="Representing-an-Unbounded-Sequence-of-Types">Representing an Unbounded Sequence of Types<a class="anchor-link" href="#Representing-an-Unbounded-Sequence-of-Types">&#182;</a></h3><p>We can borrow a trick from <a href="https://en.wikipedia.org/wiki/Brzozowski_derivative">Brzozowski's Derivatives of Regular Expressions</a> to invent a new type of type variable, a "sequence type" (I think this is what they mean in the literature by that term...) or "<a href="https://en.wikipedia.org/wiki/Kleene_star">Kleene Star</a>" type.  I'm going to represent it as a type letter and the asterix, so a sequence of zero or more <code>AnyJoyType</code> variables would be:</p>
 
 <pre><code>A*</code></pre>
 
@@ -15733,7 +15646,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[91]:</div>
+<div class="prompt input_prompt">In&nbsp;[89]:</div>
 <div class="inner_cell">
     <div class="input_area">
 <div class=" highlight hl-ipython2"><pre><span></span><span class="k">class</span> <span class="nc">KleeneStar</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
@@ -15796,7 +15709,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[92]:</div>
+<div class="prompt input_prompt">In&nbsp;[90]:</div>
 <div class="inner_cell">
     <div class="input_area">
 <div class=" highlight hl-ipython2"><pre><span></span><span class="k">def</span> <span class="nf">unify</span><span class="p">(</span><span class="n">u</span><span class="p">,</span> <span class="n">v</span><span class="p">,</span> <span class="n">s</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
@@ -15845,7 +15758,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
                 <span class="n">sn</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
             <span class="k">return</span> <span class="n">t</span>
 
-        <span class="n">ses</span> <span class="o">=</span> <span class="n">unify</span><span class="p">(</span><span class="n">u</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">v</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
+        <span class="n">ses</span> <span class="o">=</span> <span class="n">unify</span><span class="p">(</span><span class="n">u</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">v</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">s</span><span class="p">)</span>
         <span class="n">results</span> <span class="o">=</span> <span class="p">()</span>
         <span class="k">for</span> <span class="n">sn</span> <span class="ow">in</span> <span class="n">ses</span><span class="p">:</span>
             <span class="n">results</span> <span class="o">+=</span> <span class="n">unify</span><span class="p">(</span><span class="n">u</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">v</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">sn</span><span class="p">)</span>
@@ -15877,7 +15790,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[93]:</div>
+<div class="prompt input_prompt">In&nbsp;[91]:</div>
 <div class="inner_cell">
     <div class="input_area">
 <div class=" highlight hl-ipython2"><pre><span></span><span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="n">As</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
@@ -15894,7 +15807,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 
 <div class="output_area">
 
-<div class="prompt output_prompt">Out[93]:</div>
+<div class="prompt output_prompt">Out[91]:</div>
 
 
 
@@ -15911,7 +15824,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[94]:</div>
+<div class="prompt input_prompt">In&nbsp;[92]:</div>
 <div class="inner_cell">
     <div class="input_area">
 <div class=" highlight hl-ipython2"><pre><span></span><span class="n">b</span> <span class="o">=</span> <span class="p">(</span><span class="n">A</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
@@ -15928,7 +15841,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 
 <div class="output_area">
 
-<div class="prompt output_prompt">Out[94]:</div>
+<div class="prompt output_prompt">Out[92]:</div>
 
 
 
@@ -15945,7 +15858,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[95]:</div>
+<div class="prompt input_prompt">In&nbsp;[93]:</div>
 <div class="inner_cell">
     <div class="input_area">
 <div class=" highlight hl-ipython2"><pre><span></span><span class="k">for</span> <span class="n">result</span> <span class="ow">in</span> <span class="n">unify</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="p">):</span>
@@ -15978,7 +15891,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[96]:</div>
+<div class="prompt input_prompt">In&nbsp;[94]:</div>
 <div class="inner_cell">
     <div class="input_area">
 <div class=" highlight hl-ipython2"><pre><span></span><span class="k">for</span> <span class="n">result</span> <span class="ow">in</span> <span class="n">unify</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
@@ -16025,7 +15938,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[97]:</div>
+<div class="prompt input_prompt">In&nbsp;[95]:</div>
 <div class="inner_cell">
     <div class="input_area">
 <div class=" highlight hl-ipython2"><pre><span></span><span class="n">sum_</span> <span class="o">=</span> <span class="p">((</span><span class="n">Ns</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span> <span class="p">(</span><span class="n">N</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
@@ -16058,7 +15971,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[98]:</div>
+<div class="prompt input_prompt">In&nbsp;[96]:</div>
 <div class="inner_cell">
     <div class="input_area">
 <div class=" highlight hl-ipython2"><pre><span></span><span class="n">f</span> <span class="o">=</span> <span class="p">(</span><span class="n">N</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="p">(</span><span class="n">N</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="p">(</span><span class="n">N</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">1</span><span class="p">]))),</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
@@ -16091,7 +16004,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[99]:</div>
+<div class="prompt input_prompt">In&nbsp;[97]:</div>
 <div class="inner_cell">
     <div class="input_area">
 <div class=" highlight hl-ipython2"><pre><span></span><span class="k">for</span> <span class="n">result</span> <span class="ow">in</span> <span class="n">unify</span><span class="p">(</span><span class="n">sum_</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">f</span><span class="p">):</span>
@@ -16128,35 +16041,23 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<h4 id="compose()-version-3"><code>compose()</code> version 3<a class="anchor-link" href="#compose()-version-3">&#182;</a></h4><p>This function has to be modified to use the new datastructures and it is no longer recursive, instead recursion happens as part of unification.</p>
+<h4 id="compose()-version-3"><code>compose()</code> version 3<a class="anchor-link" href="#compose()-version-3">&#182;</a></h4><p>This function has to be modified to yield multiple results.</p>
 
 </div>
 </div>
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[100]:</div>
+<div class="prompt input_prompt">In&nbsp;[98]:</div>
 <div class="inner_cell">
     <div class="input_area">
 <div class=" highlight hl-ipython2"><pre><span></span><span class="k">def</span> <span class="nf">compose</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">g</span><span class="p">):</span>
-
     <span class="p">(</span><span class="n">f_in</span><span class="p">,</span> <span class="n">f_out</span><span class="p">),</span> <span class="p">(</span><span class="n">g_in</span><span class="p">,</span> <span class="n">g_out</span><span class="p">)</span> <span class="o">=</span> <span class="n">f</span><span class="p">,</span> <span class="n">g</span>
-
-    <span class="k">if</span> <span class="ow">not</span> <span class="n">g_in</span><span class="p">:</span>
-        <span class="k">yield</span> <span class="n">f_in</span><span class="p">,</span> <span class="n">stack_concat</span><span class="p">(</span><span class="n">g_out</span><span class="p">,</span> <span class="n">f_out</span><span class="p">)</span>
-
-    <span class="k">elif</span> <span class="ow">not</span> <span class="n">f_out</span><span class="p">:</span>
-        <span class="k">yield</span> <span class="n">stack_concat</span><span class="p">(</span><span class="n">f_in</span><span class="p">,</span> <span class="n">g_in</span><span class="p">),</span> <span class="n">g_out</span>
-
-    <span class="k">else</span><span class="p">:</span> <span class="c1"># Unify and update.</span>
-
-        <span class="n">s</span> <span class="o">=</span> <span class="n">unify</span><span class="p">(</span><span class="n">g_in</span><span class="p">,</span> <span class="n">f_out</span><span class="p">)</span>
-
-        <span class="k">if</span> <span class="ow">not</span> <span class="n">s</span><span class="p">:</span>
-            <span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s1">&#39;Cannot unify </span><span class="si">%r</span><span class="s1"> and </span><span class="si">%r</span><span class="s1">.&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">fo</span><span class="p">,</span> <span class="n">gi</span><span class="p">))</span>
-
-        <span class="k">for</span> <span class="n">result</span> <span class="ow">in</span> <span class="n">s</span><span class="p">:</span>
-            <span class="k">yield</span> <span class="n">update</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="p">(</span><span class="n">f_in</span><span class="p">,</span> <span class="n">g_out</span><span class="p">))</span>
+    <span class="n">s</span> <span class="o">=</span> <span class="n">unify</span><span class="p">(</span><span class="n">g_in</span><span class="p">,</span> <span class="n">f_out</span><span class="p">)</span>
+    <span class="k">if</span> <span class="ow">not</span> <span class="n">s</span><span class="p">:</span>
+        <span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s1">&#39;Cannot unify </span><span class="si">%r</span><span class="s1"> and </span><span class="si">%r</span><span class="s1">.&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">f_out</span><span class="p">,</span> <span class="n">g_in</span><span class="p">))</span>
+    <span class="k">for</span> <span class="n">result</span> <span class="ow">in</span> <span class="n">s</span><span class="p">:</span>
+        <span class="k">yield</span> <span class="n">update</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="p">(</span><span class="n">f_in</span><span class="p">,</span> <span class="n">g_out</span><span class="p">))</span>
 </pre></div>
 
 </div>
@@ -16166,7 +16067,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[101]:</div>
+<div class="prompt input_prompt">In&nbsp;[99]:</div>
 <div class="inner_cell">
     <div class="input_area">
 <div class=" highlight hl-ipython2"><pre><span></span><span class="k">def</span> <span class="nf">meta_compose</span><span class="p">(</span><span class="n">F</span><span class="p">,</span> <span class="n">G</span><span class="p">):</span>
@@ -16191,7 +16092,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[102]:</div>
+<div class="prompt input_prompt">In&nbsp;[100]:</div>
 <div class="inner_cell">
     <div class="input_area">
 <div class=" highlight hl-ipython2"><pre><span></span><span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">MC</span><span class="p">([</span><span class="n">dup</span><span class="p">],</span> <span class="n">muls</span><span class="p">):</span>
@@ -16212,8 +16113,8 @@ uncons = ([a1 .1.] -- a1 [.1.])
 
 
 <div class="output_subarea output_stream output_stdout output_text">
-<pre>(a0 -- f0)
-(a0 -- i0)
+<pre>(f0 -- f1)
+(i0 -- i1)
 </pre>
 </div>
 </div>
@@ -16224,7 +16125,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[103]:</div>
+<div class="prompt input_prompt">In&nbsp;[101]:</div>
 <div class="inner_cell">
     <div class="input_area">
 <div class=" highlight hl-ipython2"><pre><span></span><span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">MC</span><span class="p">([</span><span class="n">dup</span><span class="p">],</span> <span class="p">[</span><span class="n">sum_</span><span class="p">]):</span>
@@ -16256,7 +16157,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[104]:</div>
+<div class="prompt input_prompt">In&nbsp;[102]:</div>
 <div class="inner_cell">
     <div class="input_area">
 <div class=" highlight hl-ipython2"><pre><span></span><span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">MC</span><span class="p">([</span><span class="n">cons</span><span class="p">],</span> <span class="p">[</span><span class="n">sum_</span><span class="p">]):</span>
@@ -16289,7 +16190,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[105]:</div>
+<div class="prompt input_prompt">In&nbsp;[103]:</div>
 <div class="inner_cell">
     <div class="input_area">
 <div class=" highlight hl-ipython2"><pre><span></span><span class="n">sum_</span> <span class="o">=</span> <span class="p">(((</span><span class="n">N</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="p">(</span><span class="n">Ns</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">1</span><span class="p">])),</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span> <span class="p">(</span><span class="n">N</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span>
@@ -16325,7 +16226,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[106]:</div>
+<div class="prompt input_prompt">In&nbsp;[104]:</div>
 <div class="inner_cell">
     <div class="input_area">
 <div class=" highlight hl-ipython2"><pre><span></span><span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="n">A</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="p">(</span><span class="n">As</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="p">(</span><span class="n">A</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">1</span><span class="p">])))</span>
@@ -16342,7 +16243,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 
 <div class="output_area">
 
-<div class="prompt output_prompt">Out[106]:</div>
+<div class="prompt output_prompt">Out[104]:</div>
 
 
 
@@ -16359,7 +16260,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[107]:</div>
+<div class="prompt input_prompt">In&nbsp;[105]:</div>
 <div class="inner_cell">
     <div class="input_area">
 <div class=" highlight hl-ipython2"><pre><span></span><span class="n">b</span> <span class="o">=</span> <span class="p">(</span><span class="n">A</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="p">(</span><span class="n">A</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">2</span><span class="p">]))</span>
@@ -16376,7 +16277,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 
 <div class="output_area">
 
-<div class="prompt output_prompt">Out[107]:</div>
+<div class="prompt output_prompt">Out[105]:</div>
 
 
 
@@ -16393,7 +16294,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[108]:</div>
+<div class="prompt input_prompt">In&nbsp;[106]:</div>
 <div class="inner_cell">
     <div class="input_area">
 <div class=" highlight hl-ipython2"><pre><span></span><span class="k">for</span> <span class="n">result</span> <span class="ow">in</span> <span class="n">unify</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="p">):</span>
@@ -16426,7 +16327,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[109]:</div>
+<div class="prompt input_prompt">In&nbsp;[107]:</div>
 <div class="inner_cell">
     <div class="input_area">
 <div class=" highlight hl-ipython2"><pre><span></span><span class="k">for</span> <span class="n">result</span> <span class="ow">in</span> <span class="n">unify</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
@@ -16461,16 +16362,14 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<h3 id="represent-concat">represent <code>concat</code><a class="anchor-link" href="#represent-concat">&#182;</a></h3>
-<pre><code>([.0.] [.1.] -- [A*(.0.) .1.])
+<h2 id="Part-VII:-Typing-Combinators">Part VII: Typing Combinators<a class="anchor-link" href="#Part-VII:-Typing-Combinators">&#182;</a></h2><p>TBD</p>
+<p>This is an open subject.</p>
+<p>The obvious thing is that you now need two pairs of tuples to describe the combinators' effects,  a stack effect comment and an expression effect comment:</p>
 
-</code></pre>
-<p>Meaning that <code>A*</code> on the right-hand side should all the crap from <code>.0.</code>.</p>
+<pre><code>dip (a [F] --)--(-- F a)
 
-<pre><code>([      .0.] [.1.] -- [      A* .1.])
-([a     .0.] [.1.] -- [a     A* .1.])
-([a b   .0.] [.1.] -- [a b   A* .1.])
-([a b c .0.] [.1.] -- [a b c A* .1.])</code></pre>
+</code></pre>
+<p>One thing that might help is...</p>
 
 </div>
 </div>
@@ -16479,47 +16378,66 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<p>or...</p>
+<p>Consider the type of:</p>
 
-<pre><code>([       .0.] [.1.] -- [       .1.])
-([a      .0.] [.1.] -- [a      .1.])
-([a b    .0.] [.1.] -- [a b    .1.])
-([a b  c .0.] [.1.] -- [a b  c .1.])
-([a A* c .0.] [.1.] -- [a A* c .1.])</code></pre>
+<pre><code>[cons] dip
+
+</code></pre>
+<p>Obviously it would be:</p>
+
+<pre><code>(a1 [..1] a2 -- [a1 ..1] a2)
+
+</code></pre>
+<p><code>dip</code> itself could have:</p>
+
+<pre><code>(a1 [..1] -- ... then what?</code></pre>
 
 </div>
 </div>
 </div>
-<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
-</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[108]:</div>
 <div class="inner_cell">
-<div class="text_cell_render border-box-sizing rendered_html">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="k">class</span> <span class="nc">SymbolJoyType</span><span class="p">(</span><span class="n">AnyJoyType</span><span class="p">):</span> <span class="n">prefix</span> <span class="o">=</span> <span class="s1">&#39;F&#39;</span>
 
-<pre><code>(a, (b, S0)) . S1 = (a, (b, (A*, S1)))</code></pre>
+<span class="n">W</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="n">SymbolJoyType</span><span class="p">,</span> <span class="n">_R</span><span class="p">)</span>
+
+<span class="n">k</span> <span class="o">=</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="p">((</span><span class="n">W</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">2</span><span class="p">]),</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
+<span class="n">Symbol</span><span class="p">(</span><span class="s1">&#39;cons&#39;</span><span class="p">)</span>
+<span class="k">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">k</span><span class="p">)</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+<div class="output_wrapper">
+<div class="output">
+
+
+<div class="output_area">
+
+<div class="prompt"></div>
+
+
+<div class="output_subarea output_stream output_stdout output_text">
+<pre>(-- [F1 .2.])
+</pre>
+</div>
+</div>
 
 </div>
 </div>
+
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[110]:</div>
+<div class="prompt input_prompt">In&nbsp;[109]:</div>
 <div class="inner_cell">
     <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="k">class</span> <span class="nc">Astar</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
-    <span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
-        <span class="k">return</span> <span class="s1">&#39;A*&#39;</span>
-
-
-<span class="k">def</span> <span class="nf">concat</span><span class="p">(</span><span class="n">s0</span><span class="p">,</span> <span class="n">s1</span><span class="p">):</span>
-    <span class="n">a</span> <span class="o">=</span> <span class="p">[]</span>
-    <span class="k">while</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">s0</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">):</span>
-        <span class="n">term</span><span class="p">,</span> <span class="n">s0</span> <span class="o">=</span> <span class="n">s0</span>
-        <span class="n">a</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">term</span><span class="p">)</span>
-    <span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">s0</span><span class="p">,</span> <span class="n">StackJoyType</span><span class="p">),</span> <span class="nb">repr</span><span class="p">(</span><span class="n">s0</span><span class="p">)</span>
-    <span class="n">s1</span> <span class="o">=</span> <span class="n">Astar</span><span class="p">(),</span> <span class="n">s1</span>
-    <span class="k">for</span> <span class="n">term</span> <span class="ow">in</span> <span class="nb">reversed</span><span class="p">(</span><span class="n">a</span><span class="p">):</span>
-        <span class="n">s1</span> <span class="o">=</span> <span class="n">term</span><span class="p">,</span> <span class="n">s1</span>
-    <span class="k">return</span> <span class="n">s1</span>
+<div class=" highlight hl-ipython2"><pre><span></span><span class="n">dip_a</span> <span class="o">=</span> <span class="p">((</span><span class="n">W</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">2</span><span class="p">]),</span> <span class="p">(</span><span class="n">A</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span>
 </pre></div>
 
 </div>
@@ -16529,23 +16447,43 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[111]:</div>
+<div class="prompt input_prompt">In&nbsp;[110]:</div>
 <div class="inner_cell">
     <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="p">(</span><span class="n">A</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span> <span class="p">(</span><span class="n">A</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
+<div class=" highlight hl-ipython2"><pre><span></span><span class="n">d</span> <span class="o">=</span> <span class="n">relabel</span><span class="p">(</span><span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">dip_a</span><span class="p">)</span>
+<span class="k">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">d</span><span class="p">)</span>
 </pre></div>
 
 </div>
 </div>
 </div>
 
+<div class="output_wrapper">
+<div class="output">
+
+
+<div class="output_area">
+
+<div class="prompt"></div>
+
+
+<div class="output_subarea output_stream output_stdout output_text">
+<pre>(-- a1001 [F1001 .1002.])
+</pre>
+</div>
+</div>
+
+</div>
+</div>
+
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[112]:</div>
+<div class="prompt input_prompt">In&nbsp;[111]:</div>
 <div class="inner_cell">
     <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">concat</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
+<div class=" highlight hl-ipython2"><pre><span></span><span class="n">s</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">unify</span><span class="p">(</span><span class="n">d</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">k</span><span class="p">[</span><span class="mi">1</span><span class="p">]))[</span><span class="mi">0</span><span class="p">]</span>
+<span class="n">s</span>
 </pre></div>
 
 </div>
@@ -16558,13 +16496,13 @@ uncons = ([a1 .1.] -- a1 [.1.])
 
 <div class="output_area">
 
-<div class="prompt output_prompt">Out[112]:</div>
+<div class="prompt output_prompt">Out[111]:</div>
 
 
 
 
 <div class="output_text output_subarea output_execute_result">
-<pre>(a1, (A*, (a2, s1)))</pre>
+<pre>{s0: (a1001, s1000), s1002: s2, F1001: F1}</pre>
 </div>
 
 </div>
@@ -16573,23 +16511,25 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 
 </div>
-<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
-</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[112]:</div>
 <div class="inner_cell">
-<div class="text_cell_render border-box-sizing rendered_html">
-<h2 id="Joy-in-the-Logical-Paradigm">Joy in the Logical Paradigm<a class="anchor-link" href="#Joy-in-the-Logical-Paradigm">&#182;</a></h2><p>For this to work the type label classes have to be modified to let <code>T &gt;= t</code> succeed, where e.g. <code>T</code> is <code>IntJoyType</code> and <code>t</code> is <code>int</code></p>
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="n">j</span> <span class="o">=</span> <span class="n">update</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">k</span><span class="p">)</span>
+</pre></div>
 
 </div>
 </div>
 </div>
+
+</div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
 <div class="prompt input_prompt">In&nbsp;[113]:</div>
 <div class="inner_cell">
     <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">F</span> <span class="o">=</span> <span class="nb">reduce</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="p">(</span><span class="n">pop</span><span class="p">,</span> <span class="n">swap</span><span class="p">,</span> <span class="n">roll_down</span><span class="p">,</span> <span class="n">rest</span><span class="p">,</span> <span class="n">rest</span><span class="p">,</span> <span class="n">cons</span><span class="p">,</span> <span class="n">cons</span><span class="p">))</span>
-
-<span class="k">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">F</span><span class="p">)</span>
+<div class=" highlight hl-ipython2"><pre><span></span><span class="k">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">j</span><span class="p">)</span>
 </pre></div>
 
 </div>
@@ -16605,79 +16545,832 @@ uncons = ([a1 .1.] -- a1 [.1.])
 <div class="prompt"></div>
 
 
-<div class="output_subarea output_text output_error">
-<pre>
-<span class="ansi-red-fg">---------------------------------------------------------------------------</span>
-<span class="ansi-red-fg">ValueError</span>                                Traceback (most recent call last)
-<span class="ansi-green-fg">&lt;ipython-input-113-4b4cb6ff86e5&gt;</span> in <span class="ansi-cyan-fg">&lt;module&gt;</span><span class="ansi-blue-fg">()</span>
+<div class="output_subarea output_stream output_stdout output_text">
+<pre>(a1001 -- a1001 [F1 .2.])
+</pre>
+</div>
+</div>
+
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[114]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="n">j</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+<div class="output_wrapper">
+<div class="output">
+
+
+<div class="output_area">
+
+<div class="prompt output_prompt">Out[114]:</div>
+
+
+
+
+<div class="output_text output_subarea output_execute_result">
+<pre>((a1001, s1000), ((F1, s2), (a1001, s1000)))</pre>
+</div>
+
+</div>
+
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[115]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="n">cons</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+<div class="output_wrapper">
+<div class="output">
+
+
+<div class="output_area">
+
+<div class="prompt output_prompt">Out[115]:</div>
+
+
+
+
+<div class="output_text output_subarea output_execute_result">
+<pre>((s1, (a1, s23)), ((a1, s1), s23))</pre>
+</div>
+
+</div>
+
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[116]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">MC</span><span class="p">([</span><span class="n">k</span><span class="p">],</span> <span class="p">[</span><span class="n">dup</span><span class="p">]):</span>
+    <span class="k">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">f</span><span class="p">)</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+<div class="output_wrapper">
+<div class="output">
+
+
+<div class="output_area">
+
+<div class="prompt"></div>
+
+
+<div class="output_subarea output_stream output_stdout output_text">
+<pre>(-- [F0 .1.] [F0 .1.])
+</pre>
+</div>
+</div>
+
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[117]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="n">l</span> <span class="o">=</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="p">((</span><span class="n">cons</span><span class="p">,</span> <span class="n">S</span><span class="p">[</span><span class="mi">2</span><span class="p">]),</span> <span class="p">(</span><span class="n">A</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[118]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="k">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">l</span><span class="p">)</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+<div class="output_wrapper">
+<div class="output">
+
+
+<div class="output_area">
+
+<div class="prompt"></div>
+
+
+<div class="output_subarea output_stream output_stdout output_text">
+<pre>(-- a1 [[[[.1.] a1 .23.] [a1 .1.] .23.] .2.])
+</pre>
+</div>
+</div>
+
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[119]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="k">def</span> <span class="nf">dip_t</span><span class="p">(</span><span class="n">F</span><span class="p">):</span>
+    <span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">sec</span><span class="p">))</span> <span class="o">=</span> <span class="n">F</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
+    <span class="n">G</span> <span class="o">=</span> <span class="n">F</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">sec</span>
+    <span class="n">P</span> <span class="o">=</span> <span class="n">S</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">S</span><span class="p">[</span><span class="mi">3</span><span class="p">])</span>
+    <span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span>
+    <span class="k">while</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">):</span>
+        <span class="n">term</span><span class="p">,</span> <span class="n">quote</span> <span class="o">=</span> <span class="n">quote</span>
+        <span class="n">a</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">term</span><span class="p">)</span>
+    <span class="n">a</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">G</span><span class="p">)</span>
+    <span class="k">return</span> <span class="n">a</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[120]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="kn">from</span> <span class="nn">joy.utils.stack</span> <span class="kn">import</span> <span class="n">iter_stack</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[121]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span> <span class="o">=</span> <span class="n">dip_t</span><span class="p">(</span><span class="n">l</span><span class="p">)</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[122]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="n">a</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+<div class="output_wrapper">
+<div class="output">
+
+
+<div class="output_area">
+
+<div class="prompt output_prompt">Out[122]:</div>
+
+
+
+
+<div class="output_text output_subarea output_execute_result">
+<pre>(s0, s0)</pre>
+</div>
+
+</div>
+
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[123]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="n">b</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+<div class="output_wrapper">
+<div class="output">
+
+
+<div class="output_area">
+
+<div class="prompt output_prompt">Out[123]:</div>
+
+
+
+
+<div class="output_text output_subarea output_execute_result">
+<pre>((s1, (a1, s23)), ((a1, s1), s23))</pre>
+</div>
+
+</div>
+
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[124]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="n">c</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+<div class="output_wrapper">
+<div class="output">
+
+
+<div class="output_area">
+
+<div class="prompt output_prompt">Out[124]:</div>
+
+
+
+
+<div class="output_text output_subarea output_execute_result">
+<pre>(s3, (a1, s3))</pre>
+</div>
+
+</div>
+
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[125]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="n">MC</span><span class="p">([</span><span class="n">a</span><span class="p">],</span> <span class="p">[</span><span class="n">b</span><span class="p">])</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+<div class="output_wrapper">
+<div class="output">
+
+
+<div class="output_area">
+
+<div class="prompt output_prompt">Out[125]:</div>
+
+
+
+
+<div class="output_text output_subarea output_execute_result">
+<pre>[((s0, (a0, s1)), ((a0, s0), s1))]</pre>
+</div>
+
+</div>
+
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[126]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="n">kjs</span> <span class="o">=</span> <span class="n">MC</span><span class="p">(</span><span class="n">MC</span><span class="p">([</span><span class="n">a</span><span class="p">],</span> <span class="p">[</span><span class="n">b</span><span class="p">]),</span> <span class="p">[</span><span class="n">c</span><span class="p">])</span>
+<span class="n">kjs</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+<div class="output_wrapper">
+<div class="output">
+
+
+<div class="output_area">
+
+<div class="prompt output_prompt">Out[126]:</div>
+
+
+
+
+<div class="output_text output_subarea output_execute_result">
+<pre>[((s0, (a0, s1)), (a1, ((a0, s0), s1)))]</pre>
+</div>
+
+</div>
+
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[127]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="k">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">kjs</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+<div class="output_wrapper">
+<div class="output">
+
+
+<div class="output_area">
+
+<div class="prompt"></div>
+
+
+<div class="output_subarea output_stream output_stdout output_text">
+<pre>(a0 [.0.] -- [a0 .0.] a1)
+</pre>
+</div>
+</div>
+
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
+</div>
+<div class="inner_cell">
+<div class="text_cell_render border-box-sizing rendered_html">
+
+<pre><code>(a0 [.0.] -- [a0 .0.] a1)
+
+   a0 [.0.] a1 [cons] dip
+----------------------------
+   [a0 .0.] a1</code></pre>
+
+</div>
+</div>
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[128]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="n">stack_concat</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">q</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="p">(</span><span class="n">q</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">stack_concat</span><span class="p">(</span><span class="n">q</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">e</span><span class="p">))</span> <span class="k">if</span> <span class="n">q</span> <span class="k">else</span> <span class="n">e</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[129]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="k">class</span> <span class="nc">SymbolJoyType</span><span class="p">(</span><span class="n">AnyJoyType</span><span class="p">):</span>
+    <span class="n">prefix</span> <span class="o">=</span> <span class="s1">&#39;F&#39;</span>
+
+    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">sec</span><span class="p">,</span> <span class="n">number</span><span class="p">):</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">stack_effects</span> <span class="o">=</span> <span class="n">sec</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">number</span> <span class="o">=</span> <span class="n">number</span>
+
+<span class="k">class</span> <span class="nc">CombinatorJoyType</span><span class="p">(</span><span class="n">SymbolJoyType</span><span class="p">):</span> <span class="n">prefix</span> <span class="o">=</span> <span class="s1">&#39;C&#39;</span>
+
+<span class="k">def</span> <span class="nf">dip_t</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">):</span>
+    <span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">stack</span><span class="p">))</span> <span class="o">=</span> <span class="n">stack</span>
+    <span class="n">expression</span> <span class="o">=</span> <span class="n">stack_concat</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">expression</span><span class="p">))</span>
+    <span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">expression</span>
+
+<span class="n">CONS</span> <span class="o">=</span> <span class="n">SymbolJoyType</span><span class="p">(</span><span class="s1">&#39;cons&#39;</span><span class="p">,</span> <span class="p">[</span><span class="n">cons</span><span class="p">],</span> <span class="mi">23</span><span class="p">)</span>
+<span class="n">DIP</span> <span class="o">=</span> <span class="n">CombinatorJoyType</span><span class="p">(</span><span class="s1">&#39;dip&#39;</span><span class="p">,</span> <span class="p">[</span><span class="n">dip_t</span><span class="p">],</span> <span class="mi">44</span><span class="p">)</span>
+
+
+<span class="k">def</span> <span class="nf">kav</span><span class="p">(</span><span class="n">F</span><span class="p">,</span> <span class="n">e</span><span class="p">):</span>
+    <span class="c1">#i, stack = F</span>
+    <span class="k">if</span> <span class="ow">not</span> <span class="n">e</span><span class="p">:</span>
+        <span class="k">return</span> <span class="p">[(</span><span class="n">F</span><span class="p">,</span> <span class="n">e</span><span class="p">)]</span>
+    <span class="n">n</span><span class="p">,</span> <span class="n">e</span> <span class="o">=</span> <span class="n">e</span>
+    <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">SymbolJoyType</span><span class="p">):</span>
+        <span class="n">Fs</span> <span class="o">=</span> <span class="p">[]</span>
+        <span class="k">for</span> <span class="n">sec</span> <span class="ow">in</span> <span class="n">n</span><span class="o">.</span><span class="n">stack_effects</span><span class="p">:</span>
+            <span class="n">Fs</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">MC</span><span class="p">([</span><span class="n">F</span><span class="p">],</span> <span class="n">sec</span><span class="p">))</span>
+        <span class="k">return</span> <span class="p">[</span><span class="n">kav</span><span class="p">(</span><span class="n">Fn</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span> <span class="k">for</span> <span class="n">Fn</span> <span class="ow">in</span> <span class="n">Fs</span><span class="p">]</span>
+    <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">CombinatorJoyType</span><span class="p">):</span>
+        <span class="n">res</span> <span class="o">=</span> <span class="p">[]</span>
+        <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">n</span><span class="o">.</span><span class="n">stack_effects</span><span class="p">:</span>
+            <span class="n">s</span><span class="p">,</span> <span class="n">e</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="n">F</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">e</span><span class="p">)</span>
+            <span class="n">new_F</span> <span class="o">=</span> <span class="n">F</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">s</span>
+            <span class="n">res</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">kav</span><span class="p">(</span><span class="n">new_F</span><span class="p">,</span> <span class="n">e</span><span class="p">))</span>
+        <span class="k">return</span> <span class="n">res</span>
+    <span class="n">lit</span> <span class="o">=</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
+    <span class="k">return</span> <span class="p">[</span><span class="n">kav</span><span class="p">(</span><span class="n">Fn</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span> <span class="k">for</span> <span class="n">Fn</span> <span class="ow">in</span> <span class="n">MC</span><span class="p">([</span><span class="n">F</span><span class="p">],</span> <span class="p">[</span><span class="n">lit</span><span class="p">])]</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
+</div>
+<div class="inner_cell">
+<div class="text_cell_render border-box-sizing rendered_html">
+<p>compare, and be amazed:</p>
+
+</div>
+</div>
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[130]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="k">def</span> <span class="nf">dip_t</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">):</span>
+    <span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">stack</span><span class="p">))</span> <span class="o">=</span> <span class="n">stack</span>
+    <span class="n">expression</span> <span class="o">=</span> <span class="n">stack_concat</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">expression</span><span class="p">))</span>
+    <span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">expression</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[131]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="k">def</span> <span class="nf">dip</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">):</span>
+    <span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">stack</span><span class="p">))</span> <span class="o">=</span> <span class="n">stack</span>
+    <span class="n">expression</span> <span class="o">=</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">expression</span><span class="p">)</span>
+    <span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">concat</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
+</div>
+<div class="inner_cell">
+<div class="text_cell_render border-box-sizing rendered_html">
+<p>And that brings us to current Work-In-Progress.  I'm pretty hopeful that the mixed-mode inferencer/interpreter <code>kav()</code> function along with the ability to specify multiple implementations for the combinators will permit modelling of the stack effects of e.g. <code>ifte</code>.  If I can keep up the pace I should be able to verify that conjecture by the end of June.</p>
+
+</div>
+</div>
+</div>
+<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
+</div>
+<div class="inner_cell">
+<div class="text_cell_render border-box-sizing rendered_html">
+<p>The rest of this stuff is junk and/or unfinished material.</p>
+
+</div>
+</div>
+</div>
+<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
+</div>
+<div class="inner_cell">
+<div class="text_cell_render border-box-sizing rendered_html">
+<h3 id="concat"><code>concat</code><a class="anchor-link" href="#concat">&#182;</a></h3><p>How to deal with <code>concat</code>?</p>
+
+<pre><code>concat ([.0.] [.1.] -- [.0. .1.])
+
+</code></pre>
+<p>We would like to represent this in Python somehow...</p>
+
+</div>
+</div>
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[132]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="n">concat</span> <span class="o">=</span> <span class="p">(</span><span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span> <span class="p">((</span><span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">1</span><span class="p">]),)</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
+</div>
+<div class="inner_cell">
+<div class="text_cell_render border-box-sizing rendered_html">
+<p>But this is actually <code>cons</code> with the first argument restricted to be a stack:</p>
+
+<pre><code>([.0.] [.1.] -- [[.0.] .1.])
+
+</code></pre>
+<p>What we have implemented so far would actually only permit:</p>
+
+<pre><code>([.0.] [.1.] -- [.2.])</code></pre>
+
+</div>
+</div>
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[133]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="n">concat</span> <span class="o">=</span> <span class="p">(</span><span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span> <span class="p">(</span><span class="n">S</span><span class="p">[</span><span class="mi">2</span><span class="p">],)</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
+</div>
+<div class="inner_cell">
+<div class="text_cell_render border-box-sizing rendered_html">
+<p>Which works but can lose information.  Consider <code>cons concat</code>, this is how much information we <em>could</em> retain:</p>
+
+<pre><code>(1 [.0.] [.1.] -- [1 .0. .1.])
+
+</code></pre>
+<p>As opposed to just:</p>
+
+<pre><code>(1 [.0.] [.1.] -- [.2.])</code></pre>
+
+</div>
+</div>
+</div>
+<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
+</div>
+<div class="inner_cell">
+<div class="text_cell_render border-box-sizing rendered_html">
+<h3 id="represent-concat">represent <code>concat</code><a class="anchor-link" href="#represent-concat">&#182;</a></h3>
+<pre><code>([.0.] [.1.] -- [A*(.0.) .1.])
+
+</code></pre>
+<p>Meaning that <code>A*</code> on the right-hand side should all the crap from <code>.0.</code>.</p>
+
+<pre><code>([      .0.] [.1.] -- [      A* .1.])
+([a     .0.] [.1.] -- [a     A* .1.])
+([a b   .0.] [.1.] -- [a b   A* .1.])
+([a b c .0.] [.1.] -- [a b c A* .1.])</code></pre>
+
+</div>
+</div>
+</div>
+<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
+</div>
+<div class="inner_cell">
+<div class="text_cell_render border-box-sizing rendered_html">
+<p>or...</p>
+
+<pre><code>([       .0.] [.1.] -- [       .1.])
+([a      .0.] [.1.] -- [a      .1.])
+([a b    .0.] [.1.] -- [a b    .1.])
+([a b  c .0.] [.1.] -- [a b  c .1.])
+([a A* c .0.] [.1.] -- [a A* c .1.])</code></pre>
+
+</div>
+</div>
+</div>
+<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
+</div>
+<div class="inner_cell">
+<div class="text_cell_render border-box-sizing rendered_html">
+
+<pre><code>(a, (b, S0)) . S1 = (a, (b, (A*, S1)))</code></pre>
+
+</div>
+</div>
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[134]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="k">class</span> <span class="nc">Astar</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+    <span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="k">return</span> <span class="s1">&#39;A*&#39;</span>
+
+
+<span class="k">def</span> <span class="nf">concat</span><span class="p">(</span><span class="n">s0</span><span class="p">,</span> <span class="n">s1</span><span class="p">):</span>
+    <span class="n">a</span> <span class="o">=</span> <span class="p">[]</span>
+    <span class="k">while</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">s0</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">):</span>
+        <span class="n">term</span><span class="p">,</span> <span class="n">s0</span> <span class="o">=</span> <span class="n">s0</span>
+        <span class="n">a</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">term</span><span class="p">)</span>
+    <span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">s0</span><span class="p">,</span> <span class="n">StackJoyType</span><span class="p">),</span> <span class="nb">repr</span><span class="p">(</span><span class="n">s0</span><span class="p">)</span>
+    <span class="n">s1</span> <span class="o">=</span> <span class="n">Astar</span><span class="p">(),</span> <span class="n">s1</span>
+    <span class="k">for</span> <span class="n">term</span> <span class="ow">in</span> <span class="nb">reversed</span><span class="p">(</span><span class="n">a</span><span class="p">):</span>
+        <span class="n">s1</span> <span class="o">=</span> <span class="n">term</span><span class="p">,</span> <span class="n">s1</span>
+    <span class="k">return</span> <span class="n">s1</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[135]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="p">(</span><span class="n">A</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span> <span class="p">(</span><span class="n">A</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[136]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="n">concat</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+<div class="output_wrapper">
+<div class="output">
+
+
+<div class="output_area">
+
+<div class="prompt output_prompt">Out[136]:</div>
+
+
+
+
+<div class="output_text output_subarea output_execute_result">
+<pre>(a1, (A*, (a2, s1)))</pre>
+</div>
+
+</div>
+
+</div>
+</div>
+
+</div>
+<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
+</div>
+<div class="inner_cell">
+<div class="text_cell_render border-box-sizing rendered_html">
+<h2 id="Appendix:-Joy-in-the-Logical-Paradigm">Appendix: Joy in the Logical Paradigm<a class="anchor-link" href="#Appendix:-Joy-in-the-Logical-Paradigm">&#182;</a></h2><p>For this to work the type label classes have to be modified to let <code>T &gt;= t</code> succeed, where e.g. <code>T</code> is <code>IntJoyType</code> and <code>t</code> is <code>int</code></p>
+
+</div>
+</div>
+</div>
+<div class="cell border-box-sizing code_cell rendered">
+<div class="input">
+<div class="prompt input_prompt">In&nbsp;[137]:</div>
+<div class="inner_cell">
+    <div class="input_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="n">F</span> <span class="o">=</span> <span class="nb">reduce</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="p">(</span><span class="n">pop</span><span class="p">,</span> <span class="n">swap</span><span class="p">,</span> <span class="n">roll_down</span><span class="p">,</span> <span class="n">rest</span><span class="p">,</span> <span class="n">rest</span><span class="p">,</span> <span class="n">cons</span><span class="p">,</span> <span class="n">cons</span><span class="p">))</span>
+
+<span class="k">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">F</span><span class="p">)</span>
+</pre></div>
+
+</div>
+</div>
+</div>
+
+<div class="output_wrapper">
+<div class="output">
+
+
+<div class="output_area">
+
+<div class="prompt"></div>
+
+
+<div class="output_subarea output_text output_error">
+<pre>
+<span class="ansi-red-fg">---------------------------------------------------------------------------</span>
+<span class="ansi-red-fg">ValueError</span>                                Traceback (most recent call last)
+<span class="ansi-green-fg">&lt;ipython-input-137-4b4cb6ff86e5&gt;</span> in <span class="ansi-cyan-fg">&lt;module&gt;</span><span class="ansi-blue-fg">()</span>
 <span class="ansi-green-intense-fg ansi-bold">      1</span> F <span class="ansi-blue-fg">=</span> reduce<span class="ansi-blue-fg">(</span>C<span class="ansi-blue-fg">,</span> <span class="ansi-blue-fg">(</span>pop<span class="ansi-blue-fg">,</span> swap<span class="ansi-blue-fg">,</span> roll_down<span class="ansi-blue-fg">,</span> rest<span class="ansi-blue-fg">,</span> rest<span class="ansi-blue-fg">,</span> cons<span class="ansi-blue-fg">,</span> cons<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">)</span>
 <span class="ansi-green-intense-fg ansi-bold">      2</span> 
 <span class="ansi-green-fg">----&gt; 3</span><span class="ansi-red-fg"> </span><span class="ansi-green-fg">print</span> doc_from_stack_effect<span class="ansi-blue-fg">(</span><span class="ansi-blue-fg">*</span>F<span class="ansi-blue-fg">)</span>
 
-<span class="ansi-green-fg">&lt;ipython-input-101-ddee30dbb1a6&gt;</span> in <span class="ansi-cyan-fg">C</span><span class="ansi-blue-fg">(f, g)</span>
+<span class="ansi-green-fg">&lt;ipython-input-99-ddee30dbb1a6&gt;</span> in <span class="ansi-cyan-fg">C</span><span class="ansi-blue-fg">(f, g)</span>
 <span class="ansi-green-intense-fg ansi-bold">     10</span> <span class="ansi-green-fg">def</span> C<span class="ansi-blue-fg">(</span>f<span class="ansi-blue-fg">,</span> g<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">:</span>
 <span class="ansi-green-intense-fg ansi-bold">     11</span>     f<span class="ansi-blue-fg">,</span> g <span class="ansi-blue-fg">=</span> relabel<span class="ansi-blue-fg">(</span>f<span class="ansi-blue-fg">,</span> g<span class="ansi-blue-fg">)</span>
 <span class="ansi-green-fg">---&gt; 12</span><span class="ansi-red-fg">     </span><span class="ansi-green-fg">for</span> fg <span class="ansi-green-fg">in</span> compose<span class="ansi-blue-fg">(</span>f<span class="ansi-blue-fg">,</span> g<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">:</span>
 <span class="ansi-green-intense-fg ansi-bold">     13</span>         <span class="ansi-green-fg">yield</span> delabel<span class="ansi-blue-fg">(</span>fg<span class="ansi-blue-fg">)</span>
 
-<span class="ansi-green-fg">&lt;ipython-input-100-4237a6bb159d&gt;</span> in <span class="ansi-cyan-fg">compose</span><span class="ansi-blue-fg">(f, g)</span>
+<span class="ansi-green-fg">&lt;ipython-input-98-5eb7ac5ad2c2&gt;</span> in <span class="ansi-cyan-fg">compose</span><span class="ansi-blue-fg">(f, g)</span>
 <span class="ansi-green-intense-fg ansi-bold">      1</span> <span class="ansi-green-fg">def</span> compose<span class="ansi-blue-fg">(</span>f<span class="ansi-blue-fg">,</span> g<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">:</span>
-<span class="ansi-green-intense-fg ansi-bold">      2</span> 
-<span class="ansi-green-fg">----&gt; 3</span><span class="ansi-red-fg">     </span><span class="ansi-blue-fg">(</span>f_in<span class="ansi-blue-fg">,</span> f_out<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">,</span> <span class="ansi-blue-fg">(</span>g_in<span class="ansi-blue-fg">,</span> g_out<span class="ansi-blue-fg">)</span> <span class="ansi-blue-fg">=</span> f<span class="ansi-blue-fg">,</span> g
-<span class="ansi-green-intense-fg ansi-bold">      4</span> 
-<span class="ansi-green-intense-fg ansi-bold">      5</span>     <span class="ansi-green-fg">if</span> <span class="ansi-green-fg">not</span> g_in<span class="ansi-blue-fg">:</span>
+<span class="ansi-green-fg">----&gt; 2</span><span class="ansi-red-fg">     </span><span class="ansi-blue-fg">(</span>f_in<span class="ansi-blue-fg">,</span> f_out<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">,</span> <span class="ansi-blue-fg">(</span>g_in<span class="ansi-blue-fg">,</span> g_out<span class="ansi-blue-fg">)</span> <span class="ansi-blue-fg">=</span> f<span class="ansi-blue-fg">,</span> g
+<span class="ansi-green-intense-fg ansi-bold">      3</span>     s <span class="ansi-blue-fg">=</span> unify<span class="ansi-blue-fg">(</span>g_in<span class="ansi-blue-fg">,</span> f_out<span class="ansi-blue-fg">)</span>
+<span class="ansi-green-intense-fg ansi-bold">      4</span>     <span class="ansi-green-fg">if</span> <span class="ansi-green-fg">not</span> s<span class="ansi-blue-fg">:</span>
+<span class="ansi-green-intense-fg ansi-bold">      5</span>         <span class="ansi-green-fg">raise</span> TypeError<span class="ansi-blue-fg">(</span><span class="ansi-blue-fg">&#39;Cannot unify %r and %r.&#39;</span> <span class="ansi-blue-fg">%</span> <span class="ansi-blue-fg">(</span>f_out<span class="ansi-blue-fg">,</span> g_in<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">)</span>
 
-<span class="ansi-green-fg">&lt;ipython-input-101-ddee30dbb1a6&gt;</span> in <span class="ansi-cyan-fg">C</span><span class="ansi-blue-fg">(f, g)</span>
+<span class="ansi-green-fg">&lt;ipython-input-99-ddee30dbb1a6&gt;</span> in <span class="ansi-cyan-fg">C</span><span class="ansi-blue-fg">(f, g)</span>
 <span class="ansi-green-intense-fg ansi-bold">     10</span> <span class="ansi-green-fg">def</span> C<span class="ansi-blue-fg">(</span>f<span class="ansi-blue-fg">,</span> g<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">:</span>
 <span class="ansi-green-intense-fg ansi-bold">     11</span>     f<span class="ansi-blue-fg">,</span> g <span class="ansi-blue-fg">=</span> relabel<span class="ansi-blue-fg">(</span>f<span class="ansi-blue-fg">,</span> g<span class="ansi-blue-fg">)</span>
 <span class="ansi-green-fg">---&gt; 12</span><span class="ansi-red-fg">     </span><span class="ansi-green-fg">for</span> fg <span class="ansi-green-fg">in</span> compose<span class="ansi-blue-fg">(</span>f<span class="ansi-blue-fg">,</span> g<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">:</span>
 <span class="ansi-green-intense-fg ansi-bold">     13</span>         <span class="ansi-green-fg">yield</span> delabel<span class="ansi-blue-fg">(</span>fg<span class="ansi-blue-fg">)</span>
 
-<span class="ansi-green-fg">&lt;ipython-input-100-4237a6bb159d&gt;</span> in <span class="ansi-cyan-fg">compose</span><span class="ansi-blue-fg">(f, g)</span>
+<span class="ansi-green-fg">&lt;ipython-input-98-5eb7ac5ad2c2&gt;</span> in <span class="ansi-cyan-fg">compose</span><span class="ansi-blue-fg">(f, g)</span>
 <span class="ansi-green-intense-fg ansi-bold">      1</span> <span class="ansi-green-fg">def</span> compose<span class="ansi-blue-fg">(</span>f<span class="ansi-blue-fg">,</span> g<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">:</span>
-<span class="ansi-green-intense-fg ansi-bold">      2</span> 
-<span class="ansi-green-fg">----&gt; 3</span><span class="ansi-red-fg">     </span><span class="ansi-blue-fg">(</span>f_in<span class="ansi-blue-fg">,</span> f_out<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">,</span> <span class="ansi-blue-fg">(</span>g_in<span class="ansi-blue-fg">,</span> g_out<span class="ansi-blue-fg">)</span> <span class="ansi-blue-fg">=</span> f<span class="ansi-blue-fg">,</span> g
-<span class="ansi-green-intense-fg ansi-bold">      4</span> 
-<span class="ansi-green-intense-fg ansi-bold">      5</span>     <span class="ansi-green-fg">if</span> <span class="ansi-green-fg">not</span> g_in<span class="ansi-blue-fg">:</span>
+<span class="ansi-green-fg">----&gt; 2</span><span class="ansi-red-fg">     </span><span class="ansi-blue-fg">(</span>f_in<span class="ansi-blue-fg">,</span> f_out<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">,</span> <span class="ansi-blue-fg">(</span>g_in<span class="ansi-blue-fg">,</span> g_out<span class="ansi-blue-fg">)</span> <span class="ansi-blue-fg">=</span> f<span class="ansi-blue-fg">,</span> g
+<span class="ansi-green-intense-fg ansi-bold">      3</span>     s <span class="ansi-blue-fg">=</span> unify<span class="ansi-blue-fg">(</span>g_in<span class="ansi-blue-fg">,</span> f_out<span class="ansi-blue-fg">)</span>
+<span class="ansi-green-intense-fg ansi-bold">      4</span>     <span class="ansi-green-fg">if</span> <span class="ansi-green-fg">not</span> s<span class="ansi-blue-fg">:</span>
+<span class="ansi-green-intense-fg ansi-bold">      5</span>         <span class="ansi-green-fg">raise</span> TypeError<span class="ansi-blue-fg">(</span><span class="ansi-blue-fg">&#39;Cannot unify %r and %r.&#39;</span> <span class="ansi-blue-fg">%</span> <span class="ansi-blue-fg">(</span>f_out<span class="ansi-blue-fg">,</span> g_in<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">)</span>
 
-<span class="ansi-green-fg">&lt;ipython-input-101-ddee30dbb1a6&gt;</span> in <span class="ansi-cyan-fg">C</span><span class="ansi-blue-fg">(f, g)</span>
+<span class="ansi-green-fg">&lt;ipython-input-99-ddee30dbb1a6&gt;</span> in <span class="ansi-cyan-fg">C</span><span class="ansi-blue-fg">(f, g)</span>
 <span class="ansi-green-intense-fg ansi-bold">     10</span> <span class="ansi-green-fg">def</span> C<span class="ansi-blue-fg">(</span>f<span class="ansi-blue-fg">,</span> g<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">:</span>
 <span class="ansi-green-intense-fg ansi-bold">     11</span>     f<span class="ansi-blue-fg">,</span> g <span class="ansi-blue-fg">=</span> relabel<span class="ansi-blue-fg">(</span>f<span class="ansi-blue-fg">,</span> g<span class="ansi-blue-fg">)</span>
 <span class="ansi-green-fg">---&gt; 12</span><span class="ansi-red-fg">     </span><span class="ansi-green-fg">for</span> fg <span class="ansi-green-fg">in</span> compose<span class="ansi-blue-fg">(</span>f<span class="ansi-blue-fg">,</span> g<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">:</span>
 <span class="ansi-green-intense-fg ansi-bold">     13</span>         <span class="ansi-green-fg">yield</span> delabel<span class="ansi-blue-fg">(</span>fg<span class="ansi-blue-fg">)</span>
 
-<span class="ansi-green-fg">&lt;ipython-input-100-4237a6bb159d&gt;</span> in <span class="ansi-cyan-fg">compose</span><span class="ansi-blue-fg">(f, g)</span>
+<span class="ansi-green-fg">&lt;ipython-input-98-5eb7ac5ad2c2&gt;</span> in <span class="ansi-cyan-fg">compose</span><span class="ansi-blue-fg">(f, g)</span>
 <span class="ansi-green-intense-fg ansi-bold">      1</span> <span class="ansi-green-fg">def</span> compose<span class="ansi-blue-fg">(</span>f<span class="ansi-blue-fg">,</span> g<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">:</span>
-<span class="ansi-green-intense-fg ansi-bold">      2</span> 
-<span class="ansi-green-fg">----&gt; 3</span><span class="ansi-red-fg">     </span><span class="ansi-blue-fg">(</span>f_in<span class="ansi-blue-fg">,</span> f_out<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">,</span> <span class="ansi-blue-fg">(</span>g_in<span class="ansi-blue-fg">,</span> g_out<span class="ansi-blue-fg">)</span> <span class="ansi-blue-fg">=</span> f<span class="ansi-blue-fg">,</span> g
-<span class="ansi-green-intense-fg ansi-bold">      4</span> 
-<span class="ansi-green-intense-fg ansi-bold">      5</span>     <span class="ansi-green-fg">if</span> <span class="ansi-green-fg">not</span> g_in<span class="ansi-blue-fg">:</span>
+<span class="ansi-green-fg">----&gt; 2</span><span class="ansi-red-fg">     </span><span class="ansi-blue-fg">(</span>f_in<span class="ansi-blue-fg">,</span> f_out<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">,</span> <span class="ansi-blue-fg">(</span>g_in<span class="ansi-blue-fg">,</span> g_out<span class="ansi-blue-fg">)</span> <span class="ansi-blue-fg">=</span> f<span class="ansi-blue-fg">,</span> g
+<span class="ansi-green-intense-fg ansi-bold">      3</span>     s <span class="ansi-blue-fg">=</span> unify<span class="ansi-blue-fg">(</span>g_in<span class="ansi-blue-fg">,</span> f_out<span class="ansi-blue-fg">)</span>
+<span class="ansi-green-intense-fg ansi-bold">      4</span>     <span class="ansi-green-fg">if</span> <span class="ansi-green-fg">not</span> s<span class="ansi-blue-fg">:</span>
+<span class="ansi-green-intense-fg ansi-bold">      5</span>         <span class="ansi-green-fg">raise</span> TypeError<span class="ansi-blue-fg">(</span><span class="ansi-blue-fg">&#39;Cannot unify %r and %r.&#39;</span> <span class="ansi-blue-fg">%</span> <span class="ansi-blue-fg">(</span>f_out<span class="ansi-blue-fg">,</span> g_in<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">)</span>
 
-<span class="ansi-green-fg">&lt;ipython-input-101-ddee30dbb1a6&gt;</span> in <span class="ansi-cyan-fg">C</span><span class="ansi-blue-fg">(f, g)</span>
+<span class="ansi-green-fg">&lt;ipython-input-99-ddee30dbb1a6&gt;</span> in <span class="ansi-cyan-fg">C</span><span class="ansi-blue-fg">(f, g)</span>
 <span class="ansi-green-intense-fg ansi-bold">     10</span> <span class="ansi-green-fg">def</span> C<span class="ansi-blue-fg">(</span>f<span class="ansi-blue-fg">,</span> g<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">:</span>
 <span class="ansi-green-intense-fg ansi-bold">     11</span>     f<span class="ansi-blue-fg">,</span> g <span class="ansi-blue-fg">=</span> relabel<span class="ansi-blue-fg">(</span>f<span class="ansi-blue-fg">,</span> g<span class="ansi-blue-fg">)</span>
 <span class="ansi-green-fg">---&gt; 12</span><span class="ansi-red-fg">     </span><span class="ansi-green-fg">for</span> fg <span class="ansi-green-fg">in</span> compose<span class="ansi-blue-fg">(</span>f<span class="ansi-blue-fg">,</span> g<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">:</span>
 <span class="ansi-green-intense-fg ansi-bold">     13</span>         <span class="ansi-green-fg">yield</span> delabel<span class="ansi-blue-fg">(</span>fg<span class="ansi-blue-fg">)</span>
 
-<span class="ansi-green-fg">&lt;ipython-input-100-4237a6bb159d&gt;</span> in <span class="ansi-cyan-fg">compose</span><span class="ansi-blue-fg">(f, g)</span>
+<span class="ansi-green-fg">&lt;ipython-input-98-5eb7ac5ad2c2&gt;</span> in <span class="ansi-cyan-fg">compose</span><span class="ansi-blue-fg">(f, g)</span>
 <span class="ansi-green-intense-fg ansi-bold">      1</span> <span class="ansi-green-fg">def</span> compose<span class="ansi-blue-fg">(</span>f<span class="ansi-blue-fg">,</span> g<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">:</span>
-<span class="ansi-green-intense-fg ansi-bold">      2</span> 
-<span class="ansi-green-fg">----&gt; 3</span><span class="ansi-red-fg">     </span><span class="ansi-blue-fg">(</span>f_in<span class="ansi-blue-fg">,</span> f_out<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">,</span> <span class="ansi-blue-fg">(</span>g_in<span class="ansi-blue-fg">,</span> g_out<span class="ansi-blue-fg">)</span> <span class="ansi-blue-fg">=</span> f<span class="ansi-blue-fg">,</span> g
-<span class="ansi-green-intense-fg ansi-bold">      4</span> 
-<span class="ansi-green-intense-fg ansi-bold">      5</span>     <span class="ansi-green-fg">if</span> <span class="ansi-green-fg">not</span> g_in<span class="ansi-blue-fg">:</span>
+<span class="ansi-green-fg">----&gt; 2</span><span class="ansi-red-fg">     </span><span class="ansi-blue-fg">(</span>f_in<span class="ansi-blue-fg">,</span> f_out<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">,</span> <span class="ansi-blue-fg">(</span>g_in<span class="ansi-blue-fg">,</span> g_out<span class="ansi-blue-fg">)</span> <span class="ansi-blue-fg">=</span> f<span class="ansi-blue-fg">,</span> g
+<span class="ansi-green-intense-fg ansi-bold">      3</span>     s <span class="ansi-blue-fg">=</span> unify<span class="ansi-blue-fg">(</span>g_in<span class="ansi-blue-fg">,</span> f_out<span class="ansi-blue-fg">)</span>
+<span class="ansi-green-intense-fg ansi-bold">      4</span>     <span class="ansi-green-fg">if</span> <span class="ansi-green-fg">not</span> s<span class="ansi-blue-fg">:</span>
+<span class="ansi-green-intense-fg ansi-bold">      5</span>         <span class="ansi-green-fg">raise</span> TypeError<span class="ansi-blue-fg">(</span><span class="ansi-blue-fg">&#39;Cannot unify %r and %r.&#39;</span> <span class="ansi-blue-fg">%</span> <span class="ansi-blue-fg">(</span>f_out<span class="ansi-blue-fg">,</span> g_in<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">)</span>
 
-<span class="ansi-green-fg">&lt;ipython-input-101-ddee30dbb1a6&gt;</span> in <span class="ansi-cyan-fg">C</span><span class="ansi-blue-fg">(f, g)</span>
+<span class="ansi-green-fg">&lt;ipython-input-99-ddee30dbb1a6&gt;</span> in <span class="ansi-cyan-fg">C</span><span class="ansi-blue-fg">(f, g)</span>
 <span class="ansi-green-intense-fg ansi-bold">     10</span> <span class="ansi-green-fg">def</span> C<span class="ansi-blue-fg">(</span>f<span class="ansi-blue-fg">,</span> g<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">:</span>
 <span class="ansi-green-intense-fg ansi-bold">     11</span>     f<span class="ansi-blue-fg">,</span> g <span class="ansi-blue-fg">=</span> relabel<span class="ansi-blue-fg">(</span>f<span class="ansi-blue-fg">,</span> g<span class="ansi-blue-fg">)</span>
 <span class="ansi-green-fg">---&gt; 12</span><span class="ansi-red-fg">     </span><span class="ansi-green-fg">for</span> fg <span class="ansi-green-fg">in</span> compose<span class="ansi-blue-fg">(</span>f<span class="ansi-blue-fg">,</span> g<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">:</span>
 <span class="ansi-green-intense-fg ansi-bold">     13</span>         <span class="ansi-green-fg">yield</span> delabel<span class="ansi-blue-fg">(</span>fg<span class="ansi-blue-fg">)</span>
 
-<span class="ansi-green-fg">&lt;ipython-input-100-4237a6bb159d&gt;</span> in <span class="ansi-cyan-fg">compose</span><span class="ansi-blue-fg">(f, g)</span>
+<span class="ansi-green-fg">&lt;ipython-input-98-5eb7ac5ad2c2&gt;</span> in <span class="ansi-cyan-fg">compose</span><span class="ansi-blue-fg">(f, g)</span>
 <span class="ansi-green-intense-fg ansi-bold">      1</span> <span class="ansi-green-fg">def</span> compose<span class="ansi-blue-fg">(</span>f<span class="ansi-blue-fg">,</span> g<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">:</span>
-<span class="ansi-green-intense-fg ansi-bold">      2</span> 
-<span class="ansi-green-fg">----&gt; 3</span><span class="ansi-red-fg">     </span><span class="ansi-blue-fg">(</span>f_in<span class="ansi-blue-fg">,</span> f_out<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">,</span> <span class="ansi-blue-fg">(</span>g_in<span class="ansi-blue-fg">,</span> g_out<span class="ansi-blue-fg">)</span> <span class="ansi-blue-fg">=</span> f<span class="ansi-blue-fg">,</span> g
-<span class="ansi-green-intense-fg ansi-bold">      4</span> 
-<span class="ansi-green-intense-fg ansi-bold">      5</span>     <span class="ansi-green-fg">if</span> <span class="ansi-green-fg">not</span> g_in<span class="ansi-blue-fg">:</span>
+<span class="ansi-green-fg">----&gt; 2</span><span class="ansi-red-fg">     </span><span class="ansi-blue-fg">(</span>f_in<span class="ansi-blue-fg">,</span> f_out<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">,</span> <span class="ansi-blue-fg">(</span>g_in<span class="ansi-blue-fg">,</span> g_out<span class="ansi-blue-fg">)</span> <span class="ansi-blue-fg">=</span> f<span class="ansi-blue-fg">,</span> g
+<span class="ansi-green-intense-fg ansi-bold">      3</span>     s <span class="ansi-blue-fg">=</span> unify<span class="ansi-blue-fg">(</span>g_in<span class="ansi-blue-fg">,</span> f_out<span class="ansi-blue-fg">)</span>
+<span class="ansi-green-intense-fg ansi-bold">      4</span>     <span class="ansi-green-fg">if</span> <span class="ansi-green-fg">not</span> s<span class="ansi-blue-fg">:</span>
+<span class="ansi-green-intense-fg ansi-bold">      5</span>         <span class="ansi-green-fg">raise</span> TypeError<span class="ansi-blue-fg">(</span><span class="ansi-blue-fg">&#39;Cannot unify %r and %r.&#39;</span> <span class="ansi-blue-fg">%</span> <span class="ansi-blue-fg">(</span>f_out<span class="ansi-blue-fg">,</span> g_in<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">)</span>
 
 <span class="ansi-red-fg">ValueError</span>: need more than 1 value to unpack</pre>
 </div>
@@ -16771,42 +17464,8 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<h2 id="Typing-Combinators">Typing Combinators<a class="anchor-link" href="#Typing-Combinators">&#182;</a></h2><p>TBD</p>
-<p>This is an open subject.</p>
-<p>The obvious thing is that you now need two pairs of tuples to describe the combinators' effects,  a stack effect comment and an expression effect comment:</p>
-
-<pre><code>dip (a [F] --)--(-- F a)
-
-</code></pre>
-<p>One thing that might help is...</p>
-
-</div>
-</div>
-</div>
-<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
-</div>
-<div class="inner_cell">
-<div class="text_cell_render border-box-sizing rendered_html">
-<h2 id="Abstract-Interpretation">Abstract Interpretation<a class="anchor-link" href="#Abstract-Interpretation">&#182;</a></h2>
-</div>
-</div>
-</div>
-<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
-</div>
-<div class="inner_cell">
-<div class="text_cell_render border-box-sizing rendered_html">
-<h2 id="Something-else...">Something else...<a class="anchor-link" href="#Something-else...">&#182;</a></h2>
-<pre><code>[4 5 ...] 2 1 0 pop∘swap∘roll&lt;∘rest∘rest∘cons∘cons
-[4 5 ...] 2 1       swap∘roll&lt;∘rest∘rest∘cons∘cons
-[4 5 ...] 1 2            roll&lt;∘rest∘rest∘cons∘cons
-1 2 [4 5 ...]                  rest∘rest∘cons∘cons
-1 2   [5 ...]                       rest∘cons∘cons
-1 2     [...]                            cons∘cons
-1     [2 ...]                                 cons
-    [1 2 ...]
-
-</code></pre>
-<p>Eh?</p>
+<h2 id="Abstract-Interpretation"><a href="https://en.wikipedia.org/wiki/Abstract_interpretation">Abstract Interpretation</a><a class="anchor-link" href="#Abstract-Interpretation">&#182;</a></h2><p>I <em>think</em> this might be sorta what I'm doing above with the <code>kav()</code> function...
+  In any event "mixed-mode" interpreters that include values and type variables and can track constraints, etc. will be, uh, super-useful.  And Abstract Interpretation should be a rich source of ideas.</p>
 
 </div>
 </div>
index ed16c7f..2f9ddf1 100644 (file)
@@ -4,14 +4,16 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "# Type Inference"
+    "# Type Inference\n",
+    "\n",
+    "Cf. [\"Type Inference in Stack-Based Programming Languages\"](http://prl.ccs.neu.edu/blog/2017/03/10/type-inference-in-stack-based-programming-languages/) by Rob Kleffner, 2017-03-10."
    ]
   },
   {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "## Pöial's Rules\n",
+    "## Part I: Pöial's Rules\n",
     "\n",
     "[\"Typing Tools for Typeless Stack Languages\" by Jaanus Pöial\n",
     "](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.212.6026)\n",
@@ -55,7 +57,7 @@
    "metadata": {},
    "source": [
     "### Third Rule\n",
-    "The third rule is actually two rules.  These two rules deal with composing functions when the second one will consume one of items the first one produces.  The two types must be *unified* or a type conflict declared.\n",
+    "The third rule is actually two rules.  These two rules deal with composing functions when the second one will consume one of items the first one produces.  The two types must be [*unified*](https://en.wikipedia.org/wiki/Robinson's_unification_algorithm) or a type conflict declared.\n",
     "\n",
     "       (a -- b t[i])∘(c u[j] -- d)   t <= u (t is subtype of u)\n",
     "    -------------------------------\n",
@@ -71,7 +73,6 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "## Examples\n",
     "Let's work through some examples by hand to develop an intuition for the algorithm."
    ]
   },
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "## Implementation"
+    "## Part II: Implementation"
    ]
   },
   {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "### List Functions\n",
-    "Here's that trick to represent functions like `rest` and `cons` that manipulate lists.  We use a cons-list of tuples and give the tails their own numbers.  Then everything above already works. "
+    "### Stack Functions\n",
+    "Here's that trick to represent functions like `rest` and `cons` that manipulate stacks.  We use a cons-list of tuples and give the tails their own numbers.  Then everything above already works. "
    ]
   },
   {
    "source": [
     "Compare with the stack effect comment and you can see it works fine:\n",
     "\n",
-    "    ([4 5 ...] 2 3 1 -- [3 2 ...])"
+    "    ([4 5 ...] 2 3 1 -- [3 2 ...])\n",
+    "      3 4  5   1 2 0     2 1  5"
    ]
   },
   {
     "def unify(u, v, s=None):\n",
     "    if s is None:\n",
     "        s = {}\n",
-    "    else:\n",
+    "    elif s:\n",
     "        u = update(s, u)\n",
     "        v = update(s, v)\n",
     "\n",
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "## Compiling\n",
+    "## Part III: Compiling Stack Functions\n",
     "Now consider the Python function we would like to derive:"
    ]
   },
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "## Types and Subtypes of Arguments\n",
+    "## Part IV: Types and Subtypes of Arguments\n",
     "So far we have dealt with types of functions, those dealing with simple stack manipulation.  Let's extend our machinery to deal with types of arguments."
    ]
   },
     "def unify(u, v, s=None):\n",
     "    if s is None:\n",
     "        s = {}\n",
-    "    else:\n",
+    "    elif s:\n",
     "        u = update(s, u)\n",
     "        v = update(s, v)\n",
     "\n",
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "## Functions that use the Stack\n",
+    "## Part V: Functions that use the Stack\n",
     "\n",
     "Consider the `stack` function which grabs the whole stack, quotes it, and puts it on itself:\n",
     "\n",
    "metadata": {},
    "source": [
     "#### `compose()` version 2\n",
-    "This function has to be modified to use the new datastructures and it is no longer recursive, instead recursion happens as part of unification."
+    "This function has to be modified to use the new datastructures and it is no longer recursive, instead recursion happens as part of unification.  Further, the first and second of Pöial's rules are now handled automatically by the unification algorithm."
    ]
   },
   {
    "outputs": [],
    "source": [
     "def compose(f, g):\n",
-    "\n",
     "    (f_in, f_out), (g_in, g_out) = f, g\n",
-    "\n",
-    "    if not g_in:\n",
-    "        fg_in, fg_out = f_in, stack_concat(g_out, f_out)\n",
-    "\n",
-    "    elif not f_out:\n",
-    "        fg_in, fg_out = stack_concat(f_in, g_in), g_out\n",
-    "\n",
-    "    else: # Unify and update.\n",
-    "\n",
-    "        s = unify(g_in, f_out)\n",
-    "\n",
-    "        if s == False:  # s can also be the empty dict, which is ok.\n",
-    "            raise TypeError('Cannot unify %r and %r.' % (fo, gi))\n",
-    "\n",
-    "        fg_in, fg_out = update(s, (f_in, g_out))\n",
-    "\n",
-    "    return fg_in, fg_out\n",
-    "\n",
-    "\n",
-    "stack_concat = lambda q, e: (q[0], stack_concat(q[1], e)) if q else e"
+    "    s = unify(g_in, f_out)\n",
+    "    if s == False:  # s can also be the empty dict, which is ok.\n",
+    "        raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))\n",
+    "    return update(s, (f_in, g_out))"
    ]
   },
   {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "## Multiple Stack Effects\n",
+    "## Part VI: Multiple Stack Effects\n",
     "..."
    ]
   },
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "## `concat`\n",
-    "\n",
-    "How to deal with `concat`?\n",
-    "\n",
-    "    concat ([.0.] [.1.] -- [.0. .1.])\n",
-    "    \n",
-    "We would like to represent this in Python somehow..."
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 89,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "concat = (S[0], S[1]), ((S[0], S[1]),)"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "But this is actually `cons` with the first argument restricted to be a stack:\n",
-    "\n",
-    "    ([.0.] [.1.] -- [[.0.] .1.])\n",
-    "\n",
-    "What we have implemented so far would actually only permit:\n",
-    "\n",
-    "    ([.0.] [.1.] -- [.2.])"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 90,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "concat = (S[0], S[1]), (S[2],)"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "    \n",
-    "Which works but can lose information.  Consider `cons concat`, this is how much information we *could* retain:\n",
-    "\n",
-    "    (1 [.0.] [.1.] -- [1 .0. .1.])\n",
-    "\n",
-    "As opposed to just:\n",
-    "\n",
-    "    (1 [.0.] [.1.] -- [.2.])"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "### Brzo...'s Derivitives of Regular Expressions\n",
+    "### Representing an Unbounded Sequence of Types\n",
     "\n",
-    "We can invent a new type of type variable, a \"sequence type\" (I think this is what they mean in the literature by that term...) or \"Kleene Star\" type.  I'm going to represent it as a type letter and the asterix, so a sequence of zero or more `AnyJoyType` variables would be:\n",
+    "We can borrow a trick from [Brzozowski's Derivatives of Regular Expressions](https://en.wikipedia.org/wiki/Brzozowski_derivative) to invent a new type of type variable, a \"sequence type\" (I think this is what they mean in the literature by that term...) or \"[Kleene Star](https://en.wikipedia.org/wiki/Kleene_star)\" type.  I'm going to represent it as a type letter and the asterix, so a sequence of zero or more `AnyJoyType` variables would be:\n",
     "\n",
     "    A*"
    ]
     "                            w/ {d: e}\n",
     "    [  A* b .0.] U [  .1.]\n",
     "                            w/ {.1.: A* b .0.}\n",
-    "    [  A* b .0.] U [  .1.]"
+    "    [  A* b .0.] U [  A* b .0.]"
    ]
   },
   {
   },
   {
    "cell_type": "code",
-   "execution_count": 91,
+   "execution_count": 89,
    "metadata": {},
    "outputs": [],
    "source": [
   },
   {
    "cell_type": "code",
-   "execution_count": 92,
+   "execution_count": 90,
    "metadata": {},
    "outputs": [],
    "source": [
     "                sn.update(s)\n",
     "            return t\n",
     "\n",
-    "        ses = unify(u[0], v[0])\n",
+    "        ses = unify(u[0], v[0], s)\n",
     "        results = ()\n",
     "        for sn in ses:\n",
     "            results += unify(u[1], v[1], sn)\n",
   },
   {
    "cell_type": "code",
-   "execution_count": 93,
+   "execution_count": 91,
    "metadata": {},
    "outputs": [
     {
        "(a1*, s1)"
       ]
      },
-     "execution_count": 93,
+     "execution_count": 91,
      "metadata": {},
      "output_type": "execute_result"
     }
   },
   {
    "cell_type": "code",
-   "execution_count": 94,
+   "execution_count": 92,
    "metadata": {},
    "outputs": [
     {
        "(a1, s2)"
       ]
      },
-     "execution_count": 94,
+     "execution_count": 92,
      "metadata": {},
      "output_type": "execute_result"
     }
   },
   {
    "cell_type": "code",
-   "execution_count": 95,
+   "execution_count": 93,
    "metadata": {},
    "outputs": [
     {
   },
   {
    "cell_type": "code",
-   "execution_count": 96,
+   "execution_count": 94,
    "metadata": {},
    "outputs": [
     {
   },
   {
    "cell_type": "code",
-   "execution_count": 97,
+   "execution_count": 95,
    "metadata": {},
    "outputs": [
     {
   },
   {
    "cell_type": "code",
-   "execution_count": 98,
+   "execution_count": 96,
    "metadata": {},
    "outputs": [
     {
   },
   {
    "cell_type": "code",
-   "execution_count": 99,
+   "execution_count": 97,
    "metadata": {},
    "outputs": [
     {
    "metadata": {},
    "source": [
     "#### `compose()` version 3\n",
-    "This function has to be modified to use the new datastructures and it is no longer recursive, instead recursion happens as part of unification."
+    "This function has to be modified to yield multiple results."
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 100,
+   "execution_count": 98,
    "metadata": {},
    "outputs": [],
    "source": [
     "def compose(f, g):\n",
-    "\n",
     "    (f_in, f_out), (g_in, g_out) = f, g\n",
-    "\n",
-    "    if not g_in:\n",
-    "        yield f_in, stack_concat(g_out, f_out)\n",
-    "\n",
-    "    elif not f_out:\n",
-    "        yield stack_concat(f_in, g_in), g_out\n",
-    "\n",
-    "    else: # Unify and update.\n",
-    "\n",
-    "        s = unify(g_in, f_out)\n",
-    "\n",
-    "        if not s:\n",
-    "            raise TypeError('Cannot unify %r and %r.' % (fo, gi))\n",
-    "\n",
-    "        for result in s:\n",
-    "            yield update(result, (f_in, g_out))\n"
+    "    s = unify(g_in, f_out)\n",
+    "    if not s:\n",
+    "        raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))\n",
+    "    for result in s:\n",
+    "        yield update(result, (f_in, g_out))\n"
    ]
   },
   {
   },
   {
    "cell_type": "code",
-   "execution_count": 101,
+   "execution_count": 99,
    "metadata": {},
    "outputs": [],
    "source": [
   },
   {
    "cell_type": "code",
-   "execution_count": 102,
+   "execution_count": 100,
    "metadata": {},
    "outputs": [
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "(a0 -- f0)\n",
-      "(a0 -- i0)\n"
+      "(f0 -- f1)\n",
+      "(i0 -- i1)\n"
      ]
     }
    ],
   },
   {
    "cell_type": "code",
-   "execution_count": 103,
+   "execution_count": 101,
    "metadata": {},
    "outputs": [
     {
   },
   {
    "cell_type": "code",
-   "execution_count": 104,
+   "execution_count": 102,
    "metadata": {},
    "outputs": [
     {
   },
   {
    "cell_type": "code",
-   "execution_count": 105,
+   "execution_count": 103,
    "metadata": {},
    "outputs": [
     {
   },
   {
    "cell_type": "code",
-   "execution_count": 106,
+   "execution_count": 104,
    "metadata": {},
    "outputs": [
     {
        "(a4, (a1*, (a3, s1)))"
       ]
      },
-     "execution_count": 106,
+     "execution_count": 104,
      "metadata": {},
      "output_type": "execute_result"
     }
   },
   {
    "cell_type": "code",
-   "execution_count": 107,
+   "execution_count": 105,
    "metadata": {},
    "outputs": [
     {
        "(a1, (a2, s2))"
       ]
      },
-     "execution_count": 107,
+     "execution_count": 105,
      "metadata": {},
      "output_type": "execute_result"
     }
   },
   {
    "cell_type": "code",
-   "execution_count": 108,
+   "execution_count": 106,
    "metadata": {},
    "outputs": [
     {
   },
   {
    "cell_type": "code",
-   "execution_count": 109,
+   "execution_count": 107,
    "metadata": {},
    "outputs": [
     {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "### represent `concat`\n",
+    "## Part VII: Typing Combinators\n",
     "\n",
-    "    ([.0.] [.1.] -- [A*(.0.) .1.])\n",
+    "TBD\n",
     "\n",
-    "Meaning that `A*` on the right-hand side should all the crap from `.0.`.\n",
+    "This is an open subject.\n",
     "\n",
-    "    ([      .0.] [.1.] -- [      A* .1.])\n",
-    "    ([a     .0.] [.1.] -- [a     A* .1.])\n",
-    "    ([a b   .0.] [.1.] -- [a b   A* .1.])\n",
-    "    ([a b c .0.] [.1.] -- [a b c A* .1.])\n",
+    "The obvious thing is that you now need two pairs of tuples to describe the combinators' effects,  a stack effect comment and an expression effect comment:\n",
     "\n",
-    "    "
+    "    dip (a [F] --)--(-- F a)\n",
+    "\n",
+    "One thing that might help is..."
    ]
   },
   {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "or...\n",
+    "Consider the type of:\n",
     "\n",
-    "    ([       .0.] [.1.] -- [       .1.])\n",
-    "    ([a      .0.] [.1.] -- [a      .1.])\n",
-    "    ([a b    .0.] [.1.] -- [a b    .1.])\n",
-    "    ([a b  c .0.] [.1.] -- [a b  c .1.])\n",
-    "    ([a A* c .0.] [.1.] -- [a A* c .1.])\n",
+    "    [cons] dip\n",
     "\n",
-    "    "
+    "Obviously it would be:\n",
+    "\n",
+    "    (a1 [..1] a2 -- [a1 ..1] a2)\n",
+    "\n",
+    "`dip` itself could have:\n",
+    "\n",
+    "    (a1 [..1] -- ... then what?\n"
    ]
   },
   {
-   "cell_type": "markdown",
+   "cell_type": "code",
+   "execution_count": 108,
    "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(-- [F1 .2.])\n"
+     ]
+    }
+   ],
    "source": [
-    "    (a, (b, S0)) . S1 = (a, (b, (A*, S1)))"
+    "class SymbolJoyType(AnyJoyType): prefix = 'F'\n",
+    "\n",
+    "W = map(SymbolJoyType, _R)\n",
+    "\n",
+    "k = S[0], ((W[1], S[2]), S[0])\n",
+    "Symbol('cons')\n",
+    "print doc_from_stack_effect(*k)\n"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 110,
+   "execution_count": 109,
    "metadata": {},
    "outputs": [],
    "source": [
-    "class Astar(object):\n",
-    "    def __repr__(self):\n",
-    "        return 'A*'\n",
-    "\n",
-    "\n",
-    "def concat(s0, s1):\n",
-    "    a = []\n",
-    "    while isinstance(s0, tuple):\n",
-    "        term, s0 = s0\n",
-    "        a.append(term)\n",
-    "    assert isinstance(s0, StackJoyType), repr(s0)\n",
-    "    s1 = Astar(), s1\n",
-    "    for term in reversed(a):\n",
-    "        s1 = term, s1\n",
-    "    return s1"
+    "dip_a = ((W[1], S[2]), (A[1], S[0]))"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 111,
+   "execution_count": 110,
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(-- a1001 [F1001 .1002.])\n"
+     ]
+    }
+   ],
    "source": [
-    "a, b = (A[1], S[0]), (A[2], S[1])"
+    "d = relabel(S[0], dip_a)\n",
+    "print doc_from_stack_effect(*d)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 112,
+   "execution_count": 111,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "(a1, (A*, (a2, s1)))"
+       "{s0: (a1001, s1000), s1002: s2, F1001: F1}"
       ]
      },
-     "execution_count": 112,
+     "execution_count": 111,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "concat(a, b)"
+    "s = list(unify(d[1], k[1]))[0]\n",
+    "s"
    ]
   },
   {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
    "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
+   "execution_count": 112,
+   "metadata": {
+    "scrolled": true
+   },
    "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
    "source": [
-    "## Joy in the Logical Paradigm\n",
-    "For this to work the type label classes have to be modified to let `T >= t` succeed, where e.g. `T` is `IntJoyType` and `t` is `int`"
+    "j = update(s, k)"
    ]
   },
   {
    "metadata": {},
    "outputs": [
     {
-     "ename": "ValueError",
-     "evalue": "need more than 1 value to unpack",
-     "output_type": "error",
-     "traceback": [
-      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
-      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
-      "\u001b[0;32m<ipython-input-113-4b4cb6ff86e5>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0mF\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mreduce\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mC\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mpop\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mswap\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mroll_down\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrest\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrest\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcons\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcons\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0;32mprint\u001b[0m \u001b[0mdoc_from_stack_effect\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mF\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
-      "\u001b[0;32m<ipython-input-101-ddee30dbb1a6>\u001b[0m in \u001b[0;36mC\u001b[0;34m(f, g)\u001b[0m\n\u001b[1;32m     10\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mC\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     11\u001b[0m     \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrelabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m     \u001b[0;32mfor\u001b[0m \u001b[0mfg\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mcompose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     13\u001b[0m         \u001b[0;32myield\u001b[0m \u001b[0mdelabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
-      "\u001b[0;32m<ipython-input-100-4237a6bb159d>\u001b[0m in \u001b[0;36mcompose\u001b[0;34m(f, g)\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mcompose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m     \u001b[0;34m(\u001b[0m\u001b[0mf_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mf_out\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mg_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg_out\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mg_in\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
-      "\u001b[0;32m<ipython-input-101-ddee30dbb1a6>\u001b[0m in \u001b[0;36mC\u001b[0;34m(f, g)\u001b[0m\n\u001b[1;32m     10\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mC\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     11\u001b[0m     \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrelabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m     \u001b[0;32mfor\u001b[0m \u001b[0mfg\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mcompose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     13\u001b[0m         \u001b[0;32myield\u001b[0m \u001b[0mdelabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
-      "\u001b[0;32m<ipython-input-100-4237a6bb159d>\u001b[0m in \u001b[0;36mcompose\u001b[0;34m(f, g)\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mcompose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m     \u001b[0;34m(\u001b[0m\u001b[0mf_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mf_out\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mg_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg_out\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mg_in\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
-      "\u001b[0;32m<ipython-input-101-ddee30dbb1a6>\u001b[0m in \u001b[0;36mC\u001b[0;34m(f, g)\u001b[0m\n\u001b[1;32m     10\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mC\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     11\u001b[0m     \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrelabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m     \u001b[0;32mfor\u001b[0m \u001b[0mfg\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mcompose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     13\u001b[0m         \u001b[0;32myield\u001b[0m \u001b[0mdelabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
-      "\u001b[0;32m<ipython-input-100-4237a6bb159d>\u001b[0m in \u001b[0;36mcompose\u001b[0;34m(f, g)\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mcompose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m     \u001b[0;34m(\u001b[0m\u001b[0mf_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mf_out\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mg_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg_out\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mg_in\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
-      "\u001b[0;32m<ipython-input-101-ddee30dbb1a6>\u001b[0m in \u001b[0;36mC\u001b[0;34m(f, g)\u001b[0m\n\u001b[1;32m     10\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mC\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     11\u001b[0m     \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrelabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m     \u001b[0;32mfor\u001b[0m \u001b[0mfg\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mcompose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     13\u001b[0m         \u001b[0;32myield\u001b[0m \u001b[0mdelabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
-      "\u001b[0;32m<ipython-input-100-4237a6bb159d>\u001b[0m in \u001b[0;36mcompose\u001b[0;34m(f, g)\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mcompose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m     \u001b[0;34m(\u001b[0m\u001b[0mf_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mf_out\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mg_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg_out\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mg_in\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
-      "\u001b[0;32m<ipython-input-101-ddee30dbb1a6>\u001b[0m in \u001b[0;36mC\u001b[0;34m(f, g)\u001b[0m\n\u001b[1;32m     10\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mC\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     11\u001b[0m     \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrelabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m     \u001b[0;32mfor\u001b[0m \u001b[0mfg\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mcompose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     13\u001b[0m         \u001b[0;32myield\u001b[0m \u001b[0mdelabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
-      "\u001b[0;32m<ipython-input-100-4237a6bb159d>\u001b[0m in \u001b[0;36mcompose\u001b[0;34m(f, g)\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mcompose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m     \u001b[0;34m(\u001b[0m\u001b[0mf_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mf_out\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mg_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg_out\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mg_in\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
-      "\u001b[0;31mValueError\u001b[0m: need more than 1 value to unpack"
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(a1001 -- a1001 [F1 .2.])\n"
      ]
     }
    ],
    "source": [
-    "F = reduce(C, (pop, swap, roll_down, rest, rest, cons, cons))\n",
-    "\n",
-    "print doc_from_stack_effect(*F)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "from joy.parser import text_to_expression"
+    "print doc_from_stack_effect(*j)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 114,
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "((a1001, s1000), ((F1, s2), (a1001, s1000)))"
+      ]
+     },
+     "execution_count": 114,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
    "source": [
-    "s = text_to_expression('[3 4 ...] 2 1')\n",
-    "s"
+    "j"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 115,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "((s1, (a1, s23)), ((a1, s1), s23))"
+      ]
+     },
+     "execution_count": 115,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "cons"
    ]
   },
   {
    "execution_count": null,
    "metadata": {},
    "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 116,
+   "metadata": {
+    "scrolled": true
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(-- [F0 .1.] [F0 .1.])\n"
+     ]
+    }
+   ],
    "source": [
-    "L = unify(F[1], s)\n",
-    "L"
+    "for f in MC([k], [dup]):\n",
+    "    print doc_from_stack_effect(*f)"
    ]
   },
   {
    "execution_count": null,
    "metadata": {},
    "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 117,
+   "metadata": {},
+   "outputs": [],
    "source": [
-    "F[1]"
+    "l = S[0], ((cons, S[2]), (A[1], S[0]))"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 118,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(-- a1 [[[[.1.] a1 .23.] [a1 .1.] .23.] .2.])\n"
+     ]
+    }
+   ],
+   "source": [
+    "print doc_from_stack_effect(*l)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 119,
    "metadata": {},
    "outputs": [],
    "source": [
-    "F[1][0]"
+    "\n",
+    "def dip_t(F):\n",
+    "    (quote, (a1, sec)) = F[1]\n",
+    "    G = F[0], sec\n",
+    "    P = S[3], (a1, S[3])\n",
+    "    a = [P]\n",
+    "    while isinstance(quote, tuple):\n",
+    "        term, quote = quote\n",
+    "        a.append(term)\n",
+    "    a.append(G)\n",
+    "    return a[::-1]\n",
+    "\n",
+    "\n",
+    "\n"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 120,
    "metadata": {},
    "outputs": [],
    "source": [
-    "s[0]"
+    "from joy.utils.stack import iter_stack"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 121,
    "metadata": {},
    "outputs": [],
-   "source": []
+   "source": [
+    "a, b, c = dip_t(l)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 122,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "(s0, s0)"
+      ]
+     },
+     "execution_count": 122,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "a"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 123,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "((s1, (a1, s23)), ((a1, s1), s23))"
+      ]
+     },
+     "execution_count": 123,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "b"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 124,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "(s3, (a1, s3))"
+      ]
+     },
+     "execution_count": 124,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "c"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 125,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[((s0, (a0, s1)), ((a0, s0), s1))]"
+      ]
+     },
+     "execution_count": 125,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "MC([a], [b])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 126,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[((s0, (a0, s1)), (a1, ((a0, s0), s1)))]"
+      ]
+     },
+     "execution_count": 126,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "kjs = MC(MC([a], [b]), [c])\n",
+    "kjs"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 127,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(a0 [.0.] -- [a0 .0.] a1)\n"
+     ]
+    }
+   ],
+   "source": [
+    "print doc_from_stack_effect(*kjs[0])"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "    (a0 [.0.] -- [a0 .0.] a1)\n",
+    "    \n",
+    "       a0 [.0.] a1 [cons] dip\n",
+    "    ----------------------------\n",
+    "       [a0 .0.] a1"
+   ]
   },
   {
    "cell_type": "code",
    "source": []
   },
   {
-   "cell_type": "markdown",
+   "cell_type": "code",
+   "execution_count": 128,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "stack_concat = lambda q, e: (q[0], stack_concat(q[1], e)) if q else e"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 129,
    "metadata": {},
+   "outputs": [],
    "source": [
-    "## Typing Combinators\n",
+    "class SymbolJoyType(AnyJoyType):\n",
+    "    prefix = 'F'\n",
     "\n",
-    "TBD\n",
+    "    def __init__(self, name, sec, number):\n",
+    "        self.name = name\n",
+    "        self.stack_effects = sec\n",
+    "        self.number = number\n",
     "\n",
-    "This is an open subject.\n",
+    "class CombinatorJoyType(SymbolJoyType): prefix = 'C'\n",
     "\n",
-    "The obvious thing is that you now need two pairs of tuples to describe the combinators' effects,  a stack effect comment and an expression effect comment:\n",
+    "def dip_t(stack, expression):\n",
+    "    (quote, (a1, stack)) = stack\n",
+    "    expression = stack_concat(quote, (a1, expression))\n",
+    "    return stack, expression\n",
     "\n",
-    "    dip (a [F] --)--(-- F a)\n",
+    "CONS = SymbolJoyType('cons', [cons], 23)\n",
+    "DIP = CombinatorJoyType('dip', [dip_t], 44)\n",
     "\n",
-    "One thing that might help is..."
+    "\n",
+    "def kav(F, e):\n",
+    "    #i, stack = F\n",
+    "    if not e:\n",
+    "        return [(F, e)]\n",
+    "    n, e = e\n",
+    "    if isinstance(n, SymbolJoyType):\n",
+    "        Fs = []\n",
+    "        for sec in n.stack_effects:\n",
+    "            Fs.extend(MC([F], sec))\n",
+    "        return [kav(Fn, e) for Fn in Fs]\n",
+    "    if isinstance(n, CombinatorJoyType):\n",
+    "        res = []\n",
+    "        for f in n.stack_effects:\n",
+    "            s, e = f(F[1], e)\n",
+    "            new_F = F[0], s\n",
+    "            res.extend(kav(new_F, e))\n",
+    "        return res\n",
+    "    lit = S[0], (n, S[0])\n",
+    "    return [kav(Fn, e) for Fn in MC([F], [lit])]\n"
    ]
   },
   {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "## Abstract Interpretation"
+    "compare, and be amazed:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 130,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def dip_t(stack, expression):\n",
+    "    (quote, (a1, stack)) = stack\n",
+    "    expression = stack_concat(quote, (a1, expression))\n",
+    "    return stack, expression"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 131,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def dip(stack, expression, dictionary):\n",
+    "    (quote, (x, stack)) = stack\n",
+    "    expression = (x, expression)\n",
+    "    return stack, concat(quote, expression), dictionary"
    ]
   },
   {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "## Something else...\n",
-    "    [4 5 ...] 2 1 0 pop∘swap∘roll<∘rest∘rest∘cons∘cons\n",
-    "    [4 5 ...] 2 1       swap∘roll<∘rest∘rest∘cons∘cons\n",
-    "    [4 5 ...] 1 2            roll<∘rest∘rest∘cons∘cons\n",
-    "    1 2 [4 5 ...]                  rest∘rest∘cons∘cons\n",
-    "    1 2   [5 ...]                       rest∘cons∘cons\n",
-    "    1 2     [...]                            cons∘cons\n",
-    "    1     [2 ...]                                 cons\n",
-    "        [1 2 ...]\n",
-    "\n",
-    "Eh?"
+    "And that brings us to current Work-In-Progress.  I'm pretty hopeful that the mixed-mode inferencer/interpreter `kav()` function along with the ability to specify multiple implementations for the combinators will permit modelling of the stack effects of e.g. `ifte`.  If I can keep up the pace I should be able to verify that conjecture by the end of June."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "The rest of this stuff is junk and/or unfinished material."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### `concat`\n",
+    "\n",
+    "How to deal with `concat`?\n",
+    "\n",
+    "    concat ([.0.] [.1.] -- [.0. .1.])\n",
+    "    \n",
+    "We would like to represent this in Python somehow..."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 132,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "concat = (S[0], S[1]), ((S[0], S[1]),)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "But this is actually `cons` with the first argument restricted to be a stack:\n",
+    "\n",
+    "    ([.0.] [.1.] -- [[.0.] .1.])\n",
+    "\n",
+    "What we have implemented so far would actually only permit:\n",
+    "\n",
+    "    ([.0.] [.1.] -- [.2.])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 133,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "concat = (S[0], S[1]), (S[2],)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "    \n",
+    "Which works but can lose information.  Consider `cons concat`, this is how much information we *could* retain:\n",
+    "\n",
+    "    (1 [.0.] [.1.] -- [1 .0. .1.])\n",
+    "\n",
+    "As opposed to just:\n",
+    "\n",
+    "    (1 [.0.] [.1.] -- [.2.])"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### represent `concat`\n",
+    "\n",
+    "    ([.0.] [.1.] -- [A*(.0.) .1.])\n",
+    "\n",
+    "Meaning that `A*` on the right-hand side should all the crap from `.0.`.\n",
+    "\n",
+    "    ([      .0.] [.1.] -- [      A* .1.])\n",
+    "    ([a     .0.] [.1.] -- [a     A* .1.])\n",
+    "    ([a b   .0.] [.1.] -- [a b   A* .1.])\n",
+    "    ([a b c .0.] [.1.] -- [a b c A* .1.])\n",
+    "\n",
+    "    "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "or...\n",
+    "\n",
+    "    ([       .0.] [.1.] -- [       .1.])\n",
+    "    ([a      .0.] [.1.] -- [a      .1.])\n",
+    "    ([a b    .0.] [.1.] -- [a b    .1.])\n",
+    "    ([a b  c .0.] [.1.] -- [a b  c .1.])\n",
+    "    ([a A* c .0.] [.1.] -- [a A* c .1.])\n",
+    "\n",
+    "    "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "    (a, (b, S0)) . S1 = (a, (b, (A*, S1)))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 134,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class Astar(object):\n",
+    "    def __repr__(self):\n",
+    "        return 'A*'\n",
+    "\n",
+    "\n",
+    "def concat(s0, s1):\n",
+    "    a = []\n",
+    "    while isinstance(s0, tuple):\n",
+    "        term, s0 = s0\n",
+    "        a.append(term)\n",
+    "    assert isinstance(s0, StackJoyType), repr(s0)\n",
+    "    s1 = Astar(), s1\n",
+    "    for term in reversed(a):\n",
+    "        s1 = term, s1\n",
+    "    return s1"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 135,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "a, b = (A[1], S[0]), (A[2], S[1])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 136,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "(a1, (A*, (a2, s1)))"
+      ]
+     },
+     "execution_count": 136,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "concat(a, b)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Appendix: Joy in the Logical Paradigm\n",
+    "For this to work the type label classes have to be modified to let `T >= t` succeed, where e.g. `T` is `IntJoyType` and `t` is `int`"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 137,
+   "metadata": {},
+   "outputs": [
+    {
+     "ename": "ValueError",
+     "evalue": "need more than 1 value to unpack",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
+      "\u001b[0;32m<ipython-input-137-4b4cb6ff86e5>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0mF\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mreduce\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mC\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mpop\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mswap\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mroll_down\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrest\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrest\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcons\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcons\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0;32mprint\u001b[0m \u001b[0mdoc_from_stack_effect\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mF\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
+      "\u001b[0;32m<ipython-input-99-ddee30dbb1a6>\u001b[0m in \u001b[0;36mC\u001b[0;34m(f, g)\u001b[0m\n\u001b[1;32m     10\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mC\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     11\u001b[0m     \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrelabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m     \u001b[0;32mfor\u001b[0m \u001b[0mfg\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mcompose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     13\u001b[0m         \u001b[0;32myield\u001b[0m \u001b[0mdelabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+      "\u001b[0;32m<ipython-input-98-5eb7ac5ad2c2>\u001b[0m in \u001b[0;36mcompose\u001b[0;34m(f, g)\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mcompose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m     \u001b[0;34m(\u001b[0m\u001b[0mf_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mf_out\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mg_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg_out\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      3\u001b[0m     \u001b[0ms\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0munify\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mf_out\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0ms\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m         \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Cannot unify %r and %r.'\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mf_out\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg_in\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+      "\u001b[0;32m<ipython-input-99-ddee30dbb1a6>\u001b[0m in \u001b[0;36mC\u001b[0;34m(f, g)\u001b[0m\n\u001b[1;32m     10\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mC\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     11\u001b[0m     \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrelabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m     \u001b[0;32mfor\u001b[0m \u001b[0mfg\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mcompose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     13\u001b[0m         \u001b[0;32myield\u001b[0m \u001b[0mdelabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+      "\u001b[0;32m<ipython-input-98-5eb7ac5ad2c2>\u001b[0m in \u001b[0;36mcompose\u001b[0;34m(f, g)\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mcompose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m     \u001b[0;34m(\u001b[0m\u001b[0mf_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mf_out\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mg_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg_out\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      3\u001b[0m     \u001b[0ms\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0munify\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mf_out\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0ms\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m         \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Cannot unify %r and %r.'\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mf_out\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg_in\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+      "\u001b[0;32m<ipython-input-99-ddee30dbb1a6>\u001b[0m in \u001b[0;36mC\u001b[0;34m(f, g)\u001b[0m\n\u001b[1;32m     10\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mC\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     11\u001b[0m     \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrelabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m     \u001b[0;32mfor\u001b[0m \u001b[0mfg\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mcompose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     13\u001b[0m         \u001b[0;32myield\u001b[0m \u001b[0mdelabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+      "\u001b[0;32m<ipython-input-98-5eb7ac5ad2c2>\u001b[0m in \u001b[0;36mcompose\u001b[0;34m(f, g)\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mcompose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m     \u001b[0;34m(\u001b[0m\u001b[0mf_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mf_out\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mg_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg_out\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      3\u001b[0m     \u001b[0ms\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0munify\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mf_out\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0ms\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m         \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Cannot unify %r and %r.'\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mf_out\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg_in\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+      "\u001b[0;32m<ipython-input-99-ddee30dbb1a6>\u001b[0m in \u001b[0;36mC\u001b[0;34m(f, g)\u001b[0m\n\u001b[1;32m     10\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mC\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     11\u001b[0m     \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrelabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m     \u001b[0;32mfor\u001b[0m \u001b[0mfg\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mcompose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     13\u001b[0m         \u001b[0;32myield\u001b[0m \u001b[0mdelabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+      "\u001b[0;32m<ipython-input-98-5eb7ac5ad2c2>\u001b[0m in \u001b[0;36mcompose\u001b[0;34m(f, g)\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mcompose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m     \u001b[0;34m(\u001b[0m\u001b[0mf_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mf_out\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mg_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg_out\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      3\u001b[0m     \u001b[0ms\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0munify\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mf_out\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0ms\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m         \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Cannot unify %r and %r.'\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mf_out\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg_in\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+      "\u001b[0;32m<ipython-input-99-ddee30dbb1a6>\u001b[0m in \u001b[0;36mC\u001b[0;34m(f, g)\u001b[0m\n\u001b[1;32m     10\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mC\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     11\u001b[0m     \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrelabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m     \u001b[0;32mfor\u001b[0m \u001b[0mfg\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mcompose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     13\u001b[0m         \u001b[0;32myield\u001b[0m \u001b[0mdelabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+      "\u001b[0;32m<ipython-input-98-5eb7ac5ad2c2>\u001b[0m in \u001b[0;36mcompose\u001b[0;34m(f, g)\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mcompose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m     \u001b[0;34m(\u001b[0m\u001b[0mf_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mf_out\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mg_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg_out\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      3\u001b[0m     \u001b[0ms\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0munify\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg_in\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mf_out\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0ms\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m         \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Cannot unify %r and %r.'\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mf_out\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg_in\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+      "\u001b[0;31mValueError\u001b[0m: need more than 1 value to unpack"
+     ]
+    }
+   ],
+   "source": [
+    "F = reduce(C, (pop, swap, roll_down, rest, rest, cons, cons))\n",
+    "\n",
+    "print doc_from_stack_effect(*F)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from joy.parser import text_to_expression"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "s = text_to_expression('[3 4 ...] 2 1')\n",
+    "s"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "L = unify(F[1], s)\n",
+    "L"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "F[1]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "F[1][0]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "s[0]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## [Abstract Interpretation](https://en.wikipedia.org/wiki/Abstract_interpretation)\n",
+    "I *think* this might be sorta what I'm doing above with the `kav()` function...\n",
+    "  In any event \"mixed-mode\" interpreters that include values and type variables and can track constraints, etc. will be, uh, super-useful.  And Abstract Interpretation should be a rich source of ideas.\n"
    ]
   },
   {
index 35be81b..b3f9f2a 100644 (file)
@@ -1,7 +1,9 @@
 
 # Type Inference
 
-## Pöial's Rules
+Cf. ["Type Inference in Stack-Based Programming Languages"](http://prl.ccs.neu.edu/blog/2017/03/10/type-inference-in-stack-based-programming-languages/) by Rob Kleffner, 2017-03-10.
+
+## Part I: Pöial's Rules
 
 ["Typing Tools for Typeless Stack Languages" by Jaanus Pöial
 ](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.212.6026)
@@ -30,7 +32,7 @@ This rule deals with functions that consume items from the stack `(a --)`:
          (c a -- d)
 
 ### Third Rule
-The third rule is actually two rules.  These two rules deal with composing functions when the second one will consume one of items the first one produces.  The two types must be *unified* or a type conflict declared.
+The third rule is actually two rules.  These two rules deal with composing functions when the second one will consume one of items the first one produces.  The two types must be [*unified*](https://en.wikipedia.org/wiki/Robinson's_unification_algorithm) or a type conflict declared.
 
        (a -- b t[i])∘(c u[j] -- d)   t <= u (t is subtype of u)
     -------------------------------
@@ -41,7 +43,6 @@ The third rule is actually two rules.  These two rules deal with composing funct
     -------------------------------
        (a -- b     )∘(c      -- d)   t[i] == u[k] == u[j]
 
-## Examples
 Let's work through some examples by hand to develop an intuition for the algorithm.
 
 There's a function in one of the other notebooks.
@@ -267,7 +268,7 @@ def F(stack):
     return (d, (c, S0)), stack
 ```
 
-## Implementation
+## Part II: Implementation
 
 ### Representing Stack Effect Comments in Python
 
@@ -485,8 +486,8 @@ poswrd
 
 
 
-### List Functions
-Here's that trick to represent functions like `rest` and `cons` that manipulate lists.  We use a cons-list of tuples and give the tails their own numbers.  Then everything above already works. 
+### Stack Functions
+Here's that trick to represent functions like `rest` and `cons` that manipulate stacks.  We use a cons-list of tuples and give the tails their own numbers.  Then everything above already works. 
 
 
 ```python
@@ -539,6 +540,7 @@ F
 Compare with the stack effect comment and you can see it works fine:
 
     ([4 5 ...] 2 3 1 -- [3 2 ...])
+      3 4  5   1 2 0     2 1  5
 
 ### Dealing with `cons` and `uncons`
 However, if we try to compose e.g. `cons` and `uncons` it won't work:
@@ -567,7 +569,7 @@ The problem is that the `unify()` function as written doesn't handle the case wh
 def unify(u, v, s=None):
     if s is None:
         s = {}
-    else:
+    elif s:
         u = update(s, u)
         v = update(s, v)
 
@@ -606,7 +608,7 @@ C(cons, uncons)
 
 
 
-## Compiling
+## Part III: Compiling Stack Functions
 Now consider the Python function we would like to derive:
 
 
@@ -904,7 +906,7 @@ for name, stack_effect_comment in sorted(defs().items()):
     
 
 
-## Types and Subtypes of Arguments
+## Part IV: Types and Subtypes of Arguments
 So far we have dealt with types of functions, those dealing with simple stack manipulation.  Let's extend our machinery to deal with types of arguments.
 
 ### "Number" Type
@@ -1158,7 +1160,7 @@ delabel(foo)
 def unify(u, v, s=None):
     if s is None:
         s = {}
-    else:
+    elif s:
         u = update(s, u)
         v = update(s, v)
 
@@ -1460,7 +1462,7 @@ for name, stack_effect_comment in sorted(defs().items()):
     uncons = ([a1 .1.] -- a1 [.1.])
 
 
-## Functions that use the Stack
+## Part V: Functions that use the Stack
 
 Consider the `stack` function which grabs the whole stack, quotes it, and puts it on itself:
 
@@ -1518,33 +1520,16 @@ Let's try `stack∘uncons∘uncons`:
 It works.
 
 #### `compose()` version 2
-This function has to be modified to use the new datastructures and it is no longer recursive, instead recursion happens as part of unification.
+This function has to be modified to use the new datastructures and it is no longer recursive, instead recursion happens as part of unification.  Further, the first and second of Pöial's rules are now handled automatically by the unification algorithm.
 
 
 ```python
 def compose(f, g):
-
     (f_in, f_out), (g_in, g_out) = f, g
-
-    if not g_in:
-        fg_in, fg_out = f_in, stack_concat(g_out, f_out)
-
-    elif not f_out:
-        fg_in, fg_out = stack_concat(f_in, g_in), g_out
-
-    else: # Unify and update.
-
-        s = unify(g_in, f_out)
-
-        if s == False:  # s can also be the empty dict, which is ok.
-            raise TypeError('Cannot unify %r and %r.' % (fo, gi))
-
-        fg_in, fg_out = update(s, (f_in, g_out))
-
-    return fg_in, fg_out
-
-
-stack_concat = lambda q, e: (q[0], stack_concat(q[1], e)) if q else e
+    s = unify(g_in, f_out)
+    if s == False:  # s can also be the empty dict, which is ok.
+        raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
+    return update(s, (f_in, g_out))
 ```
 
 I don't want to rewrite all the defs myself, so I'll write a little conversion function instead.  This is programmer's laziness.
@@ -1796,7 +1781,7 @@ C(cons, unstack)
 
 
 
-## Multiple Stack Effects
+## Part VI: Multiple Stack Effects
 ...
 
 
@@ -1880,44 +1865,9 @@ for f in MC([dup], [mul]):
     (n0 -- n1)
 
 
-## `concat`
-
-How to deal with `concat`?
-
-    concat ([.0.] [.1.] -- [.0. .1.])
-    
-We would like to represent this in Python somehow...
-
-
-```python
-concat = (S[0], S[1]), ((S[0], S[1]),)
-```
-
-But this is actually `cons` with the first argument restricted to be a stack:
-
-    ([.0.] [.1.] -- [[.0.] .1.])
-
-What we have implemented so far would actually only permit:
-
-    ([.0.] [.1.] -- [.2.])
-
-
-```python
-concat = (S[0], S[1]), (S[2],)
-```
-
-    
-Which works but can lose information.  Consider `cons concat`, this is how much information we *could* retain:
-
-    (1 [.0.] [.1.] -- [1 .0. .1.])
-
-As opposed to just:
-
-    (1 [.0.] [.1.] -- [.2.])
-
-### Brzo...'s Derivitives of Regular Expressions
+### Representing an Unbounded Sequence of Types
 
-We can invent a new type of type variable, a "sequence type" (I think this is what they mean in the literature by that term...) or "Kleene Star" type.  I'm going to represent it as a type letter and the asterix, so a sequence of zero or more `AnyJoyType` variables would be:
+We can borrow a trick from [Brzozowski's Derivatives of Regular Expressions](https://en.wikipedia.org/wiki/Brzozowski_derivative) to invent a new type of type variable, a "sequence type" (I think this is what they mean in the literature by that term...) or "[Kleene Star](https://en.wikipedia.org/wiki/Kleene_star)" type.  I'm going to represent it as a type letter and the asterix, so a sequence of zero or more `AnyJoyType` variables would be:
 
     A*
 
@@ -2049,7 +1999,7 @@ def unify(u, v, s=None):
                 sn.update(s)
             return t
 
-        ses = unify(u[0], v[0])
+        ses = unify(u[0], v[0], s)
         results = ()
         for sn in ses:
             results += unify(u[1], v[1], sn)
@@ -2160,29 +2110,17 @@ for result in unify(sum_[0], f):
 
 
 #### `compose()` version 3
-This function has to be modified to use the new datastructures and it is no longer recursive, instead recursion happens as part of unification.
+This function has to be modified to yield multiple results.
 
 
 ```python
 def compose(f, g):
-
     (f_in, f_out), (g_in, g_out) = f, g
-
-    if not g_in:
-        yield f_in, stack_concat(g_out, f_out)
-
-    elif not f_out:
-        yield stack_concat(f_in, g_in), g_out
-
-    else: # Unify and update.
-
-        s = unify(g_in, f_out)
-
-        if not s:
-            raise TypeError('Cannot unify %r and %r.' % (fo, gi))
-
-        for result in s:
-            yield update(result, (f_in, g_out))
+    s = unify(g_in, f_out)
+    if not s:
+        raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
+    for result in s:
+        yield update(result, (f_in, g_out))
 
 ```
 
@@ -2209,8 +2147,8 @@ for f in MC([dup], muls):
     print doc_from_stack_effect(*f)
 ```
 
-    (a0 -- f0)
-    (a0 -- i0)
+    (f0 -- f1)
+    (i0 -- i1)
 
 
 
@@ -2295,6 +2233,341 @@ for result in unify(a, b):
     {s2: (a1*, (a3, s1)), a2: a10004, a4: a1}
 
 
+## Part VII: Typing Combinators
+
+TBD
+
+This is an open subject.
+
+The obvious thing is that you now need two pairs of tuples to describe the combinators' effects,  a stack effect comment and an expression effect comment:
+
+    dip (a [F] --)--(-- F a)
+
+One thing that might help is...
+
+Consider the type of:
+
+    [cons] dip
+
+Obviously it would be:
+
+    (a1 [..1] a2 -- [a1 ..1] a2)
+
+`dip` itself could have:
+
+    (a1 [..1] -- ... then what?
+
+
+
+```python
+class SymbolJoyType(AnyJoyType): prefix = 'F'
+
+W = map(SymbolJoyType, _R)
+
+k = S[0], ((W[1], S[2]), S[0])
+Symbol('cons')
+print doc_from_stack_effect(*k)
+
+```
+
+    (-- [F1 .2.])
+
+
+
+```python
+dip_a = ((W[1], S[2]), (A[1], S[0]))
+```
+
+
+```python
+d = relabel(S[0], dip_a)
+print doc_from_stack_effect(*d)
+```
+
+    (-- a1001 [F1001 .1002.])
+
+
+
+```python
+s = list(unify(d[1], k[1]))[0]
+s
+```
+
+
+
+
+    {s0: (a1001, s1000), s1002: s2, F1001: F1}
+
+
+
+
+```python
+j = update(s, k)
+```
+
+
+```python
+print doc_from_stack_effect(*j)
+```
+
+    (a1001 -- a1001 [F1 .2.])
+
+
+
+```python
+j
+```
+
+
+
+
+    ((a1001, s1000), ((F1, s2), (a1001, s1000)))
+
+
+
+
+```python
+cons
+```
+
+
+
+
+    ((s1, (a1, s23)), ((a1, s1), s23))
+
+
+
+
+```python
+for f in MC([k], [dup]):
+    print doc_from_stack_effect(*f)
+```
+
+    (-- [F0 .1.] [F0 .1.])
+
+
+
+```python
+l = S[0], ((cons, S[2]), (A[1], S[0]))
+```
+
+
+```python
+print doc_from_stack_effect(*l)
+```
+
+    (-- a1 [[[[.1.] a1 .23.] [a1 .1.] .23.] .2.])
+
+
+
+```python
+
+def dip_t(F):
+    (quote, (a1, sec)) = F[1]
+    G = F[0], sec
+    P = S[3], (a1, S[3])
+    a = [P]
+    while isinstance(quote, tuple):
+        term, quote = quote
+        a.append(term)
+    a.append(G)
+    return a[::-1]
+
+
+
+
+```
+
+
+```python
+from joy.utils.stack import iter_stack
+```
+
+
+```python
+a, b, c = dip_t(l)
+```
+
+
+```python
+a
+```
+
+
+
+
+    (s0, s0)
+
+
+
+
+```python
+b
+```
+
+
+
+
+    ((s1, (a1, s23)), ((a1, s1), s23))
+
+
+
+
+```python
+c
+```
+
+
+
+
+    (s3, (a1, s3))
+
+
+
+
+```python
+MC([a], [b])
+```
+
+
+
+
+    [((s0, (a0, s1)), ((a0, s0), s1))]
+
+
+
+
+```python
+kjs = MC(MC([a], [b]), [c])
+kjs
+```
+
+
+
+
+    [((s0, (a0, s1)), (a1, ((a0, s0), s1)))]
+
+
+
+
+```python
+print doc_from_stack_effect(*kjs[0])
+```
+
+    (a0 [.0.] -- [a0 .0.] a1)
+
+
+    (a0 [.0.] -- [a0 .0.] a1)
+    
+       a0 [.0.] a1 [cons] dip
+    ----------------------------
+       [a0 .0.] a1
+
+
+```python
+stack_concat = lambda q, e: (q[0], stack_concat(q[1], e)) if q else e
+```
+
+
+```python
+class SymbolJoyType(AnyJoyType):
+    prefix = 'F'
+
+    def __init__(self, name, sec, number):
+        self.name = name
+        self.stack_effects = sec
+        self.number = number
+
+class CombinatorJoyType(SymbolJoyType): prefix = 'C'
+
+def dip_t(stack, expression):
+    (quote, (a1, stack)) = stack
+    expression = stack_concat(quote, (a1, expression))
+    return stack, expression
+
+CONS = SymbolJoyType('cons', [cons], 23)
+DIP = CombinatorJoyType('dip', [dip_t], 44)
+
+
+def kav(F, e):
+    #i, stack = F
+    if not e:
+        return [(F, e)]
+    n, e = e
+    if isinstance(n, SymbolJoyType):
+        Fs = []
+        for sec in n.stack_effects:
+            Fs.extend(MC([F], sec))
+        return [kav(Fn, e) for Fn in Fs]
+    if isinstance(n, CombinatorJoyType):
+        res = []
+        for f in n.stack_effects:
+            s, e = f(F[1], e)
+            new_F = F[0], s
+            res.extend(kav(new_F, e))
+        return res
+    lit = S[0], (n, S[0])
+    return [kav(Fn, e) for Fn in MC([F], [lit])]
+
+```
+
+compare, and be amazed:
+
+
+```python
+def dip_t(stack, expression):
+    (quote, (a1, stack)) = stack
+    expression = stack_concat(quote, (a1, expression))
+    return stack, expression
+```
+
+
+```python
+def dip(stack, expression, dictionary):
+    (quote, (x, stack)) = stack
+    expression = (x, expression)
+    return stack, concat(quote, expression), dictionary
+```
+
+And that brings us to current Work-In-Progress.  I'm pretty hopeful that the mixed-mode inferencer/interpreter `kav()` function along with the ability to specify multiple implementations for the combinators will permit modelling of the stack effects of e.g. `ifte`.  If I can keep up the pace I should be able to verify that conjecture by the end of June.
+
+The rest of this stuff is junk and/or unfinished material.
+
+### `concat`
+
+How to deal with `concat`?
+
+    concat ([.0.] [.1.] -- [.0. .1.])
+    
+We would like to represent this in Python somehow...
+
+
+```python
+concat = (S[0], S[1]), ((S[0], S[1]),)
+```
+
+But this is actually `cons` with the first argument restricted to be a stack:
+
+    ([.0.] [.1.] -- [[.0.] .1.])
+
+What we have implemented so far would actually only permit:
+
+    ([.0.] [.1.] -- [.2.])
+
+
+```python
+concat = (S[0], S[1]), (S[2],)
+```
+
+    
+Which works but can lose information.  Consider `cons concat`, this is how much information we *could* retain:
+
+    (1 [.0.] [.1.] -- [1 .0. .1.])
+
+As opposed to just:
+
+    (1 [.0.] [.1.] -- [.2.])
+
 ### represent `concat`
 
     ([.0.] [.1.] -- [A*(.0.) .1.])
@@ -2356,7 +2629,7 @@ concat(a, b)
 
 
 
-## Joy in the Logical Paradigm
+## Appendix: Joy in the Logical Paradigm
 For this to work the type label classes have to be modified to let `T >= t` succeed, where e.g. `T` is `IntJoyType` and `t` is `int`
 
 
@@ -2371,85 +2644,85 @@ print doc_from_stack_effect(*F)
 
     ValueError                                Traceback (most recent call last)
 
-    <ipython-input-113-4b4cb6ff86e5> in <module>()
+    <ipython-input-137-4b4cb6ff86e5> in <module>()
           1 F = reduce(C, (pop, swap, roll_down, rest, rest, cons, cons))
           2 
     ----> 3 print doc_from_stack_effect(*F)
     
 
-    <ipython-input-101-ddee30dbb1a6> in C(f, g)
+    <ipython-input-99-ddee30dbb1a6> in C(f, g)
          10 def C(f, g):
          11     f, g = relabel(f, g)
     ---> 12     for fg in compose(f, g):
          13         yield delabel(fg)
 
 
-    <ipython-input-100-4237a6bb159d> in compose(f, g)
+    <ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
           1 def compose(f, g):
-          2 
-    ----> 3     (f_in, f_out), (g_in, g_out) = f, g
-          4 
-          5     if not g_in:
+    ----> 2     (f_in, f_out), (g_in, g_out) = f, g
+          3     s = unify(g_in, f_out)
+          4     if not s:
+          5         raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
 
 
-    <ipython-input-101-ddee30dbb1a6> in C(f, g)
+    <ipython-input-99-ddee30dbb1a6> in C(f, g)
          10 def C(f, g):
          11     f, g = relabel(f, g)
     ---> 12     for fg in compose(f, g):
          13         yield delabel(fg)
 
 
-    <ipython-input-100-4237a6bb159d> in compose(f, g)
+    <ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
           1 def compose(f, g):
-          2 
-    ----> 3     (f_in, f_out), (g_in, g_out) = f, g
-          4 
-          5     if not g_in:
+    ----> 2     (f_in, f_out), (g_in, g_out) = f, g
+          3     s = unify(g_in, f_out)
+          4     if not s:
+          5         raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
 
 
-    <ipython-input-101-ddee30dbb1a6> in C(f, g)
+    <ipython-input-99-ddee30dbb1a6> in C(f, g)
          10 def C(f, g):
          11     f, g = relabel(f, g)
     ---> 12     for fg in compose(f, g):
          13         yield delabel(fg)
 
 
-    <ipython-input-100-4237a6bb159d> in compose(f, g)
+    <ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
           1 def compose(f, g):
-          2 
-    ----> 3     (f_in, f_out), (g_in, g_out) = f, g
-          4 
-          5     if not g_in:
+    ----> 2     (f_in, f_out), (g_in, g_out) = f, g
+          3     s = unify(g_in, f_out)
+          4     if not s:
+          5         raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
 
 
-    <ipython-input-101-ddee30dbb1a6> in C(f, g)
+    <ipython-input-99-ddee30dbb1a6> in C(f, g)
          10 def C(f, g):
          11     f, g = relabel(f, g)
     ---> 12     for fg in compose(f, g):
          13         yield delabel(fg)
 
 
-    <ipython-input-100-4237a6bb159d> in compose(f, g)
+    <ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
           1 def compose(f, g):
-          2 
-    ----> 3     (f_in, f_out), (g_in, g_out) = f, g
-          4 
-          5     if not g_in:
+    ----> 2     (f_in, f_out), (g_in, g_out) = f, g
+          3     s = unify(g_in, f_out)
+          4     if not s:
+          5         raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
 
 
-    <ipython-input-101-ddee30dbb1a6> in C(f, g)
+    <ipython-input-99-ddee30dbb1a6> in C(f, g)
          10 def C(f, g):
          11     f, g = relabel(f, g)
     ---> 12     for fg in compose(f, g):
          13         yield delabel(fg)
 
 
-    <ipython-input-100-4237a6bb159d> in compose(f, g)
+    <ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
           1 def compose(f, g):
-          2 
-    ----> 3     (f_in, f_out), (g_in, g_out) = f, g
-          4 
-          5     if not g_in:
+    ----> 2     (f_in, f_out), (g_in, g_out) = f, g
+          3     s = unify(g_in, f_out)
+          4     if not s:
+          5         raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
 
 
     ValueError: need more than 1 value to unpack
@@ -2487,28 +2760,7 @@ F[1][0]
 s[0]
 ```
 
-## Typing Combinators
-
-TBD
-
-This is an open subject.
-
-The obvious thing is that you now need two pairs of tuples to describe the combinators' effects,  a stack effect comment and an expression effect comment:
-
-    dip (a [F] --)--(-- F a)
+## [Abstract Interpretation](https://en.wikipedia.org/wiki/Abstract_interpretation)
+I *think* this might be sorta what I'm doing above with the `kav()` function...
+  In any event "mixed-mode" interpreters that include values and type variables and can track constraints, etc. will be, uh, super-useful.  And Abstract Interpretation should be a rich source of ideas.
 
-One thing that might help is...
-
-## Abstract Interpretation
-
-## Something else...
-    [4 5 ...] 2 1 0 pop∘swap∘roll<∘rest∘rest∘cons∘cons
-    [4 5 ...] 2 1       swap∘roll<∘rest∘rest∘cons∘cons
-    [4 5 ...] 1 2            roll<∘rest∘rest∘cons∘cons
-    1 2 [4 5 ...]                  rest∘rest∘cons∘cons
-    1 2   [5 ...]                       rest∘cons∘cons
-    1 2     [...]                            cons∘cons
-    1     [2 ...]                                 cons
-        [1 2 ...]
-
-Eh?
index c6ab68e..0385776 100644 (file)
@@ -2,8 +2,12 @@
 Type Inference
 ==============
 
-Pöial's Rules
--------------
+Cf. `"Type Inference in Stack-Based Programming
+Languages" <http://prl.ccs.neu.edu/blog/2017/03/10/type-inference-in-stack-based-programming-languages/>`__
+by Rob Kleffner, 2017-03-10.
+
+Part I: Pöial's Rules
+---------------------
 
 `"Typing Tools for Typeless Stack Languages" by Jaanus
 Pöial <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.212.6026>`__
@@ -47,8 +51,9 @@ Third Rule
 
 The third rule is actually two rules. These two rules deal with
 composing functions when the second one will consume one of items the
-first one produces. The two types must be *unified* or a type conflict
-declared.
+first one produces. The two types must be
+`*unified* <https://en.wikipedia.org/wiki/Robinson's_unification_algorithm>`__
+or a type conflict declared.
 
 ::
 
@@ -61,9 +66,6 @@ declared.
     -------------------------------
        (a -- b     )∘(c      -- d)   t[i] == u[k] == u[j]
 
-Examples
---------
-
 Let's work through some examples by hand to develop an intuition for the
 algorithm.
 
@@ -387,8 +389,8 @@ following Python code:
         (_, (d, (c, ((a, (b, S0)), stack)))) = stack
         return (d, (c, S0)), stack
 
-Implementation
---------------
+Part II: Implementation
+-----------------------
 
 Representing Stack Effect Comments in Python
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -618,11 +620,11 @@ Let's try it out.
 
 
 
-List Functions
-~~~~~~~~~~~~~~
+Stack Functions
+~~~~~~~~~~~~~~~
 
 Here's that trick to represent functions like ``rest`` and ``cons`` that
-manipulate lists. We use a cons-list of tuples and give the tails their
+manipulate stacks. We use a cons-list of tuples and give the tails their
 own numbers. Then everything above already works.
 
 .. code:: ipython2
@@ -683,6 +685,7 @@ Compare with the stack effect comment and you can see it works fine:
 ::
 
     ([4 5 ...] 2 3 1 -- [3 2 ...])
+      3 4  5   1 2 0     2 1  5
 
 Dealing with ``cons`` and ``uncons``
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -719,7 +722,7 @@ deal with this recursively:
     def unify(u, v, s=None):
         if s is None:
             s = {}
-        else:
+        elif s:
             u = update(s, u)
             v = update(s, v)
     
@@ -758,8 +761,8 @@ deal with this recursively:
 
 
 
-Compiling
----------
+Part III: Compiling Stack Functions
+-----------------------------------
 
 Now consider the Python function we would like to derive:
 
@@ -1094,8 +1097,8 @@ from their stack effect comments:
     
 
 
-Types and Subtypes of Arguments
--------------------------------
+Part IV: Types and Subtypes of Arguments
+----------------------------------------
 
 So far we have dealt with types of functions, those dealing with simple
 stack manipulation. Let's extend our machinery to deal with types of
@@ -1396,7 +1399,7 @@ of how many labels of each domain it has "seen".
     def unify(u, v, s=None):
         if s is None:
             s = {}
-        else:
+        elif s:
             u = update(s, u)
             v = update(s, v)
     
@@ -1719,8 +1722,8 @@ comments. We can write a function to check that:
     uncons = ([a1 .1.] -- a1 [.1.])
 
 
-Functions that use the Stack
-----------------------------
+Part V: Functions that use the Stack
+------------------------------------
 
 Consider the ``stack`` function which grabs the whole stack, quotes it,
 and puts it on itself:
@@ -1803,32 +1806,17 @@ It works.
 
 This function has to be modified to use the new datastructures and it is
 no longer recursive, instead recursion happens as part of unification.
+Further, the first and second of Pöial's rules are now handled
+automatically by the unification algorithm.
 
 .. code:: ipython2
 
     def compose(f, g):
-    
         (f_in, f_out), (g_in, g_out) = f, g
-    
-        if not g_in:
-            fg_in, fg_out = f_in, stack_concat(g_out, f_out)
-    
-        elif not f_out:
-            fg_in, fg_out = stack_concat(f_in, g_in), g_out
-    
-        else: # Unify and update.
-    
-            s = unify(g_in, f_out)
-    
-            if s == False:  # s can also be the empty dict, which is ok.
-                raise TypeError('Cannot unify %r and %r.' % (fo, gi))
-    
-            fg_in, fg_out = update(s, (f_in, g_out))
-    
-        return fg_in, fg_out
-    
-    
-    stack_concat = lambda q, e: (q[0], stack_concat(q[1], e)) if q else e
+        s = unify(g_in, f_out)
+        if s == False:  # s can also be the empty dict, which is ok.
+            raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
+        return update(s, (f_in, g_out))
 
 I don't want to rewrite all the defs myself, so I'll write a little
 conversion function instead. This is programmer's laziness.
@@ -2100,8 +2088,8 @@ comments are now already in the form needed for the Python code:
 
 
 
-Multiple Stack Effects
-----------------------
+Part VI: Multiple Stack Effects
+-------------------------------
 
 ...
 
@@ -2191,58 +2179,16 @@ Multiple Stack Effects
     (n0 -- n1)
 
 
-``concat``
-----------
-
-How to deal with ``concat``?
-
-::
-
-    concat ([.0.] [.1.] -- [.0. .1.])
-
-We would like to represent this in Python somehow...
-
-.. code:: ipython2
-
-    concat = (S[0], S[1]), ((S[0], S[1]),)
-
-But this is actually ``cons`` with the first argument restricted to be a
-stack:
-
-::
-
-    ([.0.] [.1.] -- [[.0.] .1.])
+Representing an Unbounded Sequence of Types
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-What we have implemented so far would actually only permit:
-
-::
-
-    ([.0.] [.1.] -- [.2.])
-
-.. code:: ipython2
-
-    concat = (S[0], S[1]), (S[2],)
-
-Which works but can lose information. Consider ``cons concat``, this is
-how much information we *could* retain:
-
-::
-
-    (1 [.0.] [.1.] -- [1 .0. .1.])
-
-As opposed to just:
-
-::
-
-    (1 [.0.] [.1.] -- [.2.])
-
-Brzo...'s Derivitives of Regular Expressions
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-We can invent a new type of type variable, a "sequence type" (I think
-this is what they mean in the literature by that term...) or "Kleene
-Star" type. I'm going to represent it as a type letter and the asterix,
-so a sequence of zero or more ``AnyJoyType`` variables would be:
+We can borrow a trick from `Brzozowski's Derivatives of Regular
+Expressions <https://en.wikipedia.org/wiki/Brzozowski_derivative>`__ to
+invent a new type of type variable, a "sequence type" (I think this is
+what they mean in the literature by that term...) or "`Kleene
+Star <https://en.wikipedia.org/wiki/Kleene_star>`__" type. I'm going to
+represent it as a type letter and the asterix, so a sequence of zero or
+more ``AnyJoyType`` variables would be:
 
 ::
 
@@ -2392,7 +2338,7 @@ Can now return multiple results...
                     sn.update(s)
                 return t
     
-            ses = unify(u[0], v[0])
+            ses = unify(u[0], v[0], s)
             results = ()
             for sn in ses:
                 results += unify(u[1], v[1], sn)
@@ -2517,30 +2463,17 @@ Can now return multiple results...
 ``compose()`` version 3
 ^^^^^^^^^^^^^^^^^^^^^^^
 
-This function has to be modified to use the new datastructures and it is
-no longer recursive, instead recursion happens as part of unification.
+This function has to be modified to yield multiple results.
 
 .. code:: ipython2
 
     def compose(f, g):
-    
         (f_in, f_out), (g_in, g_out) = f, g
-    
-        if not g_in:
-            yield f_in, stack_concat(g_out, f_out)
-    
-        elif not f_out:
-            yield stack_concat(f_in, g_in), g_out
-    
-        else: # Unify and update.
-    
-            s = unify(g_in, f_out)
-    
-            if not s:
-                raise TypeError('Cannot unify %r and %r.' % (fo, gi))
-    
-            for result in s:
-                yield update(result, (f_in, g_out))
+        s = unify(g_in, f_out)
+        if not s:
+            raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
+        for result in s:
+            yield update(result, (f_in, g_out))
 
 
 .. code:: ipython2
@@ -2567,8 +2500,8 @@ no longer recursive, instead recursion happens as part of unification.
 
 .. parsed-literal::
 
-    (a0 -- f0)
-    (a0 -- i0)
+    (f0 -- f1)
+    (i0 -- i1)
 
 
 .. code:: ipython2
@@ -2665,6 +2598,377 @@ no longer recursive, instead recursion happens as part of unification.
     {s2: (a1*, (a3, s1)), a2: a10004, a4: a1}
 
 
+Part VII: Typing Combinators
+----------------------------
+
+TBD
+
+This is an open subject.
+
+The obvious thing is that you now need two pairs of tuples to describe
+the combinators' effects, a stack effect comment and an expression
+effect comment:
+
+::
+
+    dip (a [F] --)--(-- F a)
+
+One thing that might help is...
+
+Consider the type of:
+
+::
+
+    [cons] dip
+
+Obviously it would be:
+
+::
+
+    (a1 [..1] a2 -- [a1 ..1] a2)
+
+``dip`` itself could have:
+
+::
+
+    (a1 [..1] -- ... then what?
+
+.. code:: ipython2
+
+    class SymbolJoyType(AnyJoyType): prefix = 'F'
+    
+    W = map(SymbolJoyType, _R)
+    
+    k = S[0], ((W[1], S[2]), S[0])
+    Symbol('cons')
+    print doc_from_stack_effect(*k)
+
+
+
+.. parsed-literal::
+
+    (-- [F1 .2.])
+
+
+.. code:: ipython2
+
+    dip_a = ((W[1], S[2]), (A[1], S[0]))
+
+.. code:: ipython2
+
+    d = relabel(S[0], dip_a)
+    print doc_from_stack_effect(*d)
+
+
+.. parsed-literal::
+
+    (-- a1001 [F1001 .1002.])
+
+
+.. code:: ipython2
+
+    s = list(unify(d[1], k[1]))[0]
+    s
+
+
+
+
+.. parsed-literal::
+
+    {s0: (a1001, s1000), s1002: s2, F1001: F1}
+
+
+
+.. code:: ipython2
+
+    j = update(s, k)
+
+.. code:: ipython2
+
+    print doc_from_stack_effect(*j)
+
+
+.. parsed-literal::
+
+    (a1001 -- a1001 [F1 .2.])
+
+
+.. code:: ipython2
+
+    j
+
+
+
+
+.. parsed-literal::
+
+    ((a1001, s1000), ((F1, s2), (a1001, s1000)))
+
+
+
+.. code:: ipython2
+
+    cons
+
+
+
+
+.. parsed-literal::
+
+    ((s1, (a1, s23)), ((a1, s1), s23))
+
+
+
+.. code:: ipython2
+
+    for f in MC([k], [dup]):
+        print doc_from_stack_effect(*f)
+
+
+.. parsed-literal::
+
+    (-- [F0 .1.] [F0 .1.])
+
+
+.. code:: ipython2
+
+    l = S[0], ((cons, S[2]), (A[1], S[0]))
+
+.. code:: ipython2
+
+    print doc_from_stack_effect(*l)
+
+
+.. parsed-literal::
+
+    (-- a1 [[[[.1.] a1 .23.] [a1 .1.] .23.] .2.])
+
+
+.. code:: ipython2
+
+    
+    def dip_t(F):
+        (quote, (a1, sec)) = F[1]
+        G = F[0], sec
+        P = S[3], (a1, S[3])
+        a = [P]
+        while isinstance(quote, tuple):
+            term, quote = quote
+            a.append(term)
+        a.append(G)
+        return a[::-1]
+    
+    
+    
+
+
+.. code:: ipython2
+
+    from joy.utils.stack import iter_stack
+
+.. code:: ipython2
+
+    a, b, c = dip_t(l)
+
+.. code:: ipython2
+
+    a
+
+
+
+
+.. parsed-literal::
+
+    (s0, s0)
+
+
+
+.. code:: ipython2
+
+    b
+
+
+
+
+.. parsed-literal::
+
+    ((s1, (a1, s23)), ((a1, s1), s23))
+
+
+
+.. code:: ipython2
+
+    c
+
+
+
+
+.. parsed-literal::
+
+    (s3, (a1, s3))
+
+
+
+.. code:: ipython2
+
+    MC([a], [b])
+
+
+
+
+.. parsed-literal::
+
+    [((s0, (a0, s1)), ((a0, s0), s1))]
+
+
+
+.. code:: ipython2
+
+    kjs = MC(MC([a], [b]), [c])
+    kjs
+
+
+
+
+.. parsed-literal::
+
+    [((s0, (a0, s1)), (a1, ((a0, s0), s1)))]
+
+
+
+.. code:: ipython2
+
+    print doc_from_stack_effect(*kjs[0])
+
+
+.. parsed-literal::
+
+    (a0 [.0.] -- [a0 .0.] a1)
+
+
+::
+
+    (a0 [.0.] -- [a0 .0.] a1)
+
+       a0 [.0.] a1 [cons] dip
+    ----------------------------
+       [a0 .0.] a1
+
+.. code:: ipython2
+
+    stack_concat = lambda q, e: (q[0], stack_concat(q[1], e)) if q else e
+
+.. code:: ipython2
+
+    class SymbolJoyType(AnyJoyType):
+        prefix = 'F'
+    
+        def __init__(self, name, sec, number):
+            self.name = name
+            self.stack_effects = sec
+            self.number = number
+    
+    class CombinatorJoyType(SymbolJoyType): prefix = 'C'
+    
+    def dip_t(stack, expression):
+        (quote, (a1, stack)) = stack
+        expression = stack_concat(quote, (a1, expression))
+        return stack, expression
+    
+    CONS = SymbolJoyType('cons', [cons], 23)
+    DIP = CombinatorJoyType('dip', [dip_t], 44)
+    
+    
+    def kav(F, e):
+        #i, stack = F
+        if not e:
+            return [(F, e)]
+        n, e = e
+        if isinstance(n, SymbolJoyType):
+            Fs = []
+            for sec in n.stack_effects:
+                Fs.extend(MC([F], sec))
+            return [kav(Fn, e) for Fn in Fs]
+        if isinstance(n, CombinatorJoyType):
+            res = []
+            for f in n.stack_effects:
+                s, e = f(F[1], e)
+                new_F = F[0], s
+                res.extend(kav(new_F, e))
+            return res
+        lit = S[0], (n, S[0])
+        return [kav(Fn, e) for Fn in MC([F], [lit])]
+
+
+compare, and be amazed:
+
+.. code:: ipython2
+
+    def dip_t(stack, expression):
+        (quote, (a1, stack)) = stack
+        expression = stack_concat(quote, (a1, expression))
+        return stack, expression
+
+.. code:: ipython2
+
+    def dip(stack, expression, dictionary):
+        (quote, (x, stack)) = stack
+        expression = (x, expression)
+        return stack, concat(quote, expression), dictionary
+
+And that brings us to current Work-In-Progress. I'm pretty hopeful that
+the mixed-mode inferencer/interpreter ``kav()`` function along with the
+ability to specify multiple implementations for the combinators will
+permit modelling of the stack effects of e.g. ``ifte``. If I can keep up
+the pace I should be able to verify that conjecture by the end of June.
+
+The rest of this stuff is junk and/or unfinished material.
+
+``concat``
+~~~~~~~~~~
+
+How to deal with ``concat``?
+
+::
+
+    concat ([.0.] [.1.] -- [.0. .1.])
+
+We would like to represent this in Python somehow...
+
+.. code:: ipython2
+
+    concat = (S[0], S[1]), ((S[0], S[1]),)
+
+But this is actually ``cons`` with the first argument restricted to be a
+stack:
+
+::
+
+    ([.0.] [.1.] -- [[.0.] .1.])
+
+What we have implemented so far would actually only permit:
+
+::
+
+    ([.0.] [.1.] -- [.2.])
+
+.. code:: ipython2
+
+    concat = (S[0], S[1]), (S[2],)
+
+Which works but can lose information. Consider ``cons concat``, this is
+how much information we *could* retain:
+
+::
+
+    (1 [.0.] [.1.] -- [1 .0. .1.])
+
+As opposed to just:
+
+::
+
+    (1 [.0.] [.1.] -- [.2.])
+
 represent ``concat``
 ~~~~~~~~~~~~~~~~~~~~
 
@@ -2731,8 +3035,8 @@ or...
 
 
 
-Joy in the Logical Paradigm
----------------------------
+Appendix: Joy in the Logical Paradigm
+-------------------------------------
 
 For this to work the type label classes have to be modified to let
 ``T >= t`` succeed, where e.g. ``T`` is ``IntJoyType`` and ``t`` is
@@ -2752,85 +3056,85 @@ For this to work the type label classes have to be modified to let
 
     ValueError                                Traceback (most recent call last)
 
-    <ipython-input-113-4b4cb6ff86e5> in <module>()
+    <ipython-input-137-4b4cb6ff86e5> in <module>()
           1 F = reduce(C, (pop, swap, roll_down, rest, rest, cons, cons))
           2 
     ----> 3 print doc_from_stack_effect(*F)
     
 
-    <ipython-input-101-ddee30dbb1a6> in C(f, g)
+    <ipython-input-99-ddee30dbb1a6> in C(f, g)
          10 def C(f, g):
          11     f, g = relabel(f, g)
     ---> 12     for fg in compose(f, g):
          13         yield delabel(fg)
 
 
-    <ipython-input-100-4237a6bb159d> in compose(f, g)
+    <ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
           1 def compose(f, g):
-          2 
-    ----> 3     (f_in, f_out), (g_in, g_out) = f, g
-          4 
-          5     if not g_in:
+    ----> 2     (f_in, f_out), (g_in, g_out) = f, g
+          3     s = unify(g_in, f_out)
+          4     if not s:
+          5         raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
 
 
-    <ipython-input-101-ddee30dbb1a6> in C(f, g)
+    <ipython-input-99-ddee30dbb1a6> in C(f, g)
          10 def C(f, g):
          11     f, g = relabel(f, g)
     ---> 12     for fg in compose(f, g):
          13         yield delabel(fg)
 
 
-    <ipython-input-100-4237a6bb159d> in compose(f, g)
+    <ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
           1 def compose(f, g):
-          2 
-    ----> 3     (f_in, f_out), (g_in, g_out) = f, g
-          4 
-          5     if not g_in:
+    ----> 2     (f_in, f_out), (g_in, g_out) = f, g
+          3     s = unify(g_in, f_out)
+          4     if not s:
+          5         raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
 
 
-    <ipython-input-101-ddee30dbb1a6> in C(f, g)
+    <ipython-input-99-ddee30dbb1a6> in C(f, g)
          10 def C(f, g):
          11     f, g = relabel(f, g)
     ---> 12     for fg in compose(f, g):
          13         yield delabel(fg)
 
 
-    <ipython-input-100-4237a6bb159d> in compose(f, g)
+    <ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
           1 def compose(f, g):
-          2 
-    ----> 3     (f_in, f_out), (g_in, g_out) = f, g
-          4 
-          5     if not g_in:
+    ----> 2     (f_in, f_out), (g_in, g_out) = f, g
+          3     s = unify(g_in, f_out)
+          4     if not s:
+          5         raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
 
 
-    <ipython-input-101-ddee30dbb1a6> in C(f, g)
+    <ipython-input-99-ddee30dbb1a6> in C(f, g)
          10 def C(f, g):
          11     f, g = relabel(f, g)
     ---> 12     for fg in compose(f, g):
          13         yield delabel(fg)
 
 
-    <ipython-input-100-4237a6bb159d> in compose(f, g)
+    <ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
           1 def compose(f, g):
-          2 
-    ----> 3     (f_in, f_out), (g_in, g_out) = f, g
-          4 
-          5     if not g_in:
+    ----> 2     (f_in, f_out), (g_in, g_out) = f, g
+          3     s = unify(g_in, f_out)
+          4     if not s:
+          5         raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
 
 
-    <ipython-input-101-ddee30dbb1a6> in C(f, g)
+    <ipython-input-99-ddee30dbb1a6> in C(f, g)
          10 def C(f, g):
          11     f, g = relabel(f, g)
     ---> 12     for fg in compose(f, g):
          13         yield delabel(fg)
 
 
-    <ipython-input-100-4237a6bb159d> in compose(f, g)
+    <ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
           1 def compose(f, g):
-          2 
-    ----> 3     (f_in, f_out), (g_in, g_out) = f, g
-          4 
-          5     if not g_in:
+    ----> 2     (f_in, f_out), (g_in, g_out) = f, g
+          3     s = unify(g_in, f_out)
+          4     if not s:
+          5         raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
 
 
     ValueError: need more than 1 value to unpack
@@ -2862,38 +3166,11 @@ For this to work the type label classes have to be modified to let
 
     s[0]
 
-Typing Combinators
-------------------
-
-TBD
-
-This is an open subject.
-
-The obvious thing is that you now need two pairs of tuples to describe
-the combinators' effects, a stack effect comment and an expression
-effect comment:
-
-::
+`Abstract Interpretation <https://en.wikipedia.org/wiki/Abstract_interpretation>`__
+-----------------------------------------------------------------------------------
 
-    dip (a [F] --)--(-- F a)
-
-One thing that might help is...
-
-Abstract Interpretation
------------------------
-
-Something else...
------------------
-
-::
-
-    [4 5 ...] 2 1 0 pop∘swap∘roll<∘rest∘rest∘cons∘cons
-    [4 5 ...] 2 1       swap∘roll<∘rest∘rest∘cons∘cons
-    [4 5 ...] 1 2            roll<∘rest∘rest∘cons∘cons
-    1 2 [4 5 ...]                  rest∘rest∘cons∘cons
-    1 2   [5 ...]                       rest∘cons∘cons
-    1 2     [...]                            cons∘cons
-    1     [2 ...]                                 cons
-        [1 2 ...]
-
-Eh?
+I *think* this might be sorta what I'm doing above with the ``kav()``
+function... In any event "mixed-mode" interpreters that include values
+and type variables and can track constraints, etc. will be, uh,
+super-useful. And Abstract Interpretation should be a rich source of
+ideas.
index 4c74e30..4269353 100644 (file)
 </ul>
 </li>
 <li class="toctree-l1"><a class="reference internal" href="Types.html">Type Inference</a><ul>
-<li class="toctree-l2"><a class="reference internal" href="Types.html#poial-s-rules">Pöial’s Rules</a></li>
-<li class="toctree-l2"><a class="reference internal" href="Types.html#examples">Examples</a></li>
-<li class="toctree-l2"><a class="reference internal" href="Types.html#implementation">Implementation</a></li>
-<li class="toctree-l2"><a class="reference internal" href="Types.html#compiling">Compiling</a></li>
-<li class="toctree-l2"><a class="reference internal" href="Types.html#types-and-subtypes-of-arguments">Types and Subtypes of Arguments</a></li>
-<li class="toctree-l2"><a class="reference internal" href="Types.html#functions-that-use-the-stack">Functions that use the Stack</a></li>
-<li class="toctree-l2"><a class="reference internal" href="Types.html#sets-of-stack-effects">Sets of Stack Effects</a></li>
-<li class="toctree-l2"><a class="reference internal" href="Types.html#concat"><code class="docutils literal notranslate"><span class="pre">concat</span></code></a></li>
-<li class="toctree-l2"><a class="reference internal" href="Types.html#typing-combinators">Typing Combinators</a></li>
+<li class="toctree-l2"><a class="reference internal" href="Types.html#part-i-poial-s-rules">Part I: Pöial’s Rules</a></li>
+<li class="toctree-l2"><a class="reference internal" href="Types.html#part-ii-implementation">Part II: Implementation</a></li>
+<li class="toctree-l2"><a class="reference internal" href="Types.html#part-iii-compiling-stack-functions">Part III: Compiling Stack Functions</a></li>
+<li class="toctree-l2"><a class="reference internal" href="Types.html#part-iv-types-and-subtypes-of-arguments">Part IV: Types and Subtypes of Arguments</a></li>
+<li class="toctree-l2"><a class="reference internal" href="Types.html#part-v-functions-that-use-the-stack">Part V: Functions that use the Stack</a></li>
+<li class="toctree-l2"><a class="reference internal" href="Types.html#part-vi-multiple-stack-effects">Part VI: Multiple Stack Effects</a></li>
+<li class="toctree-l2"><a class="reference internal" href="Types.html#part-vii-typing-combinators">Part VII: Typing Combinators</a></li>
+<li class="toctree-l2"><a class="reference internal" href="Types.html#appendix-joy-in-the-logical-paradigm">Appendix: Joy in the Logical Paradigm</a></li>
 <li class="toctree-l2"><a class="reference internal" href="Types.html#abstract-interpretation">Abstract Interpretation</a></li>
-<li class="toctree-l2"><a class="reference internal" href="Types.html#something-else">Something else…</a></li>
 </ul>
 </li>
 <li class="toctree-l1"><a class="reference internal" href="NoUpdates.html">No Updates</a></li>
index c2ac2b0..d3e2225 100644 (file)
@@ -1 +1 @@
-Search.setIndex({docnames:["index","joy","lib","library","notebooks/Categorical","notebooks/Developing","notebooks/Generator_Programs","notebooks/Intro","notebooks/Newton-Raphson","notebooks/NoUpdates","notebooks/Ordered_Binary_Trees","notebooks/Quadratic","notebooks/Recursion_Combinators","notebooks/Replacing","notebooks/Treestep","notebooks/Types","notebooks/Zipper","notebooks/index","parser","pretty","stack"],envversion:52,filenames:["index.rst","joy.rst","lib.rst","library.rst","notebooks/Categorical.rst","notebooks/Developing.rst","notebooks/Generator_Programs.rst","notebooks/Intro.rst","notebooks/Newton-Raphson.rst","notebooks/NoUpdates.rst","notebooks/Ordered_Binary_Trees.rst","notebooks/Quadratic.rst","notebooks/Recursion_Combinators.rst","notebooks/Replacing.rst","notebooks/Treestep.rst","notebooks/Types.rst","notebooks/Zipper.rst","notebooks/index.rst","parser.rst","pretty.rst","stack.rst"],objects:{"joy.joy":{joy:[1,1,1,""],repl:[1,1,1,""],run:[1,1,1,""]},"joy.library":{"void":[3,1,1,""],BinaryBuiltinWrapper:[3,1,1,""],DefinitionWrapper:[3,2,1,""],FunctionWrapper:[3,1,1,""],SimpleFunctionWrapper:[3,1,1,""],UnaryBuiltinWrapper:[3,1,1,""],add_aliases:[3,1,1,""],app1:[3,1,1,""],app2:[3,1,1,""],app3:[3,1,1,""],b:[3,1,1,""],branch:[3,1,1,""],choice:[3,1,1,""],clear:[3,1,1,""],cmp_:[3,1,1,""],concat_:[3,1,1,""],cond:[3,1,1,""],dip:[3,1,1,""],dipd:[3,1,1,""],dipdd:[3,1,1,""],divmod_:[3,1,1,""],drop:[3,1,1,""],dupdip:[3,1,1,""],floor:[3,1,1,""],genrec:[3,1,1,""],getitem:[3,1,1,""],help_:[3,1,1,""],i:[3,1,1,""],id_:[3,1,1,""],ifte:[3,1,1,""],infra:[3,1,1,""],initialize:[3,1,1,""],inscribe:[3,1,1,""],loop:[3,1,1,""],map_:[3,1,1,""],max_:[3,1,1,""],min_:[3,1,1,""],parse:[3,1,1,""],pm:[3,1,1,""],pred:[3,1,1,""],remove:[3,1,1,""],reverse:[3,1,1,""],select:[3,1,1,""],sharing:[3,1,1,""],shunt:[3,1,1,""],sort_:[3,1,1,""],sqrt:[3,1,1,""],step:[3,1,1,""],succ:[3,1,1,""],sum_:[3,1,1,""],swaack:[3,1,1,""],take:[3,1,1,""],times:[3,1,1,""],unique:[3,1,1,""],unstack:[3,1,1,""],warranty:[3,1,1,""],words:[3,1,1,""],x:[3,1,1,""],zip_:[3,1,1,""]},"joy.library.DefinitionWrapper":{add_def:[3,3,1,""],add_definitions:[3,3,1,""],parse_definition:[3,3,1,""]},"joy.parser":{ParseError:[18,4,1,""],Symbol:[18,2,1,""],text_to_expression:[18,1,1,""]},"joy.utils":{generated_library:[3,0,0,"-"],pretty_print:[19,0,0,"-"],stack:[20,0,0,"-"]},"joy.utils.generated_library":{ccons:[3,1,1,""],cons:[3,1,1,""],dup:[3,1,1,""],dupd:[3,1,1,""],dupdd:[3,1,1,""],first:[3,1,1,""],first_two:[3,1,1,""],fourth:[3,1,1,""],over:[3,1,1,""],pop:[3,1,1,""],popd:[3,1,1,""],popdd:[3,1,1,""],popop:[3,1,1,""],popopd:[3,1,1,""],popopdd:[3,1,1,""],rest:[3,1,1,""],rolldown:[3,1,1,""],rollup:[3,1,1,""],rrest:[3,1,1,""],second:[3,1,1,""],stack:[3,1,1,""],stuncons:[3,1,1,""],stununcons:[3,1,1,""],swap:[3,1,1,""],swons:[3,1,1,""],third:[3,1,1,""],tuck:[3,1,1,""],uncons:[3,1,1,""],unswons:[3,1,1,""]},"joy.utils.pretty_print":{TracePrinter:[19,2,1,""]},"joy.utils.pretty_print.TracePrinter":{go:[19,5,1,""],viewer:[19,5,1,""]},"joy.utils.stack":{concat:[20,1,1,""],expression_to_string:[20,1,1,""],iter_stack:[20,1,1,""],list_to_stack:[20,1,1,""],pick:[20,1,1,""],stack_to_string:[20,1,1,""]},joy:{joy:[1,0,0,"-"],library:[3,0,0,"-"],parser:[18,0,0,"-"]}},objnames:{"0":["py","module","Python module"],"1":["py","function","Python function"],"2":["py","class","Python class"],"3":["py","classmethod","Python class method"],"4":["py","exception","Python exception"],"5":["py","method","Python method"]},objtypes:{"0":"py:module","1":"py:function","2":"py:class","3":"py:classmethod","4":"py:exception","5":"py:method"},terms:{"0b11100111011011":5,"23rd":15,"5bkei":10,"\u03b5":8,"abstract":[7,10,17],"boolean":[2,3,7,10],"break":[7,15],"byte":5,"case":[2,3,12,14,15,20],"class":[3,7,15,18,19,20],"default":[3,6,10,20],"export":[3,18],"final":[2,10,12],"float":[3,7,15,16,18],"function":[0,1,4,5,6,9,11,16,17,18,19,20],"g\u00e9rard":16,"import":[2,5,6,8,10,11,12,13,14,15,16],"int":[6,7,12,15,16,18,20],"long":[10,17],"new":[2,3,6,7,9,12,13,15],"p\u00f6ial":17,"p\u00f6ial06typingtool":15,"public":9,"return":[1,3,5,7,10,12,13,14,15,18,19,20],"static":[2,9],"switch":[2,15],"throw":10,"true":[2,3,5,12,15],"try":[6,8,11,12,14,15],"void":[0,3],"while":[3,7,10,15,18,20],Adding:[7,13,17],And:[5,6,8,10,12,15,16,20],But:[0,4,5,6,7,10,13,15],CPS:7,For:[2,3,10,12,13,15,17,20],Has:3,Its:3,One:[2,7,15,17],TOS:[2,3],That:[5,10],The:[0,1,2,3,4,6,8,9,11,15,16,17,18,20],Then:[2,3,10,11,12,15],There:[11,12,14,15,20],These:[15,17,20],Use:[3,8,12],Using:[0,8,10,17],With:[8,12,15,17],_1000:15,__add__:15,__class__:15,__eq__:15,__ge__:15,__hash__:15,__init__:15,__main__:15,__radd__:15,__repr__:15,__str__:19,_names_for:15,_to_str:15,_tree_add_:10,_tree_add_e:10,_tree_add_p:10,_tree_add_r:10,_tree_add_t:10,_tree_delete_:10,_tree_delete_clear_stuff:10,_tree_delete_del:10,_tree_delete_r0:10,_tree_delete_r1:10,_tree_delete_rightmost:10,_tree_delete_w:10,_tree_get_:10,_tree_get_p:10,_tree_get_r:10,_tree_get_t:10,_tree_iter_order_curr:10,_tree_iter_order_left:10,_tree_iter_order_r:10,_tree_iter_order_right:10,_tree_t:10,_treestep_0:14,_treestep_1:14,_uniqu:15,_within_b:8,_within_p:8,_within_r:8,abbrevi:14,abl:15,about:[0,7,10,16,20],abov:[0,5,8,10,12,15],abs:8,absolut:7,accept:[1,2,3,5,6,7,10,11,13,14,15,16],accordingli:10,accumul:5,action:[7,13,15,16],actual:[2,5,7,10,15],adapt:17,add:[3,5,6,7,13,15,19],add_alias:3,add_def:3,add_definit:[3,10,14],added:[4,10],adding:[9,15],addit:[0,2,3,5,7,12,13,14],address:17,adjust:10,after:[5,6,7,12],afterward:7,again:[2,3,5,7,10,12,15],aggreg:16,ahead:15,aka:[7,16],albrecht:0,algorithm:[7,15],alia:3,alias:[3,7],align:[7,19],all:[3,5,6,7,10,12,13,14,15,19],alloc:15,allow:[9,10],almost:10,along:[7,12],alphabet:3,alreadi:[8,13,15,16],also:[0,5,7,10,15,20],alter:15,altern:4,although:[4,10],altogeth:6,alwai:[5,9,12],among:15,amort:10,analysi:[4,17],anamorph:[7,17],ani:[4,5,7,9,10,15,16,18],annual:7,anonym:10,anoth:[10,20],anyjoytyp:15,anymor:15,anyth:[2,3,7,15],api:9,app1:3,app2:[3,7,11,12,13],app3:3,app:7,appear:[2,4,5,10],append:15,appendix:17,appli:[2,3,5,6,10,12,15],applic:6,approach:5,approxim:17,archiv:0,aren:16,arg:[2,3],argument:[2,3,7,8,11,12,17,19,20],arithmet:2,ariti:2,around:[5,20],arrang:14,arriv:[6,14],articl:[0,4,6,12],ask:[4,6,15],aspect:0,assert:15,assign:20,associ:10,assum:8,asterisk:14,attack:7,attempt:[0,1],attribut:3,attributeerror:15,author:15,auto:0,automat:[4,15],auxiliari:14,avail:[0,15],averag:[7,13],avoid:10,awai:10,awar:2,awkward:[10,12],azur:17,back:10,backward:[9,10,11,14],bag:7,banana:12,barb:12,base:[0,2,3,9,12,14],basic:[1,2,3,7,10],becaus:[2,3,7,10,14,15,16,20],becom:[10,14,20],been:[8,9,10,15,16],befor:[6,7,10],begin:[10,14],behavior:[9,14],behaviour:[0,1,15],being:0,below:[2,3,5,6,10,15,16],bespok:7,best:0,better:[5,10,12],between:[0,5],beyond:6,biannual:7,binari:[0,6,7,17],binary_search_tre:10,binarybuiltinwrapp:3,bind:7,bingo:16,bit:[5,6,10,15],block:5,bodi:[2,7,10],body_text:3,booktitl:15,bool:12,borrow:7,both:[2,5,7,11,12,13,15,20],bottom:6,bracket:[7,15,18],branch:[3,5,6,12],breakpoint:7,bring:[5,7],bruijn:15,btree:[10,14],buck:10,bug:[0,7],build:[6,7,11,12,16,20],built:[11,15],bundl:[2,3,12],burgeon:7,calculu:4,call:[2,7,9,10,12,15,19,20],caller:10,can:[0,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,20],cannot:15,captur:7,card:7,care:[5,20],carefulli:16,carri:[6,10],cartesian:4,catamorph:17,categor:[0,17],categori:4,ccc:4,ccon:[3,10,15],cell:[12,15],certain:[7,20],certainli:10,chain:3,chang:[2,9,10,15,16],charact:16,chat:7,chatter:[0,15],check:[6,8,15],child:14,choic:[3,12],choos:9,chop:11,cinf:10,circuit:4,cite_not:10,classmethod:3,claus:[3,15],clean:15,clear:[3,5,7],clear_stuff:10,cleav:[7,11,13],close:[0,1,4],clunki:[5,15],cmp:[3,14,17],cmp_:3,code:[0,1,4,11,12,15,17],codireco:[6,8],collaps:12,collect:[4,6,7,15],combin:[0,3,5,6,7,8,11,14,16,17],come:[7,10],command:[7,10,15],common:[2,5],compar:[3,4,15],comparison:[0,10],compel:4,compil:[2,4,7,10,13,17],complet:4,complex:[3,15,16],complic:15,composit:15,compound:10,comput:[2,4,5,7,11,15],con:[3,5,6,7,8,10,11,12,14,16,20],conal:4,concat:[3,6,7,14,17,20],concat_:3,concaten:0,concatin:[0,3,20],conclus:17,concurr:2,cond:[3,10],condit:[3,7],confer:15,conflict:[10,15],consecut:17,consid:[5,6,10,12,14,15,16],consist:[2,6,7,14],constant:10,constitu:12,construct:15,consum:15,contain:[0,2,3,6,7,12],context:2,conting:10,continu:[0,12,16],control:7,conveni:[4,15],convers:15,convert:[12,13,14,15,18,20],cool:10,copi:[2,3,5,10,12,14,17],copyright:7,correspond:4,could:[2,4,5,7,9,10,15,16],count:3,counter:[5,15],coupl:14,cours:[5,10],crack:10,crash:10,creat:[0,2,3,5,8,10,15],creativ:15,crude:[10,15,18],current:[2,3,7,12,14,16,19],custom:9,cycl:[5,6],cython:7,dai:7,data:[2,3,12],datastructur:[0,2,12,15,17,18,20],datatyp:20,ddididi:16,deal:[0,10],dealt:15,decid:10,declar:15,decor:3,decoupl:12,decrement:3,deduc:[5,15],deeper:0,deepli:4,def:[3,7,12,13,15,20],defaultdict:15,defi:3,defin:[2,3,4,5,6,7,8,9,11,12,13,15,16,17],definit:[2,3,5,6,7,9,10,12,14,15,17],definitionwrapp:[3,10,12,14],deleg:7,delet:17,deliber:15,demonstr:4,depend:[3,10,12],deposit:14,dequot:12,der:10,deriv:[2,3,5,7,8,10,15,17],describ:[3,4,10,12,14,15,18],descript:[5,7],descriptor:15,design:[2,3,10,17],desir:[7,14],destruct:10,detail:[7,10,15],detect:[6,10,12,15],determin:17,develop:[0,6,7,15,17],diagram:5,dialect:1,dict:[1,3,15],dictionari:[0,1,3,7,17],differ:[0,4,5,8,10,11,12,20],differenti:4,dig:[10,16],digit:5,dinfrirst:7,dip:[3,5,6,7,8,10,11,12,13,14,15,17],dipd:[3,6,7,10,11,12,16],dipdd:[3,10],direco:17,direct:7,directli:[5,14,15,20],disappear:2,discard:[3,6,8,10,12],disciplin:10,disenstacken:7,disk:7,displac:2,displai:15,distiguish:15,ditch:10,div:[3,7],dive:14,divis:10,divmod:3,divmod_:[3,15],doc:[2,3,7,15],document:[17,18,20],doe:[0,1,4,6,7,13,17,19],doesn:[5,9,10,14,15,20],doing:[4,5,7,15,16],domain:[4,15],don:[5,7,10,15],done:[2,5,7,9,15],door:7,dot:19,doubl:[5,7,15],down:[2,8,12,16],down_to_zero:7,dozen:7,draft:[4,9],dream:7,drive:[6,8],driven:5,driver:6,drop:[3,10],dudipd:7,due:15,dup:[3,5,6,7,8,10,11,12,16,20],dupd:[3,15],dupdd:3,dupdip:[3,5,10,11,12],duplic:[3,10,12],durat:2,dure:[2,12],each:[2,3,4,5,7,12,13,14,15,19],easi:[0,10,14,15,16],easier:[3,10],easili:4,edit:17,effect:[2,3,7,16,17],effici:[6,13,16],either:[1,2,3,10,12,15],eleg:[7,10,15],element:2,elif:15,elimin:15,elliott:4,els:[2,3,12,17],embed:[4,10,16],emit:15,empti:[3,7,14,15,20],encapsul:7,enclos:7,encod:6,encount:15,end:[5,10,12,14,15,20],endless:6,enforc:[2,7],engend:7,enough:[7,12,19],enstacken:[6,7,15],enter:7,entir:20,entri:[3,16,19],enumer:15,epsilon:8,equal:[5,14,20],equat:[7,8],ergo:10,err:10,error:[7,18],essai:0,establish:15,etc:[3,14,15,16,18],euler:17,euro:15,eval:[0,15],evalu:[1,2,3,7,8,10,11,12,13,14],everi:6,everyth:[3,10,11,15],evolv:9,examin:12,exampl:[0,3,5,17,18,20],exce:6,except:[7,10,15,18],execut:[0,1,2,3,7,12,13,14,16,20],exercis:10,exist:[4,10],expand:10,expect:[2,3,14,20],experi:[7,14],explain:15,explan:7,explor:7,express:[0,1,2,3,4,10,12,13,15,16,19,20],expression_to_str:20,extend:15,extra:[5,6],extract:[10,11,17],extrem:7,extrememli:7,f_g:15,f_in:15,f_out:15,f_python:15,facet:0,facil:7,fact:18,factor:[2,5,7,10,15],factori:17,fail:[2,3,10,18],fairli:15,fals:[2,3,5,12,15],far:[8,10,12,15],fascin:0,fear:[10,15],few:[5,7,8,11],fewer:[3,7],fg_in:15,fg_out:15,fib:6,fib_gen:6,fibonacci:17,figur:[2,3,10,12],filter:10,fin:5,find:[2,3,5,6,14,15,17],finder:8,fine:[0,5,10,15],first:[3,6,7,8,10,11,12,13,14,16,17],first_two:[3,10],fit:[5,7],five:[5,7,17],fix:[2,3,12],flatten:[7,14],flexibl:17,floatjoytyp:15,floor:3,floordiv:5,flow:7,follow:[0,2,3,7,9,12,14,15,16],foo:[7,9,10,15],foo_ii:9,form:[2,3,4,5,6,12,14,15,20],forman:7,format:[15,17,19],formula:[0,5,17],forth:[7,15],forum:0,found:7,four:[2,3,5,6,7,10,17],fourteen:5,fourth:[2,3,10,12],fractal:7,fraction0:7,fraction:[2,7],frame:12,framework:7,free:[4,7,10],freeli:2,from:[0,1,2,3,5,6,7,8,10,11,12,13,14,15,16,17,20],front:[2,3,12],full:5,fun:17,func:15,functionwrapp:3,funtion:10,further:[8,17],g_in:15,g_out:15,garbag:7,gari:10,gcd:7,gener:[0,2,4,12,15,17,20],generated_librari:3,genrec:[3,7,10,12,14],geometr:5,get:[2,4,5,6,7,11,12,15,17],getitem:3,getrecursionlimit:20,getsourc:7,ghc:4,give:[4,5,10,12,14,15,20],given:[2,3,5,6,8,10,12,16,17],global:15,glue:7,going:[10,11,14,15,16],good:[5,10,15],grab:[3,15],grammar:18,grand:7,great:[0,7,17],greater:20,group:0,gsra:8,guard:10,had:[5,16],haiku:7,half:[5,16],hand:[7,13,15,17],handi:[8,15],handl:[10,15,20],happen:[7,15],hard:[15,16],hardwar:4,has:[0,2,6,7,8,9,10,12,15,16,20],hash:15,haskel:4,have:[2,3,5,6,7,8,9,12,13,15,16,17,20],head:20,help:[7,10,12,15],help_:3,helper:3,herd:7,here:[5,6,10,14,15,16],hide:10,hierarchi:15,higher:[7,10],highli:7,histori:19,hmm:10,hoist:3,hold:[5,15],hood:10,hope:[0,5,7,17],hopefulli:12,host:17,how:[0,4,8,10,12,15,16,17],howev:[12,13,15],html:[2,3,6,11,12,17],http:10,huet:16,huge:10,hugh:[8,14],human:7,hylomorph:17,hypothet:2,id_:3,idea:[4,5,7,15],ident:[3,12],if_not_empti:10,ift:[3,10,12,14],ignor:[3,10,15],illustr:12,imagin:16,imap:15,imit:14,immedi:12,immut:[7,10],imper:12,implement:[0,1,2,3,4,7,9,10,12,13,17],implicit:7,includ:[4,10,14],inclus:5,incom:20,incompat:9,incorpor:11,increas:5,increment:[3,4,5,9],index:[0,7,15,20],indexerror:20,indic:[14,15],ineffici:15,infer:[0,17],inform:[3,15],infra:[3,6,7,10,11,13,14,17],infrastructur:3,initi:[2,3,7,8,10],inlin:10,inner:15,inproceed:15,input:[1,8,15],inscrib:3,insight:12,inspect:7,instal:0,instanti:[4,19],instead:[5,6,10,12,15,16,20],integ:[2,3,7,12,14,15],integr:3,intend:[0,7],interact:[7,17],interest:[0,5,10,15,17],interlud:17,intermedi:12,intern:[0,15,19,20],interpret:[0,4,9,13,17,18,19],interrupt:7,interv:[4,5],intjoytyp:15,introduc:9,introduct:0,intuit:15,invari:3,involv:15,ipf:7,isinst:15,isn:[10,16],issubclass:15,item:[2,3,7,10,12,14,15,17,20],iter:[1,3,7,12,14,15,17,20],iter_stack:[13,20],iteritem:15,itertool:15,its:[0,2,3,4,5,7,10,12,14,15,20],itself:[0,2,7,10,15],j05cmp:[2,3,12],jaanu:15,job:17,john:[8,14],joi:[2,4,9,10,11,13,15],join:15,joypi:[7,16],junk:15,jupyt:17,just:[0,2,3,6,7,9,10,12,14,15,16],keep:[10,11,15,16],kei:[14,17],kevin:0,key_n:10,keyerror:[10,15],kind:[2,4,7,10,12,14],kleen:14,know:[5,10],known:4,l_kei:10,l_left:10,l_right:10,l_valu:10,label:15,lambda:[4,15],languag:[4,7,9,10,13,15],larger:20,largest:3,last:[5,10,12,15],lastli:6,later:[7,14,15],law:2,lazi:15,lazili:8,lcm:5,lead:7,leaf:10,lean:7,learn:0,least:[2,5,12,15,20],least_fract:7,leav:5,left:[7,11,12,14,15,16,19,20],leftov:12,len:15,length:[3,5,20],lens:12,less:[5,6,7,12,15,20],let:[6,8,10,11,12,14,15,16],level:[4,10],librari:[0,13],like:[2,3,5,7,14,15,17,18],limit:15,line:[3,7,10,11,19],linear:20,link:0,linux:0,list:[0,3,5,7,8,10,12,14,16,19],list_to_stack:20,liter:[1,10,14,15,16,18],littl:[6,10,15,17],live:17,lkei:14,load:[5,7],local:15,locat:2,locu:19,log_2:10,logic:[0,5],longer:[10,15],look:[6,7,8,10,11,15],lookup:7,loop:[0,1,3,5],lose:15,lot:[7,10,16],love:5,low:4,lower:5,lowest:10,machin:0,machineri:[10,15],macro:7,made:[0,7,15,16],magic:15,mai:[2,12],mail:0,main:[0,3,7,11,15,16],mainloop:9,maintain:16,major:9,make:[2,3,4,5,7,10,12,13,14,15,16,17],make_gener:8,manfr:[0,2,3,4,12],mani:[0,7,15],manipul:15,manner:11,map:[1,3,5,7,9,12,14,15],map_:3,marker:7,mask:[5,6],match:[0,1],materi:0,math:[0,7,8,10,11,15],mathemat:7,matter:[5,8,10,14],max_:3,maximum:3,mayb:10,mean:[4,5,7,8,10,12,14,20],meant:[7,10,12,14],member:[2,3,12],mental:7,mention:2,mercuri:0,mess:15,meta:[7,10,13],method:[0,3,7,15,17,19],midpoint:5,might:[4,6,10,15],mike:10,million:6,min_:3,mind:15,minimum:3,minor:10,minu:3,mirror:0,miscellan:0,mix:7,mod:3,model:[4,7],modern:0,modif:6,modifi:[7,10,16],modul:[0,1,3,7,18],modulu:7,moment:15,month:7,more:[0,3,4,5,6,7,8,12,13,14,15,18,20],most:15,mostli:0,move:10,movement:2,much:[5,6,10,12,15],muck:10,mul:[7,11,16,19],multi:3,multipl:17,must:[2,3,5,9,12,14,15],myself:15,n1001:15,n1002:15,n1003:15,name:[1,3,7,9,10,12,15,16,17,18,20],natur:[5,6,10],navig:16,nearli:15,neat:10,neato:15,necessarili:15,need:[2,3,5,6,8,9,10,12,15],neg:[3,11],nest:[3,7,10,16],network:7,never:[9,12],new_def:15,new_kei:10,new_valu:10,newton:[0,17],next:[5,14,15],nice:[0,12,20],niether:2,node:[14,17],node_kei:10,node_valu:10,non:14,none:[1,3,15],nope:14,notat:[7,10],note:[2,5,8,10,12,15,20],notebook:[5,6,7,15,16,17],notebook_preambl:[2,5,6,8,10,11,12,13,14,15,16],noth:[2,10],notic:5,now:[5,6,7,12,13,14,15,17],nth:[3,20],nullari:[7,10],number:[1,2,3,5,6,8,20],numberjoytyp:15,numer:15,object:[15,18],observ:5,obviou:[6,15],occur:10,odd:[5,6],off:[2,3,5,6,11,16],old:[2,13],old_k:10,old_kei:10,old_valu:10,omit:[12,15],onc:[3,9,10],one:[2,3,5,6,10,12,14,15,19,20],ones:[6,15],onli:[2,3,5,10,12,15,16,20],onto:[1,2,3,7,12,20],open:[7,15],oper:[3,7,10,12,20],oppos:15,optim:10,option:[1,7,10,20],order:[0,2,3,7,12,15,17,20],org:[0,10],origin:[0,1,2,3,10,16],other:[0,2,3,4,7,10,12,14,15,20],otherwis:[3,5,6,10,14,15],our:[5,6,7,8,12,14,15],out:[2,3,4,5,6,7,8,10,11,12,15,16],outcom:14,output:[8,12,15],outsid:4,over:[3,4,5,6,7,8,10,11,14,15,17],overhaul:15,own:[10,15],pack:20,packag:[0,7],page:[0,10,15,20],pair:[2,3,5,6,10,15],palidrom:5,palindrom:5,pam:7,paper:[4,7,12,16],parallel:2,paramet:[1,2,3,12,13,18,19,20],parameter:17,paramorph:12,parenthes:[10,20],pariti:6,pars:[0,3,7],parse_definit:3,parseerror:18,parser:[0,15],part:[2,3,8,12,14,15],partial:15,particular:16,pass:[0,10,15,19],path:17,pattern:[5,14,17],pe1:[5,6],pe2:6,pearl:16,pend:[3,7,12,16,19],peopl:17,per:[7,14],perform:15,perhap:6,period:7,permit:[15,20],permut:15,persist:10,phase:2,pick:[5,6,20],pickl:7,pictur:10,piec:12,pip:0,place:[3,5,7],plai:0,plu:3,plug:[6,12,14],point:[4,7,10,12],pointless:2,pop:[3,5,6,7,10,12,13,14,20],popd:[3,7,8,10,13,15],popdd:[3,6,11,15],popop:[3,5,6,7,8,10,14,15],popopd:3,popopdd:3,posit:[3,5,7,12],possibilit:10,possibl:[10,14,15,17],post:7,poswrd:15,power:7,pragmat:5,preambl:8,precis:[0,1],pred:[3,15],predic:[2,3,6,12],prefix:[15,19],preserv:[4,14],pretti:[8,10,11,14,15,19,20],pretty_print:0,previou:7,prime:8,primit:[2,3,15,17],primrec:[3,6,7,8,12],print:[0,1,2,3,15,19,20],probabl:[6,7,10,15],problem:[7,15,17],proc_curr:10,proc_left:10,proc_right:10,proce:5,process:[7,14,15,19],produc:[5,10,12,14,15],product:[6,7],program:[0,2,3,6,7,8,10,12,16],programm:15,project:17,prompt:7,proper:[2,3,12],properti:0,provid:[0,3,4,7],pun:[0,7],punctuat:15,pure:0,puriti:7,purpos:7,push:[2,3,7,12,16,20],pushback:7,put:[1,2,6,7,15,17,20],pypi:0,python:[0,2,3,10,12,16,17,18,20],quadrat:[0,17],queri:[10,14],query_kei:14,queu:12,quit:[0,1,14],quot:[0,3,6,7,10,11,12,14,15,16,19],quotat:[2,3,12],quotient:3,r_kei:10,r_left:10,r_right:10,r_valu:10,rais:[10,15,18,20],rang:[7,15],range_revers:12,range_to_zero:7,ranger:12,ranger_revers:12,raphson:8,rather:[5,7,12,14],ratio:7,reach:[5,6,12],read:[0,1,5,6,10,15,16],readabl:13,reader:10,readi:15,real:10,realiz:[4,10],rearrang:[2,10,15],reason:[5,7,15],rebuild:[14,16],rec1:[2,3,12],rec2:[2,3,12],recogn:18,record:[7,19],recur:[12,15],recurs:[0,2,3,6,7,8,15,17,20],recus:7,redefin:17,redistribut:[3,7],reduc:[2,15],redund:20,refactor:[7,9],refer:[0,2],regist:2,regular:18,reimplement:17,relat:15,releas:9,remain:[2,7,9],remaind:[3,8],remind:15,remov:[3,10,15,20],render:17,repeat:5,repeatedli:5,repl:[0,1],replac:[0,2,3,6,11,12,14,15,16,17,20],repositori:0,repr:15,repres:[2,7,10,18,19],represent:20,reprod:6,repurpos:15,requir:20,resembl:7,respect:5,rest:[3,5,6,7,10,12,16,17,20],rest_two:10,restor:2,restrict:15,result:[1,2,3,5,10,11,12,14,15,16],resum:7,retain:15,retir:2,retri:7,reus:[10,15],revers:[3,5,6,12,15,16,20],revisit:15,rewrit:[3,7,15],rewritten:7,rid:10,right:[6,7,11,14,15,17,19,20],rightest:10,rightmost:5,rkei:14,roll:[3,8,10,14],roll_dn:15,roll_down:15,roll_up:15,rolldown:3,rollup:3,root:[3,8,11],round:15,rrest:[3,15],rule:17,run:[0,1,3,5,7,8,10,11,12,14,16],runtimeerror:20,sai:[6,10,11,14,15],same:[2,4,5,10,15,20],sandwich:[2,3,12],save:[2,5,7],scan:3,scanner:[7,18],scenario:16,scope:[6,10],search:[0,10],second:[3,7,10,12,14,20],section:12,see:[0,6,7,8,9,11,12,13,15,16,19],seem:[0,5,7,14,15],seen:[15,16],select:3,self:15,semant:[2,3,7,9,10,15],semi:7,send:7,sens:[0,2,5,15,16],separ:[7,15],seq:15,sequenc:[0,1,2,3,5,7,10,12,13,15,16,17,18],sequence_to_stack:15,seri:[5,6,10,16],set:[2,3,12,17],seven:[5,6],sever:[0,4,7,12],share:[3,7],shelf:2,shift:[5,6],shorter:17,shorthand:10,should:[2,3,5,10,12,15],shouldn:7,show:[4,16],shunt:[3,16],side:[10,15],signifi:[7,10],similar:[10,14,15],simon:7,simpl:[7,12,15,20],simplefunctionwrapp:[3,13,15],simpler:14,simplest:[15,17],simpli:4,simplifi:[5,10,16],sinc:[2,5,10],singl:[3,6,7,13,15,18],situ:10,situat:10,six:[5,6,7],sixti:[5,6],size:[7,17],skeptic:7,skip:15,slight:8,slightli:[10,12,15],smallest:3,smart:10,softwar:7,solei:2,solut:[5,6],solvabl:7,some:[2,3,6,7,10,12,14,15,17,20],somehow:[10,15],someth:[2,9,10,17],sometim:10,somewher:[10,17],sort:[3,10,15],sort_:3,sourc:[0,1,3,15,17,18,19,20],space:[5,19],span:5,special:[6,10,15,17],specif:[0,4],specifi:10,speed:13,spell:14,sphinx:[17,20],spirit:[0,1,14],sqr:[7,8,11,16],sqrt:[3,8,15],squar:[3,8,15,18],stack:[0,1,3,5,6,8,10,11,12,13,14,16,17,18,19],stack_concat:15,stack_effect_com:15,stack_to_str:20,stacki:15,stackjoytyp:15,stage:14,stai:[0,1],stand:4,standard:[7,10],star:14,stare:10,start:[5,6,7,8,10,12,14],state:7,statement:3,step:[3,5,7,10,13,15,16,17],still:[10,15],stop:10,storag:[5,10],store:[5,12],stori:12,str:[1,15,18,19,20],straightforward:[1,6,8,17],stream:5,stretch:10,string:[1,2,3,7,15,16,18,19,20],structur:[7,14,15,16,17,20],stuff:[10,15],stuncon:3,stununcon:3,style:[0,4,15],sub:9,subclass:7,subject:[15,16],subset:15,substitut:[10,15],subtract:5,subtyp:17,succ:[3,15],success:8,suffic:15,suffici:10,suffix:15,suggest:[4,10],suitabl:[3,4,5],sum:[3,6,7,11,12,13,14],sum_:3,summand:5,sumtre:14,suppli:[10,18],support:[7,19,20],suspect:2,swaack:[3,11,13,16],swap:[3,5,6,7,8,10,12,13,14,16],swon:[3,6,7,12,14,15,16],swoncat:[6,7,8,12,14],swuncon:12,symbol:[2,3,15,16,17,18],symmetr:[5,10],syntact:7,syntax:[7,20],sys:20,system:[7,10],tabl:15,tag:15,tail:[10,15,17,20],take:[3,5,7,8,10,12,15,20],talk:[7,10,20],target:16,tast:4,tbd:[7,15],tear:12,technic:2,techniqu:[4,16],technolog:2,temporari:16,ten:5,term:[1,2,7,8,12,15,17,18,20],termin:[2,3,12],ternari:7,test:[2,3,12],text:[0,1,3,15],text_to_express:[7,18],textual:7,than:[0,3,5,6,7,8,12,14,20],thei:[2,5,6,7,10,12,15,16,18,20],them:[2,3,5,6,10,12,15,16,17],themselv:15,theori:[2,3,12],therefor:6,thi:[0,1,2,3,4,5,6,7,8,11,12,14,15,16,17,18,19,20],thing:[2,6,10,12,15,16,18,20],think:[2,5,7,10,12,14],third:[3,6,7,10],thirti:5,those:[2,3,10,12,15,17],though:5,thought:7,thousand:5,thread:2,three:[2,3,5,7,10,11,14,15,17],through:[1,5,7,14,15,16,20],thun:[2,3,4,9,12],thunder:7,time:[3,5,7,8,10,12,15,16],titl:15,to_set:10,todai:7,todo:[7,18],togeth:[6,7,15,17],token:18,toler:17,too:[12,15],tool:[7,15],top:[2,3,7,12,15,19,20],total:5,tower:15,trace:[0,7,11,12,16,17,20],traceprint:19,track:[11,15,16],tracker:0,transform:4,translat:[4,11,15],travers:[0,17],treasur:0,treat:[0,2,3,12,17],treatment:6,tree:[0,7,17],treegrind:17,treestep:[0,17],tri:5,triangular_numb:12,trick:[5,15],tricki:15,trobe:0,trove:0,truthi:[3,7],tuck:[3,7,15],tupl:[3,7,15,20],turn:[2,3],twice:[10,12],two:[2,3,5,7,8,10,11,12,14,15,16,17,20],type:[0,1,4,7,10,12,17,18,19,20],typeerror:15,typeless:15,typic:[2,3,11,12],unari:7,unarybuiltinwrapp:3,unbalanc:[10,18],unchang:10,uncompil:15,uncon:[3,6,7,10,12,14,16],under:[2,3,7,10],underli:15,underscor:15,understand:[0,10],undistinguish:10,undocu:7,unfortun:20,unif:15,uniqu:[3,10,15],unit:[7,12],univers:[0,7],unnecessari:17,unnecesssari:15,unpack:[2,3,10,20],unpair:5,unquot:[7,14],unstack:[3,15],unswon:3,untangl:12,until:6,unus:5,unusu:10,updat:[0,17],usag:7,use:[0,2,3,4,5,6,7,8,9,10,11,12,13,14,16,17,20],used:[3,4,7,10,12,16,18,20],useful:0,user:14,uses:[2,5,12],using:[3,6,10,11,12,14,16],usual:[0,2,12],util:[0,3,13],valid:15,valu:[0,2,3,5,7,8,11,12,13,14,15,17,20],value_n:10,valueerror:[15,20],variabl:17,variant:10,variat:[12,17],varieti:[4,7],variou:0,vener:20,verbos:4,veri:[0,1,4,7,10,20],versa:[2,15],version:[0,1,2,6,9,14,16,17],via:7,vice:[2,15],view:[10,17],viewer:[1,7,9,19],von:[0,2,3,4,12],wai:[0,2,3,4,5,7,12,13,15],want:[2,5,6,8,10,12,15],warranti:[3,7],wash:7,wast:7,web:20,websit:[0,5],welcom:7,well:[0,4,7,8,10,15,18],were:[7,15,16],what:[2,3,4,7,10,12,14,15,19],whatev:[2,3,12,14,20],when:[5,6,7,10,12,15,16,18,20],where:[2,3,7,10,12,17,20],whether:12,which:[0,1,3,5,7,8,10,12,14,15,16,20],whole:[2,3,5,12,14,15],whose:6,why:[8,14],wiki:10,wikipedia:[0,10,16],wildli:7,wind:7,wire:12,within:[7,10,13,17],without:[2,7,10,11],won:[10,15,20],word:[0,3,5,7,12,16],work:[0,3,5,6,7,8,10,11,12,14,15,16,20],worth:5,would:[2,5,6,7,8,10,12,15,16,20],wrap:[3,7],wrapper:15,write:[4,8,10,12,14,15,16,17,20],written:[0,1,8,10,13,15,20],wrong:2,wrote:15,xrang:15,year:[7,15],yet:[10,15,16],yield:[2,3,12,20],you:[0,2,3,5,6,7,9,10,11,12,13,14,15,16,19,20],your:[2,3,7,12,15],yourself:[7,10],zero:[3,10,12,14,18,20],zip:[5,15],zip_:3,zipper:[0,17],zstr:16},titles:["Thun 0.2.0 Documentation","Joy Interpreter","Functions Grouped by, er, Function with Examples","Function Reference","Categorical Programming","Developing a Program in Joy","Using <code class=\"docutils literal notranslate\"><span class=\"pre\">x</span></code> to Generate Values","Thun: Joy in Python","Newton\u2019s method","No Updates","Treating Trees I: Ordered Binary Trees","Quadratic formula","Recursive Combinators","Replacing Functions in the Dictionary","Treating Trees II: <code class=\"docutils literal notranslate\"><span class=\"pre\">treestep</span></code>","Type Inference","Traversing Datastructures with Zippers","Essays about Programming in Joy","Parsing Text into Joy Expressions","Tracing Joy Execution","Stack or Quote or Sequence or List\u2026"],titleterms:{"abstract":15,"case":[8,10],"function":[2,3,7,8,10,12,13,14,15],"long":13,"new":10,"p\u00f6ial":15,"void":2,"while":2,Adding:10,One:[6,10],The:[5,7,10,12,14],There:7,Using:6,With:14,about:17,add:[2,10],adding:10,address:16,altern:14,ana:12,analysi:5,anamorph:[2,12],app1:2,app2:2,app3:2,appendix:[10,12],approxim:8,argument:15,auto:3,averag:2,base:[8,10],binari:[2,10,14],both:10,branch:[2,10],can:10,cata:12,catamorph:12,categor:4,chatter:2,child:10,choic:2,clear:2,cleav:2,cmp:10,code:[7,10],combin:[2,10,12,15],comment:15,compar:10,comparison:2,compil:[6,15],compile_:15,compos:15,comput:8,con:[2,15],concat:[2,15],conclus:12,consecut:8,continu:7,current:10,datastructur:[7,10,16],deal:15,defin:[10,14],definit:11,delabel:15,delet:10,deriv:[11,12,14],design:12,determin:16,develop:5,dialect:0,dictionari:13,dip:[2,16],dipd:2,dipdd:2,direco:6,disenstacken:2,distinguish:15,div:2,doc_from_stack_effect:15,document:0,doe:10,down_to_zero:2,drop:2,dup:[2,15],dupd:2,dupdip:2,effect:15,els:[10,15],empti:10,enstacken:2,equal:10,essai:17,euler:[5,6],eval:7,even:6,exampl:[2,7,10,12,14,15],execut:19,express:[7,18],extract:14,factori:12,fibonacci:6,filter:5,find:[8,10,12],first:[2,5,15],five:6,flatten:2,flexibl:14,floordiv:2,formula:11,found:10,four:12,fun:12,further:5,gcd:2,gener:[3,5,6,8],genrec:2,get:[10,14],getitem:2,given:14,greater:10,group:2,have:[10,14],help:2,highest:10,host:0,how:[5,6],hylo:12,hylomorph:12,identifi:15,ift:2,implement:15,indic:0,infer:15,inferenc:15,inform:0,infra:[2,16],integ:5,interest:6,interlud:10,intern:18,interpret:[1,7,15],item:16,iter:[5,10],joi:[0,1,3,5,7,12,16,17,18,19,20],just:5,kei:10,languag:0,least_fract:2,left:10,less:10,let:5,librari:[3,7,15],like:10,list:[2,15,20],literari:7,littl:5,logic:2,loop:[2,7],lower:10,lshift:2,make:[6,8],mani:5,map:2,math:2,method:8,min:2,miscellan:2,mod:2,modifi:15,modulu:2,more:10,most:10,mul:[2,15],multipl:[5,6],must:10,name:11,neg:2,newton:8,next:8,node:10,non:10,now:10,nullari:2,number:[12,15],one:7,onli:7,order:[10,14],osdn:0,our:10,over:2,pack:5,pam:2,para:12,parameter:[10,14],pars:[2,18],parser:[7,18],pass:7,path:16,pattern:12,per:10,pop:[2,15],popd:2,popop:2,pow:2,power:6,pred:2,predic:[5,8,10,14],pretty_print:19,primit:12,primrec:2,print:7,problem:[5,6],process:10,product:2,program:[4,5,11,14,17],project:[0,5,6],pure:7,put:[10,11,14],python:[7,13,15],quadrat:11,quick:0,quot:[2,20],rang:[2,5,12],range_to_zero:2,read:7,recur:[8,10],recurs:[10,12,14],redefin:[10,14],refactor:[5,10],refer:3,regular:7,reimplement:14,relabel:15,rem:2,remaind:2,remov:2,render:5,repl:7,replac:[10,13],repres:15,reset:6,rest:[2,15],revers:2,right:[10,16],rightmost:10,roll:[2,15],rolldown:2,rollup:2,rshift:2,rule:15,run:[2,6],second:[2,15],select:2,sequenc:[6,20],set:[8,10,15],shorter:13,should:7,shunt:2,simplest:5,size:[2,13],someth:15,sourc:10,special:12,sqr:[2,15],sqrt:[2,11],stack:[2,7,15,20],start:0,step:[2,12,14],straightforward:11,structur:10,style:7,sub:[2,10],subtyp:15,succ:2,sum:[2,5],swaack:2,swap:[2,15],swon:2,swoncat:2,symbol:[7,12],tabl:0,tail:12,take:2,term:[5,6,14],ternari:2,text:18,than:10,them:11,thi:10,third:[2,15],three:6,thun:[0,7],time:[2,6],togeth:[10,11,14],token:7,toler:8,trace:[13,19],traceprint:7,travers:[10,14,16],treat:[10,14],tree:[10,14,16],treegrind:14,treestep:14,triangular:12,truediv:2,truthi:2,tuck:2,two:6,type:15,unari:2,uncon:[2,15],unifi:15,unit:2,unnecessari:5,unquot:2,unstack:2,updat:[9,15],use:15,util:[19,20],valu:[6,10],variabl:11,variat:6,version:[5,10,13,15],view:7,within:8,word:2,write:11,xor:2,zero:6,zip:2,zipper:16}})
\ No newline at end of file
+Search.setIndex({docnames:["index","joy","lib","library","notebooks/Categorical","notebooks/Developing","notebooks/Generator_Programs","notebooks/Intro","notebooks/Newton-Raphson","notebooks/NoUpdates","notebooks/Ordered_Binary_Trees","notebooks/Quadratic","notebooks/Recursion_Combinators","notebooks/Replacing","notebooks/Treestep","notebooks/Types","notebooks/Zipper","notebooks/index","parser","pretty","stack"],envversion:52,filenames:["index.rst","joy.rst","lib.rst","library.rst","notebooks/Categorical.rst","notebooks/Developing.rst","notebooks/Generator_Programs.rst","notebooks/Intro.rst","notebooks/Newton-Raphson.rst","notebooks/NoUpdates.rst","notebooks/Ordered_Binary_Trees.rst","notebooks/Quadratic.rst","notebooks/Recursion_Combinators.rst","notebooks/Replacing.rst","notebooks/Treestep.rst","notebooks/Types.rst","notebooks/Zipper.rst","notebooks/index.rst","parser.rst","pretty.rst","stack.rst"],objects:{"joy.joy":{joy:[1,1,1,""],repl:[1,1,1,""],run:[1,1,1,""]},"joy.library":{"void":[3,1,1,""],BinaryBuiltinWrapper:[3,1,1,""],DefinitionWrapper:[3,2,1,""],FunctionWrapper:[3,1,1,""],SimpleFunctionWrapper:[3,1,1,""],UnaryBuiltinWrapper:[3,1,1,""],add_aliases:[3,1,1,""],app1:[3,1,1,""],app2:[3,1,1,""],app3:[3,1,1,""],b:[3,1,1,""],branch:[3,1,1,""],choice:[3,1,1,""],clear:[3,1,1,""],cmp_:[3,1,1,""],concat_:[3,1,1,""],cond:[3,1,1,""],dip:[3,1,1,""],dipd:[3,1,1,""],dipdd:[3,1,1,""],divmod_:[3,1,1,""],drop:[3,1,1,""],dupdip:[3,1,1,""],floor:[3,1,1,""],genrec:[3,1,1,""],getitem:[3,1,1,""],help_:[3,1,1,""],i:[3,1,1,""],id_:[3,1,1,""],ifte:[3,1,1,""],infra:[3,1,1,""],initialize:[3,1,1,""],inscribe:[3,1,1,""],loop:[3,1,1,""],map_:[3,1,1,""],max_:[3,1,1,""],min_:[3,1,1,""],parse:[3,1,1,""],pm:[3,1,1,""],pred:[3,1,1,""],remove:[3,1,1,""],reverse:[3,1,1,""],select:[3,1,1,""],sharing:[3,1,1,""],shunt:[3,1,1,""],sort_:[3,1,1,""],sqrt:[3,1,1,""],step:[3,1,1,""],succ:[3,1,1,""],sum_:[3,1,1,""],swaack:[3,1,1,""],take:[3,1,1,""],times:[3,1,1,""],unique:[3,1,1,""],unstack:[3,1,1,""],warranty:[3,1,1,""],words:[3,1,1,""],x:[3,1,1,""],zip_:[3,1,1,""]},"joy.library.DefinitionWrapper":{add_def:[3,3,1,""],add_definitions:[3,3,1,""],parse_definition:[3,3,1,""]},"joy.parser":{ParseError:[18,4,1,""],Symbol:[18,2,1,""],text_to_expression:[18,1,1,""]},"joy.utils":{generated_library:[3,0,0,"-"],pretty_print:[19,0,0,"-"],stack:[20,0,0,"-"]},"joy.utils.generated_library":{ccons:[3,1,1,""],cons:[3,1,1,""],dup:[3,1,1,""],dupd:[3,1,1,""],dupdd:[3,1,1,""],first:[3,1,1,""],first_two:[3,1,1,""],fourth:[3,1,1,""],over:[3,1,1,""],pop:[3,1,1,""],popd:[3,1,1,""],popdd:[3,1,1,""],popop:[3,1,1,""],popopd:[3,1,1,""],popopdd:[3,1,1,""],rest:[3,1,1,""],rolldown:[3,1,1,""],rollup:[3,1,1,""],rrest:[3,1,1,""],second:[3,1,1,""],stack:[3,1,1,""],stuncons:[3,1,1,""],stununcons:[3,1,1,""],swap:[3,1,1,""],swons:[3,1,1,""],third:[3,1,1,""],tuck:[3,1,1,""],uncons:[3,1,1,""],unswons:[3,1,1,""]},"joy.utils.pretty_print":{TracePrinter:[19,2,1,""]},"joy.utils.pretty_print.TracePrinter":{go:[19,5,1,""],viewer:[19,5,1,""]},"joy.utils.stack":{concat:[20,1,1,""],expression_to_string:[20,1,1,""],iter_stack:[20,1,1,""],list_to_stack:[20,1,1,""],pick:[20,1,1,""],stack_to_string:[20,1,1,""]},joy:{joy:[1,0,0,"-"],library:[3,0,0,"-"],parser:[18,0,0,"-"]}},objnames:{"0":["py","module","Python module"],"1":["py","function","Python function"],"2":["py","class","Python class"],"3":["py","classmethod","Python class method"],"4":["py","exception","Python exception"],"5":["py","method","Python method"]},objtypes:{"0":"py:module","1":"py:function","2":"py:class","3":"py:classmethod","4":"py:exception","5":"py:method"},terms:{"0b11100111011011":5,"23rd":15,"4b4cb6ff86e5":15,"5bkei":10,"5eb7ac5ad2c2":15,"\u03b5":8,"abstract":[7,10,17],"boolean":[2,3,7,10],"break":[7,15],"byte":5,"case":[2,3,12,14,15,20],"class":[3,7,15,18,19,20],"default":[3,6,10,20],"export":[3,18],"final":[2,10,12],"float":[3,7,15,16,18],"function":[0,1,4,5,6,9,11,16,17,18,19,20],"g\u00e9rard":16,"import":[2,5,6,8,10,11,12,13,14,15,16],"int":[6,7,12,15,16,18,20],"long":[10,17],"new":[2,3,6,7,9,12,13,15],"p\u00f6ial":17,"p\u00f6ial06typingtool":15,"public":9,"return":[1,3,5,7,10,12,13,14,15,18,19,20],"static":[2,9],"super":15,"switch":[2,15],"throw":10,"true":[2,3,5,12,15],"try":[6,8,11,12,14,15],"void":[0,3],"while":[3,7,10,15,18,20],Adding:[7,13,17],And:[5,6,8,10,12,15,16,20],But:[0,4,5,6,7,10,13,15],CPS:7,For:[2,3,10,12,13,15,17,20],Has:3,Its:3,One:[2,7,15,17],TOS:[2,3],That:[5,10],The:[0,1,2,3,4,6,8,9,11,15,16,17,18,20],Then:[2,3,10,11,12,15],There:[11,12,14,15,20],These:[15,17,20],Use:[3,8,12],Using:[0,8,10,17],With:[8,12,15,17],_1000:15,__add__:15,__class__:15,__eq__:15,__ge__:15,__hash__:15,__init__:15,__main__:15,__radd__:15,__repr__:15,__str__:19,_names_for:15,_to_str:15,_tree_add_:10,_tree_add_e:10,_tree_add_p:10,_tree_add_r:10,_tree_add_t:10,_tree_delete_:10,_tree_delete_clear_stuff:10,_tree_delete_del:10,_tree_delete_r0:10,_tree_delete_r1:10,_tree_delete_rightmost:10,_tree_delete_w:10,_tree_get_:10,_tree_get_p:10,_tree_get_r:10,_tree_get_t:10,_tree_iter_order_curr:10,_tree_iter_order_left:10,_tree_iter_order_r:10,_tree_iter_order_right:10,_tree_t:10,_treestep_0:14,_treestep_1:14,_uniqu:15,_within_b:8,_within_p:8,_within_r:8,a10001:15,a10002:15,a10003:15,a10004:15,a1001:15,abbrevi:14,abil:15,abl:15,about:[0,7,10,16,20],abov:[0,5,8,10,12,15],abs:8,absolut:7,accept:[1,2,3,5,6,7,10,11,13,14,15,16],accordingli:10,accumul:5,action:[7,13,15,16],actual:[2,5,7,10,15],adapt:17,add:[3,5,6,7,13,15,19],add_alias:3,add_def:3,add_definit:[3,10,14],added:[4,10],adding:[9,15],addit:[0,2,3,5,7,12,13,14],address:17,adjust:10,after:[5,6,7,12],afterward:7,again:[2,3,5,7,10,12,15],aggreg:16,ahead:15,aka:[7,16],albrecht:0,algorithm:[7,15],alia:3,alias:[3,7],align:[7,19],all:[3,5,6,7,10,12,13,14,15,19],alloc:15,allow:[9,10],almost:10,along:[7,12,15],alphabet:3,alreadi:[8,13,15,16],also:[0,5,7,10,15,20],alter:15,altern:[4,15],although:[4,10],altogeth:6,alwai:[5,9,12],amaz:15,among:15,amort:10,analysi:[4,17],anamorph:[7,17],ani:[4,5,7,9,10,15,16,18],annual:7,anonym:10,anoth:[10,15,20],anyjoytyp:15,anymor:15,anystarjoytyp:15,anyth:[2,3,7,15],api:9,app1:3,app2:[3,7,11,12,13],app3:3,app:7,appear:[2,4,5,10],append:15,appendix:17,appli:[2,3,5,6,10,12,15],applic:6,approach:5,approxim:17,archiv:0,aren:16,arg:[2,3],argument:[2,3,7,8,11,12,17,19,20],arithmet:2,ariti:2,around:[5,20],arrang:14,arriv:[6,14],articl:[0,4,6,12],ask:[4,6,15],aspect:0,assert:15,assign:20,associ:10,assum:8,astar:15,asterisk:14,asterix:15,attack:7,attempt:[0,1],attribut:3,attributeerror:15,author:15,auto:0,automat:[4,15],auxiliari:14,avail:[0,15],averag:[7,13],avoid:10,awai:10,awar:2,awkward:[10,12],azur:17,back:10,backward:[9,10,11,14],bag:7,banana:12,barb:12,base:[0,2,3,9,12,14,15],basic:[1,2,3,7,10],becaus:[2,3,7,10,14,15,16,20],becom:[10,14,20],been:[8,9,10,15,16],befor:[6,7,10],begin:[10,14],behavior:[9,14],behaviour:[0,1,15],being:0,below:[2,3,5,6,10,15,16],bespok:7,best:0,better:[5,10,12],between:[0,5],beyond:6,biannual:7,binari:[0,6,7,17],binary_search_tre:10,binarybuiltinwrapp:3,bind:7,bingo:16,bit:[5,6,10,15],block:5,bodi:[2,7,10],body_text:3,booktitl:15,bool:12,borrow:[7,15],both:[2,5,7,11,12,13,15,20],bottom:6,bracket:[7,15,18],branch:[3,5,6,12],breakpoint:7,bring:[5,7,15],bruijn:15,brzozowski:15,btree:[10,14],buck:10,bug:[0,7],build:[6,7,11,12,16,20],built:[11,15],bundl:[2,3,12],burgeon:7,calculu:4,call:[2,7,9,10,12,15,19,20],caller:10,can:[0,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,20],cannot:15,captur:7,card:7,care:[5,20],carefulli:16,carri:[6,10],cartesian:4,catamorph:17,categor:[0,17],categori:4,ccc:4,ccon:[3,10,15],cell:[12,15],certain:[7,20],certainli:10,chain:3,chang:[2,9,10,15,16],charact:16,chat:7,chatter:[0,15],check:[6,8,15],child:14,choic:[3,12],choos:9,chop:11,cinf:10,circuit:4,cite_not:10,classmethod:3,claus:[3,15],clean:15,clear:[3,5,7],clear_stuff:10,cleav:[7,11,13],close:[0,1,4],clunki:[5,15],cmp:[3,14,17],cmp_:3,code:[0,1,4,11,12,15,17],codireco:[6,8],collaps:12,collect:[4,6,7,15],combin:[0,3,5,6,7,8,11,14,16,17],combinatorjoytyp:15,come:[7,10],command:[7,10,15],common:[2,5],compar:[3,4,15],comparison:[0,10],compel:4,compil:[2,4,7,10,13,17],complet:4,complex:[3,15,16],complic:15,composit:15,compound:10,comput:[2,4,5,7,11,15],con:[3,5,6,7,8,10,11,12,14,16,20],conal:4,concat:[3,6,7,14,20],concat_:3,concaten:0,concatin:[0,3,20],conclus:17,concurr:2,cond:[3,10],condit:[3,7],confer:15,conflict:[10,15],conjectur:15,consecut:17,consid:[5,6,10,12,14,15,16],consist:[2,6,7,14],constant:10,constitu:12,constraint:15,construct:15,consum:15,contain:[0,2,3,6,7,12],context:2,conting:10,continu:[0,12,15,16],control:7,conveni:[4,15],convers:15,convert:[12,13,14,15,18,20],cool:10,copi:[2,3,5,10,12,14,17],copyright:7,correspond:4,could:[2,4,5,7,9,10,15,16],count:[3,15],counter:[5,15],coupl:14,cours:[5,10],crack:10,crap:15,crash:10,creat:[0,2,3,5,8,10,15],creativ:15,crude:[10,15,18],current:[2,3,7,12,14,15,16,19],custom:9,cycl:[5,6],cython:7,dai:7,data:[2,3,12],datastructur:[0,2,12,15,17,18,20],datatyp:20,ddee30dbb1a6:15,ddididi:16,deal:[0,10],dealt:15,decid:10,declar:15,decor:3,decoupl:12,decrement:3,deduc:[5,15],deeper:0,deepli:4,def:[3,7,12,13,15,20],defaultdict:15,defi:3,defin:[2,3,4,5,6,7,8,9,11,12,13,15,16,17],definit:[2,3,5,6,7,9,10,12,14,15,17],definitionwrapp:[3,10,12,14],deleg:7,delet:17,deliber:15,demonstr:4,depend:[3,10,12],deposit:14,dequot:12,der:10,deriv:[2,3,5,7,8,10,15,17],describ:[3,4,10,12,14,15,18],descript:[5,7],descriptor:15,design:[2,3,10,17],desir:[7,14],destruct:10,detail:[7,10,15],detect:[6,10,12,15],determin:17,develop:[0,6,7,15,17],diagram:5,dialect:1,dict:[1,3,15],dictionari:[0,1,3,7,15,17],differ:[0,4,5,8,10,11,12,20],differenti:4,dig:[10,16],digit:5,dinfrirst:7,dip:[3,5,6,7,8,10,11,12,13,14,15,17],dip_a:15,dip_t:15,dipd:[3,6,7,10,11,12,16],dipdd:[3,10],direco:17,direct:7,directli:[5,14,15,20],disappear:[2,15],discard:[3,6,8,10,12],disciplin:10,disenstacken:7,disk:7,displac:2,displai:15,distiguish:15,ditch:10,div:[3,7],dive:14,divis:10,divmod:3,divmod_:[3,15],doc:[2,3,7,15],document:[17,18,20],doe:[0,1,4,6,7,13,17,19],doesn:[5,9,10,14,15,20],doing:[4,5,7,15,16],domain:[4,15],don:[5,7,10,15],done:[2,5,7,9,15],door:7,dot:19,doubl:[5,7,15],down:[2,8,12,16],down_to_zero:7,dozen:7,draft:[4,9],dream:7,drive:[6,8],driven:5,driver:6,drop:[3,10],dudipd:7,due:15,dup:[3,5,6,7,8,10,11,12,16,20],dupd:[3,15],dupdd:3,dupdip:[3,5,10,11,12],duplic:[3,10,12],durat:2,dure:[2,12],each:[2,3,4,5,7,12,13,14,15,19],easi:[0,10,14,15,16],easier:[3,10],easili:4,edit:17,effect:[2,3,7,16,17],effici:[6,13,16],either:[1,2,3,10,12,15],eleg:[7,10,15],element:2,elif:15,elimin:15,elliott:4,els:[2,3,12,15],embed:[4,10,16],emit:15,empti:[3,7,14,15,20],encapsul:7,enclos:7,encod:6,encount:15,end:[5,10,12,14,15,20],endless:6,enforc:[2,7],engend:7,enough:[7,12,19],enstacken:[6,7,15],enter:7,entir:20,entri:[3,16,19],enumer:15,epsilon:8,equal:[5,14,20],equat:[7,8],ergo:10,err:10,error:[7,18],essai:0,establish:15,etc:[3,14,15,16,18],euler:17,euro:15,eval:[0,15],evalu:[1,2,3,7,8,10,11,12,13,14],event:15,everi:6,everyth:[3,10,11,15],evolv:9,examin:12,exampl:[0,3,5,15,17,18,20],exce:6,except:[7,10,15,18],execut:[0,1,2,3,7,12,13,14,16,20],exercis:10,exist:[4,10],expand:10,expect:[2,3,14,20],experi:[7,14],explain:15,explan:7,explor:7,express:[0,1,2,3,4,10,12,13,15,16,19,20],expression_to_str:20,extend:15,extra:[5,6],extract:[10,11,17],extrem:7,extrememli:7,f1001:15,f_g:15,f_in:15,f_out:15,f_python:15,facet:0,facil:7,fact:18,factor:[2,5,7,10,15],factori:17,fail:[2,3,10,18],fairli:15,fals:[2,3,5,12,15],far:[8,10,12,15],fascin:0,fear:[10,15],few:[5,7,8,11],fewer:[3,7],fg_in:15,fg_out:15,fib:6,fib_gen:6,fibonacci:17,figur:[2,3,10,12],filter:10,fin:5,find:[2,3,5,6,14,15,17],finder:8,fine:[0,5,10,15],first:[3,6,7,8,10,11,12,13,14,16,17],first_two:[3,10],fit:[5,7],five:[5,7,17],fix:[2,3,12],flatten:[7,14],flexibl:17,floatjoytyp:15,floatstarjoytyp:15,floor:3,floordiv:5,flow:7,follow:[0,2,3,7,9,12,14,15,16],foo:[7,9,10,15],foo_ii:9,form:[2,3,4,5,6,12,14,15,20],forman:7,format:[15,17,19],formula:[0,5,17],forth:[7,15],forum:0,found:7,four:[2,3,5,6,7,10,17],fourteen:5,fourth:[2,3,10,12],fractal:7,fraction0:7,fraction:[2,7],frame:12,framework:7,free:[4,7,10],freeli:2,from:[0,1,2,3,5,6,7,8,10,11,12,13,14,15,16,17,20],front:[2,3,12],full:5,fun:17,func:15,functionwrapp:3,funtion:10,further:[8,15,17],g_in:15,g_out:15,garbag:7,gari:10,gcd:7,gener:[0,2,4,12,15,17,20],generated_librari:3,genrec:[3,7,10,12,14],geometr:5,get:[2,4,5,6,7,11,12,15,17],getitem:3,getrecursionlimit:20,getsourc:7,ghc:4,give:[4,5,10,12,14,15,20],given:[2,3,5,6,8,10,12,16,17],global:15,glue:7,going:[10,11,14,15,16],good:[5,10],grab:[3,15],grammar:18,grand:7,great:[0,7,17],greater:20,group:0,gsra:8,guard:10,had:[5,16],haiku:7,half:[5,16],hand:[7,13,15,17],handi:[8,15],handl:[10,15,20],happen:[7,15],hard:[15,16],hardwar:4,has:[0,2,6,7,8,9,10,12,15,16,20],hash:15,haskel:4,have:[2,3,5,6,7,8,9,12,13,15,16,17,20],head:20,help:[7,10,12,15],help_:3,helper:3,herd:7,here:[5,6,10,14,15,16],hide:10,hierarchi:15,higher:[7,10],highli:7,histori:[15,19],hmm:10,hoist:3,hold:[5,15],hood:10,hope:[0,5,7,15,17],hopefulli:12,host:17,how:[0,4,8,10,12,15,16,17],howev:[12,13,15],html:[2,3,6,11,12,17],http:10,huet:16,huge:10,hugh:[8,14],human:7,hylomorph:17,hypothet:2,id_:3,idea:[4,5,7,15],ident:[3,12],if_not_empti:10,ift:[3,10,12,14,15],ignor:[3,10,15],iii:17,illustr:12,imagin:16,imap:15,imit:14,immedi:12,immut:[7,10],imper:12,implement:[0,1,2,3,4,7,9,10,12,13,17],implicit:7,includ:[4,10,14,15],inclus:5,incom:20,incompat:9,incorpor:11,increas:5,increment:[3,4,5,9],index:[0,7,15,20],indexerror:20,indic:[14,15],ineffici:15,infer:[0,17],inform:[3,15],infra:[3,6,7,10,11,13,14,17],infrastructur:3,initi:[2,3,7,8,10],inlin:10,inner:15,inproceed:15,input:[1,8,15],inscrib:3,insight:12,inspect:7,instal:0,instanti:[4,19],instead:[5,6,10,12,15,16,20],integ:[2,3,7,12,14,15],integr:3,intend:[0,7],interact:[7,17],interest:[0,5,10,15,17],interlud:17,intermedi:12,intern:[0,15,19,20],interpret:[0,4,9,13,17,18,19],interrupt:7,interv:[4,5],intjoytyp:15,introduc:9,introduct:0,intstarjoytyp:15,intuit:15,invari:3,invent:15,involv:15,ipf:7,ipython:15,isinst:15,isn:[10,16],issubclass:15,item:[2,3,7,10,12,14,15,17,20],iter:[1,3,7,12,14,15,17,20],iter_stack:[13,15,20],iteritem:15,itertool:15,its:[0,2,3,4,5,7,10,12,14,15,20],itself:[0,2,7,10,15],j05cmp:[2,3,12],jaanu:15,job:17,john:[8,14],joi:[2,4,9,10,11,13],join:15,joypi:[7,16],june:15,junk:15,jupyt:17,just:[0,2,3,6,7,9,10,12,14,15,16],kav:15,keep:[10,11,15,16],kei:[14,17],kevin:0,key_n:10,keyerror:[10,15],kind:[2,4,7,10,12,14,15],kjs:15,kleen:[14,15],kleenestar:15,kleffner:15,know:[5,10],known:4,l_kei:10,l_left:10,l_right:10,l_valu:10,label:15,lambda:[4,15],languag:[4,7,9,10,13,15],larger:20,largest:3,last:[5,10,12,15],lastli:6,later:[7,14,15],law:2,lazi:15,lazili:8,lcm:5,lead:[7,15],leaf:10,lean:7,learn:0,least:[2,5,12,15,20],least_fract:7,leav:5,left:[7,11,12,14,15,16,19,20],leftov:12,len:15,length:[3,5,20],lens:12,less:[5,6,7,12,15,20],let:[6,8,10,11,12,14,15,16],letter:15,level:[4,10],librari:[0,13],like:[2,3,5,7,14,15,17,18],limit:15,line:[3,7,10,11,19],linear:20,link:0,linux:0,list:[0,3,5,7,8,10,12,14,16,19],list_to_stack:20,lit:15,liter:[1,10,14,15,16,18],literatur:15,littl:[6,10,15,17],live:17,lkei:14,load:[5,7],local:15,locat:2,locu:19,log_2:10,logic:[0,5,17],longer:[10,15],look:[6,7,8,10,11,15],lookup:7,loop:[0,1,3,5],lose:15,lot:[7,10,16],love:5,low:4,lower:5,lowercas:15,lowest:10,machin:0,machineri:[10,15],macro:7,made:[0,7,15,16],magic:15,mai:[2,12],mail:0,main:[0,3,7,11,15,16],mainloop:9,maintain:16,major:9,make:[2,3,4,5,7,10,12,13,14,15,16,17],make_gener:8,manfr:[0,2,3,4,12],mani:[0,7,15],manipul:15,manner:11,map:[1,3,5,7,9,12,14,15],map_:3,marker:7,mask:[5,6],match:[0,1],materi:[0,15],math:[0,7,8,10,11,15],mathemat:7,matter:[5,8,10,14],max_:3,maximum:3,mayb:10,mean:[4,5,7,8,10,12,14,15,20],meant:[7,10,12,14],member:[2,3,12],mental:7,mention:2,mercuri:0,mess:15,meta:[7,10,13],meta_compos:15,method:[0,3,7,15,17,19],midpoint:5,might:[4,6,10,15],mike:10,million:6,min_:3,mind:15,minimum:3,minor:10,minu:3,mirror:0,miscellan:0,mix:[7,15],mod:3,mode:15,model:[4,7,15],modern:0,modif:6,modifi:[7,10,16],modul:[0,1,3,7,15,18],modulu:7,moment:15,month:7,more:[0,3,4,5,6,7,8,12,13,14,15,18,20],most:15,mostli:0,move:10,movement:2,much:[5,6,10,12,15],muck:10,mul:[7,11,16,19],multi:3,multipl:17,must:[2,3,5,9,12,14,15],myself:15,n10001:15,n10002:15,n10003:15,n1001:15,n1002:15,n1003:15,name:[1,3,7,9,10,12,15,16,17,18,20],natur:[5,6,10],navig:16,nearli:15,neat:10,neato:15,necessarili:15,need:[2,3,5,6,8,9,10,12,15],neg:[3,11],nest:[3,7,10,16],network:7,never:[9,12],new_def:15,new_f:15,new_kei:10,new_valu:10,newton:[0,17],next:[5,14,15],nice:[0,12,20],niether:2,node:[14,17],node_kei:10,node_valu:10,non:14,none:[1,3,15],nope:14,notat:[7,10],note:[2,5,8,10,12,15,20],notebook:[5,6,7,15,16,17],notebook_preambl:[2,5,6,8,10,11,12,13,14,15,16],noth:[2,10],notic:5,now:[5,6,7,12,13,14,15,17],nth:[3,20],nullari:[7,10],number:[1,2,3,5,6,8,20],numberjoytyp:15,numberstarjoytyp:15,numer:15,object:[15,18],observ:5,obviou:[6,15],obvious:15,occur:10,odd:[5,6],off:[2,3,5,6,11,16],old:[2,13],old_k:10,old_kei:10,old_valu:10,omit:[12,15],onc:[3,9,10],one:[2,3,5,6,10,12,14,15,19,20],ones:[6,15],onli:[2,3,5,10,12,15,16,20],onto:[1,2,3,7,12,20],open:[7,15],oper:[3,7,10,12,20],oppos:15,optim:10,option:[1,7,10,20],order:[0,2,3,7,12,15,17,20],org:[0,10],origin:[0,1,2,3,10,16],other:[0,2,3,4,7,10,12,14,15,20],otherwis:[3,5,6,10,14,15],our:[5,6,7,8,12,14,15],out:[2,3,4,5,6,7,8,10,11,12,15,16],outcom:14,output:[8,12,15],outsid:4,over:[3,4,5,6,7,8,10,11,14,15,17],overhaul:15,own:[10,15],pace:15,pack:20,packag:[0,7],page:[0,10,15,20],pair:[2,3,5,6,10,15],palidrom:5,palindrom:5,pam:7,paper:[4,7,12,16],paradigm:17,parallel:2,paramet:[1,2,3,12,13,18,19,20],parameter:17,paramorph:12,parenthes:[10,20],pariti:6,pars:[0,3,7],parse_definit:3,parseerror:18,parser:[0,15],part:[2,3,8,12,14,17],partial:15,particular:16,pass:[0,10,15,19],path:17,pattern:[5,14,17],pe1:[5,6],pe2:6,pearl:16,pend:[3,7,12,16,19],peopl:17,per:[7,14],perform:15,perhap:6,period:7,permit:[15,20],permut:15,persist:10,phase:2,pick:[5,6,20],pickl:7,pictur:10,piec:12,pip:0,place:[3,5,7],plai:0,plu:3,plug:[6,12,14],point:[4,7,10,12],pointless:2,pop:[3,5,6,7,10,12,13,14,20],popd:[3,7,8,10,13,15],popdd:[3,6,11,15],popop:[3,5,6,7,8,10,14,15],popopd:3,popopdd:3,posit:[3,5,7,12],possibilit:10,possibl:[10,14,15,17],post:7,poswrd:15,power:7,pragmat:5,preambl:8,precis:[0,1],pred:[3,15],predic:[2,3,6,12],prefix:[15,19],preserv:[4,14],pretti:[8,10,11,14,15,19,20],pretty_print:0,previou:7,prime:8,primit:[2,3,15,17],primrec:[3,6,7,8,12],print:[0,1,2,3,15,19,20],probabl:[6,7,10,15],problem:[7,15,17],proc_curr:10,proc_left:10,proc_right:10,proce:5,process:[7,14,15,19],produc:[5,10,12,14,15],product:[6,7,15],program:[0,2,3,6,7,8,10,12,15,16],programm:15,progress:15,project:17,prompt:7,proper:[2,3,12],properti:0,provid:[0,3,4,7],pun:[0,7],punctuat:15,pure:0,puriti:7,purpos:7,push:[2,3,7,12,16,20],pushback:7,put:[1,2,6,7,15,17,20],pypi:0,python:[0,2,3,10,12,16,17,18,20],quadrat:[0,17],queri:[10,14],query_kei:14,queu:12,quit:[0,1,14],quot:[0,3,6,7,10,11,12,14,15,16,19],quotat:[2,3,12],quotient:3,r_kei:10,r_left:10,r_right:10,r_valu:10,rais:[10,15,18,20],rang:[7,15],range_revers:12,range_to_zero:7,ranger:12,ranger_revers:12,raphson:8,rather:[5,7,12,14],ratio:7,reach:[5,6,12],read:[0,1,5,6,10,15,16],readabl:13,reader:10,readi:15,real:10,realiz:[4,10],rearrang:[2,10,15],reason:[5,7,15],rebuild:[14,16],rec1:[2,3,12],rec2:[2,3,12],recent:15,recogn:18,record:[7,19],recur:[12,15],recurs:[0,2,3,6,7,8,15,17,20],recus:7,redefin:17,redistribut:[3,7],reduc:[2,15],redund:20,refactor:[7,9],refer:[0,2],regist:2,regular:[15,18],reimplement:17,relat:15,releas:9,remain:[2,7,9],remaind:[3,8],remind:15,remov:[3,10,15,20],render:17,repeat:5,repeatedli:5,repl:[0,1],replac:[0,2,3,6,11,12,14,15,16,17,20],repositori:0,repr:15,repres:[2,7,10,18,19],represent:20,reprod:6,repurpos:15,requir:20,res:15,resembl:7,respect:5,rest:[3,5,6,7,10,12,16,17,20],rest_two:10,restor:2,restrict:15,result:[1,2,3,5,10,11,12,14,15,16],resum:7,retain:15,retir:2,retri:7,reus:[10,15],revers:[3,5,6,12,15,16,20],revisit:15,rewrit:[3,7,15],rewritten:7,rich:15,rid:10,right:[6,7,11,14,15,17,19,20],rightest:10,rightmost:5,rkei:14,rob:15,roll:[3,8,10,14],roll_dn:15,roll_down:15,roll_up:15,rolldown:3,rollup:3,root:[3,8,11],round:15,rrest:[3,15],rule:17,run:[0,1,3,5,7,8,10,11,12,14,16],runtimeerror:20,s1000:15,s1002:15,s23:15,sai:[6,10,11,14,15],same:[2,4,5,10,15,20],sandwich:[2,3,12],save:[2,5,7],scan:3,scanner:[7,18],scenario:16,scope:[6,10],search:[0,10],sec:15,second:[3,7,10,12,14,20],section:12,see:[0,6,7,8,9,11,12,13,15,16,19],seem:[0,5,7,14,15],seen:[15,16],select:3,self:15,semant:[2,3,7,9,10,15],semi:7,send:7,sens:[0,2,5,15,16],separ:[7,15],seq:15,sequenc:[0,1,2,3,5,7,10,12,13,16,17,18],sequence_to_stack:15,seri:[5,6,10,16],ses:15,set:[2,3,12,15,17],seven:[5,6],sever:[0,4,7,12],share:[3,7],shelf:2,shift:[5,6],shorter:17,shorthand:10,should:[2,3,5,10,12,15],shouldn:7,show:[4,16],shunt:[3,16],side:[10,15],signifi:[7,10],similar:[10,14,15],simon:7,simpl:[7,12,15,20],simplefunctionwrapp:[3,13,15],simpler:14,simplest:[15,17],simpli:4,simplifi:[5,10,16],sinc:[2,5,10],singl:[3,6,7,13,15,18],situ:10,situat:10,six:[5,6,7],sixti:[5,6],size:[7,17],skeptic:7,skip:15,slight:8,slightli:[10,12,15],smallest:3,smart:10,softwar:7,solei:2,solut:[5,6],solvabl:7,some:[2,3,6,7,10,12,14,15,17,20],somehow:[10,15],someth:[2,9,10,15],sometim:10,somewher:[10,17],sort:[3,10,15],sort_:3,sorta:15,sourc:[0,1,3,15,17,18,19,20],space:[5,19],span:5,spawn:15,special:[6,10,15,17],specif:[0,4],specifi:[10,15],speed:13,spell:14,sphinx:[17,20],spirit:[0,1,14],split:15,sqr:[7,8,11,16],sqrt:[3,8,15],squar:[3,8,15,18],stack:[0,1,3,5,6,8,10,11,12,13,14,16,17,18,19],stack_concat:15,stack_effect:15,stack_effect_com:15,stack_to_str:20,stacki:15,stackjoytyp:15,stackstarjoytyp:15,stage:14,stai:[0,1],stand:4,standard:[7,10],star:[14,15],stare:10,start:[5,6,7,8,10,12,14],state:7,statement:3,step:[3,5,7,10,13,15,16,17],still:[10,15],stop:10,storag:[5,10],store:[5,12],stori:12,str:[1,15,18,19,20],straightforward:[1,6,8,17],stream:5,stretch:10,string:[1,2,3,7,15,16,18,19,20],structur:[7,14,15,16,17,20],stuff:[10,15],stuncon:3,stununcon:3,style:[0,4,15],sub:9,subclass:7,subject:[15,16],subset:15,substitut:[10,15],subtract:5,subtyp:17,succ:[3,15],succe:15,success:8,suffic:15,suffici:10,suffix:15,suggest:[4,10],suitabl:[3,4,5],sum:[3,6,7,11,12,13,14],sum_:[3,15],summand:5,sumtre:14,suppli:[10,18],support:[7,19,20],suspect:2,swaack:[3,11,13,16],swap:[3,5,6,7,8,10,12,13,14,16],swon:[3,6,7,12,14,15,16],swoncat:[6,7,8,12,14],swuncon:12,symbol:[2,3,15,16,17,18],symboljoytyp:15,symmetr:[5,10],syntact:7,syntax:[7,20],sys:20,system:[7,10],tabl:15,tag:15,tail:[10,15,17,20],take:[3,5,7,8,10,12,15,20],talk:[7,10,20],target:16,tast:4,tbd:[7,15],tear:12,technic:2,techniqu:[4,16],technolog:2,temporari:16,ten:5,term:[1,2,7,8,12,15,17,18,20],termin:[2,3,12],ternari:7,test:[2,3,12],text:[0,1,3,15],text_to_express:[7,15,18],textual:7,than:[0,3,5,6,7,8,12,14,15,20],thei:[2,5,6,7,10,12,15,16,18,20],them:[2,3,5,6,10,12,15,16,17],themselv:15,theori:[2,3,12],therefor:6,thi:[0,1,2,3,4,5,6,7,8,11,12,14,15,16,17,18,19,20],thing:[2,6,10,12,15,16,18,20],think:[2,5,7,10,12,14,15],third:[3,6,7,10],thirti:5,those:[2,3,10,12,15,17],though:5,thought:7,thousand:5,thread:2,three:[2,3,5,7,10,11,14,15,17],through:[1,5,7,14,15,16,20],thun:[2,3,4,9,12],thunder:7,time:[3,5,7,8,10,12,15,16],titl:15,to_set:10,todai:7,todo:[7,18],togeth:[6,7,15,17],token:18,toler:17,too:[12,15],tool:[7,15],top:[2,3,7,12,15,19,20],total:5,tower:15,trace:[0,7,11,12,16,17,20],traceback:15,traceprint:19,track:[11,15,16],tracker:0,transform:4,translat:[4,11,15],travers:[0,17],treasur:0,treat:[0,2,3,12,17],treatment:6,tree:[0,7,17],treegrind:17,treestep:[0,17],tri:5,triangular_numb:12,trick:[5,15],tricki:15,trobe:0,trove:0,truthi:[3,7],tuck:[3,7,15],tupl:[3,7,15,20],turn:[2,3,15],twice:[10,12],two:[2,3,5,7,8,10,11,12,14,15,16,17,20],type:[0,1,4,7,10,12,17,18,19,20],typeerror:15,typeless:15,typic:[2,3,11,12],unari:7,unarybuiltinwrapp:3,unbalanc:[10,18],unchang:10,uncompil:15,uncon:[3,6,7,10,12,14,16],under:[2,3,7,10],underli:15,underscor:15,understand:[0,10],undistinguish:10,undocu:7,unfinish:15,unfortun:20,unif:15,uniqu:[3,10,15],unit:[7,12],univers:[0,7,15],unnecessari:17,unnecesssari:15,unpack:[2,3,10,15,20],unpair:5,unquot:[7,14],unstack:[3,15],unswon:3,untangl:12,until:6,unus:5,unusu:10,updat:[0,17],usag:7,use:[0,2,3,4,5,6,7,8,9,10,11,12,13,14,16,17,20],used:[3,4,7,10,12,16,18,20],useful:[0,15],user:14,uses:[2,5,12],using:[3,6,10,11,12,14,16],usual:[0,2,12],util:[0,3,13,15],valid:15,valu:[0,2,3,5,7,8,11,12,13,14,15,17,20],value_n:10,valueerror:[15,20],variabl:[15,17],variant:10,variat:[12,17],varieti:[4,7],variou:0,vener:20,verbos:4,veri:[0,1,4,7,10,20],verifi:15,versa:[2,15],version:[0,1,2,6,9,14,16,17],via:7,vice:[2,15],view:[10,17],viewer:[1,7,9,19],vii:17,von:[0,2,3,4,12],wai:[0,2,3,4,5,7,12,13,15],want:[2,5,6,8,10,12,15],warranti:[3,7],wash:7,wast:7,web:20,websit:[0,5],welcom:7,well:[0,4,7,8,10,15,18],were:[7,15,16],what:[2,3,4,7,10,12,14,15,19],whatev:[2,3,12,14,20],when:[5,6,7,10,12,15,16,18,20],where:[2,3,7,10,12,15,17,20],whether:12,which:[0,1,3,5,7,8,10,12,14,15,16,20],whole:[2,3,5,12,14,15],whose:6,why:[8,14],wiki:10,wikipedia:[0,10,16],wildli:7,wind:7,wire:12,within:[7,10,13,17],without:[2,7,10,11,15],won:[10,15,20],word:[0,3,5,7,12,16],work:[0,3,5,6,7,8,10,11,12,14,15,16,20],worth:5,would:[2,5,6,7,8,10,12,15,16,20],wrap:[3,7],wrapper:15,write:[4,8,10,12,14,15,16,17,20],written:[0,1,8,10,13,15,20],wrong:2,wrote:15,xrang:15,year:[7,15],yet:[10,15,16],yield:[2,3,12,15,20],you:[0,2,3,5,6,7,9,10,11,12,13,14,15,16,19,20],your:[2,3,7,12,15],yourself:[7,10],zero:[3,10,12,14,15,18,20],zip:[5,15],zip_:3,zipper:[0,17],zstr:16},titles:["Thun 0.2.0 Documentation","Joy Interpreter","Functions Grouped by, er, Function with Examples","Function Reference","Categorical Programming","Developing a Program in Joy","Using <code class=\"docutils literal notranslate\"><span class=\"pre\">x</span></code> to Generate Values","Thun: Joy in Python","Newton\u2019s method","No Updates","Treating Trees I: Ordered Binary Trees","Quadratic formula","Recursive Combinators","Replacing Functions in the Dictionary","Treating Trees II: <code class=\"docutils literal notranslate\"><span class=\"pre\">treestep</span></code>","Type Inference","Traversing Datastructures with Zippers","Essays about Programming in Joy","Parsing Text into Joy Expressions","Tracing Joy Execution","Stack or Quote or Sequence or List\u2026"],titleterms:{"abstract":15,"case":[8,10],"function":[2,3,7,8,10,12,13,14,15],"long":13,"new":10,"p\u00f6ial":15,"void":2,"while":2,Adding:10,One:[6,10],The:[5,7,10,12,14],There:7,Using:6,With:14,about:17,add:[2,10],adding:10,address:16,altern:14,ana:12,analysi:5,anamorph:[2,12],app1:2,app2:2,app3:2,appendix:[10,12,15],approxim:8,argument:15,auto:3,averag:2,base:[8,10],binari:[2,10,14],both:10,branch:[2,10],can:10,cata:12,catamorph:12,categor:4,chatter:2,child:10,choic:2,clear:2,cleav:2,cmp:10,code:[7,10],combin:[2,10,12,15],comment:15,compar:10,comparison:2,compil:[6,15],compile_:15,compos:15,comput:8,con:[2,15],concat:[2,15],conclus:12,consecut:8,continu:7,current:10,datastructur:[7,10,16],deal:15,defin:[10,14],definit:11,delabel:15,delet:10,deriv:[11,12,14],design:12,determin:16,develop:5,dialect:0,dictionari:13,dip:[2,16],dipd:2,dipdd:2,direco:6,disenstacken:2,distinguish:15,div:2,doc_from_stack_effect:15,document:0,doe:10,down_to_zero:2,drop:2,dup:[2,15],dupd:2,dupdip:2,effect:15,els:10,empti:10,enstacken:2,equal:10,essai:17,euler:[5,6],eval:7,even:6,exampl:[2,7,10,12,14],execut:19,express:[7,18],extract:14,factori:12,fibonacci:6,filter:5,find:[8,10,12],first:[2,5,15],five:6,flatten:2,flexibl:14,floordiv:2,formula:11,found:10,four:12,fun:12,further:5,gcd:2,gener:[3,5,6,8],genrec:2,get:[10,14],getitem:2,given:14,greater:10,group:2,have:[10,14],help:2,highest:10,host:0,how:[5,6],hylo:12,hylomorph:12,identifi:15,ift:2,iii:15,implement:15,indic:0,infer:15,inferenc:15,inform:0,infra:[2,16],integ:5,interest:6,interlud:10,intern:18,interpret:[1,7,15],item:16,iter:[5,10],joi:[0,1,3,5,7,12,15,16,17,18,19,20],just:5,kei:10,languag:0,least_fract:2,left:10,less:10,let:5,librari:[3,7,15],like:10,list:[2,15,20],literari:7,littl:5,logic:[2,15],loop:[2,7],lower:10,lshift:2,make:[6,8],mani:5,map:2,math:2,method:8,min:2,miscellan:2,mod:2,modifi:15,modulu:2,more:10,most:10,mul:[2,15],multipl:[5,6,15],must:10,name:11,neg:2,newton:8,next:8,node:10,non:10,now:10,nullari:2,number:[12,15],one:7,onli:7,order:[10,14],osdn:0,our:10,over:2,pack:5,pam:2,para:12,paradigm:15,parameter:[10,14],pars:[2,18],parser:[7,18],part:15,pass:7,path:16,pattern:12,per:10,pop:[2,15],popd:2,popop:2,pow:2,power:6,pred:2,predic:[5,8,10,14],pretty_print:19,primit:12,primrec:2,print:7,problem:[5,6],process:10,product:2,program:[4,5,11,14,17],project:[0,5,6],pure:7,put:[10,11,14],python:[7,13,15],quadrat:11,quick:0,quot:[2,20],rang:[2,5,12],range_to_zero:2,read:7,recur:[8,10],recurs:[10,12,14],redefin:[10,14],refactor:[5,10],refer:3,regular:7,reimplement:14,relabel:15,rem:2,remaind:2,remov:2,render:5,repl:7,replac:[10,13],repres:15,reset:6,rest:[2,15],revers:2,right:[10,16],rightmost:10,roll:[2,15],rolldown:2,rollup:2,rshift:2,rule:15,run:[2,6],second:[2,15],select:2,sequenc:[6,15,20],set:[8,10],shorter:13,should:7,shunt:2,simplest:5,size:[2,13],someth:[],sourc:10,special:12,sqr:[2,15],sqrt:[2,11],stack:[2,7,15,20],start:0,step:[2,12,14],straightforward:11,structur:10,style:7,sub:[2,10],subtyp:15,succ:2,sum:[2,5],swaack:2,swap:[2,15],swon:2,swoncat:2,symbol:[7,12],tabl:0,tail:12,take:2,term:[5,6,14],ternari:2,text:18,than:10,them:11,thi:10,third:[2,15],three:6,thun:[0,7],time:[2,6],togeth:[10,11,14],token:7,toler:8,trace:[13,19],traceprint:7,travers:[10,14,16],treat:[10,14],tree:[10,14,16],treegrind:14,treestep:14,triangular:12,truediv:2,truthi:2,tuck:2,two:6,type:15,unari:2,unbound:15,uncon:[2,15],unifi:15,unit:2,unnecessari:5,unquot:2,unstack:2,updat:[9,15],use:15,util:[19,20],valu:[6,10],variabl:11,variat:6,version:[5,10,13,15],view:7,vii:15,within:8,word:2,write:11,xor:2,zero:6,zip:2,zipper:16}})
\ No newline at end of file
index 971fdfc..0385776 100644 (file)
@@ -2,8 +2,12 @@
 Type Inference
 ==============
 
-Pöial's Rules
--------------
+Cf. `"Type Inference in Stack-Based Programming
+Languages" <http://prl.ccs.neu.edu/blog/2017/03/10/type-inference-in-stack-based-programming-languages/>`__
+by Rob Kleffner, 2017-03-10.
+
+Part I: Pöial's Rules
+---------------------
 
 `"Typing Tools for Typeless Stack Languages" by Jaanus
 Pöial <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.212.6026>`__
@@ -47,8 +51,9 @@ Third Rule
 
 The third rule is actually two rules. These two rules deal with
 composing functions when the second one will consume one of items the
-first one produces. The two types must be *unified* or a type conflict
-declared.
+first one produces. The two types must be
+`*unified* <https://en.wikipedia.org/wiki/Robinson's_unification_algorithm>`__
+or a type conflict declared.
 
 ::
 
@@ -61,9 +66,6 @@ declared.
     -------------------------------
        (a -- b     )∘(c      -- d)   t[i] == u[k] == u[j]
 
-Examples
---------
-
 Let's work through some examples by hand to develop an intuition for the
 algorithm.
 
@@ -387,8 +389,8 @@ following Python code:
         (_, (d, (c, ((a, (b, S0)), stack)))) = stack
         return (d, (c, S0)), stack
 
-Implementation
---------------
+Part II: Implementation
+-----------------------
 
 Representing Stack Effect Comments in Python
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -618,11 +620,11 @@ Let's try it out.
 
 
 
-List Functions
-~~~~~~~~~~~~~~
+Stack Functions
+~~~~~~~~~~~~~~~
 
 Here's that trick to represent functions like ``rest`` and ``cons`` that
-manipulate lists. We use a cons-list of tuples and give the tails their
+manipulate stacks. We use a cons-list of tuples and give the tails their
 own numbers. Then everything above already works.
 
 .. code:: ipython2
@@ -683,6 +685,7 @@ Compare with the stack effect comment and you can see it works fine:
 ::
 
     ([4 5 ...] 2 3 1 -- [3 2 ...])
+      3 4  5   1 2 0     2 1  5
 
 Dealing with ``cons`` and ``uncons``
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -719,7 +722,7 @@ deal with this recursively:
     def unify(u, v, s=None):
         if s is None:
             s = {}
-        else:
+        elif s:
             u = update(s, u)
             v = update(s, v)
     
@@ -758,8 +761,8 @@ deal with this recursively:
 
 
 
-Compiling
----------
+Part III: Compiling Stack Functions
+-----------------------------------
 
 Now consider the Python function we would like to derive:
 
@@ -1094,8 +1097,8 @@ from their stack effect comments:
     
 
 
-Types and Subtypes of Arguments
--------------------------------
+Part IV: Types and Subtypes of Arguments
+----------------------------------------
 
 So far we have dealt with types of functions, those dealing with simple
 stack manipulation. Let's extend our machinery to deal with types of
@@ -1396,7 +1399,7 @@ of how many labels of each domain it has "seen".
     def unify(u, v, s=None):
         if s is None:
             s = {}
-        else:
+        elif s:
             u = update(s, u)
             v = update(s, v)
     
@@ -1410,11 +1413,11 @@ of how many labels of each domain it has "seen".
             if v >= u:
                 s[v] = u
                 return s
-            raise ValueError('Cannot unify %r and %r.' % (u, v))
+            raise TypeError('Cannot unify %r and %r.' % (u, v))
     
         if isinstance(u, tuple) and isinstance(v, tuple):
             if len(u) != len(v) != 2:
-                raise ValueError(repr((u, v)))
+                raise TypeError(repr((u, v)))
             for uu, vv in zip(u, v):
                 s = unify(uu, vv, s)
                 if s == False: # (instead of a substitution dict.)
@@ -1423,13 +1426,13 @@ of how many labels of each domain it has "seen".
      
         if isinstance(v, tuple):
             if not stacky(u):
-                raise ValueError('Cannot unify %r and %r.' % (u, v))
+                raise TypeError('Cannot unify %r and %r.' % (u, v))
             s[u] = v
             return s
     
         if isinstance(u, tuple):
             if not stacky(v):
-                raise ValueError('Cannot unify %r and %r.' % (v, u))
+                raise TypeError('Cannot unify %r and %r.' % (v, u))
             s[v] = u
             return s
     
@@ -1719,8 +1722,8 @@ comments. We can write a function to check that:
     uncons = ([a1 .1.] -- a1 [.1.])
 
 
-Functions that use the Stack
-----------------------------
+Part V: Functions that use the Stack
+------------------------------------
 
 Consider the ``stack`` function which grabs the whole stack, quotes it,
 and puts it on itself:
@@ -1803,32 +1806,17 @@ It works.
 
 This function has to be modified to use the new datastructures and it is
 no longer recursive, instead recursion happens as part of unification.
+Further, the first and second of Pöial's rules are now handled
+automatically by the unification algorithm.
 
 .. code:: ipython2
 
     def compose(f, g):
-    
         (f_in, f_out), (g_in, g_out) = f, g
-    
-        if not g_in:
-            fg_in, fg_out = f_in, stack_concat(g_out, f_out)
-    
-        elif not f_out:
-            fg_in, fg_out = stack_concat(f_in, g_in), g_out
-    
-        else: # Unify and update.
-    
-            s = unify(g_in, f_out)
-    
-            if s == False:  # s can also be the empty dict, which is ok.
-                raise TypeError('Cannot unify %r and %r.' % (fo, gi))
-    
-            fg_in, fg_out = update(s, (f_in, g_out))
-    
-        return fg_in, fg_out
-    
-    
-    stack_concat = lambda q, e: (q[0], stack_concat(q[1], e)) if q else e
+        s = unify(g_in, f_out)
+        if s == False:  # s can also be the empty dict, which is ok.
+            raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
+        return update(s, (f_in, g_out))
 
 I don't want to rewrite all the defs myself, so I'll write a little
 conversion function instead. This is programmer's laziness.
@@ -2100,107 +2088,1089 @@ comments are now already in the form needed for the Python code:
 
 
 
-Sets of Stack Effects
----------------------
+Part VI: Multiple Stack Effects
+-------------------------------
 
 ...
 
-``concat``
-----------
+.. code:: ipython2
 
-How to deal with ``concat``?
+    class IntJoyType(NumberJoyType): prefix = 'i'
+    
+    
+    F = map(FloatJoyType, _R)
+    I = map(IntJoyType, _R)
 
-::
+.. code:: ipython2
 
-    concat ([.0.] [.1.] -- [.0. .1.])
+    muls = [
+         ((I[2], (I[1], S[0])), (I[3], S[0])),
+         ((F[2], (I[1], S[0])), (F[3], S[0])),
+         ((I[2], (F[1], S[0])), (F[3], S[0])),
+         ((F[2], (F[1], S[0])), (F[3], S[0])),
+    ]
+
+.. code:: ipython2
+
+    for f in muls:
+        print doc_from_stack_effect(*f)
+
+
+.. parsed-literal::
+
+    (i1 i2 -- i3)
+    (i1 f2 -- f3)
+    (f1 i2 -- f3)
+    (f1 f2 -- f3)
 
-We would like to represent this in Python somehow...
 
 .. code:: ipython2
 
-    concat = (S[0], S[1]), ((S[0], S[1]),)
+    for f in muls:
+        try:
+            e = C(dup, f)
+        except TypeError:
+            continue
+        print doc_from_stack_effect(*dup), doc_from_stack_effect(*f), doc_from_stack_effect(*e)
+
+
+.. parsed-literal::
+
+    (a1 -- a1 a1) (i1 i2 -- i3) (i0 -- i1)
+    (a1 -- a1 a1) (f1 f2 -- f3) (f0 -- f1)
+
+
+.. code:: ipython2
+
+    from itertools import product
+    
+    
+    def meta_compose(F, G):
+        for f, g in product(F, G):
+            try:
+                yield C(f, g)
+            except TypeError:
+                pass
+    
+    
+    def MC(F, G):
+        return sorted(set(meta_compose(F, G)))
+
+.. code:: ipython2
+
+    for f in MC([dup], muls):
+        print doc_from_stack_effect(*f)
 
-But this is actually ``cons`` with the first argument restricted to be a
-stack:
+
+.. parsed-literal::
+
+    (f0 -- f1)
+    (i0 -- i1)
+
+
+.. code:: ipython2
+
+    for f in MC([dup], [mul]):
+        print doc_from_stack_effect(*f)
+
+
+.. parsed-literal::
+
+    (n0 -- n1)
+
+
+Representing an Unbounded Sequence of Types
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+We can borrow a trick from `Brzozowski's Derivatives of Regular
+Expressions <https://en.wikipedia.org/wiki/Brzozowski_derivative>`__ to
+invent a new type of type variable, a "sequence type" (I think this is
+what they mean in the literature by that term...) or "`Kleene
+Star <https://en.wikipedia.org/wiki/Kleene_star>`__" type. I'm going to
+represent it as a type letter and the asterix, so a sequence of zero or
+more ``AnyJoyType`` variables would be:
 
 ::
 
-    ([.0.] [.1.] -- [[.0.] .1.])
+    A*
 
-What we have implemented so far would actually only permit:
+The ``A*`` works by splitting the universe into two alternate histories:
 
 ::
 
-    ([.0.] [.1.] -- [.2.])
+    A* -> 0 | A A*
 
-.. code:: ipython2
+The Kleene star variable disappears in one universe, and in the other it
+turns into an ``AnyJoyType`` variable followed by itself again. We have
+to return all universes (represented by their substitution dicts, the
+"unifiers") that don't lead to type conflicts.
 
-    concat = (S[0], S[1]), (S[2],)
+Consider unifying two stacks (the lowercase letters are any type
+variables of the kinds we have defined so far):
 
-Which works but can lose information. Consider ``cons concat``, this is
-how much information we *could* retain:
+::
+
+    [a A* b .0.] U [c d .1.]
+                              w/ {c: a}
+    [  A* b .0.] U [  d .1.]
+
+Now we have to split universes to unify ``A*``. In the first universe it
+disappears:
 
 ::
 
-    (1 [.0.] [.1.] -- [1 .0. .1.])
+    [b .0.] U [d .1.]
+                       w/ {d: b, .1.: .0.} 
+         [] U []
 
-As opposed to just:
+While in the second it spawns an ``A``, which we will label ``e``:
 
 ::
 
-    (1 [.0.] [.1.] -- [.2.])
+    [e A* b .0.] U [d .1.]
+                            w/ {d: e}
+    [  A* b .0.] U [  .1.]
+                            w/ {.1.: A* b .0.}
+    [  A* b .0.] U [  .1.]
 
-Which works but can lose information. Consider ``cons concat``, this is
-how much information we *could* retain:
+Giving us two unifiers:
 
 ::
 
-    (1 [.0.] [.1.] -- [1 .0. .1.]) uncons uncons
+    {c: a,  d: b,  .1.:      .0.}
+    {c: a,  d: e,  .1.: A* b .0.}
+
+.. code:: ipython2
+
+    class KleeneStar(object):
+    
+        kind = AnyJoyType
+    
+        def __init__(self, number):
+            self.number = number
+            self.count = 0
+            self.prefix = repr(self)
+    
+        def __repr__(self):
+            return '%s%i*' % (self.kind.prefix, self.number)
+    
+        def another(self):
+            self.count += 1
+            return self.kind(10000 * self.number + self.count)
+    
+        def __eq__(self, other):
+            return (
+                isinstance(other, self.__class__)
+                and other.number == self.number
+            )
+    
+        def __ge__(self, other):
+            return self.kind >= other.kind
+    
+        def __add__(self, other):
+            return self.__class__(self.number + other)
+        __radd__ = __add__
+        
+        def __hash__(self):
+            return hash(repr(self))
+    
+    class AnyStarJoyType(KleeneStar): kind = AnyJoyType
+    class NumberStarJoyType(KleeneStar): kind = NumberJoyType
+    #class FloatStarJoyType(KleeneStar): kind = FloatJoyType
+    #class IntStarJoyType(KleeneStar): kind = IntJoyType
+    class StackStarJoyType(KleeneStar): kind = StackJoyType
+    
+    
+    As = map(AnyStarJoyType, _R)
+    Ns = map(NumberStarJoyType, _R)
+    Ss = map(StackStarJoyType, _R)
+
+``unify()`` version 4
+^^^^^^^^^^^^^^^^^^^^^
+
+Can now return multiple results...
+
+.. code:: ipython2
+
+    def unify(u, v, s=None):
+        if s is None:
+            s = {}
+        elif s:
+            u = update(s, u)
+            v = update(s, v)
+    
+        if u == v:
+            return s,
+    
+        if isinstance(u, AnyJoyType) and isinstance(v, AnyJoyType):
+            if u >= v:
+                s[u] = v
+                return s,
+            if v >= u:
+                s[v] = u
+                return s,
+            raise TypeError('Cannot unify %r and %r.' % (u, v))
+    
+        if isinstance(u, tuple) and isinstance(v, tuple):
+            if len(u) != len(v) != 2:
+                raise TypeError(repr((u, v)))
+                
+            a, b = v
+            if isinstance(a, KleeneStar):
+                # Two universes, in one the Kleene star disappears and unification
+                # continues without it...
+                s0 = unify(u, b)
+                
+                # In the other it spawns a new variable.
+                s1 = unify(u, (a.another(), v))
+                
+                t = s0 + s1
+                for sn in t:
+                    sn.update(s)
+                return t
+    
+            a, b = u
+            if isinstance(a, KleeneStar):
+                s0 = unify(v, b)
+                s1 = unify(v, (a.another(), u))
+                t = s0 + s1
+                for sn in t:
+                    sn.update(s)
+                return t
+    
+            ses = unify(u[0], v[0], s)
+            results = ()
+            for sn in ses:
+                results += unify(u[1], v[1], sn)
+            return results
+     
+        if isinstance(v, tuple):
+            if not stacky(u):
+                raise TypeError('Cannot unify %r and %r.' % (u, v))
+            s[u] = v
+            return s,
+    
+        if isinstance(u, tuple):
+            if not stacky(v):
+                raise TypeError('Cannot unify %r and %r.' % (v, u))
+            s[v] = u
+            return s,
+    
+        return ()
+    
+    
+    def stacky(thing):
+        return thing.__class__ in {AnyJoyType, StackJoyType}
+
+.. code:: ipython2
 
-    (1 [.0.] [.1.] -- 1 [.0. .1.])        uncons
-                                                    So far so good...
-    (1 [2 .2.] [.1.] -- 1 2 [.2. .1.])
+    a = (As[1], S[1])
+    a
 
 
 
 
-    (1 [.0.] [.1.] -- 1 [.0. .1.]) ([a1 .10.] -- a1 [.10.])
-                                                             w/ { [a1 .10.] : [  .0.   .1.] }
-                                                           -or-
-                                                             w/ { [  .0.   .1.] : [a1 .10.    ] }
+.. parsed-literal::
 
-Typing Combinators
-------------------
+    (a1*, s1)
 
-TBD
 
-This is an open subject.
 
-The obvious thing is that you now need two pairs of tuples to describe
-the combinators' effects, a stack effect comment and an expression
-effect comment:
+.. code:: ipython2
 
-::
+    b = (A[1], S[2])
+    b
 
-    dip (a [F] --)--(-- F a)
 
-One thing that might help is...
 
-Abstract Interpretation
------------------------
 
-Something else...
------------------
+.. parsed-literal::
+
+    (a1, s2)
+
+
+
+.. code:: ipython2
+
+    for result in unify(b, a):
+        print result, '->', update(result, a), update(result, b)
+
+
+.. parsed-literal::
+
+    {s1: (a1, s2)} -> (a1*, (a1, s2)) (a1, s2)
+    {a1: a10001, s2: (a1*, s1)} -> (a1*, s1) (a10001, (a1*, s1))
+
+
+.. code:: ipython2
+
+    for result in unify(a, b):
+        print result, '->', update(result, a), update(result, b)
+
+
+.. parsed-literal::
+
+    {s1: (a1, s2)} -> (a1*, (a1, s2)) (a1, s2)
+    {a1: a10002, s2: (a1*, s1)} -> (a1*, s1) (a10002, (a1*, s1))
+
 
 ::
 
-    [4 5 ...] 2 1 0 pop∘swap∘roll<∘rest∘rest∘cons∘cons
-    [4 5 ...] 2 1       swap∘roll<∘rest∘rest∘cons∘cons
-    [4 5 ...] 1 2            roll<∘rest∘rest∘cons∘cons
-    1 2 [4 5 ...]                  rest∘rest∘cons∘cons
-    1 2   [5 ...]                       rest∘cons∘cons
-    1 2     [...]                            cons∘cons
-    1     [2 ...]                                 cons
-        [1 2 ...]
+    (a1*, s1)       [a1*]       (a1, s2)        [a1]
 
-Eh?
+    (a1*, (a1, s2)) [a1* a1]    (a1, s2)        [a1]
+
+    (a1*, s1)       [a1*]       (a2, (a1*, s1)) [a2 a1*]
+
+.. code:: ipython2
+
+    sum_ = ((Ns[1], S[1]), S[0]), (N[0], S[0])
+    
+    print doc_from_stack_effect(*sum_)
+
+
+.. parsed-literal::
+
+    ([n1* .1.] -- n0)
+
+
+.. code:: ipython2
+
+    f = (N[1], (N[2], (N[3], S[1]))), S[0]
+    
+    print doc_from_stack_effect(S[0], f)
+
+
+.. parsed-literal::
+
+    (-- [n1 n2 n3 .1.])
+
+
+.. code:: ipython2
+
+    for result in unify(sum_[0], f):
+        print result, '->', update(result, sum_[1])
+
+
+.. parsed-literal::
+
+    {s1: (n1, (n2, (n3, s1)))} -> (n0, s0)
+    {n1: n10001, s1: (n2, (n3, s1))} -> (n0, s0)
+    {n1: n10001, s1: (n3, s1), n2: n10002} -> (n0, s0)
+    {n1: n10001, s1: (n1*, s1), n3: n10003, n2: n10002} -> (n0, s0)
+
+
+``compose()`` version 3
+^^^^^^^^^^^^^^^^^^^^^^^
+
+This function has to be modified to yield multiple results.
+
+.. code:: ipython2
+
+    def compose(f, g):
+        (f_in, f_out), (g_in, g_out) = f, g
+        s = unify(g_in, f_out)
+        if not s:
+            raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
+        for result in s:
+            yield update(result, (f_in, g_out))
+
+
+.. code:: ipython2
+
+    def meta_compose(F, G):
+        for f, g in product(F, G):
+            try:
+                for result in C(f, g):
+                    yield result
+            except TypeError:
+                pass
+    
+    
+    def C(f, g):
+        f, g = relabel(f, g)
+        for fg in compose(f, g):
+            yield delabel(fg)
+
+.. code:: ipython2
+
+    for f in MC([dup], muls):
+        print doc_from_stack_effect(*f)
+
+
+.. parsed-literal::
+
+    (f0 -- f1)
+    (i0 -- i1)
+
+
+.. code:: ipython2
+
+    
+    
+    for f in MC([dup], [sum_]):
+        print doc_from_stack_effect(*f)
+
+
+.. parsed-literal::
+
+    ([n0* .0.] -- [n0* .0.] n0)
+
+
+.. code:: ipython2
+
+    
+    
+    for f in MC([cons], [sum_]):
+        print doc_from_stack_effect(*f)
+
+
+.. parsed-literal::
+
+    (a0 [.0.] -- n0)
+    (n0 [n0* .0.] -- n1)
+
+
+.. code:: ipython2
+
+    sum_ = (((N[1], (Ns[1], S[1])), S[0]), (N[0], S[0]))
+    print doc_from_stack_effect(*cons),
+    print doc_from_stack_effect(*sum_),
+    
+    for f in MC([cons], [sum_]):
+        print doc_from_stack_effect(*f)
+
+
+.. parsed-literal::
+
+    (a1 [.1.] -- [a1 .1.]) ([n1 n1* .1.] -- n0) (n0 [n0* .0.] -- n1)
+
+
+.. code:: ipython2
+
+    a = (A[4], (As[1], (A[3], S[1])))
+    a
+
+
+
+
+.. parsed-literal::
+
+    (a4, (a1*, (a3, s1)))
+
+
+
+.. code:: ipython2
+
+    b = (A[1], (A[2], S[2]))
+    b
+
+
+
+
+.. parsed-literal::
+
+    (a1, (a2, s2))
+
+
+
+.. code:: ipython2
+
+    for result in unify(b, a):
+        print result
+
+
+.. parsed-literal::
+
+    {a1: a4, s2: s1, a2: a3}
+    {a1: a4, s2: (a1*, (a3, s1)), a2: a10003}
+
+
+.. code:: ipython2
+
+    for result in unify(a, b):
+        print result
+
+
+.. parsed-literal::
+
+    {s2: s1, a2: a3, a4: a1}
+    {s2: (a1*, (a3, s1)), a2: a10004, a4: a1}
+
+
+Part VII: Typing Combinators
+----------------------------
+
+TBD
+
+This is an open subject.
+
+The obvious thing is that you now need two pairs of tuples to describe
+the combinators' effects, a stack effect comment and an expression
+effect comment:
+
+::
+
+    dip (a [F] --)--(-- F a)
+
+One thing that might help is...
+
+Consider the type of:
+
+::
+
+    [cons] dip
+
+Obviously it would be:
+
+::
+
+    (a1 [..1] a2 -- [a1 ..1] a2)
+
+``dip`` itself could have:
+
+::
+
+    (a1 [..1] -- ... then what?
+
+.. code:: ipython2
+
+    class SymbolJoyType(AnyJoyType): prefix = 'F'
+    
+    W = map(SymbolJoyType, _R)
+    
+    k = S[0], ((W[1], S[2]), S[0])
+    Symbol('cons')
+    print doc_from_stack_effect(*k)
+
+
+
+.. parsed-literal::
+
+    (-- [F1 .2.])
+
+
+.. code:: ipython2
+
+    dip_a = ((W[1], S[2]), (A[1], S[0]))
+
+.. code:: ipython2
+
+    d = relabel(S[0], dip_a)
+    print doc_from_stack_effect(*d)
+
+
+.. parsed-literal::
+
+    (-- a1001 [F1001 .1002.])
+
+
+.. code:: ipython2
+
+    s = list(unify(d[1], k[1]))[0]
+    s
+
+
+
+
+.. parsed-literal::
+
+    {s0: (a1001, s1000), s1002: s2, F1001: F1}
+
+
+
+.. code:: ipython2
+
+    j = update(s, k)
+
+.. code:: ipython2
+
+    print doc_from_stack_effect(*j)
+
+
+.. parsed-literal::
+
+    (a1001 -- a1001 [F1 .2.])
+
+
+.. code:: ipython2
+
+    j
+
+
+
+
+.. parsed-literal::
+
+    ((a1001, s1000), ((F1, s2), (a1001, s1000)))
+
+
+
+.. code:: ipython2
+
+    cons
+
+
+
+
+.. parsed-literal::
+
+    ((s1, (a1, s23)), ((a1, s1), s23))
+
+
+
+.. code:: ipython2
+
+    for f in MC([k], [dup]):
+        print doc_from_stack_effect(*f)
+
+
+.. parsed-literal::
+
+    (-- [F0 .1.] [F0 .1.])
+
+
+.. code:: ipython2
+
+    l = S[0], ((cons, S[2]), (A[1], S[0]))
+
+.. code:: ipython2
+
+    print doc_from_stack_effect(*l)
+
+
+.. parsed-literal::
+
+    (-- a1 [[[[.1.] a1 .23.] [a1 .1.] .23.] .2.])
+
+
+.. code:: ipython2
+
+    
+    def dip_t(F):
+        (quote, (a1, sec)) = F[1]
+        G = F[0], sec
+        P = S[3], (a1, S[3])
+        a = [P]
+        while isinstance(quote, tuple):
+            term, quote = quote
+            a.append(term)
+        a.append(G)
+        return a[::-1]
+    
+    
+    
+
+
+.. code:: ipython2
+
+    from joy.utils.stack import iter_stack
+
+.. code:: ipython2
+
+    a, b, c = dip_t(l)
+
+.. code:: ipython2
+
+    a
+
+
+
+
+.. parsed-literal::
+
+    (s0, s0)
+
+
+
+.. code:: ipython2
+
+    b
+
+
+
+
+.. parsed-literal::
+
+    ((s1, (a1, s23)), ((a1, s1), s23))
+
+
+
+.. code:: ipython2
+
+    c
+
+
+
+
+.. parsed-literal::
+
+    (s3, (a1, s3))
+
+
+
+.. code:: ipython2
+
+    MC([a], [b])
+
+
+
+
+.. parsed-literal::
+
+    [((s0, (a0, s1)), ((a0, s0), s1))]
+
+
+
+.. code:: ipython2
+
+    kjs = MC(MC([a], [b]), [c])
+    kjs
+
+
+
+
+.. parsed-literal::
+
+    [((s0, (a0, s1)), (a1, ((a0, s0), s1)))]
+
+
+
+.. code:: ipython2
+
+    print doc_from_stack_effect(*kjs[0])
+
+
+.. parsed-literal::
+
+    (a0 [.0.] -- [a0 .0.] a1)
+
+
+::
+
+    (a0 [.0.] -- [a0 .0.] a1)
+
+       a0 [.0.] a1 [cons] dip
+    ----------------------------
+       [a0 .0.] a1
+
+.. code:: ipython2
+
+    stack_concat = lambda q, e: (q[0], stack_concat(q[1], e)) if q else e
+
+.. code:: ipython2
+
+    class SymbolJoyType(AnyJoyType):
+        prefix = 'F'
+    
+        def __init__(self, name, sec, number):
+            self.name = name
+            self.stack_effects = sec
+            self.number = number
+    
+    class CombinatorJoyType(SymbolJoyType): prefix = 'C'
+    
+    def dip_t(stack, expression):
+        (quote, (a1, stack)) = stack
+        expression = stack_concat(quote, (a1, expression))
+        return stack, expression
+    
+    CONS = SymbolJoyType('cons', [cons], 23)
+    DIP = CombinatorJoyType('dip', [dip_t], 44)
+    
+    
+    def kav(F, e):
+        #i, stack = F
+        if not e:
+            return [(F, e)]
+        n, e = e
+        if isinstance(n, SymbolJoyType):
+            Fs = []
+            for sec in n.stack_effects:
+                Fs.extend(MC([F], sec))
+            return [kav(Fn, e) for Fn in Fs]
+        if isinstance(n, CombinatorJoyType):
+            res = []
+            for f in n.stack_effects:
+                s, e = f(F[1], e)
+                new_F = F[0], s
+                res.extend(kav(new_F, e))
+            return res
+        lit = S[0], (n, S[0])
+        return [kav(Fn, e) for Fn in MC([F], [lit])]
+
+
+compare, and be amazed:
+
+.. code:: ipython2
+
+    def dip_t(stack, expression):
+        (quote, (a1, stack)) = stack
+        expression = stack_concat(quote, (a1, expression))
+        return stack, expression
+
+.. code:: ipython2
+
+    def dip(stack, expression, dictionary):
+        (quote, (x, stack)) = stack
+        expression = (x, expression)
+        return stack, concat(quote, expression), dictionary
+
+And that brings us to current Work-In-Progress. I'm pretty hopeful that
+the mixed-mode inferencer/interpreter ``kav()`` function along with the
+ability to specify multiple implementations for the combinators will
+permit modelling of the stack effects of e.g. ``ifte``. If I can keep up
+the pace I should be able to verify that conjecture by the end of June.
+
+The rest of this stuff is junk and/or unfinished material.
+
+``concat``
+~~~~~~~~~~
+
+How to deal with ``concat``?
+
+::
+
+    concat ([.0.] [.1.] -- [.0. .1.])
+
+We would like to represent this in Python somehow...
+
+.. code:: ipython2
+
+    concat = (S[0], S[1]), ((S[0], S[1]),)
+
+But this is actually ``cons`` with the first argument restricted to be a
+stack:
+
+::
+
+    ([.0.] [.1.] -- [[.0.] .1.])
+
+What we have implemented so far would actually only permit:
+
+::
+
+    ([.0.] [.1.] -- [.2.])
+
+.. code:: ipython2
+
+    concat = (S[0], S[1]), (S[2],)
+
+Which works but can lose information. Consider ``cons concat``, this is
+how much information we *could* retain:
+
+::
+
+    (1 [.0.] [.1.] -- [1 .0. .1.])
+
+As opposed to just:
+
+::
+
+    (1 [.0.] [.1.] -- [.2.])
+
+represent ``concat``
+~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    ([.0.] [.1.] -- [A*(.0.) .1.])
+
+Meaning that ``A*`` on the right-hand side should all the crap from
+``.0.``.
+
+::
+
+    ([      .0.] [.1.] -- [      A* .1.])
+    ([a     .0.] [.1.] -- [a     A* .1.])
+    ([a b   .0.] [.1.] -- [a b   A* .1.])
+    ([a b c .0.] [.1.] -- [a b c A* .1.])
+
+or...
+
+::
+
+    ([       .0.] [.1.] -- [       .1.])
+    ([a      .0.] [.1.] -- [a      .1.])
+    ([a b    .0.] [.1.] -- [a b    .1.])
+    ([a b  c .0.] [.1.] -- [a b  c .1.])
+    ([a A* c .0.] [.1.] -- [a A* c .1.])
+
+::
+
+    (a, (b, S0)) . S1 = (a, (b, (A*, S1)))
+
+.. code:: ipython2
+
+    class Astar(object):
+        def __repr__(self):
+            return 'A*'
+    
+    
+    def concat(s0, s1):
+        a = []
+        while isinstance(s0, tuple):
+            term, s0 = s0
+            a.append(term)
+        assert isinstance(s0, StackJoyType), repr(s0)
+        s1 = Astar(), s1
+        for term in reversed(a):
+            s1 = term, s1
+        return s1
+
+.. code:: ipython2
+
+    a, b = (A[1], S[0]), (A[2], S[1])
+
+.. code:: ipython2
+
+    concat(a, b)
+
+
+
+
+.. parsed-literal::
+
+    (a1, (A*, (a2, s1)))
+
+
+
+Appendix: Joy in the Logical Paradigm
+-------------------------------------
+
+For this to work the type label classes have to be modified to let
+``T >= t`` succeed, where e.g. ``T`` is ``IntJoyType`` and ``t`` is
+``int``
+
+.. code:: ipython2
+
+    F = reduce(C, (pop, swap, roll_down, rest, rest, cons, cons))
+    
+    print doc_from_stack_effect(*F)
+
+
+::
+
+
+    ---------------------------------------------------------------------------
+
+    ValueError                                Traceback (most recent call last)
+
+    <ipython-input-137-4b4cb6ff86e5> in <module>()
+          1 F = reduce(C, (pop, swap, roll_down, rest, rest, cons, cons))
+          2 
+    ----> 3 print doc_from_stack_effect(*F)
+    
+
+    <ipython-input-99-ddee30dbb1a6> in C(f, g)
+         10 def C(f, g):
+         11     f, g = relabel(f, g)
+    ---> 12     for fg in compose(f, g):
+         13         yield delabel(fg)
+
+
+    <ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
+          1 def compose(f, g):
+    ----> 2     (f_in, f_out), (g_in, g_out) = f, g
+          3     s = unify(g_in, f_out)
+          4     if not s:
+          5         raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
+
+
+    <ipython-input-99-ddee30dbb1a6> in C(f, g)
+         10 def C(f, g):
+         11     f, g = relabel(f, g)
+    ---> 12     for fg in compose(f, g):
+         13         yield delabel(fg)
+
+
+    <ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
+          1 def compose(f, g):
+    ----> 2     (f_in, f_out), (g_in, g_out) = f, g
+          3     s = unify(g_in, f_out)
+          4     if not s:
+          5         raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
+
+
+    <ipython-input-99-ddee30dbb1a6> in C(f, g)
+         10 def C(f, g):
+         11     f, g = relabel(f, g)
+    ---> 12     for fg in compose(f, g):
+         13         yield delabel(fg)
+
+
+    <ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
+          1 def compose(f, g):
+    ----> 2     (f_in, f_out), (g_in, g_out) = f, g
+          3     s = unify(g_in, f_out)
+          4     if not s:
+          5         raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
+
+
+    <ipython-input-99-ddee30dbb1a6> in C(f, g)
+         10 def C(f, g):
+         11     f, g = relabel(f, g)
+    ---> 12     for fg in compose(f, g):
+         13         yield delabel(fg)
+
+
+    <ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
+          1 def compose(f, g):
+    ----> 2     (f_in, f_out), (g_in, g_out) = f, g
+          3     s = unify(g_in, f_out)
+          4     if not s:
+          5         raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
+
+
+    <ipython-input-99-ddee30dbb1a6> in C(f, g)
+         10 def C(f, g):
+         11     f, g = relabel(f, g)
+    ---> 12     for fg in compose(f, g):
+         13         yield delabel(fg)
+
+
+    <ipython-input-98-5eb7ac5ad2c2> in compose(f, g)
+          1 def compose(f, g):
+    ----> 2     (f_in, f_out), (g_in, g_out) = f, g
+          3     s = unify(g_in, f_out)
+          4     if not s:
+          5         raise TypeError('Cannot unify %r and %r.' % (f_out, g_in))
+
+
+    ValueError: need more than 1 value to unpack
+
+
+.. code:: ipython2
+
+    from joy.parser import text_to_expression
+
+.. code:: ipython2
+
+    s = text_to_expression('[3 4 ...] 2 1')
+    s
+
+.. code:: ipython2
+
+    L = unify(F[1], s)
+    L
+
+.. code:: ipython2
+
+    F[1]
+
+.. code:: ipython2
+
+    F[1][0]
+
+.. code:: ipython2
+
+    s[0]
+
+`Abstract Interpretation <https://en.wikipedia.org/wiki/Abstract_interpretation>`__
+-----------------------------------------------------------------------------------
+
+I *think* this might be sorta what I'm doing above with the ``kav()``
+function... In any event "mixed-mode" interpreters that include values
+and type variables and can track constraints, etc. will be, uh,
+super-useful. And Abstract Interpretation should be a rich source of
+ideas.
diff --git a/joy/utils/polytypes.py b/joy/utils/polytypes.py
new file mode 100644 (file)
index 0000000..4171893
--- /dev/null
@@ -0,0 +1,331 @@
+'''
+
+Multiple Stack Effects
+
+By adjusting the machinery in types.py to handles lists of stackeffect comments
+we can capture more information about the type signatures of some functions,
+and we can introduce a kind of Kleene Star or sequence type that can stand for
+an unbounded sequence of other types.
+
+'''
+import sys
+sys.path.append('/home/sforman/Desktop/Joypy-hg')
+from itertools import product
+from joy.utils.types import (
+  AnyJoyType, A,
+  C,
+  DEFS,
+  doc_from_stack_effect,
+  FloatJoyType,
+  NumberJoyType, N,
+  StackJoyType, S,
+  stacky,
+  _R,
+  relabel, delabel,
+  update,
+  )
+
+
+# We no longer want FloatJoyType to accept IntJoyType.
+class IntJoyType(NumberJoyType): prefix = 'i'
+
+
+a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 = A
+n0, n1, n2, n3, n4, n5, n6, n7, n8, n9 = N
+s0, s1, s2, s3, s4, s5, s6, s7, s8, s9 = S
+f0, f1, f2, f3, f4, f5, f6, f7, f8, f9 = F = map(FloatJoyType, _R)
+i0, i1, i2, i3, i4, i5, i6, i7, i8, i9 = I = map(IntJoyType, _R)
+
+
+class KleeneStar(object):
+    '''
+    A sequence of zero or more `AnyJoyType` variables would be:
+
+       A*
+
+    The `A*` works by splitting the universe into two alternate histories:
+
+       A* -> 0
+
+       A* -> A A*
+
+    The Kleene star variable disappears in one universe, and in the other
+    it turns into an `AnyJoyType` variable followed by itself again.
+
+    We have to return all universes (represented by their substitution
+    dicts, the "unifiers") that don't lead to type conflicts.
+    '''
+
+    kind = AnyJoyType
+
+    def __init__(self, number):
+        self.number = number
+        self.count = 0
+        self.prefix = repr(self)
+
+    def __repr__(self):
+        return '%s%i*' % (self.kind.prefix, self.number)
+
+    def another(self):
+        self.count += 1
+        return self.kind(10000 * self.number + self.count)
+
+    def __eq__(self, other):
+        return (
+            isinstance(other, self.__class__)
+            and other.number == self.number
+        )
+
+    def __ge__(self, other):
+        return self.kind >= other.kind
+
+    def __add__(self, other):
+        return self.__class__(self.number + other)
+    __radd__ = __add__
+    
+    def __hash__(self):
+        return hash(repr(self))
+
+
+class AnyStarJoyType(KleeneStar): kind = AnyJoyType
+class NumberStarJoyType(KleeneStar): kind = NumberJoyType
+#class FloatStarJoyType(KleeneStar): kind = FloatJoyType
+#class IntStarJoyType(KleeneStar): kind = IntJoyType
+class StackStarJoyType(KleeneStar): kind = StackJoyType
+
+
+As = map(AnyStarJoyType, _R)
+Ns = map(NumberStarJoyType, _R)
+Ss = map(StackStarJoyType, _R)
+
+
+def _lil_uni(u, v, s):
+    if u >= v:
+        s[u] = v
+        return s,
+    if v >= u:
+        s[v] = u
+        return s,
+    raise TypeError('Cannot unify %r and %r.' % (u, v))
+
+
+
+def unify(u, v, s=None):
+    if s is None:
+        s = {}
+    elif s:
+        u = update(s, u)
+        v = update(s, v)
+
+    if u == v:
+        return s,
+
+    if isinstance(u, AnyJoyType) and isinstance(v, AnyJoyType):
+        return _lil_uni(u, v, s)
+
+    if isinstance(u, tuple) and isinstance(v, tuple):
+        if len(u) != len(v) != 2:
+            raise TypeError(repr((u, v)))
+            
+        a, b = v
+        if isinstance(a, KleeneStar):
+            if isinstance(b, KleeneStar):
+                return _lil_uni(a, b, s)
+
+            # Two universes, in one the Kleene star disappears and unification
+            # continues without it...
+            s0 = unify(u, b)
+            
+            # In the other it spawns a new variable.
+            s1 = unify(u, (a.another(), v))
+            
+            t = s0 + s1
+            for sn in t:
+                sn.update(s)
+            return t
+
+        a, b = u
+        if isinstance(a, KleeneStar):
+            s0 = unify(v, b)
+            s1 = unify(v, (a.another(), u))
+            t = s0 + s1
+            for sn in t:
+                sn.update(s)
+            return t
+
+        ses = unify(u[0], v[0], s)
+        results = ()
+        for sn in ses:
+            results += unify(u[1], v[1], sn)
+        return results
+    if isinstance(v, tuple):
+        if not stacky(u):
+            raise TypeError('Cannot unify %r and %r.' % (u, v))
+        s[u] = v
+        return s,
+
+    if isinstance(u, tuple):
+        if not stacky(v):
+            raise TypeError('Cannot unify %r and %r.' % (v, u))
+        s[v] = u
+        return s,
+
+    return ()
+
+
+def compose(f, g):
+    (f_in, f_out), (g_in, g_out) = f, g
+    s = unify(g_in, f_out)
+    if not s:
+        raise TypeError('Cannot unify %r and %r.' % (fo, gi))
+    for result in s:
+        yield update(result, (f_in, g_out))
+
+
+def C(f, g):
+    f, g = relabel(f, g)
+    for fg in compose(f, g):
+        yield delabel(fg)
+
+
+def meta_compose(F, G):
+    for f, g in product(F, G):
+        try:
+            for result in C(f, g):
+                yield result
+        except TypeError:
+            pass
+
+
+def MC(F, G):
+    res = sorted(set(meta_compose(F, G)))
+    if not res:
+        raise TypeError('Cannot unify %r and %r.' % (F, G))
+    return res
+
+
+
+mul = [
+     ((i2, (i1, s0)), (i3, s0)),
+     ((f2, (i1, s0)), (f3, s0)),
+     ((i2, (f1, s0)), (f3, s0)),
+     ((f2, (f1, s0)), (f3, s0)),
+]
+
+
+dup = [DEFS['dup']]
+cons = [DEFS['cons']]
+
+
+sum_ = [(((Ns[1], s1), s0), (n0, s0))]
+f = [(s0, ((n1, (n2, (n3, s1))), s0))]
+
+
+print doc_from_stack_effect(*f[0]),  doc_from_stack_effect(*sum_[0])
+print '.......................'
+##for result in unify(sum_[0][0], f[0][1]):
+##    print result, '->', update(result, sum_[0][1])
+for g in MC(f, sum_):
+    print doc_from_stack_effect(*g)
+
+print
+print '.......................'
+print
+
+for g in MC(dup, mul):
+    print doc_from_stack_effect(*g)
+
+
+
+##stack_concat = lambda q, e: (q[0], stack_concat(q[1], e)) if isinstance(q, tuple) else e
+
+
+class FunctionJoyType(AnyJoyType):
+    def __init__(self, name, sec, number):
+        self.name = name
+        self.stack_effects = sec
+        self.number = number
+    def __add__(self, other):
+        return self
+    __radd__ = __add__
+
+
+class SymbolJoyType(FunctionJoyType): prefix = 'F'
+class CombinatorJoyType(FunctionJoyType): prefix = 'C'
+
+from joy.library import dip, dipd
+
+##def dip_t(stack, expression):
+##    (quote, (a1, stack)) = stack
+##    expression = stack_concat(quote, (a1, expression))
+##    return stack, expression
+
+CONS = SymbolJoyType('cons', cons, 23)
+DIP = CombinatorJoyType('dip', [dip], 44)
+DIPD = CombinatorJoyType('dipd', [dipd], 45)
+
+from itertools import chain
+
+flatten = lambda g: list(chain.from_iterable(g))
+
+def kav(F, e):
+    if not e:
+        return [F]
+
+    n, e = e
+
+    if isinstance(n, SymbolJoyType):
+        Fs = MC([F], n.stack_effects)
+        res = flatten(kav(Fn, e) for Fn in Fs)
+
+    elif isinstance(n, CombinatorJoyType):
+        res = []
+        for combinator in n.stack_effects:
+            fi, fo = F
+            new_fo, ee, _ = combinator(fo, e, {})
+            new_F = fi, new_fo
+            res.extend(kav(new_F, ee))
+    else:
+        lit = s9, (n, s9)
+        res = flatten(kav(Fn, e) for Fn in MC([F], [lit]))
+
+    return res
+
+
+##l = [(s0, ((CONS, s2), (A[1], s0)))]
+##
+##e = (DIP, ())
+##
+##h = kav(l[0], e)
+##
+##for z in h:
+##  print doc_from_stack_effect(*z)
+
+
+ID = s0, s0
+expression = (a1, ((CONS, s0), (DIP, ())))
+
+for sec in kav(ID, expression):
+  print doc_from_stack_effect(*sec)
+
+
+
+
+expression = (a1, (a3, ((CONS, s0), (DIPD, ()))))
+
+for sec in kav(ID, expression):
+  print doc_from_stack_effect(*sec)
+
+
+
+
+
+
+
+
+
+
+
+
+
index e018d61..e70cb7c 100644 (file)
@@ -34,7 +34,12 @@ class NumberJoyType(AnyJoyType): prefix = 'n'
 class FloatJoyType(NumberJoyType): prefix = 'f'
 class IntJoyType(FloatJoyType): prefix = 'i'
 
-class StackJoyType(AnyJoyType): prefix = 's'
+class StackJoyType(AnyJoyType):
+    prefix = 's'
+    def __nonzero__(self):
+        # Imitate () at the end of cons list.
+        return False
+
 
 _R = range(10)
 A = a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 = map(AnyJoyType, _R)
@@ -69,8 +74,12 @@ def delabel(f, seen=None, c=None):
         pass
 
     if not isinstance(f, tuple):
-        seen[f] = f.__class__(c[f.prefix])
-        c[f.prefix] += 1
+        try:
+            seen[f] = f.__class__(c[f.prefix])
+        except TypeError:  # FunctionJoyTypes break this.
+            seen[f] = f
+        else:
+            c[f.prefix] += 1
         return seen[f]
 
     return tuple(delabel(inner, seen, c) for inner in f)
@@ -97,7 +106,7 @@ def unify(u, v, s=None):
         if v >= u:
             s[v] = u
             return s
-        raise ValueError('Cannot unify %r and %r.' % (u, v))
+        raise TypeError('Cannot unify %r and %r.' % (u, v))
 
     if isinstance(u, tuple) and isinstance(v, tuple):
         if len(u) != len(v) != 2:
@@ -110,13 +119,13 @@ def unify(u, v, s=None):
 
     if isinstance(v, tuple):
         if not stacky(u):
-            raise ValueError('Cannot unify %r and %r.' % (u, v))
+            raise TypeError('Cannot unify %r and %r.' % (u, v))
         s[u] = v
         return s
 
     if isinstance(u, tuple):
         if not stacky(v):
-            raise ValueError('Cannot unify %r and %r.' % (v, u))
+            raise TypeError('Cannot unify %r and %r.' % (v, u))
         s[v] = u
         return s