<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns='http://www.w3.org/2005/Atom' xmlns:g='http://base.google.com/ns/1.0'>
  <title>Reasonably Polymorphic</title>
  <updated>2026-08-24T23:26:00Z</updated>
  <author><name>Sandy Maguire</name></author>
  <id>http://reasonablypolymorphic.com</id>
  <link rel='self' href='https://reasonablypolymorphic.com'/>

    <entry>
      <title>review2</title>
      <id>blog/reviewing-again/index.html</id>
      <link href='blog/reviewing-again/index.html'/>
      <published>2026-08-24T23:26:00Z</published>
      <updated>2026-08-24T23:26:00Z</updated>

      <content type="html" xml:base="https://reasonablypolymorphic.com">
        <![CDATA[
        <p>Last time, we took a stroll down memory lane to review some ancient code I wrote, and see what/how I’d do things differently now. That was fun, and I have a new banger for us today.</p>
<p>Today’s example comes from the same place — a little vim-like text editor I was working on. Vim has this “repeat” operator which just does the same thing you did last time. It’s nice. Delete a word. Running repeat deletes another word. Kinda dinky in this example, but it can also rerun “increment every number in the next four paragraphs.”</p>
<p>Anyway, so that’s the feature I was trying to duplicate. But the action I was running might have done some IO, and I didn’t want to repeat the IO (because maybe the IO was to gather some input from the user, and repeating shouldn’t ask again.)</p>
<p>I was still <a href="https://sandymaguire.me/blog/jurisdiction-of-heaven/">high on my own supply of writing monads</a>, so I approached this problem with a custom monad. The gist of the API was:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- | A monad transformer adding the ability to record the results of IO actions</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="co">-- and later replay them.</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Again</span> m a</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> <span class="dt">Monad</span> (<span class="dt">Again</span> m)</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">MonadIO</span> m <span class="ot">=&gt;</span> <span class="dt">MonadIO</span> (<span class="dt">Again</span> m)</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">MonadTrans</span> <span class="dt">Again</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Runs an action and records all of its sampled IO. Returns a action which</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="co">-- when invoked will use the recorded IO.</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>runAgain</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="ot">    ::</span> <span class="dt">Monad</span> m</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    <span class="ot">=&gt;</span> <span class="dt">Again</span> m a</span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> m (m a)</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Marks an IO action to be memoized after its first invocation.</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>again</span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="ot">    ::</span> ( <span class="dt">MonadIO</span> m</span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>       , <span class="dt">Typeable</span> r</span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>       )</span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>    <span class="ot">=&gt;</span> <span class="dt">IO</span> r</span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> <span class="dt">Again</span> m r</span></code></pre></div>
<p>I’m actually pretty impressed with past-me on this one. That’s a clean API, and the implementation was pretty cute.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Again</span> m a <span class="ot">=</span> <span class="dt">Again</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  {<span class="ot"> runAgain&#39; ::</span> <span class="dt">RWST</span> () [<span class="dt">Dynamic</span>] [<span class="dt">Dynamic</span>] m a</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>once</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="ot">    ::</span> <span class="kw">forall</span> m r</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>     <span class="op">.</span> ( <span class="dt">MonadIO</span> m</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>       , <span class="dt">Typeable</span> r</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>)</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>    <span class="ot">=&gt;</span> <span class="dt">IO</span> r</span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> <span class="dt">Again</span> m r</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>once action <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>    a <span class="ot">&lt;-</span> dequeue <span class="op">&gt;&gt;=</span> \<span class="kw">case</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Just</span> x  <span class="ot">-&gt;</span> <span class="fu">return</span> <span class="op">.</span> fromJust <span class="op">$</span> fromDynamic x</span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Nothing</span> <span class="ot">-&gt;</span> liftIO action</span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>    tell [toDyn a]</span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>    <span class="fu">return</span> a</span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">where</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a><span class="ot">    dequeue ::</span> <span class="dt">MonadState</span> [r] m <span class="ot">=&gt;</span> m (<span class="dt">Maybe</span> r)</span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>    dequeue <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>        get <span class="op">&gt;&gt;=</span> \<span class="kw">case</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a>            []     <span class="ot">-&gt;</span> <span class="fu">return</span> <span class="dt">Nothing</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a>            (x<span class="op">:</span>xs) <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a>                put xs</span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a>                <span class="fu">return</span> <span class="op">$</span> <span class="dt">Just</span> x</span></code></pre></div>
<p>The trick here is to keep <code>MonadState [Dynamic]</code> and a <code>MonadWriter [Dynamic]</code> instances around. This code uses the <code>MonadState</code> to pop off IO actions it’s already run, and the <code>MonadWriter</code> to keep track of new IO actions it needs to cache. The “magic” happens in <code>runAgain</code>, which runs it through once with an empty state, and then returns a new action with the MonadWriter results moved into the state for the next time around:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>runAgain</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="ot">    ::</span> <span class="dt">Monad</span> m</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    <span class="ot">=&gt;</span> <span class="dt">Again</span> m a</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> m (m a)</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>runAgain action <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    (a, w) <span class="ot">&lt;-</span> evalRWST (runAgain&#39; action) () []</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>    <span class="fu">return</span> <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>        evalRWST (runAgain&#39; action) () w</span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>        <span class="fu">return</span> a</span></code></pre></div>
<p>Simple. Clean. Elegant. Too bad it doesn’t actually work.</p>
<p>The following program crashes with an error coming from the unsafe use of <code>fromJust</code> in <code>once</code>:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ot">oops ::</span> <span class="dt">Again</span> (<span class="dt">StateT</span> <span class="dt">Bool</span> <span class="dt">IO</span>) ()</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>oops <span class="ot">=</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Branch on the StateT</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  lift get <span class="op">&gt;&gt;=</span> \<span class="kw">case</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">-- The first time around...</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">False</span> <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>      <span class="co">-- Cache a unit value</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>      once <span class="op">$</span> <span class="fu">print</span> ()</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>      <span class="co">-- Change the state value</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>      lift <span class="op">$</span> put <span class="dt">True</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>    <span class="co">-- Since the state changed at the end of the first branch, we will take this</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>    <span class="co">-- branch the second time around...</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>    <span class="dt">True</span> <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>      <span class="co">-- Calling &#39;once&#39; the second time around gets its value from the cache,</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>      <span class="co">-- which has type @()@. But at this callsite, it ought to have type</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>      <span class="co">-- @Bool -&gt; Bool@. Uh oh!</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>      f <span class="ot">&lt;-</span> once <span class="op">$</span> <span class="fu">pure</span> <span class="fu">not</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a>      lift <span class="op">$</span> <span class="fu">print</span> (<span class="st">&quot;uh oh!&quot;</span>, f <span class="dt">True</span>)</span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a><span class="ot">ohNo ::</span> <span class="dt">IO</span> ((), <span class="dt">Bool</span>)</span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true" tabindex="-1"></a>ohNo <span class="ot">=</span> <span class="fu">flip</span> runStateT <span class="dt">False</span> <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true" tabindex="-1"></a>  m <span class="ot">&lt;-</span> runAgain oops</span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true" tabindex="-1"></a>  m</span></code></pre></div>
<p>The attack here comes from the fact that we can force the <code>Again</code> program down a different code path its second time around. And that second time, it encounters a call to <code>once</code> which has a different type than the one it cached. Thus, trying to reuse the cache leads to what is effectively a type error at runtime.</p>
<p>What actually went wrong here? The problem is that <a href="https://chrispenner.ca/posts/expressiveness-spectrum">monads are too powerful</a>. Since the only way to compose monads is via bind (<code>m a -&gt; (a -&gt; m b) -&gt; m b</code>), we are forced to extend a monadic value of type <code>m a</code> by a <em>function</em> of type <code>a -&gt; m b</code>. Which is to say that the “next thing to do” in a monadic computation is always going to be a function. And functions are completely opaque. So, once we’re given a monad, there’s simply no way to know what it’s going to do without actually running the continuation.</p>
<p>The problem arises from the fact that that continuation can invisibly branch. My <code>Again</code> monad was attempting to <em>statically analyze</em> the monadic computation, and cache the IO results in a queue. But as <code>oops</code> shows, it’s trivial to break this sort of static analysis. Because the branch is hidden inside of a function, and there’s no way to determine which branches a function <em>didn’t take.</em></p>
<p>But I didn’t know that eleven years ago, so I give myself a pass on this one. Nevertheless, let’s tackle this problem with the wisdom of ages.</p>
<h2 id="no-more-monads">No More Monads</h2>
<p>So if the problem with my previous implementation of <code>Again</code> is that it’s a monad, what options do we have? As it happens, there are two very nice options available to us here: <em>arrows</em> and <em>selective applicative functors.</em> We’ll discuss arrows for now, and come back to selectives.</p>
<p>Long time readers might remember a <a href="/tags/yampa.html">series on arrows from a few years back.</a> But if you don’t, that’s OK; you’re still welcome here. A quick recap:</p>
<p>Arrows are a generalization of functions. Like functions, they take two type parameters (an input and an output). Like functions, they come with an identity arrow. They compose “end to end” just like functions do. These three properties are expressed as a <code>Category</code> superclass, which we usually call <code>c</code> and write infix:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="dt">Category</span> (<span class="ot">c ::</span> <span class="dt">Type</span> <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="ot">-&gt;</span> <span class="dt">Type</span>) <span class="kw">where</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  id  ::</span> x <span class="ot">`c`</span> x</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="ot">  (.) ::</span> (y <span class="ot">`c`</span> z) <span class="ot">-&gt;</span> (x <span class="ot">`c`</span> y) <span class="ot">-&gt;</span> (x <span class="ot">`c`</span> z)</span></code></pre></div>
<p>In addition to being categories, arrows also come with a means of transforming regular functions into arrows, and of mapping arrows over pairs:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="dt">Category</span> c <span class="ot">=&gt;</span> <span class="dt">Arrow</span> c <span class="kw">where</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  arr ::</span> (x <span class="ot">-&gt;</span> y) <span class="ot">-&gt;</span> (x <span class="ot">`c`</span> y)</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="ot">  (***) ::</span> (x <span class="ot">`c`</span> x&#39;) <span class="ot">-&gt;</span> (y <span class="ot">`c`</span> y&#39;) <span class="ot">-&gt;</span> ((x, y) <span class="ot">`c`</span> (x&#39;, y&#39;))</span></code></pre></div>
<p>What’s neat about arrows is that their values are function-like things, rather than being <em>actually functions.</em> That means when we compose arrows, we compose values whose internals we get to choose. Which in turn, means that static analysis is possible again!</p>
<p>Attentive readers will notice that there isn’t actually any way for arrows-as-such to be able to branch. To gain that capability, they require an additional <code>ArrowChoice</code>, which equips them with the ability to lift arrows over <code>Either</code>:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="dt">Arrow</span> c <span class="ot">=&gt;</span> <span class="dt">ArrowChoice</span> c <span class="kw">where</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  (+++) ::</span> (x <span class="ot">`c`</span> x&#39;) <span class="ot">-&gt;</span> (y <span class="ot">`c`</span> y&#39;) <span class="ot">-&gt;</span> (<span class="dt">Either</span> x y <span class="ot">`c`</span> <span class="dt">Either</span> x&#39; y&#39;)</span></code></pre></div>
<p>To wet our whistle, let’s write a little helper <code>Arrow</code> that shows that the composition of an applicative functor with an arrow is itself an arrow:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Static</span> m c x y <span class="ot">=</span> <span class="dt">Static</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>  {<span class="ot"> unStatic ::</span> m (c x y)</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>  }</span></code></pre></div>
<p>The arrow instances for <code>(Applicative m, Arrow c) =&gt; Static m c</code> are the usual trick of using applicative functions to lift operations into the right place. For example, identity is just <code>pure id, and composition is</code>liftA2` of composition:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">Category</span> c, <span class="dt">Applicative</span> m) <span class="ot">=&gt;</span> <span class="dt">Category</span> (<span class="dt">Static</span> m c) <span class="kw">where</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>  <span class="fu">id</span> <span class="ot">=</span> <span class="dt">Static</span> <span class="op">$</span> <span class="fu">pure</span> <span class="fu">id</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Static</span> g <span class="op">.</span> <span class="dt">Static</span> f <span class="ot">=</span> <span class="dt">Static</span> <span class="op">$</span> liftA2 (<span class="op">.</span>) g f</span></code></pre></div>
<p>We can do the same trick for <code>arr</code> and <code>(***)</code>:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">Arrow</span> c, <span class="dt">Applicative</span> m) <span class="ot">=&gt;</span> <span class="dt">Arrow</span> (<span class="dt">Static</span> m c) <span class="kw">where</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>  arr <span class="ot">=</span> <span class="dt">Static</span> <span class="op">.</span> <span class="fu">pure</span> <span class="op">.</span> arr</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Static</span> f <span class="op">***</span> <span class="dt">Static</span> g <span class="ot">=</span> <span class="dt">Static</span> <span class="op">$</span> liftA2 (<span class="op">***</span>) f g</span></code></pre></div>
<p>as well as for <code>(+++)</code>:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">ArrowChoice</span> c, <span class="dt">Applicative</span> m) <span class="ot">=&gt;</span> <span class="dt">ArrowChoice</span> (<span class="dt">Static</span> m c) <span class="kw">where</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Static</span> f <span class="op">+++</span> <span class="dt">Static</span> g <span class="ot">=</span> <span class="dt">Static</span> <span class="op">$</span> liftA2 (<span class="op">+++</span>) f g</span></code></pre></div>
<p>What’s nice about this <code>Static</code> construct we’ve built is that it gives us two degrees of freedom. We’re free to choose an arrow whose structure we’re going to reuse, and an underlying applicative functor (which can give us “static” effects as we’re <em>building</em> the underlying arrow.)</p>
<p>The idea here is that we can put the cache-<em>building</em> machinery inside of the applicative functor, but the cache-<em>reading</em> machinery inside of the underlying arrow.</p>
<h3 id="constructing-again-again">Constructing Again, Again</h3>
<p>It’s worth knowing about the Kleisli arrow:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Kleisli</span> m a b <span class="ot">=</span> <span class="dt">Kleisli</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>  {<span class="ot"> runKleisli ::</span> a <span class="ot">-&gt;</span> m b</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> <span class="dt">Category</span> (<span class="dt">Kleisli</span> m)</span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> <span class="dt">Arrow</span> (<span class="dt">Kleisli</span> m)</span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> <span class="dt">ArrowChoice</span> (<span class="dt">Kleisli</span> m)</span></code></pre></div>
<p>which says that any monadic bind function is itself an arrow. Implementing the instances yourself is a fun exercise if you’re new to this stuff. We can reuse <code>Kleisli</code> as our underlying arrow, which when you expand everything out, we get:</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Again</span> m a b <span class="ot">=</span> <span class="dt">Again</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>  {<span class="ot"> unAgain ::</span> <span class="dt">Static</span> m (<span class="dt">Kleisli</span> m) a b</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> <span class="kw">newtype</span> (<span class="dt">Category</span>, <span class="dt">Arrow</span>, <span class="dt">ArrowChoice</span>)</span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a><span class="ot">runAgain ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> <span class="dt">Again</span> m a b <span class="ot">-&gt;</span> m (a <span class="ot">-&gt;</span> m b)</span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>runAgain <span class="ot">=</span> <span class="fu">fmap</span> runKleisli <span class="op">.</span> unStatic <span class="op">.</span> unAgain</span></code></pre></div>
<p>What I think is particularly cool about this is that <code>runAgain</code> is just the composition of the newtype unwrappers, and yet its type is extremely reminiscent of my ten-year-ago implementation:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>runAgain  <span class="co">-- the original</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="ot">    ::</span> <span class="dt">Monad</span> m</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>    <span class="ot">=&gt;</span> <span class="dt">Again</span> m a</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> m (m a)</span></code></pre></div>
<p>This is an instance of a more general principle, which is that the final “observation” you want to make of your type is always a good <em>representation</em> of that type. It’s not the only representation, but it’s always a reasonable choice. Appropriately enough, this is known as a <em>final encoding.</em></p>
<p>Anyway. How can we implement <code>once</code>? By way of <code>onceF</code>:</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="ot">onceF ::</span> (<span class="dt">MonadIO</span> m, <span class="dt">Ord</span> a) <span class="ot">=&gt;</span> (a <span class="ot">-&gt;</span> <span class="dt">IO</span> b) <span class="ot">-&gt;</span> <span class="dt">Again</span> m a b</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>onceF m <span class="ot">=</span> <span class="dt">Again</span> <span class="op">$</span> <span class="dt">Static</span> <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>  cache <span class="ot">&lt;-</span> liftIO <span class="op">$</span> newIORef <span class="fu">mempty</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>  <span class="fu">pure</span> <span class="op">$</span> <span class="dt">Kleisli</span> <span class="op">$</span> \a <span class="ot">-&gt;</span> liftIO <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>    cacheMap <span class="ot">&lt;-</span> readIORef cache</span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">case</span> M.lookup a cacheMap <span class="kw">of</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>      <span class="dt">Just</span> b <span class="ot">-&gt;</span> <span class="fu">pure</span> b</span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>      <span class="dt">Nothing</span> <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a>        b <span class="ot">&lt;-</span> m a</span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a>        modifyIORef&#39; cache <span class="op">$</span> M.insert a b</span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a>        <span class="fu">pure</span> b</span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a><span class="ot">once ::</span> <span class="dt">MonadIO</span> m <span class="ot">=&gt;</span> <span class="dt">IO</span> b <span class="ot">-&gt;</span> <span class="dt">Again</span> m a b</span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true" tabindex="-1"></a>once m <span class="ot">=</span> arr (<span class="fu">const</span> ()) <span class="op">&gt;&gt;&gt;</span> onceF (<span class="fu">const</span> m)</span></code></pre></div>
<p><code>onceF</code> works by constructing a <code>cache :: IORef (Map a b)</code> at the <code>Static</code> level. Each call to <code>onceF</code> gets a unique cache. Then we drop into the implementation of the <code>Kleisli</code> arrow (which recall happens at <em>runtime</em>.) Inside the <code>Kleisli</code>, we check to see if the map has a value at the requested <code>a</code>, and if so, return the cached <code>b</code>. If not, we run our function and cache it.</p>
<p>Since there’s no <code>Dynamic</code> tomfoolery here that is existentializing away our types, we don’t need to worry about the <code>oops</code> attack; Haskell’s type system guarantees we can’t construct such a thing.</p>
<p>Because <code>Again</code> isn’t a <code>Monad</code>, it can’t be a <code>MonadIO</code> either. But it’s nice to be able to provide the equivalent of <code>liftIO</code>:</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="ot">againF ::</span> <span class="dt">MonadIO</span> m <span class="ot">=&gt;</span> (a <span class="ot">-&gt;</span> <span class="dt">IO</span> b) <span class="ot">-&gt;</span> <span class="dt">Again</span> m a b</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>againF <span class="ot">=</span> <span class="dt">Again</span> <span class="op">.</span> <span class="dt">Static</span> <span class="op">.</span> <span class="fu">pure</span> <span class="op">.</span> <span class="dt">Kleisli</span> <span class="op">.</span> <span class="fu">fmap</span> liftIO</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a><span class="ot">again ::</span> <span class="dt">MonadIO</span> m <span class="ot">=&gt;</span> <span class="dt">IO</span> a <span class="ot">-&gt;</span> <span class="dt">Again</span> m x a</span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>again m <span class="ot">=</span> arr (<span class="fu">const</span> ()) <span class="op">&gt;&gt;&gt;</span> againF (<span class="fu">const</span> m)</span></code></pre></div>
<p>So that completes our arrow-based implementation of <code>Again</code>. But there’s still something left undone.</p>
<h3 id="circling-back-to-selectives">Circling Back to Selectives</h3>
<p>I said earlier that selective applicative functors would be an alternative approach to implementing <code>Again</code>. Selectives rightfully sit between <code>Applicative</code> and <code>Monad</code> in the functor hierarchy, but were <a href="https://dl.acm.org/doi/10.1145/3341694">discovered too late</a>, and everyone was still kind of annoyed about having had just stuck <code>Applicative</code> into the hierarchy.</p>
<p>What, precisely is a selective functor? It’s a different solution to the problem of “monads are too powerful” which gives us a branching primitive to play with. Behold:</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="dt">Applicative</span> f <span class="ot">=&gt;</span> <span class="dt">Selective</span> f <span class="kw">where</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  select ::</span> f (<span class="dt">Either</span> a b) <span class="ot">-&gt;</span> f (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> f b</span></code></pre></div>
<p><code>select</code> says that you might have an <code>a</code>, in which case you must run the provided <code>f (a -&gt; b)</code>. But maybe you have a <code>b</code>, in which case you <em>may</em> run the effects of the <code>f (a -&gt; b)</code>. But nobody’s forcing you to.</p>
<p>Since there are still no raw function continuations to be seen here, we can use <code>select</code> to provide branching to our programs. But all of the branches can be identified statically, since we’re only operating on <code>f</code> values, again, whose internals we can control.</p>
<p>In fact, by aggressively nesting <code>select</code> calls, you can get back a version of monadic bind — so long as you have a finite number of select calls you’d need to make:</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>bindS</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="ot">    ::</span> (<span class="dt">Selective</span> f, <span class="dt">Enum</span> a, <span class="dt">Bounded</span> a, <span class="dt">Eq</span> a)</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>    <span class="ot">=&gt;</span> f a</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> f b)</span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> f b</span></code></pre></div>
<p>(the implementation of which is fun if you’re looking for a challenge)</p>
<p>Anyway, all of this is to say that we could have equally structured our <code>Again</code> as a selective functor rather than as an arrow! But <code>ArrowChoice</code> is at least as powerful as <code>Selective</code>, so given all of our hard work already, we can pull out a <code>Selective</code> instance for free.</p>
<p>What do I mean when I say “at least as powerful?” It means we can derive it for free, given an <code>ArrowChoice</code> instance. Behold, the <code>GenericArrow</code> newtype, which exists only for us to have something to attach some instances to.</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">GenericArrow</span> c x a <span class="ot">=</span> <span class="dt">GenericArrow</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>  {<span class="ot"> unGenericArrow ::</span> c x a</span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> <span class="kw">newtype</span> (<span class="dt">Category</span>, <span class="dt">Arrow</span>, <span class="dt">ArrowChoice</span>)</span></code></pre></div>
<p>Here we use newtype deriving to say that if <code>c</code> is a category/arrow/arrowchoice, then <code>GenericArrow c</code> is too. But now we can show that having <code>Arrow</code> is enough to get <code>Functor</code> and <code>Applicative</code> instance:</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Arrow</span> c <span class="ot">=&gt;</span> <span class="dt">Functor</span> (<span class="dt">GenericArrow</span> c x) <span class="kw">where</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>  <span class="fu">fmap</span> f c <span class="ot">=</span> arr f <span class="op">.</span> c</span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Arrow</span> c <span class="ot">=&gt;</span> <span class="dt">Applicative</span> (<span class="dt">GenericArrow</span> c x) <span class="kw">where</span></span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a>  <span class="fu">pure</span> <span class="ot">=</span> arr <span class="op">.</span> <span class="fu">const</span></span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a>  liftA2 f x y <span class="ot">=</span> (x <span class="op">&amp;&amp;&amp;</span> y) <span class="op">&gt;&gt;&gt;</span> arr (<span class="fu">uncurry</span> f)</span></code></pre></div>
<p>Then, given an <code>ArrowChoice</code>, we can get an implementation of <code>select</code>:</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">ArrowChoice</span> c <span class="ot">=&gt;</span> <span class="dt">Selective</span> (<span class="dt">GenericArrow</span> c x) <span class="kw">where</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>  select te tk <span class="ot">=</span> proc b <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>    e <span class="ot">&lt;-</span> te <span class="op">-&lt;</span> b</span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">case</span> e <span class="kw">of</span></span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>      <span class="dt">Left</span> x <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>        k <span class="ot">&lt;-</span> tk <span class="op">-&lt;</span> b</span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>        returnA <span class="op">-&lt;</span> k x</span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a>      <span class="dt">Right</span> y <span class="ot">-&gt;</span> returnA <span class="op">-&lt;</span> y</span></code></pre></div>
<p>Here we don’t have the option of choosing to invoke <code>tk</code> in the <code>Right</code> case. But that’s OK, because in <code>Again</code>, doing so would correspond to creating caches for branches that don’t need it.</p>
<p>Given all of this, we can now derive <code>Functor</code> up to <code>Selective</code> for <code>Again</code>:</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Again</span> m a b <span class="ot">=</span> <span class="dt">Again</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>  {<span class="ot"> unAgain ::</span> <span class="dt">Static</span> m (<span class="dt">Kleisli</span> m) a b</span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> <span class="kw">newtype</span> (<span class="dt">Category</span>, <span class="dt">Arrow</span>, <span class="dt">ArrowChoice</span>)</span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> (<span class="dt">Functor</span>, <span class="dt">Applicative</span>, <span class="dt">Selective</span>) via <span class="dt">GenericArrow</span> (<span class="dt">Again</span> m) a</span></code></pre></div>
<p>which means that users can now choose between the arrow hierarchy and the functor hierarchy for how they’d like to think about building <code>Again</code> actions. And to nudge them even a little further, we can introduce something that looks like a monad transformer, removing the input parameter:</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">AgainT</span> m <span class="ot">=</span> <span class="dt">Again</span> m ()</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a><span class="ot">runAgainT ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> <span class="dt">AgainT</span> m a <span class="ot">-&gt;</span> m (m a)</span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>runAgainT <span class="ot">=</span> <span class="fu">fmap</span> (<span class="op">$</span> ()) <span class="op">.</span> runAgain</span></code></pre></div>
<p>Clean. Tidy. Actually works this time around.</p>
        ]]>
      </content>
    </entry>
    <entry>
      <title>Code-Reviewing My First Monad Implementation</title>
      <id>blog/reviewing-my-first-monad/index.html</id>
      <link href='blog/reviewing-my-first-monad/index.html'/>
      <published>2026-08-21T23:50:00Z</published>
      <updated>2026-08-21T23:50:00Z</updated>

      <content type="html" xml:base="https://reasonablypolymorphic.com">
        <![CDATA[
        <p>I’ve been wanting to get back into the habit of blogging, and thought a fun project would be to go back through my old code and review it as the programmer I am now. So let’s do that.</p>
<p>Eleven years ago, I was so proud to written my first monad that I typed up a big ol<a href="https://sandymaguire.me/blog/jurisdiction-of-heaven/">blog post about it.</a> This seems like a fun thing to revisit, so let’s do it.</p>
<p>To save you the trouble of reading that ancient-ass blog post, here’s the gist. Given a big piece of state, that has many smaller stateful subcomponents, for example, a <code>World</code> is full of <code>Buffer</code>s:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">World</span> <span class="ot">=</span> <span class="dt">World</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  {<span class="ot"> wBuffers ::</span> [<span class="dt">Buffer</span>]</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  ,<span class="ot"> wCurrent ::</span> <span class="dt">Int</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  ,<span class="ot"> wMode    ::</span> <span class="dt">Mode</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Buffer</span> <span class="ot">=</span> <span class="dt">Buffer</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>  {<span class="ot"> bFilename ::</span> <span class="dt">FilePath</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>  ,<span class="ot"> bContent  ::</span> <span class="dt">String</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>  }</span></code></pre></div>
<p>my monad acted like <code>StateT</code> except that you can restrict the piece of the state you’re allowed to manipulate <em>without losing the ability to look at the rest of the state.</em></p>
<p>In the blog post, this monad is called <code>Jurisdiction</code>, but at some point in the <a href="https://github.com/isovector/eden">source code</a> it got renamed to <a href="https://github.com/isovector/eden/blob/master/src/Control/Monad/Jail.hs"><code>JailT</code></a>. Cool name. Furthermore, the implementation changed rather dramatically from the blog post, so let’s chase the implementation as given. I’ll reproduce it here:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">RLens</span> r s <span class="ot">=</span> <span class="dt">Lens</span> s s r r</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">JailT</span> s r m a <span class="ot">=</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">JailT</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    {<span class="ot"> runJailT&#39; ::</span> <span class="dt">Bool</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>                <span class="ot">-&gt;</span> <span class="dt">RLens</span> r s</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>                <span class="ot">-&gt;</span> s</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>                <span class="ot">-&gt;</span> m (a, s, <span class="dt">RLens</span> r s, <span class="dt">Bool</span>) }</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">deriving</span> (<span class="dt">Functor</span>, <span class="dt">Typeable</span>)</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">Applicative</span> m, <span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">Applicative</span> (<span class="dt">JailT</span> s r m) <span class="kw">where</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>    <span class="fu">pure</span> x <span class="ot">=</span> <span class="dt">JailT</span> <span class="op">$</span> \v l s <span class="ot">-&gt;</span> <span class="fu">pure</span> (x, s, l, v)</span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>    (<span class="op">&lt;*&gt;</span>)  <span class="ot">=</span> ap</span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">Applicative</span> m, <span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">Monad</span> (<span class="dt">JailT</span> s r m) <span class="kw">where</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>    <span class="fu">return</span>   <span class="ot">=</span> <span class="fu">pure</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>    ac <span class="op">&gt;&gt;=</span> k <span class="ot">=</span> <span class="dt">JailT</span> <span class="op">$</span> \v l s <span class="ot">-&gt;</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>        <span class="kw">if</span> v</span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>            <span class="kw">then</span> <span class="kw">do</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>                (x, st&#39;, l&#39;, v&#39;) <span class="ot">&lt;-</span> runJailT&#39; ac v l s</span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>                runJailT&#39; (k x) v&#39; l&#39; st&#39;</span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a>            <span class="kw">else</span> <span class="fu">return</span> (<span class="fu">undefined</span>, s, l, v)</span></code></pre></div>
<p>Already there’s a lot to look at. The most immediate thing that strikes me is the formatting; now I’m very much a “use two spaces for indent” kind of guy — Haskell doesn’t provide many opportunities for natural linebreaks, and our horizontal space is much more limited than our vertical space. So don’t throw away your horizontal budget on initial spacing. It’s minor, but being an artisan means caring about the minor details.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">JailT</span> s r m a <span class="ot">=</span> <span class="dt">JailT</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  { runJailT&#39;</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="ot">      ::</span> <span class="dt">Bool</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>      <span class="ot">-&gt;</span> <span class="dt">RLens</span> r s</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>      <span class="ot">-&gt;</span> s</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>      <span class="ot">-&gt;</span> m (a, s, <span class="dt">RLens</span> r s, <span class="dt">Bool</span>)</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> (<span class="dt">Functor</span>, <span class="dt">Typeable</span>)</span></code></pre></div>
<p>Much nicer.</p>
<p>The other exciting thing to see in the earlier snippet is that this code comes from before the Functor-Applicative-Monad transition. Which is to say that it’s from the long long ago before <code>Applicative</code> was a superclass on <code>Monad</code>. There’s some history for you.</p>
<p>And then there is the elephant in the room. Whatever this <code>Bool</code> is being passed around by <code>runJailT'</code>, the <code>Monad</code> instance branches on it and returns <code>undefined</code> when it’s <code>False</code>. What the hell is that???? Digging into the <code>MonadPlus</code> instance provides some insight:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">Applicative</span> m, <span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">MonadPlus</span> (<span class="dt">JailT</span> s r m) <span class="kw">where</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    mplus x y <span class="ot">=</span> <span class="dt">JailT</span> <span class="op">$</span> \v l s <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>        x&#39;<span class="op">@</span>(xa, xs, xl, v&#39;) <span class="ot">&lt;-</span> runJailT&#39; x v l s</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>        <span class="kw">if</span> v&#39;</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>           <span class="kw">then</span> <span class="fu">return</span> x&#39;</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>           <span class="kw">else</span> runJailT&#39; y v l s</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    mzero <span class="ot">=</span> <span class="dt">JailT</span> <span class="op">$</span> \v l s <span class="ot">-&gt;</span> <span class="fu">return</span> (<span class="fu">undefined</span>, s, l, <span class="dt">False</span>)</span></code></pre></div>
<p>So <code>mzero</code> returns <code>undefined</code> and some <code>False</code> value, presumably which is there to try to warn someone that there’s an <code>undefined</code> floating around.</p>
<p><em>This is a stupid design.</em> If you’re ever in the business of needing to store data-which-might-not-be-valid and a separate tag stating whether or not it’s valid, a much better design here would be to just use <code>Maybe a</code> instead of <code>(a, Bool)</code>.</p>
<p>In fact, perhaps I realized this later on, because <code>runJailT</code> does exactly this logic:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">runJailT ::</span> (<span class="dt">Functor</span> m)</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>         <span class="ot">=&gt;</span> <span class="dt">JailT</span> s s m a</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>         <span class="ot">-&gt;</span> s</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>         <span class="ot">-&gt;</span> m (<span class="dt">Maybe</span> (a, s))</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>runJailT ac <span class="ot">=</span> <span class="fu">fmap</span> (\(a, s, _, v) <span class="ot">-&gt;</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>                            <span class="kw">if</span> v <span class="kw">then</span> <span class="dt">Just</span> (a, s) <span class="kw">else</span> <span class="dt">Nothing</span>)</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>                    <span class="op">.</span> runJailT&#39; ac <span class="dt">True</span> <span class="fu">id</span></span></code></pre></div>
<p>Let’s roll back a bit. The pivotal primitive of <code>JailT</code> is the aptly-named <code>jail</code>:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ot">jail ::</span> (<span class="dt">Monad</span> m)</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>     <span class="ot">=&gt;</span> <span class="dt">RLens</span> r&#39; r</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>     <span class="ot">-&gt;</span> <span class="dt">JailT</span> s r&#39; m a</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>     <span class="ot">-&gt;</span> <span class="dt">JailT</span> s r m a</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>jail l&#39; m <span class="ot">=</span> <span class="dt">JailT</span> <span class="op">$</span> \v l s <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>    (a, s&#39;, _, v&#39;) <span class="ot">&lt;-</span> runJailT&#39; m v (l <span class="op">.</span> l&#39;) s</span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>    <span class="fu">return</span> (a, s&#39;, l, v&#39;)</span></code></pre></div>
<p>Pretty reasonable definition here. I’m not sure what the idea behind <code>RLens</code> being a flipped version of <code>Lens'</code> was for. The only odd choice here is that in the big tuple returned in <code>jail</code>, <code>l</code> gets passed along unchanged. We can tell from looking at it that <code>l</code> here is the current lens we’re looking at. But <code>jail</code> is the only primitive that changes the lens, and it takes a <code>JailT</code> as an argument. Which is all to say that there isn’t anything actually stateful going on with the <code>RLens</code>. So without looking any further, I’d bet dollars to donuts that this <code>l</code> getting returned is purely vestigial and serves absolutely no purpose. Which in turn means we should be able to chop it out of the definition of <code>JailT</code>.</p>
<p>Speaking of stupid anti-patterns, here’s another one:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ot">into ::</span> <span class="dt">RLens</span> a (<span class="dt">Maybe</span> a)</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>into <span class="ot">=</span> lens fromJust (<span class="fu">const</span> <span class="dt">Just</span>)</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="ot">jailMaybe ::</span> (<span class="dt">Applicative</span> m, <span class="dt">Monad</span> m)</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>          <span class="ot">=&gt;</span> <span class="dt">RLens</span> (<span class="dt">Maybe</span> r&#39;) r</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>          <span class="ot">-&gt;</span> a</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>          <span class="ot">-&gt;</span> <span class="dt">JailT</span> s r&#39; m a</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>          <span class="ot">-&gt;</span> <span class="dt">JailT</span> s r m a</span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>jailMaybe l d m <span class="ot">=</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>    (gets <span class="op">$</span> view l) <span class="op">&gt;&gt;=</span> \<span class="kw">case</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Just</span> _  <span class="ot">-&gt;</span> jail (l <span class="op">.</span> into) m</span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Nothing</span> <span class="ot">-&gt;</span> <span class="fu">return</span> d</span></code></pre></div>
<p>This is horrendous for a few reasons. <code>into</code> is an unsafe lens that will crash if you try to read out of a <code>Nothing</code>. But then that behavior is guarded in <code>jailMaybe</code> by checking that it isn’t already nothing. Stupid.</p>
<p>The last function I want to point out is <code>parole</code>:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ot">parole ::</span> (<span class="dt">Applicative</span> m, <span class="dt">Monad</span> m)</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>       <span class="ot">=&gt;</span> a</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>       <span class="ot">-&gt;</span> <span class="dt">JailT</span> s r m (<span class="dt">Maybe</span> a)</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>       <span class="ot">-&gt;</span> <span class="dt">JailT</span> s r m a</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>parole d m <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>    this <span class="ot">&lt;-</span> get</span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>    m <span class="op">&gt;&gt;=</span> \<span class="kw">case</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Just</span> a  <span class="ot">-&gt;</span> <span class="fu">return</span> a</span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Nothing</span> <span class="ot">-&gt;</span> put this <span class="op">&gt;&gt;</span> <span class="fu">return</span> d</span></code></pre></div>
<p>which… does… something. I guess it attempts to run a <code>Maybe</code>-valued <code>JailT</code>, and if it fails, unwinds the state and returns some default <code>a</code>. Rearing its ugly head here, however, is the ghost of the <code>undefined</code> nonsense from <code>mzero</code>. Note that if we invoke <code>parole a mzero</code> we will get a <em>crash</em> rather than the roll-back-and-default behavior that it promises on the tin.</p>
<p>So, all in all, I am not particularly impressed with my first monad. Here’s how I’d write it today.</p>
<p>First, I don’t think I’ve written a “control”-y sort of monad from scratch in the last five years. Whatever behavior you want is almost always just the composition of a few monad transformers. In this case, we have a <code>Reader</code> for the current lens, a <code>State</code> for the original state, and a <code>Maybe</code> to give us <code>mzero</code> semantics.</p>
<p>Since we want our state to roll-back when we take an alternative path, we must put <code>MaybeT</code> <em>underneath</em> our <code>StateT</code>.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> This gives us the nice formulation of a <code>JailT</code> as:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">JailT</span> s r m a <span class="ot">=</span> <span class="dt">JailT</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>  {<span class="ot"> unJailT ::</span> <span class="dt">ReaderT</span> (<span class="dt">ALens&#39;</span> s r) (<span class="dt">StateT</span> s (<span class="dt">MaybeT</span> m)) a</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>  }</span></code></pre></div>
<p>(we use <code>ALens' s r</code> here instead of <code>Lens' s r</code> since the latter requires <code>-XImpredicativeTypes</code>. Which happens to be turned on in the original implementation!)</p>
<p>Once nice thing about defining our monad as a <code>newtype</code> over a series of monad transformers, is that it allows us to newtype-derive all of the relevant instances:</p>
<pre><code>  deriving newtype (Functor, Applicative, Monad, MonadIO, Alternative)</code></pre>
<p>No implementation for such things is required, and therefore we know that the derived instances must be correct. Which means we have many fewer things to worry about.</p>
<p>I prefer to use <code>unWhatever</code> as my naming scheme for these newtypes, so that I can provide <code>runWhatever</code> as a more user-friendly function.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ot">runJailT ::</span> s <span class="ot">-&gt;</span> <span class="dt">Lens&#39;</span> s t <span class="ot">-&gt;</span> <span class="dt">JailT</span> s t m a <span class="ot">-&gt;</span> m (<span class="dt">Maybe</span> (a, s))</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>runJailT s l <span class="ot">=</span> runMaybeT <span class="op">.</span> <span class="fu">flip</span> runStateT s <span class="op">.</span> <span class="fu">flip</span> runReaderT l <span class="op">.</span> unJailT</span></code></pre></div>
<p>What’s also nice about using standard monad transformers for your implementation is that you can reuse all of their existing combinators. For example, to implement <code>jail</code> all we need to do is invoke <code>withReaderT :: (r' -&gt; r) -&gt; ReaderT r m a -&gt; ReaderT r' m a</code>, which lets us change the type of the reader.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ot">jail ::</span> <span class="dt">Lens&#39;</span> t u <span class="ot">-&gt;</span> <span class="dt">JailT</span> s u m a <span class="ot">-&gt;</span> <span class="dt">JailT</span> s t m a</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>jail ltu <span class="ot">=</span> <span class="dt">JailT</span> <span class="op">.</span> withReaderT (\lst <span class="ot">-&gt;</span> cloneLens lst <span class="op">.</span> ltu) <span class="op">.</span> unJailT</span></code></pre></div>
<p>Notice here that I like to minimize my points without going point-free; <code>jail</code> as written is very legible, but writing it entirely pointfree is a crime against humanity:</p>
<pre><code>-- don&#39;t do this!
jail = (JailT .) . (. unJailT) . withReaderT . flip ((.) . cloneLens)</code></pre>
<p>Rather than implementing <code>parole</code> directly, we can note that it is the composition of two pieces — (1) attempt something, (2) return a default if it failed. Whenever you notice de-composition opportunities like this, take them!</p>
<p>We can write <code>attempt</code>, which is wildly general and doesn’t care one fig about jails or the legal system:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="ot">attempt ::</span> (<span class="dt">Alternative</span> m, <span class="dt">Monad</span> m) <span class="ot">=&gt;</span> m (<span class="dt">Maybe</span> a) <span class="ot">-&gt;</span> m a</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>attempt m <span class="ot">=</span> <span class="fu">maybe</span> empty <span class="fu">pure</span> <span class="op">=&lt;&lt;</span> m</span></code></pre></div>
<p>and then <code>parole</code> is merely</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="ot">parole ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> a <span class="ot">-&gt;</span> <span class="dt">JailT</span> s t m (<span class="dt">Maybe</span> a) <span class="ot">-&gt;</span> <span class="dt">JailT</span> s t m a</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>parole a0 j <span class="ot">=</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>  asum</span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>    [ attempt j</span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>    , <span class="fu">pure</span> a0</span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>    ]</span></code></pre></div>
<p>All in all, significantly nicer if you ask me. <a href="https://www.youtube.com/watch?v=NgUGvZkQd0M">But I’m just a TV. Don’t take my word for it.</a> Compare for yourself!</p>
<details>
<summary>
Original Implementation
</summary>
<div class="sourceCode" id="cb16"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE GeneralizedNewtypeDeriving,</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="ot">             FlexibleInstances, MultiParamTypeClasses,</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="ot">             DeriveFunctor, ImpredicativeTypes, LambdaCase,</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a><span class="ot">             DeriveDataTypeable #-}</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Applicative</span> (<span class="dt">Alternative</span>(..))</span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Monad</span> (ap, <span class="dt">MonadPlus</span>(..))</span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Monad.State</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Lens</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Maybe</span> (fromJust)</span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Typeable</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">RLens</span> r s <span class="ot">=</span> <span class="dt">Lens</span> s s r r</span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">JailT</span> s r m a <span class="ot">=</span></span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a>    <span class="dt">JailT</span></span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a>    {<span class="ot"> runJailT&#39; ::</span> <span class="dt">Bool</span></span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a>                <span class="ot">-&gt;</span> <span class="dt">RLens</span> r s</span>
<span id="cb16-20"><a href="#cb16-20" aria-hidden="true" tabindex="-1"></a>                <span class="ot">-&gt;</span> s</span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true" tabindex="-1"></a>                <span class="ot">-&gt;</span> m (a, s, <span class="dt">RLens</span> r s, <span class="dt">Bool</span>) }</span>
<span id="cb16-22"><a href="#cb16-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">deriving</span> (<span class="dt">Functor</span>, <span class="dt">Typeable</span>)</span>
<span id="cb16-23"><a href="#cb16-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-24"><a href="#cb16-24" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">Applicative</span> m, <span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">Applicative</span> (<span class="dt">JailT</span> s r m) <span class="kw">where</span></span>
<span id="cb16-25"><a href="#cb16-25" aria-hidden="true" tabindex="-1"></a>    <span class="fu">pure</span> x <span class="ot">=</span> <span class="dt">JailT</span> <span class="op">$</span> \v l s <span class="ot">-&gt;</span> <span class="fu">pure</span> (x, s, l, v)</span>
<span id="cb16-26"><a href="#cb16-26" aria-hidden="true" tabindex="-1"></a>    (<span class="op">&lt;*&gt;</span>)  <span class="ot">=</span> ap</span>
<span id="cb16-27"><a href="#cb16-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-28"><a href="#cb16-28" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">Applicative</span> m, <span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">Monad</span> (<span class="dt">JailT</span> s r m) <span class="kw">where</span></span>
<span id="cb16-29"><a href="#cb16-29" aria-hidden="true" tabindex="-1"></a>    <span class="fu">return</span>   <span class="ot">=</span> <span class="fu">pure</span></span>
<span id="cb16-30"><a href="#cb16-30" aria-hidden="true" tabindex="-1"></a>    ac <span class="op">&gt;&gt;=</span> k <span class="ot">=</span> <span class="dt">JailT</span> <span class="op">$</span> \v l s <span class="ot">-&gt;</span></span>
<span id="cb16-31"><a href="#cb16-31" aria-hidden="true" tabindex="-1"></a>        <span class="kw">if</span> v</span>
<span id="cb16-32"><a href="#cb16-32" aria-hidden="true" tabindex="-1"></a>            <span class="kw">then</span> <span class="kw">do</span></span>
<span id="cb16-33"><a href="#cb16-33" aria-hidden="true" tabindex="-1"></a>                (x, st&#39;, l&#39;, v&#39;) <span class="ot">&lt;-</span> runJailT&#39; ac v l s</span>
<span id="cb16-34"><a href="#cb16-34" aria-hidden="true" tabindex="-1"></a>                runJailT&#39; (k x) v&#39; l&#39; st&#39;</span>
<span id="cb16-35"><a href="#cb16-35" aria-hidden="true" tabindex="-1"></a>            <span class="kw">else</span> <span class="fu">return</span> (<span class="fu">undefined</span>, s, l, v)</span>
<span id="cb16-36"><a href="#cb16-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-37"><a href="#cb16-37" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">Applicative</span> m, <span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">MonadState</span> r (<span class="dt">JailT</span> s r m) <span class="kw">where</span></span>
<span id="cb16-38"><a href="#cb16-38" aria-hidden="true" tabindex="-1"></a>    get   <span class="ot">=</span> <span class="dt">JailT</span> <span class="op">$</span> \v l s <span class="ot">-&gt;</span> <span class="fu">return</span> (view l s, s, l, v)</span>
<span id="cb16-39"><a href="#cb16-39" aria-hidden="true" tabindex="-1"></a>    put x <span class="ot">=</span> <span class="dt">JailT</span> <span class="op">$</span> \v l s <span class="ot">-&gt;</span> <span class="fu">return</span> ((), set l x s, l, v)</span>
<span id="cb16-40"><a href="#cb16-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-41"><a href="#cb16-41" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">MonadTrans</span> (<span class="dt">JailT</span> s r) <span class="kw">where</span></span>
<span id="cb16-42"><a href="#cb16-42" aria-hidden="true" tabindex="-1"></a>    lift x <span class="ot">=</span> <span class="dt">JailT</span> <span class="op">$</span> \v l s <span class="ot">-&gt;</span> x <span class="op">&gt;&gt;=</span> (\a <span class="ot">-&gt;</span> <span class="fu">return</span> (a, s, l, v))</span>
<span id="cb16-43"><a href="#cb16-43" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-44"><a href="#cb16-44" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">Applicative</span> m, <span class="dt">MonadIO</span> m) <span class="ot">=&gt;</span> <span class="dt">MonadIO</span> (<span class="dt">JailT</span> s r m) <span class="kw">where</span></span>
<span id="cb16-45"><a href="#cb16-45" aria-hidden="true" tabindex="-1"></a>    liftIO <span class="ot">=</span> lift <span class="op">.</span> liftIO</span>
<span id="cb16-46"><a href="#cb16-46" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-47"><a href="#cb16-47" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">Applicative</span> m, <span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">MonadPlus</span> (<span class="dt">JailT</span> s r m) <span class="kw">where</span></span>
<span id="cb16-48"><a href="#cb16-48" aria-hidden="true" tabindex="-1"></a>    mplus x y <span class="ot">=</span> <span class="dt">JailT</span> <span class="op">$</span> \v l s <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb16-49"><a href="#cb16-49" aria-hidden="true" tabindex="-1"></a>        x&#39;<span class="op">@</span>(xa, xs, xl, v&#39;) <span class="ot">&lt;-</span> runJailT&#39; x v l s</span>
<span id="cb16-50"><a href="#cb16-50" aria-hidden="true" tabindex="-1"></a>        <span class="kw">if</span> v&#39;</span>
<span id="cb16-51"><a href="#cb16-51" aria-hidden="true" tabindex="-1"></a>           <span class="kw">then</span> <span class="fu">return</span> x&#39;</span>
<span id="cb16-52"><a href="#cb16-52" aria-hidden="true" tabindex="-1"></a>           <span class="kw">else</span> runJailT&#39; y v l s</span>
<span id="cb16-53"><a href="#cb16-53" aria-hidden="true" tabindex="-1"></a>    mzero <span class="ot">=</span> <span class="dt">JailT</span> <span class="op">$</span> \v l s <span class="ot">-&gt;</span> <span class="fu">return</span> (<span class="fu">undefined</span>, s, l, <span class="dt">False</span>)</span>
<span id="cb16-54"><a href="#cb16-54" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-55"><a href="#cb16-55" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">Applicative</span> m, <span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">Alternative</span> (<span class="dt">JailT</span> s r m) <span class="kw">where</span></span>
<span id="cb16-56"><a href="#cb16-56" aria-hidden="true" tabindex="-1"></a>    (<span class="op">&lt;|&gt;</span>) <span class="ot">=</span> mplus</span>
<span id="cb16-57"><a href="#cb16-57" aria-hidden="true" tabindex="-1"></a>    empty <span class="ot">=</span> mzero</span>
<span id="cb16-58"><a href="#cb16-58" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-59"><a href="#cb16-59" aria-hidden="true" tabindex="-1"></a><span class="ot">runJailT ::</span> (<span class="dt">Functor</span> m)</span>
<span id="cb16-60"><a href="#cb16-60" aria-hidden="true" tabindex="-1"></a>         <span class="ot">=&gt;</span> <span class="dt">JailT</span> s s m a</span>
<span id="cb16-61"><a href="#cb16-61" aria-hidden="true" tabindex="-1"></a>         <span class="ot">-&gt;</span> s</span>
<span id="cb16-62"><a href="#cb16-62" aria-hidden="true" tabindex="-1"></a>         <span class="ot">-&gt;</span> m (<span class="dt">Maybe</span> (a, s))</span>
<span id="cb16-63"><a href="#cb16-63" aria-hidden="true" tabindex="-1"></a>runJailT ac <span class="ot">=</span> <span class="fu">fmap</span> (\(a, s, _, v) <span class="ot">-&gt;</span></span>
<span id="cb16-64"><a href="#cb16-64" aria-hidden="true" tabindex="-1"></a>                            <span class="kw">if</span> v <span class="kw">then</span> <span class="dt">Just</span> (a, s) <span class="kw">else</span> <span class="dt">Nothing</span>)</span>
<span id="cb16-65"><a href="#cb16-65" aria-hidden="true" tabindex="-1"></a>                    <span class="op">.</span> runJailT&#39; ac <span class="dt">True</span> <span class="fu">id</span></span>
<span id="cb16-66"><a href="#cb16-66" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-67"><a href="#cb16-67" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Jail</span> s r <span class="ot">=</span> <span class="dt">JailT</span> s r <span class="dt">Identity</span></span>
<span id="cb16-68"><a href="#cb16-68" aria-hidden="true" tabindex="-1"></a><span class="ot">runJail ::</span> <span class="dt">Jail</span> s s a</span>
<span id="cb16-69"><a href="#cb16-69" aria-hidden="true" tabindex="-1"></a>        <span class="ot">-&gt;</span> s</span>
<span id="cb16-70"><a href="#cb16-70" aria-hidden="true" tabindex="-1"></a>        <span class="ot">-&gt;</span> <span class="dt">Maybe</span> (a, s)</span>
<span id="cb16-71"><a href="#cb16-71" aria-hidden="true" tabindex="-1"></a>runJail ac <span class="ot">=</span> runIdentity <span class="op">.</span> runJailT ac</span>
<span id="cb16-72"><a href="#cb16-72" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-73"><a href="#cb16-73" aria-hidden="true" tabindex="-1"></a><span class="ot">jail ::</span> (<span class="dt">Monad</span> m)</span>
<span id="cb16-74"><a href="#cb16-74" aria-hidden="true" tabindex="-1"></a>     <span class="ot">=&gt;</span> <span class="dt">RLens</span> r&#39; r</span>
<span id="cb16-75"><a href="#cb16-75" aria-hidden="true" tabindex="-1"></a>     <span class="ot">-&gt;</span> <span class="dt">JailT</span> s r&#39; m a</span>
<span id="cb16-76"><a href="#cb16-76" aria-hidden="true" tabindex="-1"></a>     <span class="ot">-&gt;</span> <span class="dt">JailT</span> s r m a</span>
<span id="cb16-77"><a href="#cb16-77" aria-hidden="true" tabindex="-1"></a>jail l&#39; m <span class="ot">=</span> <span class="dt">JailT</span> <span class="op">$</span> \v l s <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb16-78"><a href="#cb16-78" aria-hidden="true" tabindex="-1"></a>    (a, s&#39;, _, v&#39;) <span class="ot">&lt;-</span> runJailT&#39; m v (l <span class="op">.</span> l&#39;) s</span>
<span id="cb16-79"><a href="#cb16-79" aria-hidden="true" tabindex="-1"></a>    <span class="fu">return</span> (a, s&#39;, l, v&#39;)</span>
<span id="cb16-80"><a href="#cb16-80" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-81"><a href="#cb16-81" aria-hidden="true" tabindex="-1"></a><span class="ot">into ::</span> <span class="dt">RLens</span> a (<span class="dt">Maybe</span> a)</span>
<span id="cb16-82"><a href="#cb16-82" aria-hidden="true" tabindex="-1"></a>into <span class="ot">=</span> lens fromJust (<span class="fu">const</span> <span class="dt">Just</span>)</span>
<span id="cb16-83"><a href="#cb16-83" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-84"><a href="#cb16-84" aria-hidden="true" tabindex="-1"></a><span class="ot">jailMaybe ::</span> (<span class="dt">Applicative</span> m, <span class="dt">Monad</span> m)</span>
<span id="cb16-85"><a href="#cb16-85" aria-hidden="true" tabindex="-1"></a>          <span class="ot">=&gt;</span> <span class="dt">RLens</span> (<span class="dt">Maybe</span> r&#39;) r</span>
<span id="cb16-86"><a href="#cb16-86" aria-hidden="true" tabindex="-1"></a>          <span class="ot">-&gt;</span> a</span>
<span id="cb16-87"><a href="#cb16-87" aria-hidden="true" tabindex="-1"></a>          <span class="ot">-&gt;</span> <span class="dt">JailT</span> s r&#39; m a</span>
<span id="cb16-88"><a href="#cb16-88" aria-hidden="true" tabindex="-1"></a>          <span class="ot">-&gt;</span> <span class="dt">JailT</span> s r m a</span>
<span id="cb16-89"><a href="#cb16-89" aria-hidden="true" tabindex="-1"></a>jailMaybe l d m <span class="ot">=</span></span>
<span id="cb16-90"><a href="#cb16-90" aria-hidden="true" tabindex="-1"></a>    (gets <span class="op">$</span> view l) <span class="op">&gt;&gt;=</span> \<span class="kw">case</span></span>
<span id="cb16-91"><a href="#cb16-91" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Just</span> _  <span class="ot">-&gt;</span> jail (l <span class="op">.</span> into) m</span>
<span id="cb16-92"><a href="#cb16-92" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Nothing</span> <span class="ot">-&gt;</span> <span class="fu">return</span> d</span>
<span id="cb16-93"><a href="#cb16-93" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-94"><a href="#cb16-94" aria-hidden="true" tabindex="-1"></a><span class="ot">escape ::</span> (<span class="dt">Applicative</span> m, <span class="dt">Monad</span> m)</span>
<span id="cb16-95"><a href="#cb16-95" aria-hidden="true" tabindex="-1"></a>       <span class="ot">=&gt;</span> <span class="dt">JailT</span> s s m a</span>
<span id="cb16-96"><a href="#cb16-96" aria-hidden="true" tabindex="-1"></a>       <span class="ot">-&gt;</span> <span class="dt">JailT</span> s r m a</span>
<span id="cb16-97"><a href="#cb16-97" aria-hidden="true" tabindex="-1"></a>escape m <span class="ot">=</span> <span class="dt">JailT</span> <span class="op">$</span> \v l s <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb16-98"><a href="#cb16-98" aria-hidden="true" tabindex="-1"></a>    (a, s&#39;, _, v&#39;) <span class="ot">&lt;-</span> runJailT&#39; m v <span class="fu">id</span> s</span>
<span id="cb16-99"><a href="#cb16-99" aria-hidden="true" tabindex="-1"></a>    <span class="fu">return</span> (a, s&#39;, l, v&#39;)</span>
<span id="cb16-100"><a href="#cb16-100" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-101"><a href="#cb16-101" aria-hidden="true" tabindex="-1"></a><span class="ot">freedom ::</span> (<span class="dt">Applicative</span> m, <span class="dt">Monad</span> m) <span class="ot">=&gt;</span> <span class="dt">JailT</span> s r m s</span>
<span id="cb16-102"><a href="#cb16-102" aria-hidden="true" tabindex="-1"></a>freedom <span class="ot">=</span> <span class="dt">JailT</span> <span class="op">$</span> \v l s <span class="ot">-&gt;</span> <span class="fu">return</span> (s, s, l, v)</span>
<span id="cb16-103"><a href="#cb16-103" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-104"><a href="#cb16-104" aria-hidden="true" tabindex="-1"></a><span class="co">-- happens to be unused, because it&#39;s kinda insane??</span></span>
<span id="cb16-105"><a href="#cb16-105" aria-hidden="true" tabindex="-1"></a><span class="ot">overwrite ::</span> (<span class="dt">Applicative</span> m, <span class="dt">Monad</span> m)</span>
<span id="cb16-106"><a href="#cb16-106" aria-hidden="true" tabindex="-1"></a>          <span class="ot">=&gt;</span> <span class="dt">RLens</span> r&#39; r</span>
<span id="cb16-107"><a href="#cb16-107" aria-hidden="true" tabindex="-1"></a>          <span class="ot">-&gt;</span> <span class="dt">JailT</span> r r&#39; m a</span>
<span id="cb16-108"><a href="#cb16-108" aria-hidden="true" tabindex="-1"></a>          <span class="ot">-&gt;</span> <span class="dt">JailT</span> s r m a</span>
<span id="cb16-109"><a href="#cb16-109" aria-hidden="true" tabindex="-1"></a>overwrite l&#39; m <span class="ot">=</span> <span class="dt">JailT</span> <span class="op">$</span> \v l s <span class="ot">-&gt;</span> <span class="kw">do</span></span>
<span id="cb16-110"><a href="#cb16-110" aria-hidden="true" tabindex="-1"></a>    (a, s&#39;, _, v&#39;) <span class="ot">&lt;-</span> runJailT&#39; m v l&#39; <span class="op">$</span> view l s</span>
<span id="cb16-111"><a href="#cb16-111" aria-hidden="true" tabindex="-1"></a>    <span class="fu">return</span> (a, set l s&#39; s, l, v&#39;)</span>
<span id="cb16-112"><a href="#cb16-112" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-113"><a href="#cb16-113" aria-hidden="true" tabindex="-1"></a><span class="ot">parole ::</span> (<span class="dt">Applicative</span> m, <span class="dt">Monad</span> m)</span>
<span id="cb16-114"><a href="#cb16-114" aria-hidden="true" tabindex="-1"></a>       <span class="ot">=&gt;</span> a</span>
<span id="cb16-115"><a href="#cb16-115" aria-hidden="true" tabindex="-1"></a>       <span class="ot">-&gt;</span> <span class="dt">JailT</span> s r m (<span class="dt">Maybe</span> a)</span>
<span id="cb16-116"><a href="#cb16-116" aria-hidden="true" tabindex="-1"></a>       <span class="ot">-&gt;</span> <span class="dt">JailT</span> s r m a</span>
<span id="cb16-117"><a href="#cb16-117" aria-hidden="true" tabindex="-1"></a>parole d m <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb16-118"><a href="#cb16-118" aria-hidden="true" tabindex="-1"></a>    this <span class="ot">&lt;-</span> get</span>
<span id="cb16-119"><a href="#cb16-119" aria-hidden="true" tabindex="-1"></a>    m <span class="op">&gt;&gt;=</span> \<span class="kw">case</span></span>
<span id="cb16-120"><a href="#cb16-120" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Just</span> a  <span class="ot">-&gt;</span> <span class="fu">return</span> a</span>
<span id="cb16-121"><a href="#cb16-121" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Nothing</span> <span class="ot">-&gt;</span> put this <span class="op">&gt;&gt;</span> <span class="fu">return</span> d</span>
<span id="cb16-122"><a href="#cb16-122" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-123"><a href="#cb16-123" aria-hidden="true" tabindex="-1"></a><span class="ot">inspect ::</span> (<span class="dt">Applicative</span> m, <span class="dt">Monad</span> m)</span>
<span id="cb16-124"><a href="#cb16-124" aria-hidden="true" tabindex="-1"></a>        <span class="ot">=&gt;</span> <span class="dt">RLens</span> i r</span>
<span id="cb16-125"><a href="#cb16-125" aria-hidden="true" tabindex="-1"></a>        <span class="ot">-&gt;</span> <span class="dt">JailT</span> s r m i</span>
<span id="cb16-126"><a href="#cb16-126" aria-hidden="true" tabindex="-1"></a>inspect l <span class="ot">=</span> gets <span class="op">$</span> view l</span>
<span id="cb16-127"><a href="#cb16-127" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-128"><a href="#cb16-128" aria-hidden="true" tabindex="-1"></a><span class="ot">inquire ::</span> (<span class="dt">Applicative</span> m, <span class="dt">Monad</span> m)</span>
<span id="cb16-129"><a href="#cb16-129" aria-hidden="true" tabindex="-1"></a>        <span class="ot">=&gt;</span> <span class="dt">RLens</span> i s</span>
<span id="cb16-130"><a href="#cb16-130" aria-hidden="true" tabindex="-1"></a>        <span class="ot">-&gt;</span> <span class="dt">JailT</span> s r m i</span>
<span id="cb16-131"><a href="#cb16-131" aria-hidden="true" tabindex="-1"></a>inquire l <span class="ot">=</span> view l <span class="op">&lt;$&gt;</span> freedom</span>
<span id="cb16-132"><a href="#cb16-132" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-133"><a href="#cb16-133" aria-hidden="true" tabindex="-1"></a><span class="ot">arrest ::</span> (<span class="dt">Applicative</span> m, <span class="dt">Monad</span> m)</span>
<span id="cb16-134"><a href="#cb16-134" aria-hidden="true" tabindex="-1"></a>       <span class="ot">=&gt;</span> <span class="dt">RLens</span> r&#39; r</span>
<span id="cb16-135"><a href="#cb16-135" aria-hidden="true" tabindex="-1"></a>       <span class="ot">-&gt;</span> r&#39;</span>
<span id="cb16-136"><a href="#cb16-136" aria-hidden="true" tabindex="-1"></a>       <span class="ot">-&gt;</span> <span class="dt">JailT</span> s r m ()</span>
<span id="cb16-137"><a href="#cb16-137" aria-hidden="true" tabindex="-1"></a>arrest l v <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb16-138"><a href="#cb16-138" aria-hidden="true" tabindex="-1"></a>    state <span class="ot">&lt;-</span> get</span>
<span id="cb16-139"><a href="#cb16-139" aria-hidden="true" tabindex="-1"></a>    put <span class="op">$</span> set l v state</span>
<span id="cb16-140"><a href="#cb16-140" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-141"><a href="#cb16-141" aria-hidden="true" tabindex="-1"></a><span class="ot">arrests ::</span> (<span class="dt">Applicative</span> m, <span class="dt">Monad</span> m)</span>
<span id="cb16-142"><a href="#cb16-142" aria-hidden="true" tabindex="-1"></a>        <span class="ot">=&gt;</span> <span class="dt">RLens</span> r&#39; r</span>
<span id="cb16-143"><a href="#cb16-143" aria-hidden="true" tabindex="-1"></a>        <span class="ot">-&gt;</span> (r&#39; <span class="ot">-&gt;</span> r&#39;)</span>
<span id="cb16-144"><a href="#cb16-144" aria-hidden="true" tabindex="-1"></a>        <span class="ot">-&gt;</span> <span class="dt">JailT</span> s r m ()</span>
<span id="cb16-145"><a href="#cb16-145" aria-hidden="true" tabindex="-1"></a>arrests l f <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb16-146"><a href="#cb16-146" aria-hidden="true" tabindex="-1"></a>    state <span class="ot">&lt;-</span> get</span>
<span id="cb16-147"><a href="#cb16-147" aria-hidden="true" tabindex="-1"></a>    put <span class="op">$</span> set l (f <span class="op">$</span> view l state) state</span></code></pre></div>
</details>
<p>vs the</p>
<details>
<summary>
New Implementation
</summary>
<div class="sourceCode" id="cb17"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE DerivingStrategies         #-}</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE FlexibleInstances          #-}</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE GeneralizedNewtypeDeriving #-}</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE MultiParamTypeClasses      #-}</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE RankNTypes                 #-}</span></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Applicative</span></span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Lens</span></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Monad.State</span></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Monad.Reader</span></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Monad.Trans.Maybe</span></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">JailT</span> s r m a <span class="ot">=</span> <span class="dt">JailT</span></span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>  {<span class="ot"> unJailT ::</span> <span class="dt">ReaderT</span> (<span class="dt">ALens&#39;</span> s r) (<span class="dt">StateT</span> s (<span class="dt">MaybeT</span> m)) a</span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb17-17"><a href="#cb17-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> <span class="kw">newtype</span> (<span class="dt">Functor</span>, <span class="dt">Applicative</span>, <span class="dt">Monad</span>, <span class="dt">MonadIO</span>, <span class="dt">Alternative</span>)</span>
<span id="cb17-18"><a href="#cb17-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-19"><a href="#cb17-19" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> <span class="dt">MonadState</span> r (<span class="dt">JailT</span> s r m) <span class="kw">where</span></span>
<span id="cb17-20"><a href="#cb17-20" aria-hidden="true" tabindex="-1"></a>  get <span class="ot">=</span> <span class="dt">JailT</span> <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb17-21"><a href="#cb17-21" aria-hidden="true" tabindex="-1"></a>    l <span class="ot">&lt;-</span> asks cloneLens</span>
<span id="cb17-22"><a href="#cb17-22" aria-hidden="true" tabindex="-1"></a>    gets <span class="op">$</span> view l</span>
<span id="cb17-23"><a href="#cb17-23" aria-hidden="true" tabindex="-1"></a>  put r <span class="ot">=</span> <span class="dt">JailT</span> <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb17-24"><a href="#cb17-24" aria-hidden="true" tabindex="-1"></a>    l <span class="ot">&lt;-</span> asks cloneLens</span>
<span id="cb17-25"><a href="#cb17-25" aria-hidden="true" tabindex="-1"></a>    modify <span class="op">$</span> set l r</span>
<span id="cb17-26"><a href="#cb17-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-27"><a href="#cb17-27" aria-hidden="true" tabindex="-1"></a><span class="ot">runJailT ::</span> s <span class="ot">-&gt;</span> <span class="dt">Lens&#39;</span> s t <span class="ot">-&gt;</span> <span class="dt">JailT</span> s t m a <span class="ot">-&gt;</span> m (<span class="dt">Maybe</span> (a, s))</span>
<span id="cb17-28"><a href="#cb17-28" aria-hidden="true" tabindex="-1"></a>runJailT s l <span class="ot">=</span> runMaybeT <span class="op">.</span> <span class="fu">flip</span> runStateT s <span class="op">.</span> <span class="fu">flip</span> runReaderT l <span class="op">.</span> unJailT</span>
<span id="cb17-29"><a href="#cb17-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-30"><a href="#cb17-30" aria-hidden="true" tabindex="-1"></a><span class="ot">jail ::</span> <span class="dt">Lens&#39;</span> t u <span class="ot">-&gt;</span> <span class="dt">JailT</span> s u m a <span class="ot">-&gt;</span> <span class="dt">JailT</span> s t m a</span>
<span id="cb17-31"><a href="#cb17-31" aria-hidden="true" tabindex="-1"></a>jail ltu <span class="ot">=</span> <span class="dt">JailT</span> <span class="op">.</span> withReaderT (\lst <span class="ot">-&gt;</span> cloneLens lst <span class="op">.</span> ltu) <span class="op">.</span> unJailT</span>
<span id="cb17-32"><a href="#cb17-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-33"><a href="#cb17-33" aria-hidden="true" tabindex="-1"></a><span class="ot">escape ::</span> <span class="dt">JailT</span> s s m a <span class="ot">-&gt;</span> <span class="dt">JailT</span> s t m a</span>
<span id="cb17-34"><a href="#cb17-34" aria-hidden="true" tabindex="-1"></a>escape (<span class="dt">JailT</span> j) <span class="ot">=</span> <span class="dt">JailT</span> <span class="op">$</span> withReaderT (<span class="fu">const</span> <span class="fu">id</span>) j</span>
<span id="cb17-35"><a href="#cb17-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-36"><a href="#cb17-36" aria-hidden="true" tabindex="-1"></a><span class="ot">freedom ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> <span class="dt">JailT</span> s t m s</span>
<span id="cb17-37"><a href="#cb17-37" aria-hidden="true" tabindex="-1"></a>freedom <span class="ot">=</span> <span class="dt">JailT</span> get</span>
<span id="cb17-38"><a href="#cb17-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-39"><a href="#cb17-39" aria-hidden="true" tabindex="-1"></a><span class="ot">attempt ::</span> (<span class="dt">Alternative</span> m, <span class="dt">Monad</span> m) <span class="ot">=&gt;</span> m (<span class="dt">Maybe</span> a) <span class="ot">-&gt;</span> m a</span>
<span id="cb17-40"><a href="#cb17-40" aria-hidden="true" tabindex="-1"></a>attempt m <span class="ot">=</span> <span class="fu">maybe</span> empty <span class="fu">pure</span> <span class="op">=&lt;&lt;</span> m</span>
<span id="cb17-41"><a href="#cb17-41" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-42"><a href="#cb17-42" aria-hidden="true" tabindex="-1"></a><span class="ot">parole ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> a <span class="ot">-&gt;</span> <span class="dt">JailT</span> s t m (<span class="dt">Maybe</span> a) <span class="ot">-&gt;</span> <span class="dt">JailT</span> s t m a</span>
<span id="cb17-43"><a href="#cb17-43" aria-hidden="true" tabindex="-1"></a>parole a0 j <span class="ot">=</span></span>
<span id="cb17-44"><a href="#cb17-44" aria-hidden="true" tabindex="-1"></a>  asum</span>
<span id="cb17-45"><a href="#cb17-45" aria-hidden="true" tabindex="-1"></a>    [ attempt j</span>
<span id="cb17-46"><a href="#cb17-46" aria-hidden="true" tabindex="-1"></a>    , <span class="fu">pure</span> a0</span>
<span id="cb17-47"><a href="#cb17-47" aria-hidden="true" tabindex="-1"></a>    ]</span>
<span id="cb17-48"><a href="#cb17-48" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-49"><a href="#cb17-49" aria-hidden="true" tabindex="-1"></a><span class="ot">arrest ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> <span class="dt">Lens&#39;</span> t u <span class="ot">-&gt;</span> u <span class="ot">-&gt;</span> <span class="dt">JailT</span> s t m ()</span>
<span id="cb17-50"><a href="#cb17-50" aria-hidden="true" tabindex="-1"></a>arrest l u <span class="ot">=</span> modify <span class="op">$</span> set l u</span></code></pre></div>
</details>
<p>Maybe this was interesting to you. It certainly was fun for me, because I like tearing apart bad code, and I don’t get to see much of it now that I have very talented colleagues. Thankfully I have a huge amount of crap code from my past, including an even more egregious monad that we’ll tackle next time around.</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Unwrap the definitions of <code>StateT s Maybe a</code> and <code>MaybeT (State s) a</code> to see why.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
        ]]>
      </content>
    </entry>
    <entry>
      <title>An Algebraic Theory of Music</title>
      <id>blog/more-algebraic-music/index.html</id>
      <link href='blog/more-algebraic-music/index.html'/>
      <published>2026-01-02T14:27:00Z</published>
      <updated>2026-01-02T14:27:00Z</updated>

      <content type="html" xml:base="https://reasonablypolymorphic.com">
        <![CDATA[
        <p>In my last post, I was <a href="/blog/algebraic-music/">struggling towards an algebraic theory of music.</a> This idea has been burning in my mind ever since, and I wanted to give some updates with where I’ve landed.</p>
<h2 id="differentiating-voices-from-music">Differentiating Voices from Music</h2>
<p>We begin by modeling a <a href="https://en.wikipedia.org/wiki/Part_(music)#Polyphony_and_part-writing">musical voice</a>, which is, roughly speaking, the abstract version of a human voice. The voice can be doing one thing at a time, or can choose to not be doing anything.</p>
<p>Voices are modeled by <a href="https://hackage.haskell.org/package/step-function">step functions</a>, which are divisions of the real line into discrete chunks. We interpret each discrete chunk as a note being played by the voice for the duration of the chunk.</p>
<p>This gives rise to a nice applicative structure that I alluded to in my previous post:</p>
<pre><code>liftA2 f
  |---- a ----|-- b --|
  |-- x --|---- y ----|
=
  |- fax -|fay|- fby -|</code></pre>
<p>where we take the union of the note boundaries in order to form the applicative. If either voice is resting, so too is the applicative. There is also an <code>Alternative</code> instance here, which chooses the first non-rest.</p>
<p>There is a similar monoidal structure here, where multiplication is given by “play these two things simultaneously,” relying on an underlying <code>Semigroup</code> instance for the meaning of “play these two things:”</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Semigroup</span> a <span class="ot">=&gt;</span> <span class="dt">Semigroup</span> (<span class="dt">Voice</span> a)</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Semigroup</span> a <span class="ot">=&gt;</span> <span class="dt">Monoid</span> (<span class="dt">Voice</span> a)</span></code></pre></div>
<p>If either voice is resting, we treat its value as <code>mempty</code>, and can happily combine the two parts in parallel.</p>
<p>All of this gives rise to the following rich structure:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Voice</span> a <span class="ot">=</span> <span class="dt">Voice</span> {<span class="ot"> unVoice ::</span> <span class="dt">SF</span> <span class="dt">Time</span> (<span class="dt">Maybe</span> a) }</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> stock</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    (<span class="dt">Eq</span>, <span class="dt">Ord</span>, <span class="dt">Show</span>, <span class="dt">Functor</span>, <span class="dt">Foldable</span>, <span class="dt">Traversable</span>, <span class="dt">Generic</span>, <span class="dt">Generic1</span>)</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> <span class="kw">newtype</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    (<span class="dt">Semigroup</span>, <span class="dt">Monoid</span>)</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Applicative</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>    via <span class="dt">Compose</span> (<span class="dt">SF</span> <span class="dt">Time</span>) <span class="dt">Maybe</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Filterable</span> <span class="dt">Voice</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Witherable</span> <span class="dt">Voice</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Alternative</span> <span class="dt">Voice</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a><span class="co">-- | Delay a voice by some amount of time.</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a><span class="ot">delayV ::</span> <span class="dt">Time</span> <span class="ot">-&gt;</span> <span class="dt">Voice</span> a <span class="ot">-&gt;</span> <span class="dt">Voice</span> a</span></code></pre></div>
<h2 id="from-voices-to-music">From Voices to Music</h2>
<p>Voices, therefore, give us our primitive notion of monophony. But real music usually has many voices doing many things, independently. This was a point in which I got stuck in my previous post.</p>
<p>The solution here, is surprisingly easy. Assign a <code>Voice</code> to each voice name:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Music</span> v a <span class="ot">=</span> <span class="dt">Music</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>  {<span class="ot"> getVoices ::</span> v <span class="ot">-&gt;</span> <span class="dt">Voice</span> a</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> stock</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>    (<span class="dt">Functor</span>, <span class="dt">Generic</span>, <span class="dt">Functor</span>)</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> <span class="kw">newtype</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    (<span class="dt">Semigroup</span>, <span class="dt">Monoid</span>)</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> (<span class="dt">Applicative</span>, <span class="dt">Alternative</span>)</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>    via <span class="dt">Compose</span> ((<span class="ot">-&gt;</span>) v) <span class="dt">Voice</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Profunctor</span> <span class="dt">Music</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Finite</span> v <span class="ot">=&gt;</span> <span class="dt">Foldable</span> (<span class="dt">Music</span> v)</span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Finite</span> v <span class="ot">=&gt;</span> <span class="dt">Traversable</span> (<span class="dt">Music</span> v)</span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Filterable</span> (<span class="dt">Music</span> v)</span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Finite</span> v <span class="ot">=&gt;</span> <span class="dt">Witherable</span> (<span class="dt">Music</span> v)</span></code></pre></div>
<p>We get an extremely rich structure here completely for free. Our monoid combines all voices in parallel; our applicative combines voices pointwise; etc. However, we also have a new <code>Profunctor Music</code> instance, whose characteristic <code>lmap :: (b -&gt; c) -&gt; Music c a -&gt; Music b a</code> method allows us to trade lines between voices.</p>
<p>In addition to the <em>in-parallel</em> monoid instance, we can also define a <a href="https://dl.acm.org/doi/10.1145/2633638.2633649">tile product</a> operator over <code>Music v a</code>, which composes things sequentially<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ot">duration ::</span> <span class="dt">Music</span> v a <span class="ot">-&gt;</span> <span class="dt">Time</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="ot">(##) ::</span> <span class="dt">Semigroup</span> a <span class="ot">=&gt;</span> <span class="dt">Music</span> v a <span class="ot">-&gt;</span> <span class="dt">Music</span> v a <span class="ot">-&gt;</span> <span class="dt">Music</span> v a</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>m<span class="op">@</span>(<span class="dt">Music</span> m1) <span class="op">##</span> <span class="dt">Music</span> m2 <span class="ot">=</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Music</span> <span class="op">$</span> liftA2 (<span class="op">&lt;&gt;</span>) m1 <span class="op">$</span> <span class="fu">fmap</span> (delayV <span class="op">$</span> duration m) m2</span></code></pre></div>
<p>The <code>Semigroup a</code> constraint on <code>(##)</code> arises from the fact that the pieces of music might extend off to infinity in either direction (which <code>pure @Voice</code> must do), and we need to deal with that.</p>
<p>There are a few other combinators we care about. First, we can lift anonymous voices (colloquially “tunes”) into multi-part <code>Music</code>:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ot">voice ::</span> <span class="dt">Eq</span> v <span class="ot">=&gt;</span> v <span class="ot">-&gt;</span> <span class="dt">Music</span> () a <span class="ot">-&gt;</span> <span class="dt">Music</span> v a</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>voice v (<span class="dt">Music</span> sf) <span class="ot">=</span> <span class="dt">Music</span> <span class="op">$</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  \<span class="kw">case</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>    ((<span class="op">==</span> v) <span class="ot">-&gt;</span> <span class="dt">True</span>) <span class="ot">-&gt;</span> sf ()</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>    _ <span class="ot">-&gt;</span> <span class="fu">mempty</span></span></code></pre></div>
<p>and we can assign the same line to everyone:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ot">everyone ::</span> <span class="dt">Music</span> () a <span class="ot">-&gt;</span> <span class="dt">Music</span> v a</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>everyone (<span class="dt">Music</span> m) <span class="ot">=</span> <span class="dt">Music</span> <span class="op">$</span> <span class="fu">const</span> <span class="op">$</span> m ()</span></code></pre></div>
<h2 id="writing-lines">Writing Lines</h2>
<p>The primitives for building little tunes are</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ot">note ::</span> <span class="dt">Time</span> <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> <span class="dt">Music</span> () a</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="ot">rest ::</span> <span class="dt">Time</span> <span class="ot">-&gt;</span> <span class="dt">Music</span> () a</span></code></pre></div>
<p>which you can then compose sequentially via <code>(##)</code>, and assign to voices via <code>voice</code>.</p>
<h2 id="harmonic-constraints">Harmonic Constraints</h2>
<p>One of the better responses to my last blog post was a link to <a href="https://dmitri.mycpanel.princeton.edu/index.html">Dmitri Tymoczko</a>’s <a href="https://www.youtube.com/watch?v=yp5Eys2L_04">FARM 2024 talk</a>.</p>
<p>There’s much more in this video than I can possibly due justice to here, but my big takeaway was that this guy is thinking about the same sorts of things that I am. So I dove into his work, and that lead to his <a href="https://www.madmusicalscience.com/quadruple.mp4">quadruple hierarchy</a>:</p>
<blockquote>
<p>Voices move within chords, which move within scales, which move within macro-harmonies.</p>
</blockquote>
<p>Tymoczko presents a <code>T</code> algebra which is a geometric space for reasoning about voice leadings. He’s got a lot of fun websites for exploring the ideas, but I couldn’t find an actual implementation of the idea anywhere, so I <a href="https://github.com/isovector/denomusic/blob/6a313a546cc376bb22f37cec55d76518bff40acd/src/DenoMusic/Harmony.hs">cooked one up</a> myself.</p>
<p>The idea here is that we have some <code>T :: [Nat] -&gt; Type</code> which describes a hierarchy of abstract scales moving with respect to one another. For example, the Western traditional of having triads move within the diatonic scale, which moves within the chromatic scale, would be represented as <code>T '[3, 7, 12]</code>. <code>T</code> forms a monoid, and has some simple generators that give rise to smooth voice leadings (chord changes.)</p>
<p>Having a model for smooth harmonic transformations means we can use it constructively. I am still working out the exact details here, but the rough shape of the idea is to build an underlying field of key changes (represented as smooth voice leadings in <code>T '[7, 12]</code>):</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="ot">keyChanges ::</span> <span class="dt">Music</span> () (<span class="dt">T</span> &#39;[<span class="dv">7</span>, <span class="dv">12</span>])</span></code></pre></div>
<p>We can then make an underlying field of functional harmonic changes (chord changes), modeled as smooth voice leadings in <code>T '[3, 7]</code>:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ot">chordChanges ::</span> <span class="dt">Music</span> () (<span class="dt">T</span> &#39;[<span class="dv">3</span>, <span class="dv">7</span>])</span></code></pre></div>
<p>Our voices responsible for harmony can now be written as values of type</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ot">harmonicVoices ::</span> <span class="dt">Music</span> h (<span class="dt">Set</span> (<span class="dt">T</span> &#39;[<span class="dv">3</span>]))</span></code></pre></div>
<p>and we can use the applicative musical structure to combine the elements together:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE ApplicativeDo #-}</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="ot">extend ::</span> <span class="dt">T</span> ns <span class="ot">-&gt;</span> <span class="dt">T</span> (ns <span class="op">++</span> ms)</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="ot">sink   ::</span> <span class="dt">T</span> ns <span class="ot">-&gt;</span> <span class="dt">T</span> (n &#39;<span class="op">:</span> ns)</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a><span class="ot">harmony ::</span> <span class="dt">Music</span> h (<span class="dt">Set</span> (<span class="dt">T</span> &#39;[<span class="dv">3</span>, <span class="dv">7</span>, <span class="dv">12</span>]))</span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>harmony <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>  k <span class="ot">&lt;-</span> everyone keyChanges</span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>  c <span class="ot">&lt;-</span> everyone chordChanges</span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>  m <span class="ot">&lt;-</span> harmonicVoices</span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>  <span class="fu">pure</span> <span class="op">$</span> extend m <span class="op">&lt;&gt;</span> extend c <span class="op">&lt;&gt;</span> sink k</span></code></pre></div>
<p>which we can later <code>fmap</code> out into concrete pitches. The result is that we can completely isolate the following pieces:</p>
<ul>
<li>key changes</li>
<li>chord changes</li>
<li>how voices express the current harmony</li>
<li>the rhythms of all of the above</li>
</ul>
<p>and the result is guaranteed to compose in a way that the ear can interpret as music. Not necessarily <em>good music,</em> but undeniably as <em>music.</em></p>
<p>The type indices on <code>T</code> are purely for my book-keeping, and nothing requires them to be there. Which means we could also use the applicative structure to modulate over different sorts of harmony (eg, move from triads to seventh chords.)</p>
<h2 id="melody-still-an-open-question">Melody: Still an Open Question</h2>
<p>I haven’t quite gotten a feel for melody yet; I think it’s probably in <code>T '[7, 12]</code>, but it would be nice to be able to target chord tones as well. Please let me know in the comments if you have any insight here.</p>
<p>However, I have been thinking about contouring, which is the overall “shape” of a musical line. Does it go up, and peak in the middle, and then come down again? Or maybe it smoothly descends down.</p>
<p>We can use the discrete intervals intrinsic inside of <code>Voice</code>s to find “reasonable” times to sample them. In essence this assigns a <code>Time</code> to each segment:</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ot">timed ::</span> <span class="dt">Music</span> v a <span class="ot">-&gt;</span> <span class="dt">Music</span> v (<span class="dt">Time</span>, a)</span></code></pre></div>
<p>and we can then use these times to then sample a function <code>Time -&gt; b</code>. This then allows us to apply contours (given as regular <code>Real -&gt; Real</code> functions) to arbitrary rhythms. I currently have this typed as</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="ot">contour ::</span> <span class="dt">Group</span> a <span class="ot">=&gt;</span> a <span class="ot">-&gt;</span> (<span class="dt">Real</span> <span class="ot">-&gt;</span> <span class="dt">Real</span>) <span class="ot">-&gt;</span> <span class="dt">Music</span> v () <span class="ot">-&gt;</span> <span class="dt">Music</span> v a</span></code></pre></div>
<p>where <code>a ~ T something</code>, and the outputted <code>Real</code>s get rounded to their nearest integer values. I’m not deeply in love with this type, but the rough idea is great—turn arbitrary real-valued functions into musical lines. This generalizes contouring, as well as scale runs.</p>
<h2 id="next-steps">Next Steps?</h2>
<p>I’m writing all of this up because I go back to work on Monday and life is going to get very busy soon. I’m afraid I won’t be able to finish all of this!</p>
<p>The types above I’m pretty certain are relatively close to perfect. They seem to capture everything I could possibly want, and nothing I don’t want. Assuming I’m right about that, they must make up the basis of musical composition.</p>
<p>The next step therefore is to build musical combinators on top. One particular combinator I’ve got my eye on is some sort of general <code>~&gt;</code> “get from here to there” operator:</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="ot">(~&gt;) ::</span> (<span class="dt">Semigroup</span> a, <span class="op">???</span>) <span class="ot">=&gt;</span> <span class="dt">Music</span> v a <span class="ot">-&gt;</span> <span class="dt">Music</span> v a <span class="ot">-&gt;</span> <span class="dt">Music</span> v a</span></code></pre></div>
<p>which I imagine would bridge a gap between the end of one piece of music with beginning of another. I think this would be roughly as easy as moving each voice linearly in <code>T</code> space from where it was to where it needs to be. This might need to be a ternary operation in order to also associate a rhythmic pattern to use for the bridge.</p>
<p>But I imagine <code>(~&gt;)</code> would be great for lots of dumb little musical things. Like when applied over the chord dimension, it would generate arpeggios. Over the scale dimension, it would generate runs. And it would make chromatic moves in the chroma dimension.</p>
<p>Choosing exactly what moves to make for <code>T</code>s consisting of components in multiple axes might just be some bespoke order, or could do something more intelligent. I think the right approach would be to steal <code>diagrams</code>’ idea of an <code>Envelope</code>, and attach some relevant metadata to each <code>Music</code>. We could then write <code>(~&gt;)</code> as a function of those envelopes, but I must admit I don’t quite know what this would look like.</p>
<p>As usual, I’d love any insight you have! Please leave it in the comments. Although I must admit I appreciate comments of the form “have you tried $X” much more than of the form “music is sublime and you’re an idiot for even trying this.”</p>
<p>Happy new year!</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Strictly speaking, the tile product can also do parallel composition, as well as sychronizing composition, but that’s not super important right now.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
        ]]>
      </content>
    </entry>
    <entry>
      <title>Struggling Towards an Algebraic Theory of Music</title>
      <id>blog/algebraic-music/index.html</id>
      <link href='blog/algebraic-music/index.html'/>
      <published>2025-12-04T20:15:00Z</published>
      <updated>2025-12-04T20:15:00Z</updated>

      <content type="html" xml:base="https://reasonablypolymorphic.com">
        <![CDATA[
        <p>For the last few months, I’ve been trying to come up with a nice, denotational basis for what music <em>is.</em> But I’m running out of steam on the project, so I thought I’d write what I’ve figured out, and what I’ve tried but doesn’t work. Hopefully this will inspire someone to come tell me what I’m being stupid about and help get the whole process unstuck.</p>
<h2 id="what-music-is-not">What Music Is Not</h2>
<p>It’s tempting to gesticulate wildly, saying that music is merely a function from time to wave amplitudes, eg something of the form:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>μ <span class="dt">Music</span> <span class="ot">=</span> <span class="dt">Time</span> <span class="ot">-&gt;</span> <span class="dt">Amplitude</span></span></code></pre></div>
<p>While I think it’s fair to say that this is indeed the underlying denotation of <em>sound,</em> this is clearly not the denotation of <em>music.</em> For example, we can transpose a song up a semitone without changing the speed—something that’s very challenging without a great deal of in the waveform representation. And we can play a musical phrase backwards, which is probably impossible in a waveform for any timbral envelope.</p>
<p>Since we have now two examples of “reasonable to want to do” with musical objects, which cannot be expressed in terms of a function <code>Time -&gt; Amplitude</code>, we must conceed that waveforms-over-time cannot be the denotation of music.</p>
<h2 id="what-music-might-be">What Music Might Be</h2>
<p>Music is obviously temporal, so keeping the “function from time” part seems relevant. But a function from time to what? As a first attempt:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Note</span> <span class="ot">=</span> <span class="dt">Note</span> <span class="dt">Pitch</span> <span class="dt">Timbre</span> <span class="dt">Volume</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>μ <span class="dt">Music</span> <span class="ot">=</span> <span class="dt">Time</span> <span class="ot">-&gt;</span> <span class="dt">Set</span> (<span class="dt">Duration</span>, <span class="dt">Note</span>)</span></code></pre></div>
<p>which, for a given time, returns a set of notes starting at that time, and how long they ought to be played for. An immediate improvement would be to parameterize the above over notes:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>μ (<span class="dt">Music</span> a) <span class="ot">=</span> <span class="dt">Time</span> <span class="ot">-&gt;</span> <span class="dt">Set</span> (<span class="dt">Duration</span>, a)</span></code></pre></div>
<p>It’s tempting to try to eliminate more of the structure here with our parametricity, but I was unable to do so. In contrapuntal music, we will want to be able to express two notes starting at the same moment, but ending at different times.</p>
<p>One alluring path here could to write monophonic voices, and combine them together for polyphony:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>μ (<span class="dt">Voice</span> a) <span class="ot">=</span> <span class="co">{- something like -}</span> <span class="dt">Time</span> <span class="ot">-&gt;</span> (<span class="dt">Duration</span>, a)</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>μ (<span class="dt">Music</span> a) <span class="ot">=</span> <span class="dt">Time</span> <span class="ot">-&gt;</span> <span class="dt">Set</span> (<span class="dt">Voice</span> a)</span></code></pre></div>
<p>Such an encoding has many unfavorable traits. First, it just feels yucky. Why are there two layers of <code>Time</code>? Second, now I-as-a-composer need to make a choice of which voice I put each note in, despite the fact that this is merely an encoding quirk. So no, I don’t think this is a viable path forward.</p>
<p>So let’s return to our best contender:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>μ (<span class="dt">Music</span> a) <span class="ot">=</span> <span class="dt">Time</span> <span class="ot">-&gt;</span> <span class="dt">Set</span> (<span class="dt">Duration</span>, a)</span></code></pre></div>
<p>This definition is trivially a monoid, pointwise over the time structure:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>μ (<span class="dt">Music</span> a <span class="op">&lt;&gt;</span> <span class="dt">Music</span> b) <span class="ot">=</span> <span class="dt">Music</span> (μ a <span class="op">&lt;&gt;</span> μ b)</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>μ <span class="fu">mempty</span> <span class="ot">=</span> <span class="dt">Music</span> <span class="fu">mempty</span></span></code></pre></div>
<p>If we think about abstract sets here, rather than <code>Data.Set.Set</code>, such an object is clearly a functor. There are many possible applicatives here, but the pointwise zipper seems most compelling to me. Pictorally:</p>
<pre><code>pure a
=
  |----- a ----forever...


liftA2 f
  |---- a ----|-- b --|
  |-- x --|---- y ----|
=
  |- fax -|fay|- fby -|</code></pre>
<p>Such an applicative structure is quite nice! It would allow us to “stamp” a rhythm on top of a pure representation of a melody.</p>
<p>However, the desirability of this instance is a point <em>against</em> <code>μ (Music a) = Time -&gt; Set (Duration, a)</code>, since by <a href="http://conal.net/papers/type-class-morphisms/">Conal Elliott’s typeclass morphism rule</a>, the meaning of the applicative here ought to be the applicative of the meaning. Nevertheless, any other applicative structure would be effecitvely useless, since it would require the notes on one side to begin at the same time as the notes on the other. To sketch:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- bad instance!</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>liftA2 f (<span class="dt">Music</span> a) (<span class="dt">Music</span> b) <span class="ot">=</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Music</span> (liftA2 (\(d1, m) (d2, n) <span class="ot">-&gt;</span> (d1 <span class="op">&lt;&gt;</span> d2, f m n)) a b)</span></code></pre></div>
<p>Good luck finding a musically meaningful <code>pure</code> for such a thing!</p>
<p>Ok, so let’s say we commit to the pointwise zippy instance as our applicative instance. Is there a corresponding monad? Such a thing would substitute notes with more music. My first idea of what to do with such a thing would be to replace chords with texture. For example, we could replace chords with broken chords, or with basslines that target the same notes.</p>
<p>Anyway, the answer is yes, there is such a monad. But it’s musically kinda troublesome. Assume we have the following function:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="ot">notes ::</span> <span class="dt">Music</span> a <span class="ot">-&gt;</span> [(<span class="dt">Maybe</span> <span class="dt">Interval</span>, a)]</span></code></pre></div>
<p>which will convert a <code>Music a</code> into its notes and an optional temporal interval (optional because <code>pure</code> goes on forever.) Then, we can write our bind as:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>m <span class="op">&gt;&gt;=</span> f <span class="ot">=</span> <span class="fu">flip</span> <span class="fu">foldMap</span> (notes m) \<span class="kw">case</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>  (<span class="dt">Nothing</span>, a) <span class="ot">-&gt;</span> f a</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>  (<span class="dt">Just</span> (start, duration), a) <span class="ot">-&gt;</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>    offset start <span class="op">$</span> _ duration <span class="op">$</span> f a</span></code></pre></div>
<p>where <code>offset</code> changes when a piece of music occurs. We are left with a hole of type:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Duration</span> <span class="ot">-&gt;</span> <span class="dt">Music</span> a <span class="ot">-&gt;</span> <span class="dt">Music</span> a</span></code></pre></div>
<p>whose semantics sure better be that it forces the given <code>Music</code> to fit in the alotted time. There are two reasonable candidates here:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ot">scaleTo  ::</span> <span class="dt">Duration</span> <span class="ot">-&gt;</span> <span class="dt">Music</span> a <span class="ot">-&gt;</span> <span class="dt">Music</span> a</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="fu">truncate</span><span class="ot"> ::</span> <span class="dt">Duration</span> <span class="ot">-&gt;</span> <span class="dt">Music</span> a <span class="ot">-&gt;</span> <span class="dt">Music</span> a</span></code></pre></div>
<p>where <code>scaleTo</code> changes the local interpretation of time such that the entire musical argument is played within the given duration, and <code>truncate</code> just takes the first <code>Duration</code>’s worth of time. Truncate is too obviously unhelpful here, since the <code>&gt;&gt;=</code> continuation doesn’t know how much time it’s been given, and thus most binds will drop almost all of their resulting music.</p>
<p>Therefore we will go with <code>scaleTo</code>. Which satisfies all of the algebraic (monad) laws, but results in some truly mystifying tunes. The problem here is that this is not an operation which respects musical meter. Each subsequent bind results in a correspondingly smaller share of the pie. Thus by using only bind and mconcat, it’s easy to get a bar full of quarter notes, followed by a bar of sixty-fourth notes, followed by two bars full of of 13-tuplets. If you want to get a steady rhythm out of the whole thing, you need a global view on how many binds deep you’re ever going to go, and you need to ensure locally that you only produce a small powers-of-two number of notes, or else you will accidentally introduce tuplets.</p>
<p>It’s a mess. But algebraically it’s fine.</p>
<h2 id="what-music-seems-like-it-should-be">What Music Seems Like It Should Be</h2>
<p>The above foray into monads seems tentatively promising for amateur would-be algorithmic composers (read: people like me.) But I have been reading <a href="https://www.goodreads.com/book/show/36288013-musical-composition">several</a> <a href="https://www.goodreads.com/book/show/890009.Twentieth_Century_Harmony">books</a> on musical composition lately, and my big takeaway from them is <em>just how damn contextual notes are.</em></p>
<p>So maybe this means we want more of a comonadic interface. One in which you can <code>extend</code> every note, by taking into account all of the notes in its local vicinity. This feels just as right as the monadic approach does, albeit in a completely different way. Being able to give a comonad instance for <code>Music</code> would require us to somehow reckon with having only a single <code>a</code> at any given time. Which appeals to my functional programmer soul, but again, I don’t know how to do it.</p>
<p>But imagine if we did have a comonadic instance. We could perform voice leading by inspecting what the next note was, and by futzing around with our pitch. We could do some sort of reharmonization by shifting notes around according to what else is happening.</p>
<p>But maybe all of this is just folly.</p>
<p>Music as it’s actually practiced doesn’t seem to have much of the functionaly-compositional properties we like—ie, that we can abstract and encapsulate. But music doesn’t appear to be like that! Instead, a happy melody takes a different character when played on major vs minor chords. Adding a dissonant interval can completely reconceptualize other notes.</p>
<p>It feels like a bit of a bummer to end like this, but I don’t really know where to go from here. I’ve worked something like six completely-different approaches over the last few months, and what’s documented here is the most promising bits and pieces. My next thought is that maybe music actually forms a <a href="https://reasonablypolymorphic.com/blog/review-sheafs/">sheaf</a>, which is to say that it is a global solution that respects many local constraints.</p>
<p>All of this research into music has given me much more thoughts about <em>music qua music</em> which I will try to articulate the next time I have an evening to myself. Until then.</p>
        ]]>
      </content>
    </entry>
    <entry>
      <title>Arrows to Arrows, Categories to Queries</title>
      <id>blog/arrows-to-arrows/index.html</id>
      <link href='blog/arrows-to-arrows/index.html'/>
      <published>2025-10-14T14:31:00Z</published>
      <updated>2025-10-14T14:31:00Z</updated>

      <content type="html" xml:base="https://reasonablypolymorphic.com">
        <![CDATA[
        <p>I’ve had a little time off of work as of late, and been spending it in characteristically unwise ways. In particular, I’ve written a <a href="https://github.com/isovector/catlang">little programming language that compiles to SQL</a>. I call it <em>catlang</em>. That’s not to say that I’ve written a new query language. It’s a programming language, whose compiler spits out one giant <code>SELECT</code> statement. When you run that query in postgres, you get the output of your program.</p>
<p>Why have I done this? Because I needed a funny compilation target to test out the actual features of the language, which is that its intermediary language is a bunch of abstract category theory nonsense. Which I’ll get to. But I’m sure you first want to see this bad boy in action.</p>
<p>Behold, the function that returns 100 regardless of what input you give it. But it does it with the equivalent of a while loop:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>count <span class="op">:</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>count <span class="ot">=</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  x <span class="ot">-&gt;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    loop x</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>      i <span class="ot">-&gt;</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>        n <span class="ot">&lt;-</span> join <span class="fu">id</span> <span class="fu">id</span> <span class="op">-&lt;</span> i</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>        z <span class="ot">&lt;-</span> <span class="fu">abs</span> <span class="op">.</span> (<span class="op">-</span>) <span class="op">-&lt;</span> (n, <span class="dv">100</span>)</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">case</span> z <span class="kw">of</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>          inl _ <span class="ot">-&gt;</span> inr <span class="op">.</span> (<span class="op">+</span>) <span class="op">-&lt;</span> (n, <span class="dv">1</span>)</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>          inr _ <span class="ot">-&gt;</span> inl <span class="op">-&lt;</span> n</span></code></pre></div>
<p>If you’re familiar with <a href="/blog/arrowized-frp/">arrow notation</a>, you’ll notice the above looks kinda like one big <code>proc</code> block. This is not a coincidence (because nothing is a coincidence). I figured if I were to go through all of this work, we might as well get a working arrow desugarer out of the mix. But I digress; that’s a story for another time.</p>
<p>Anyway, what’s going on here is we have an arrow <code>count</code>, which takes a single argument <code>x</code>. We then loop, starting from the value of <code>x</code>. Inside the loop, we now have a new variable <code>i</code>, which we do some voodoo on to compute <code>n</code>—the current value of the loop variable. Then we subtract 100 from <code>n</code>, and take the absolute value. The <code>abs</code> function here is a bit odd; it returns <code>Left (abs x)</code> if the input was negative, and <code>Right x</code> otherwise. Then we branch on the output of <code>abs</code>, where <code>Left</code> and <code>Right</code> have been renamed <code>inl</code> and <code>inr</code> respectively. If <code>n - 100</code> was less than zero, we find ourselves in the <code>inl</code> case, where we add 1 to <code>n</code> and wrap the whole thing in <code>inr</code>—which the loop interprets as “loop again with this new value.” Otherwise, <code>n - 100</code> was non-negative, and so we can return <code>n</code> directly.</p>
<p>Is it roundabout? You bet! The obtuseness here is not directly a feature, I was just looking for conceptually simple things I could do which would be easy to desugar into category-theoretical stuff. Which brings us to the intermediary language. After desugaring the source syntax for <code>count</code> above, we’re left with this IL representation:</p>
<pre><code>  id △ id
⨟ cochoice
    ( undist
    ⨟   ( (prj₁ ⨟ id ▽ id) △ id
          ⨟   ( prj₁ △ 100
              ⨟ (-)
              ⨟ abs
              )
            △ id
          ⨟ prj₁ △ id
          ⨟ dist
          ⨟   ( (prj₂ ⨟ prj₂ ⨟ prj₁) △ 1
              ⨟ (+)
              ⨟ inr
              )
            ▽ ( prj₂
              ⨟ prj₂
              ⨟ prj₁
              ⨟ inl
              )
        )
      △ prj₂
    ⨟ dist
    )
⨟ prj₁</code></pre>
<p>We’ll discuss all of this momentarily, but for now, just let your eyes glaze over the pretty unicode.</p>
<p>The underlying idea here is that each of these remaining symbols has very simple and specific algebraic semantics. For example, <code>A ⨟ B</code> means “do <code>A</code> and pipe the result into <code>B</code>.” By giving a transformation from this categorical IL into other domains, it becomes trivial to compile catlang to all sorts of weird compilation targets. Like SQL.</p>
<p>You’re probably wondering what the generated SQL looks like. Take a peek if you dare.</p>
<details>
<summary>
Ungodly Compiled SQL
</summary>
<div class="sourceCode" id="cb3"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">SELECT</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>f0 <span class="kw">AS</span> f0</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">FROM</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>(<span class="kw">SELECT</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a> f0 <span class="kw">AS</span> f0, f1 <span class="kw">AS</span> f1</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a> <span class="kw">FROM</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a> (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">FROM</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>  (<span class="kw">WITH</span> t0 <span class="kw">AS</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">FROM</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>    (<span class="kw">WITH</span> RECURSIVE recursion <span class="kw">AS</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>     (<span class="kw">SELECT</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>      clock_timestamp() <span class="kw">as</span> step</span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>      , <span class="op">*</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>      <span class="kw">FROM</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">WITH</span> t1 <span class="kw">AS</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a>       (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a>        <span class="kw">FROM</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a>        (<span class="kw">SELECT</span></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a>         f0 <span class="kw">AS</span> f0, f1 <span class="kw">AS</span> f1, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f2, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f3</span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a>         <span class="kw">FROM</span></span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a>         (<span class="kw">WITH</span> t2 <span class="kw">AS</span></span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a>          (<span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> (<span class="kw">SELECT</span> <span class="dv">0</span> <span class="kw">as</span> f0) <span class="kw">AS</span> _)</span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true" tabindex="-1"></a>          <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true" tabindex="-1"></a>          <span class="kw">FROM</span></span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true" tabindex="-1"></a>          (<span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f0 <span class="kw">FROM</span> t2 <span class="kw">AS</span> _) <span class="kw">AS</span> _</span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true" tabindex="-1"></a>           <span class="kw">CROSS</span> <span class="kw">JOIN</span></span>
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true" tabindex="-1"></a>           (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f1 <span class="kw">FROM</span> t2 <span class="kw">AS</span> _))</span>
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true" tabindex="-1"></a>          <span class="kw">AS</span> _)</span>
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true" tabindex="-1"></a>         <span class="kw">AS</span> _)</span>
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true" tabindex="-1"></a>        <span class="kw">AS</span> _)</span>
<span id="cb3-33"><a href="#cb3-33" aria-hidden="true" tabindex="-1"></a>       <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-34"><a href="#cb3-34" aria-hidden="true" tabindex="-1"></a>       <span class="kw">FROM</span></span>
<span id="cb3-35"><a href="#cb3-35" aria-hidden="true" tabindex="-1"></a>       (<span class="kw">WITH</span> t3 <span class="kw">AS</span></span>
<span id="cb3-36"><a href="#cb3-36" aria-hidden="true" tabindex="-1"></a>        (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-37"><a href="#cb3-37" aria-hidden="true" tabindex="-1"></a>         <span class="kw">FROM</span></span>
<span id="cb3-38"><a href="#cb3-38" aria-hidden="true" tabindex="-1"></a>         (<span class="co">-- undist</span></span>
<span id="cb3-39"><a href="#cb3-39" aria-hidden="true" tabindex="-1"></a>          <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-40"><a href="#cb3-40" aria-hidden="true" tabindex="-1"></a>          <span class="kw">FROM</span></span>
<span id="cb3-41"><a href="#cb3-41" aria-hidden="true" tabindex="-1"></a>          (<span class="kw">SELECT</span></span>
<span id="cb3-42"><a href="#cb3-42" aria-hidden="true" tabindex="-1"></a>           f0 <span class="kw">AS</span> f0, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f1, f1 <span class="kw">AS</span> f2</span>
<span id="cb3-43"><a href="#cb3-43" aria-hidden="true" tabindex="-1"></a>           <span class="kw">FROM</span></span>
<span id="cb3-44"><a href="#cb3-44" aria-hidden="true" tabindex="-1"></a>           (<span class="co">-- undist1</span></span>
<span id="cb3-45"><a href="#cb3-45" aria-hidden="true" tabindex="-1"></a>            <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t1 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f0&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-46"><a href="#cb3-46" aria-hidden="true" tabindex="-1"></a>           <span class="kw">AS</span> _)</span>
<span id="cb3-47"><a href="#cb3-47" aria-hidden="true" tabindex="-1"></a>          <span class="kw">AS</span> _</span>
<span id="cb3-48"><a href="#cb3-48" aria-hidden="true" tabindex="-1"></a>          <span class="kw">UNION</span></span>
<span id="cb3-49"><a href="#cb3-49" aria-hidden="true" tabindex="-1"></a>          <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-50"><a href="#cb3-50" aria-hidden="true" tabindex="-1"></a>          <span class="kw">FROM</span></span>
<span id="cb3-51"><a href="#cb3-51" aria-hidden="true" tabindex="-1"></a>          (<span class="kw">SELECT</span></span>
<span id="cb3-52"><a href="#cb3-52" aria-hidden="true" tabindex="-1"></a>           <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f0, f2 <span class="kw">AS</span> f1, f3 <span class="kw">AS</span> f2</span>
<span id="cb3-53"><a href="#cb3-53" aria-hidden="true" tabindex="-1"></a>           <span class="kw">FROM</span></span>
<span id="cb3-54"><a href="#cb3-54" aria-hidden="true" tabindex="-1"></a>           (<span class="co">-- dist2</span></span>
<span id="cb3-55"><a href="#cb3-55" aria-hidden="true" tabindex="-1"></a>            <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t1 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f2&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-56"><a href="#cb3-56" aria-hidden="true" tabindex="-1"></a>           <span class="kw">AS</span> _)</span>
<span id="cb3-57"><a href="#cb3-57" aria-hidden="true" tabindex="-1"></a>          <span class="kw">AS</span> _)</span>
<span id="cb3-58"><a href="#cb3-58" aria-hidden="true" tabindex="-1"></a>         <span class="kw">AS</span> _)</span>
<span id="cb3-59"><a href="#cb3-59" aria-hidden="true" tabindex="-1"></a>        <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-60"><a href="#cb3-60" aria-hidden="true" tabindex="-1"></a>        <span class="kw">FROM</span></span>
<span id="cb3-61"><a href="#cb3-61" aria-hidden="true" tabindex="-1"></a>        (<span class="kw">WITH</span> t4 <span class="kw">AS</span></span>
<span id="cb3-62"><a href="#cb3-62" aria-hidden="true" tabindex="-1"></a>         (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-63"><a href="#cb3-63" aria-hidden="true" tabindex="-1"></a>          <span class="kw">FROM</span></span>
<span id="cb3-64"><a href="#cb3-64" aria-hidden="true" tabindex="-1"></a>          (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-65"><a href="#cb3-65" aria-hidden="true" tabindex="-1"></a>           <span class="kw">FROM</span></span>
<span id="cb3-66"><a href="#cb3-66" aria-hidden="true" tabindex="-1"></a>           (<span class="kw">SELECT</span></span>
<span id="cb3-67"><a href="#cb3-67" aria-hidden="true" tabindex="-1"></a>            f0 <span class="kw">AS</span> f0, f1 <span class="kw">AS</span> f1</span>
<span id="cb3-68"><a href="#cb3-68" aria-hidden="true" tabindex="-1"></a>            <span class="kw">FROM</span></span>
<span id="cb3-69"><a href="#cb3-69" aria-hidden="true" tabindex="-1"></a>            (<span class="kw">WITH</span> t5 <span class="kw">AS</span></span>
<span id="cb3-70"><a href="#cb3-70" aria-hidden="true" tabindex="-1"></a>             (<span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t3 <span class="kw">AS</span> _)</span>
<span id="cb3-71"><a href="#cb3-71" aria-hidden="true" tabindex="-1"></a>             <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-72"><a href="#cb3-72" aria-hidden="true" tabindex="-1"></a>             <span class="kw">FROM</span></span>
<span id="cb3-73"><a href="#cb3-73" aria-hidden="true" tabindex="-1"></a>             (<span class="kw">WITH</span> t6 <span class="kw">AS</span></span>
<span id="cb3-74"><a href="#cb3-74" aria-hidden="true" tabindex="-1"></a>              (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-75"><a href="#cb3-75" aria-hidden="true" tabindex="-1"></a>               <span class="kw">FROM</span></span>
<span id="cb3-76"><a href="#cb3-76" aria-hidden="true" tabindex="-1"></a>               (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-77"><a href="#cb3-77" aria-hidden="true" tabindex="-1"></a>                <span class="kw">FROM</span></span>
<span id="cb3-78"><a href="#cb3-78" aria-hidden="true" tabindex="-1"></a>                (<span class="kw">SELECT</span></span>
<span id="cb3-79"><a href="#cb3-79" aria-hidden="true" tabindex="-1"></a>                 f0 <span class="kw">AS</span> f0</span>
<span id="cb3-80"><a href="#cb3-80" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">FROM</span></span>
<span id="cb3-81"><a href="#cb3-81" aria-hidden="true" tabindex="-1"></a>                 (<span class="kw">WITH</span> t7 <span class="kw">AS</span></span>
<span id="cb3-82"><a href="#cb3-82" aria-hidden="true" tabindex="-1"></a>                  (<span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f0, f1 <span class="kw">AS</span> f1 <span class="kw">FROM</span> t5 <span class="kw">AS</span> _) <span class="kw">AS</span> _)</span>
<span id="cb3-83"><a href="#cb3-83" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-84"><a href="#cb3-84" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">FROM</span></span>
<span id="cb3-85"><a href="#cb3-85" aria-hidden="true" tabindex="-1"></a>                  (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-86"><a href="#cb3-86" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">FROM</span></span>
<span id="cb3-87"><a href="#cb3-87" aria-hidden="true" tabindex="-1"></a>                   (<span class="kw">SELECT</span></span>
<span id="cb3-88"><a href="#cb3-88" aria-hidden="true" tabindex="-1"></a>                    f0 <span class="kw">AS</span> f0</span>
<span id="cb3-89"><a href="#cb3-89" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">FROM</span></span>
<span id="cb3-90"><a href="#cb3-90" aria-hidden="true" tabindex="-1"></a>                    (<span class="co">-- join1</span></span>
<span id="cb3-91"><a href="#cb3-91" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t7 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f0&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-92"><a href="#cb3-92" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">AS</span> _)</span>
<span id="cb3-93"><a href="#cb3-93" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">AS</span> _</span>
<span id="cb3-94"><a href="#cb3-94" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">UNION</span></span>
<span id="cb3-95"><a href="#cb3-95" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-96"><a href="#cb3-96" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">FROM</span></span>
<span id="cb3-97"><a href="#cb3-97" aria-hidden="true" tabindex="-1"></a>                   (<span class="kw">SELECT</span></span>
<span id="cb3-98"><a href="#cb3-98" aria-hidden="true" tabindex="-1"></a>                    f1 <span class="kw">AS</span> f0</span>
<span id="cb3-99"><a href="#cb3-99" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">FROM</span></span>
<span id="cb3-100"><a href="#cb3-100" aria-hidden="true" tabindex="-1"></a>                    (<span class="co">-- join2</span></span>
<span id="cb3-101"><a href="#cb3-101" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t7 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f1&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-102"><a href="#cb3-102" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">AS</span> _)</span>
<span id="cb3-103"><a href="#cb3-103" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">AS</span> _)</span>
<span id="cb3-104"><a href="#cb3-104" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">AS</span> _)</span>
<span id="cb3-105"><a href="#cb3-105" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">AS</span> _)</span>
<span id="cb3-106"><a href="#cb3-106" aria-hidden="true" tabindex="-1"></a>                <span class="kw">AS</span> _</span>
<span id="cb3-107"><a href="#cb3-107" aria-hidden="true" tabindex="-1"></a>                <span class="kw">CROSS</span> <span class="kw">JOIN</span></span>
<span id="cb3-108"><a href="#cb3-108" aria-hidden="true" tabindex="-1"></a>                (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f1, f1 <span class="kw">AS</span> f2, f2 <span class="kw">AS</span> f3 <span class="kw">FROM</span> t5 <span class="kw">AS</span> _))</span>
<span id="cb3-109"><a href="#cb3-109" aria-hidden="true" tabindex="-1"></a>               <span class="kw">AS</span> _)</span>
<span id="cb3-110"><a href="#cb3-110" aria-hidden="true" tabindex="-1"></a>              <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-111"><a href="#cb3-111" aria-hidden="true" tabindex="-1"></a>              <span class="kw">FROM</span></span>
<span id="cb3-112"><a href="#cb3-112" aria-hidden="true" tabindex="-1"></a>              (<span class="kw">WITH</span> t8 <span class="kw">AS</span></span>
<span id="cb3-113"><a href="#cb3-113" aria-hidden="true" tabindex="-1"></a>               (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-114"><a href="#cb3-114" aria-hidden="true" tabindex="-1"></a>                <span class="kw">FROM</span></span>
<span id="cb3-115"><a href="#cb3-115" aria-hidden="true" tabindex="-1"></a>                (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-116"><a href="#cb3-116" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">FROM</span></span>
<span id="cb3-117"><a href="#cb3-117" aria-hidden="true" tabindex="-1"></a>                 (<span class="kw">SELECT</span></span>
<span id="cb3-118"><a href="#cb3-118" aria-hidden="true" tabindex="-1"></a>                  f0 <span class="kw">AS</span> f0, f1 <span class="kw">AS</span> f1</span>
<span id="cb3-119"><a href="#cb3-119" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">FROM</span></span>
<span id="cb3-120"><a href="#cb3-120" aria-hidden="true" tabindex="-1"></a>                  (<span class="kw">WITH</span> t9 <span class="kw">AS</span></span>
<span id="cb3-121"><a href="#cb3-121" aria-hidden="true" tabindex="-1"></a>                   (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-122"><a href="#cb3-122" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">FROM</span></span>
<span id="cb3-123"><a href="#cb3-123" aria-hidden="true" tabindex="-1"></a>                    (<span class="kw">SELECT</span></span>
<span id="cb3-124"><a href="#cb3-124" aria-hidden="true" tabindex="-1"></a>                     f0 <span class="op">-</span> f1 <span class="kw">AS</span> f0</span>
<span id="cb3-125"><a href="#cb3-125" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">FROM</span></span>
<span id="cb3-126"><a href="#cb3-126" aria-hidden="true" tabindex="-1"></a>                     (<span class="kw">WITH</span> t10 <span class="kw">AS</span></span>
<span id="cb3-127"><a href="#cb3-127" aria-hidden="true" tabindex="-1"></a>                      (<span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t6 <span class="kw">AS</span> _)</span>
<span id="cb3-128"><a href="#cb3-128" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-129"><a href="#cb3-129" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">FROM</span></span>
<span id="cb3-130"><a href="#cb3-130" aria-hidden="true" tabindex="-1"></a>                      (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-131"><a href="#cb3-131" aria-hidden="true" tabindex="-1"></a>                       <span class="kw">FROM</span></span>
<span id="cb3-132"><a href="#cb3-132" aria-hidden="true" tabindex="-1"></a>                       (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f0 <span class="kw">FROM</span> (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f0 <span class="kw">FROM</span> t10 <span class="kw">AS</span> _) <span class="kw">AS</span> _)</span>
<span id="cb3-133"><a href="#cb3-133" aria-hidden="true" tabindex="-1"></a>                       <span class="kw">AS</span> _</span>
<span id="cb3-134"><a href="#cb3-134" aria-hidden="true" tabindex="-1"></a>                       <span class="kw">CROSS</span> <span class="kw">JOIN</span></span>
<span id="cb3-135"><a href="#cb3-135" aria-hidden="true" tabindex="-1"></a>                       (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f1 <span class="kw">FROM</span> (<span class="kw">SELECT</span> <span class="dv">100</span> <span class="kw">as</span> f0 <span class="kw">FROM</span> t10 <span class="kw">AS</span> _) <span class="kw">AS</span> _))</span>
<span id="cb3-136"><a href="#cb3-136" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">AS</span> _)</span>
<span id="cb3-137"><a href="#cb3-137" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">AS</span> _)</span>
<span id="cb3-138"><a href="#cb3-138" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">AS</span> _)</span>
<span id="cb3-139"><a href="#cb3-139" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-140"><a href="#cb3-140" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">FROM</span></span>
<span id="cb3-141"><a href="#cb3-141" aria-hidden="true" tabindex="-1"></a>                   (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-142"><a href="#cb3-142" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">FROM</span></span>
<span id="cb3-143"><a href="#cb3-143" aria-hidden="true" tabindex="-1"></a>                    (<span class="kw">SELECT</span></span>
<span id="cb3-144"><a href="#cb3-144" aria-hidden="true" tabindex="-1"></a>                     <span class="fu">abs</span>(f0) <span class="kw">as</span> f0, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">as</span> f1</span>
<span id="cb3-145"><a href="#cb3-145" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">FROM</span></span>
<span id="cb3-146"><a href="#cb3-146" aria-hidden="true" tabindex="-1"></a>                     t9</span>
<span id="cb3-147"><a href="#cb3-147" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">AS</span> _</span>
<span id="cb3-148"><a href="#cb3-148" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">WHERE</span></span>
<span id="cb3-149"><a href="#cb3-149" aria-hidden="true" tabindex="-1"></a>                     f0 <span class="op">&lt;</span> <span class="dv">0</span>)</span>
<span id="cb3-150"><a href="#cb3-150" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">AS</span> _</span>
<span id="cb3-151"><a href="#cb3-151" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">UNION</span></span>
<span id="cb3-152"><a href="#cb3-152" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-153"><a href="#cb3-153" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">FROM</span></span>
<span id="cb3-154"><a href="#cb3-154" aria-hidden="true" tabindex="-1"></a>                    (<span class="kw">SELECT</span> <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">as</span> f0, f0 <span class="kw">as</span> f1 <span class="kw">FROM</span> t9 <span class="kw">AS</span> _ <span class="kw">WHERE</span> f0 <span class="op">&gt;=</span> <span class="dv">0</span>)</span>
<span id="cb3-155"><a href="#cb3-155" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">AS</span> _)</span>
<span id="cb3-156"><a href="#cb3-156" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">AS</span> _)</span>
<span id="cb3-157"><a href="#cb3-157" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">AS</span> _)</span>
<span id="cb3-158"><a href="#cb3-158" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">AS</span> _</span>
<span id="cb3-159"><a href="#cb3-159" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">CROSS</span> <span class="kw">JOIN</span></span>
<span id="cb3-160"><a href="#cb3-160" aria-hidden="true" tabindex="-1"></a>                 (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f2, f1 <span class="kw">AS</span> f3, f2 <span class="kw">AS</span> f4, f3 <span class="kw">AS</span> f5 <span class="kw">FROM</span> t6 <span class="kw">AS</span> _))</span>
<span id="cb3-161"><a href="#cb3-161" aria-hidden="true" tabindex="-1"></a>                <span class="kw">AS</span> _)</span>
<span id="cb3-162"><a href="#cb3-162" aria-hidden="true" tabindex="-1"></a>               <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-163"><a href="#cb3-163" aria-hidden="true" tabindex="-1"></a>               <span class="kw">FROM</span></span>
<span id="cb3-164"><a href="#cb3-164" aria-hidden="true" tabindex="-1"></a>               (<span class="kw">WITH</span> t11 <span class="kw">AS</span></span>
<span id="cb3-165"><a href="#cb3-165" aria-hidden="true" tabindex="-1"></a>                (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-166"><a href="#cb3-166" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">FROM</span></span>
<span id="cb3-167"><a href="#cb3-167" aria-hidden="true" tabindex="-1"></a>                 (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-168"><a href="#cb3-168" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">FROM</span></span>
<span id="cb3-169"><a href="#cb3-169" aria-hidden="true" tabindex="-1"></a>                  (<span class="kw">SELECT</span></span>
<span id="cb3-170"><a href="#cb3-170" aria-hidden="true" tabindex="-1"></a>                   f0 <span class="kw">AS</span> f0, f1 <span class="kw">AS</span> f1</span>
<span id="cb3-171"><a href="#cb3-171" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">FROM</span></span>
<span id="cb3-172"><a href="#cb3-172" aria-hidden="true" tabindex="-1"></a>                   (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f0, f1 <span class="kw">AS</span> f1 <span class="kw">FROM</span> t8 <span class="kw">AS</span> _)</span>
<span id="cb3-173"><a href="#cb3-173" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">AS</span> _)</span>
<span id="cb3-174"><a href="#cb3-174" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">AS</span> _</span>
<span id="cb3-175"><a href="#cb3-175" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">CROSS</span> <span class="kw">JOIN</span></span>
<span id="cb3-176"><a href="#cb3-176" aria-hidden="true" tabindex="-1"></a>                  (<span class="kw">SELECT</span></span>
<span id="cb3-177"><a href="#cb3-177" aria-hidden="true" tabindex="-1"></a>                   f0 <span class="kw">AS</span> f2, f1 <span class="kw">AS</span> f3, f2 <span class="kw">AS</span> f4, f3 <span class="kw">AS</span> f5, f4 <span class="kw">AS</span> f6, f5 <span class="kw">AS</span> f7</span>
<span id="cb3-178"><a href="#cb3-178" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">FROM</span></span>
<span id="cb3-179"><a href="#cb3-179" aria-hidden="true" tabindex="-1"></a>                   t8</span>
<span id="cb3-180"><a href="#cb3-180" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">AS</span> _))</span>
<span id="cb3-181"><a href="#cb3-181" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">AS</span> _)</span>
<span id="cb3-182"><a href="#cb3-182" aria-hidden="true" tabindex="-1"></a>                <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-183"><a href="#cb3-183" aria-hidden="true" tabindex="-1"></a>                <span class="kw">FROM</span></span>
<span id="cb3-184"><a href="#cb3-184" aria-hidden="true" tabindex="-1"></a>                (<span class="kw">WITH</span> t12 <span class="kw">AS</span></span>
<span id="cb3-185"><a href="#cb3-185" aria-hidden="true" tabindex="-1"></a>                 (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-186"><a href="#cb3-186" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">FROM</span></span>
<span id="cb3-187"><a href="#cb3-187" aria-hidden="true" tabindex="-1"></a>                  (<span class="co">-- dist</span></span>
<span id="cb3-188"><a href="#cb3-188" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-189"><a href="#cb3-189" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">FROM</span></span>
<span id="cb3-190"><a href="#cb3-190" aria-hidden="true" tabindex="-1"></a>                   (<span class="kw">SELECT</span></span>
<span id="cb3-191"><a href="#cb3-191" aria-hidden="true" tabindex="-1"></a>                    f0 <span class="kw">AS</span> f0, f2 <span class="kw">AS</span> f1, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f10, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f11, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f12, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f13, f3 <span class="kw">AS</span> f2, f4 <span class="kw">AS</span> f3, f5 <span class="kw">AS</span> f4, f6 <span class="kw">AS</span> f5, f7 <span class="kw">AS</span> f6, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f7, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f8, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f9</span>
<span id="cb3-192"><a href="#cb3-192" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">FROM</span></span>
<span id="cb3-193"><a href="#cb3-193" aria-hidden="true" tabindex="-1"></a>                    (<span class="co">-- dist1</span></span>
<span id="cb3-194"><a href="#cb3-194" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t11 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f0&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-195"><a href="#cb3-195" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">AS</span> _)</span>
<span id="cb3-196"><a href="#cb3-196" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">AS</span> _</span>
<span id="cb3-197"><a href="#cb3-197" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">UNION</span></span>
<span id="cb3-198"><a href="#cb3-198" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-199"><a href="#cb3-199" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">FROM</span></span>
<span id="cb3-200"><a href="#cb3-200" aria-hidden="true" tabindex="-1"></a>                   (<span class="kw">SELECT</span></span>
<span id="cb3-201"><a href="#cb3-201" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f0, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f1, f4 <span class="kw">AS</span> f10, f5 <span class="kw">AS</span> f11, f6 <span class="kw">AS</span> f12, f7 <span class="kw">AS</span> f13, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f2, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f3, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f4, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f5, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f6, f1 <span class="kw">AS</span> f7, f2 <span class="kw">AS</span> f8, f3 <span class="kw">AS</span> f9</span>
<span id="cb3-202"><a href="#cb3-202" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">FROM</span></span>
<span id="cb3-203"><a href="#cb3-203" aria-hidden="true" tabindex="-1"></a>                    (<span class="co">-- dist2</span></span>
<span id="cb3-204"><a href="#cb3-204" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t11 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f1&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-205"><a href="#cb3-205" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">AS</span> _)</span>
<span id="cb3-206"><a href="#cb3-206" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">AS</span> _)</span>
<span id="cb3-207"><a href="#cb3-207" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">AS</span> _)</span>
<span id="cb3-208"><a href="#cb3-208" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-209"><a href="#cb3-209" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">FROM</span></span>
<span id="cb3-210"><a href="#cb3-210" aria-hidden="true" tabindex="-1"></a>                 (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-211"><a href="#cb3-211" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">FROM</span></span>
<span id="cb3-212"><a href="#cb3-212" aria-hidden="true" tabindex="-1"></a>                  (<span class="kw">SELECT</span></span>
<span id="cb3-213"><a href="#cb3-213" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f0, f0 <span class="kw">AS</span> f1</span>
<span id="cb3-214"><a href="#cb3-214" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">FROM</span></span>
<span id="cb3-215"><a href="#cb3-215" aria-hidden="true" tabindex="-1"></a>                   (<span class="kw">SELECT</span></span>
<span id="cb3-216"><a href="#cb3-216" aria-hidden="true" tabindex="-1"></a>                    f0 <span class="op">+</span> f1 <span class="kw">AS</span> f0</span>
<span id="cb3-217"><a href="#cb3-217" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">FROM</span></span>
<span id="cb3-218"><a href="#cb3-218" aria-hidden="true" tabindex="-1"></a>                    (<span class="kw">WITH</span> t13 <span class="kw">AS</span></span>
<span id="cb3-219"><a href="#cb3-219" aria-hidden="true" tabindex="-1"></a>                     (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-220"><a href="#cb3-220" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">FROM</span></span>
<span id="cb3-221"><a href="#cb3-221" aria-hidden="true" tabindex="-1"></a>                      (<span class="kw">SELECT</span></span>
<span id="cb3-222"><a href="#cb3-222" aria-hidden="true" tabindex="-1"></a>                       f0 <span class="kw">AS</span> f0, f1 <span class="kw">AS</span> f1, f2 <span class="kw">AS</span> f2, f3 <span class="kw">AS</span> f3, f4 <span class="kw">AS</span> f4, f5 <span class="kw">AS</span> f5, f6 <span class="kw">AS</span> f6</span>
<span id="cb3-223"><a href="#cb3-223" aria-hidden="true" tabindex="-1"></a>                       <span class="kw">FROM</span></span>
<span id="cb3-224"><a href="#cb3-224" aria-hidden="true" tabindex="-1"></a>                       (<span class="co">-- join1</span></span>
<span id="cb3-225"><a href="#cb3-225" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t12 <span class="kw">AS</span> _</span>
<span id="cb3-226"><a href="#cb3-226" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">WHERE</span></span>
<span id="cb3-227"><a href="#cb3-227" aria-hidden="true" tabindex="-1"></a>                        (<span class="ot">&quot;f0&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">AND</span> (((<span class="ot">&quot;f1&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">OR</span> (<span class="ot">&quot;f2&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)) <span class="kw">AND</span> ((<span class="ot">&quot;f3&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">AND</span> (((<span class="ot">&quot;f4&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">OR</span> (<span class="ot">&quot;f5&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)) <span class="kw">AND</span> (<span class="ot">&quot;f6&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)))))</span>
<span id="cb3-228"><a href="#cb3-228" aria-hidden="true" tabindex="-1"></a>                       <span class="kw">AS</span> _)</span>
<span id="cb3-229"><a href="#cb3-229" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">AS</span> _)</span>
<span id="cb3-230"><a href="#cb3-230" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-231"><a href="#cb3-231" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">FROM</span></span>
<span id="cb3-232"><a href="#cb3-232" aria-hidden="true" tabindex="-1"></a>                     (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-233"><a href="#cb3-233" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">FROM</span></span>
<span id="cb3-234"><a href="#cb3-234" aria-hidden="true" tabindex="-1"></a>                      (<span class="kw">SELECT</span></span>
<span id="cb3-235"><a href="#cb3-235" aria-hidden="true" tabindex="-1"></a>                       f0 <span class="kw">AS</span> f0</span>
<span id="cb3-236"><a href="#cb3-236" aria-hidden="true" tabindex="-1"></a>                       <span class="kw">FROM</span></span>
<span id="cb3-237"><a href="#cb3-237" aria-hidden="true" tabindex="-1"></a>                       (<span class="kw">SELECT</span></span>
<span id="cb3-238"><a href="#cb3-238" aria-hidden="true" tabindex="-1"></a>                        f0 <span class="kw">AS</span> f0</span>
<span id="cb3-239"><a href="#cb3-239" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">FROM</span></span>
<span id="cb3-240"><a href="#cb3-240" aria-hidden="true" tabindex="-1"></a>                        (<span class="kw">SELECT</span></span>
<span id="cb3-241"><a href="#cb3-241" aria-hidden="true" tabindex="-1"></a>                         f2 <span class="kw">AS</span> f0, f3 <span class="kw">AS</span> f1, f4 <span class="kw">AS</span> f2, f5 <span class="kw">AS</span> f3</span>
<span id="cb3-242"><a href="#cb3-242" aria-hidden="true" tabindex="-1"></a>                         <span class="kw">FROM</span></span>
<span id="cb3-243"><a href="#cb3-243" aria-hidden="true" tabindex="-1"></a>                         (<span class="kw">SELECT</span></span>
<span id="cb3-244"><a href="#cb3-244" aria-hidden="true" tabindex="-1"></a>                          f1 <span class="kw">AS</span> f0, f2 <span class="kw">AS</span> f1, f3 <span class="kw">AS</span> f2, f4 <span class="kw">AS</span> f3, f5 <span class="kw">AS</span> f4, f6 <span class="kw">AS</span> f5</span>
<span id="cb3-245"><a href="#cb3-245" aria-hidden="true" tabindex="-1"></a>                          <span class="kw">FROM</span></span>
<span id="cb3-246"><a href="#cb3-246" aria-hidden="true" tabindex="-1"></a>                          t13</span>
<span id="cb3-247"><a href="#cb3-247" aria-hidden="true" tabindex="-1"></a>                          <span class="kw">AS</span> _)</span>
<span id="cb3-248"><a href="#cb3-248" aria-hidden="true" tabindex="-1"></a>                         <span class="kw">AS</span> _)</span>
<span id="cb3-249"><a href="#cb3-249" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">AS</span> _)</span>
<span id="cb3-250"><a href="#cb3-250" aria-hidden="true" tabindex="-1"></a>                       <span class="kw">AS</span> _)</span>
<span id="cb3-251"><a href="#cb3-251" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">AS</span> _</span>
<span id="cb3-252"><a href="#cb3-252" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">CROSS</span> <span class="kw">JOIN</span></span>
<span id="cb3-253"><a href="#cb3-253" aria-hidden="true" tabindex="-1"></a>                      (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f1 <span class="kw">FROM</span> (<span class="kw">SELECT</span> <span class="dv">1</span> <span class="kw">as</span> f0 <span class="kw">FROM</span> t13 <span class="kw">AS</span> _) <span class="kw">AS</span> _))</span>
<span id="cb3-254"><a href="#cb3-254" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">AS</span> _)</span>
<span id="cb3-255"><a href="#cb3-255" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">AS</span> _)</span>
<span id="cb3-256"><a href="#cb3-256" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">AS</span> _)</span>
<span id="cb3-257"><a href="#cb3-257" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">AS</span> _</span>
<span id="cb3-258"><a href="#cb3-258" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">UNION</span></span>
<span id="cb3-259"><a href="#cb3-259" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-260"><a href="#cb3-260" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">FROM</span></span>
<span id="cb3-261"><a href="#cb3-261" aria-hidden="true" tabindex="-1"></a>                  (<span class="kw">SELECT</span></span>
<span id="cb3-262"><a href="#cb3-262" aria-hidden="true" tabindex="-1"></a>                   f0 <span class="kw">AS</span> f0, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f1</span>
<span id="cb3-263"><a href="#cb3-263" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">FROM</span></span>
<span id="cb3-264"><a href="#cb3-264" aria-hidden="true" tabindex="-1"></a>                   (<span class="kw">SELECT</span></span>
<span id="cb3-265"><a href="#cb3-265" aria-hidden="true" tabindex="-1"></a>                    f0 <span class="kw">AS</span> f0</span>
<span id="cb3-266"><a href="#cb3-266" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">FROM</span></span>
<span id="cb3-267"><a href="#cb3-267" aria-hidden="true" tabindex="-1"></a>                    (<span class="kw">SELECT</span></span>
<span id="cb3-268"><a href="#cb3-268" aria-hidden="true" tabindex="-1"></a>                     f2 <span class="kw">AS</span> f0, f3 <span class="kw">AS</span> f1, f4 <span class="kw">AS</span> f2, f5 <span class="kw">AS</span> f3</span>
<span id="cb3-269"><a href="#cb3-269" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">FROM</span></span>
<span id="cb3-270"><a href="#cb3-270" aria-hidden="true" tabindex="-1"></a>                     (<span class="kw">SELECT</span></span>
<span id="cb3-271"><a href="#cb3-271" aria-hidden="true" tabindex="-1"></a>                      f1 <span class="kw">AS</span> f0, f2 <span class="kw">AS</span> f1, f3 <span class="kw">AS</span> f2, f4 <span class="kw">AS</span> f3, f5 <span class="kw">AS</span> f4, f6 <span class="kw">AS</span> f5</span>
<span id="cb3-272"><a href="#cb3-272" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">FROM</span></span>
<span id="cb3-273"><a href="#cb3-273" aria-hidden="true" tabindex="-1"></a>                      (<span class="kw">SELECT</span></span>
<span id="cb3-274"><a href="#cb3-274" aria-hidden="true" tabindex="-1"></a>                       f7 <span class="kw">AS</span> f0, f8 <span class="kw">AS</span> f1, f9 <span class="kw">AS</span> f2, f10 <span class="kw">AS</span> f3, f11 <span class="kw">AS</span> f4, f12 <span class="kw">AS</span> f5, f13 <span class="kw">AS</span> f6</span>
<span id="cb3-275"><a href="#cb3-275" aria-hidden="true" tabindex="-1"></a>                       <span class="kw">FROM</span></span>
<span id="cb3-276"><a href="#cb3-276" aria-hidden="true" tabindex="-1"></a>                       (<span class="co">-- join2</span></span>
<span id="cb3-277"><a href="#cb3-277" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t12 <span class="kw">AS</span> _</span>
<span id="cb3-278"><a href="#cb3-278" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">WHERE</span></span>
<span id="cb3-279"><a href="#cb3-279" aria-hidden="true" tabindex="-1"></a>                        (<span class="ot">&quot;f7&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">AND</span> (((<span class="ot">&quot;f8&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">OR</span> (<span class="ot">&quot;f9&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)) <span class="kw">AND</span> ((<span class="ot">&quot;f10&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">AND</span> (((<span class="ot">&quot;f11&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">OR</span> (<span class="ot">&quot;f12&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)) <span class="kw">AND</span> (<span class="ot">&quot;f13&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)))))</span>
<span id="cb3-280"><a href="#cb3-280" aria-hidden="true" tabindex="-1"></a>                       <span class="kw">AS</span> _)</span>
<span id="cb3-281"><a href="#cb3-281" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">AS</span> _)</span>
<span id="cb3-282"><a href="#cb3-282" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">AS</span> _)</span>
<span id="cb3-283"><a href="#cb3-283" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">AS</span> _)</span>
<span id="cb3-284"><a href="#cb3-284" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">AS</span> _)</span>
<span id="cb3-285"><a href="#cb3-285" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">AS</span> _)</span>
<span id="cb3-286"><a href="#cb3-286" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">AS</span> _)</span>
<span id="cb3-287"><a href="#cb3-287" aria-hidden="true" tabindex="-1"></a>                <span class="kw">AS</span> _)</span>
<span id="cb3-288"><a href="#cb3-288" aria-hidden="true" tabindex="-1"></a>               <span class="kw">AS</span> _)</span>
<span id="cb3-289"><a href="#cb3-289" aria-hidden="true" tabindex="-1"></a>              <span class="kw">AS</span> _)</span>
<span id="cb3-290"><a href="#cb3-290" aria-hidden="true" tabindex="-1"></a>             <span class="kw">AS</span> _)</span>
<span id="cb3-291"><a href="#cb3-291" aria-hidden="true" tabindex="-1"></a>            <span class="kw">AS</span> _)</span>
<span id="cb3-292"><a href="#cb3-292" aria-hidden="true" tabindex="-1"></a>           <span class="kw">AS</span> _</span>
<span id="cb3-293"><a href="#cb3-293" aria-hidden="true" tabindex="-1"></a>           <span class="kw">CROSS</span> <span class="kw">JOIN</span></span>
<span id="cb3-294"><a href="#cb3-294" aria-hidden="true" tabindex="-1"></a>           (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f2 <span class="kw">FROM</span> (<span class="kw">SELECT</span> f2 <span class="kw">AS</span> f0 <span class="kw">FROM</span> t3 <span class="kw">AS</span> _) <span class="kw">AS</span> _))</span>
<span id="cb3-295"><a href="#cb3-295" aria-hidden="true" tabindex="-1"></a>          <span class="kw">AS</span> _)</span>
<span id="cb3-296"><a href="#cb3-296" aria-hidden="true" tabindex="-1"></a>         <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-297"><a href="#cb3-297" aria-hidden="true" tabindex="-1"></a>         <span class="kw">FROM</span></span>
<span id="cb3-298"><a href="#cb3-298" aria-hidden="true" tabindex="-1"></a>         (<span class="co">-- dist</span></span>
<span id="cb3-299"><a href="#cb3-299" aria-hidden="true" tabindex="-1"></a>          <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-300"><a href="#cb3-300" aria-hidden="true" tabindex="-1"></a>          <span class="kw">FROM</span></span>
<span id="cb3-301"><a href="#cb3-301" aria-hidden="true" tabindex="-1"></a>          (<span class="kw">SELECT</span></span>
<span id="cb3-302"><a href="#cb3-302" aria-hidden="true" tabindex="-1"></a>           f0 <span class="kw">AS</span> f0, f2 <span class="kw">AS</span> f1, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f2, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f3</span>
<span id="cb3-303"><a href="#cb3-303" aria-hidden="true" tabindex="-1"></a>           <span class="kw">FROM</span></span>
<span id="cb3-304"><a href="#cb3-304" aria-hidden="true" tabindex="-1"></a>           (<span class="co">-- dist1</span></span>
<span id="cb3-305"><a href="#cb3-305" aria-hidden="true" tabindex="-1"></a>            <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t4 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f0&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-306"><a href="#cb3-306" aria-hidden="true" tabindex="-1"></a>           <span class="kw">AS</span> _)</span>
<span id="cb3-307"><a href="#cb3-307" aria-hidden="true" tabindex="-1"></a>          <span class="kw">AS</span> _</span>
<span id="cb3-308"><a href="#cb3-308" aria-hidden="true" tabindex="-1"></a>          <span class="kw">UNION</span></span>
<span id="cb3-309"><a href="#cb3-309" aria-hidden="true" tabindex="-1"></a>          <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-310"><a href="#cb3-310" aria-hidden="true" tabindex="-1"></a>          <span class="kw">FROM</span></span>
<span id="cb3-311"><a href="#cb3-311" aria-hidden="true" tabindex="-1"></a>          (<span class="kw">SELECT</span></span>
<span id="cb3-312"><a href="#cb3-312" aria-hidden="true" tabindex="-1"></a>           <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f0, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f1, f1 <span class="kw">AS</span> f2, f2 <span class="kw">AS</span> f3</span>
<span id="cb3-313"><a href="#cb3-313" aria-hidden="true" tabindex="-1"></a>           <span class="kw">FROM</span></span>
<span id="cb3-314"><a href="#cb3-314" aria-hidden="true" tabindex="-1"></a>           (<span class="co">-- dist2</span></span>
<span id="cb3-315"><a href="#cb3-315" aria-hidden="true" tabindex="-1"></a>            <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t4 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f1&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-316"><a href="#cb3-316" aria-hidden="true" tabindex="-1"></a>           <span class="kw">AS</span> _)</span>
<span id="cb3-317"><a href="#cb3-317" aria-hidden="true" tabindex="-1"></a>          <span class="kw">AS</span> _)</span>
<span id="cb3-318"><a href="#cb3-318" aria-hidden="true" tabindex="-1"></a>         <span class="kw">AS</span> _)</span>
<span id="cb3-319"><a href="#cb3-319" aria-hidden="true" tabindex="-1"></a>        <span class="kw">AS</span> _)</span>
<span id="cb3-320"><a href="#cb3-320" aria-hidden="true" tabindex="-1"></a>       <span class="kw">AS</span> _)</span>
<span id="cb3-321"><a href="#cb3-321" aria-hidden="true" tabindex="-1"></a>      <span class="kw">AS</span> _</span>
<span id="cb3-322"><a href="#cb3-322" aria-hidden="true" tabindex="-1"></a>      <span class="kw">UNION</span> <span class="kw">ALL</span></span>
<span id="cb3-323"><a href="#cb3-323" aria-hidden="true" tabindex="-1"></a>      <span class="kw">SELECT</span></span>
<span id="cb3-324"><a href="#cb3-324" aria-hidden="true" tabindex="-1"></a>      clock_timestamp() <span class="kw">as</span> step</span>
<span id="cb3-325"><a href="#cb3-325" aria-hidden="true" tabindex="-1"></a>      , <span class="op">*</span></span>
<span id="cb3-326"><a href="#cb3-326" aria-hidden="true" tabindex="-1"></a>      <span class="kw">FROM</span></span>
<span id="cb3-327"><a href="#cb3-327" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-328"><a href="#cb3-328" aria-hidden="true" tabindex="-1"></a>       <span class="kw">FROM</span></span>
<span id="cb3-329"><a href="#cb3-329" aria-hidden="true" tabindex="-1"></a>       (<span class="kw">WITH</span> t14 <span class="kw">AS</span></span>
<span id="cb3-330"><a href="#cb3-330" aria-hidden="true" tabindex="-1"></a>        (<span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> recursion <span class="kw">AS</span> _)</span>
<span id="cb3-331"><a href="#cb3-331" aria-hidden="true" tabindex="-1"></a>        <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-332"><a href="#cb3-332" aria-hidden="true" tabindex="-1"></a>        <span class="kw">FROM</span></span>
<span id="cb3-333"><a href="#cb3-333" aria-hidden="true" tabindex="-1"></a>        (<span class="kw">WITH</span> t15 <span class="kw">AS</span></span>
<span id="cb3-334"><a href="#cb3-334" aria-hidden="true" tabindex="-1"></a>         (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-335"><a href="#cb3-335" aria-hidden="true" tabindex="-1"></a>          <span class="kw">FROM</span></span>
<span id="cb3-336"><a href="#cb3-336" aria-hidden="true" tabindex="-1"></a>          (<span class="co">-- undist</span></span>
<span id="cb3-337"><a href="#cb3-337" aria-hidden="true" tabindex="-1"></a>           <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-338"><a href="#cb3-338" aria-hidden="true" tabindex="-1"></a>           <span class="kw">FROM</span></span>
<span id="cb3-339"><a href="#cb3-339" aria-hidden="true" tabindex="-1"></a>           (<span class="kw">SELECT</span></span>
<span id="cb3-340"><a href="#cb3-340" aria-hidden="true" tabindex="-1"></a>            f0 <span class="kw">AS</span> f0, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f1, f1 <span class="kw">AS</span> f2</span>
<span id="cb3-341"><a href="#cb3-341" aria-hidden="true" tabindex="-1"></a>            <span class="kw">FROM</span></span>
<span id="cb3-342"><a href="#cb3-342" aria-hidden="true" tabindex="-1"></a>            (<span class="co">-- undist1</span></span>
<span id="cb3-343"><a href="#cb3-343" aria-hidden="true" tabindex="-1"></a>             <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t14 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f0&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-344"><a href="#cb3-344" aria-hidden="true" tabindex="-1"></a>            <span class="kw">AS</span> _)</span>
<span id="cb3-345"><a href="#cb3-345" aria-hidden="true" tabindex="-1"></a>           <span class="kw">AS</span> _</span>
<span id="cb3-346"><a href="#cb3-346" aria-hidden="true" tabindex="-1"></a>           <span class="kw">UNION</span></span>
<span id="cb3-347"><a href="#cb3-347" aria-hidden="true" tabindex="-1"></a>           <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-348"><a href="#cb3-348" aria-hidden="true" tabindex="-1"></a>           <span class="kw">FROM</span></span>
<span id="cb3-349"><a href="#cb3-349" aria-hidden="true" tabindex="-1"></a>           (<span class="kw">SELECT</span></span>
<span id="cb3-350"><a href="#cb3-350" aria-hidden="true" tabindex="-1"></a>            <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f0, f2 <span class="kw">AS</span> f1, f3 <span class="kw">AS</span> f2</span>
<span id="cb3-351"><a href="#cb3-351" aria-hidden="true" tabindex="-1"></a>            <span class="kw">FROM</span></span>
<span id="cb3-352"><a href="#cb3-352" aria-hidden="true" tabindex="-1"></a>            (<span class="co">-- dist2</span></span>
<span id="cb3-353"><a href="#cb3-353" aria-hidden="true" tabindex="-1"></a>             <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t14 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f2&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-354"><a href="#cb3-354" aria-hidden="true" tabindex="-1"></a>            <span class="kw">AS</span> _)</span>
<span id="cb3-355"><a href="#cb3-355" aria-hidden="true" tabindex="-1"></a>           <span class="kw">AS</span> _)</span>
<span id="cb3-356"><a href="#cb3-356" aria-hidden="true" tabindex="-1"></a>          <span class="kw">AS</span> _)</span>
<span id="cb3-357"><a href="#cb3-357" aria-hidden="true" tabindex="-1"></a>         <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-358"><a href="#cb3-358" aria-hidden="true" tabindex="-1"></a>         <span class="kw">FROM</span></span>
<span id="cb3-359"><a href="#cb3-359" aria-hidden="true" tabindex="-1"></a>         (<span class="kw">WITH</span> t16 <span class="kw">AS</span></span>
<span id="cb3-360"><a href="#cb3-360" aria-hidden="true" tabindex="-1"></a>          (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-361"><a href="#cb3-361" aria-hidden="true" tabindex="-1"></a>           <span class="kw">FROM</span></span>
<span id="cb3-362"><a href="#cb3-362" aria-hidden="true" tabindex="-1"></a>           (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-363"><a href="#cb3-363" aria-hidden="true" tabindex="-1"></a>            <span class="kw">FROM</span></span>
<span id="cb3-364"><a href="#cb3-364" aria-hidden="true" tabindex="-1"></a>            (<span class="kw">SELECT</span></span>
<span id="cb3-365"><a href="#cb3-365" aria-hidden="true" tabindex="-1"></a>             f0 <span class="kw">AS</span> f0, f1 <span class="kw">AS</span> f1</span>
<span id="cb3-366"><a href="#cb3-366" aria-hidden="true" tabindex="-1"></a>             <span class="kw">FROM</span></span>
<span id="cb3-367"><a href="#cb3-367" aria-hidden="true" tabindex="-1"></a>             (<span class="kw">WITH</span> t17 <span class="kw">AS</span></span>
<span id="cb3-368"><a href="#cb3-368" aria-hidden="true" tabindex="-1"></a>              (<span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t15 <span class="kw">AS</span> _)</span>
<span id="cb3-369"><a href="#cb3-369" aria-hidden="true" tabindex="-1"></a>              <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-370"><a href="#cb3-370" aria-hidden="true" tabindex="-1"></a>              <span class="kw">FROM</span></span>
<span id="cb3-371"><a href="#cb3-371" aria-hidden="true" tabindex="-1"></a>              (<span class="kw">WITH</span> t18 <span class="kw">AS</span></span>
<span id="cb3-372"><a href="#cb3-372" aria-hidden="true" tabindex="-1"></a>               (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-373"><a href="#cb3-373" aria-hidden="true" tabindex="-1"></a>                <span class="kw">FROM</span></span>
<span id="cb3-374"><a href="#cb3-374" aria-hidden="true" tabindex="-1"></a>                (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-375"><a href="#cb3-375" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">FROM</span></span>
<span id="cb3-376"><a href="#cb3-376" aria-hidden="true" tabindex="-1"></a>                 (<span class="kw">SELECT</span></span>
<span id="cb3-377"><a href="#cb3-377" aria-hidden="true" tabindex="-1"></a>                  f0 <span class="kw">AS</span> f0</span>
<span id="cb3-378"><a href="#cb3-378" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">FROM</span></span>
<span id="cb3-379"><a href="#cb3-379" aria-hidden="true" tabindex="-1"></a>                  (<span class="kw">WITH</span> t19 <span class="kw">AS</span></span>
<span id="cb3-380"><a href="#cb3-380" aria-hidden="true" tabindex="-1"></a>                   (<span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f0, f1 <span class="kw">AS</span> f1 <span class="kw">FROM</span> t17 <span class="kw">AS</span> _) <span class="kw">AS</span> _)</span>
<span id="cb3-381"><a href="#cb3-381" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-382"><a href="#cb3-382" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">FROM</span></span>
<span id="cb3-383"><a href="#cb3-383" aria-hidden="true" tabindex="-1"></a>                   (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-384"><a href="#cb3-384" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">FROM</span></span>
<span id="cb3-385"><a href="#cb3-385" aria-hidden="true" tabindex="-1"></a>                    (<span class="kw">SELECT</span></span>
<span id="cb3-386"><a href="#cb3-386" aria-hidden="true" tabindex="-1"></a>                     f0 <span class="kw">AS</span> f0</span>
<span id="cb3-387"><a href="#cb3-387" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">FROM</span></span>
<span id="cb3-388"><a href="#cb3-388" aria-hidden="true" tabindex="-1"></a>                     (<span class="co">-- join1</span></span>
<span id="cb3-389"><a href="#cb3-389" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t19 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f0&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-390"><a href="#cb3-390" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">AS</span> _)</span>
<span id="cb3-391"><a href="#cb3-391" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">AS</span> _</span>
<span id="cb3-392"><a href="#cb3-392" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">UNION</span></span>
<span id="cb3-393"><a href="#cb3-393" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-394"><a href="#cb3-394" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">FROM</span></span>
<span id="cb3-395"><a href="#cb3-395" aria-hidden="true" tabindex="-1"></a>                    (<span class="kw">SELECT</span></span>
<span id="cb3-396"><a href="#cb3-396" aria-hidden="true" tabindex="-1"></a>                     f1 <span class="kw">AS</span> f0</span>
<span id="cb3-397"><a href="#cb3-397" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">FROM</span></span>
<span id="cb3-398"><a href="#cb3-398" aria-hidden="true" tabindex="-1"></a>                     (<span class="co">-- join2</span></span>
<span id="cb3-399"><a href="#cb3-399" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t19 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f1&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-400"><a href="#cb3-400" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">AS</span> _)</span>
<span id="cb3-401"><a href="#cb3-401" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">AS</span> _)</span>
<span id="cb3-402"><a href="#cb3-402" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">AS</span> _)</span>
<span id="cb3-403"><a href="#cb3-403" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">AS</span> _)</span>
<span id="cb3-404"><a href="#cb3-404" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">AS</span> _</span>
<span id="cb3-405"><a href="#cb3-405" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">CROSS</span> <span class="kw">JOIN</span></span>
<span id="cb3-406"><a href="#cb3-406" aria-hidden="true" tabindex="-1"></a>                 (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f1, f1 <span class="kw">AS</span> f2, f2 <span class="kw">AS</span> f3 <span class="kw">FROM</span> t17 <span class="kw">AS</span> _))</span>
<span id="cb3-407"><a href="#cb3-407" aria-hidden="true" tabindex="-1"></a>                <span class="kw">AS</span> _)</span>
<span id="cb3-408"><a href="#cb3-408" aria-hidden="true" tabindex="-1"></a>               <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-409"><a href="#cb3-409" aria-hidden="true" tabindex="-1"></a>               <span class="kw">FROM</span></span>
<span id="cb3-410"><a href="#cb3-410" aria-hidden="true" tabindex="-1"></a>               (<span class="kw">WITH</span> t20 <span class="kw">AS</span></span>
<span id="cb3-411"><a href="#cb3-411" aria-hidden="true" tabindex="-1"></a>                (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-412"><a href="#cb3-412" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">FROM</span></span>
<span id="cb3-413"><a href="#cb3-413" aria-hidden="true" tabindex="-1"></a>                 (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-414"><a href="#cb3-414" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">FROM</span></span>
<span id="cb3-415"><a href="#cb3-415" aria-hidden="true" tabindex="-1"></a>                  (<span class="kw">SELECT</span></span>
<span id="cb3-416"><a href="#cb3-416" aria-hidden="true" tabindex="-1"></a>                   f0 <span class="kw">AS</span> f0, f1 <span class="kw">AS</span> f1</span>
<span id="cb3-417"><a href="#cb3-417" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">FROM</span></span>
<span id="cb3-418"><a href="#cb3-418" aria-hidden="true" tabindex="-1"></a>                   (<span class="kw">WITH</span> t21 <span class="kw">AS</span></span>
<span id="cb3-419"><a href="#cb3-419" aria-hidden="true" tabindex="-1"></a>                    (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-420"><a href="#cb3-420" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">FROM</span></span>
<span id="cb3-421"><a href="#cb3-421" aria-hidden="true" tabindex="-1"></a>                     (<span class="kw">SELECT</span></span>
<span id="cb3-422"><a href="#cb3-422" aria-hidden="true" tabindex="-1"></a>                      f0 <span class="op">-</span> f1 <span class="kw">AS</span> f0</span>
<span id="cb3-423"><a href="#cb3-423" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">FROM</span></span>
<span id="cb3-424"><a href="#cb3-424" aria-hidden="true" tabindex="-1"></a>                      (<span class="kw">WITH</span> t22 <span class="kw">AS</span></span>
<span id="cb3-425"><a href="#cb3-425" aria-hidden="true" tabindex="-1"></a>                       (<span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t18 <span class="kw">AS</span> _)</span>
<span id="cb3-426"><a href="#cb3-426" aria-hidden="true" tabindex="-1"></a>                       <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-427"><a href="#cb3-427" aria-hidden="true" tabindex="-1"></a>                       <span class="kw">FROM</span></span>
<span id="cb3-428"><a href="#cb3-428" aria-hidden="true" tabindex="-1"></a>                       (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-429"><a href="#cb3-429" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">FROM</span></span>
<span id="cb3-430"><a href="#cb3-430" aria-hidden="true" tabindex="-1"></a>                        (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f0 <span class="kw">FROM</span> (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f0 <span class="kw">FROM</span> t22 <span class="kw">AS</span> _) <span class="kw">AS</span> _)</span>
<span id="cb3-431"><a href="#cb3-431" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">AS</span> _</span>
<span id="cb3-432"><a href="#cb3-432" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">CROSS</span> <span class="kw">JOIN</span></span>
<span id="cb3-433"><a href="#cb3-433" aria-hidden="true" tabindex="-1"></a>                        (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f1 <span class="kw">FROM</span> (<span class="kw">SELECT</span> <span class="dv">100</span> <span class="kw">as</span> f0 <span class="kw">FROM</span> t22 <span class="kw">AS</span> _) <span class="kw">AS</span> _))</span>
<span id="cb3-434"><a href="#cb3-434" aria-hidden="true" tabindex="-1"></a>                       <span class="kw">AS</span> _)</span>
<span id="cb3-435"><a href="#cb3-435" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">AS</span> _)</span>
<span id="cb3-436"><a href="#cb3-436" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">AS</span> _)</span>
<span id="cb3-437"><a href="#cb3-437" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-438"><a href="#cb3-438" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">FROM</span></span>
<span id="cb3-439"><a href="#cb3-439" aria-hidden="true" tabindex="-1"></a>                    (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-440"><a href="#cb3-440" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">FROM</span></span>
<span id="cb3-441"><a href="#cb3-441" aria-hidden="true" tabindex="-1"></a>                     (<span class="kw">SELECT</span></span>
<span id="cb3-442"><a href="#cb3-442" aria-hidden="true" tabindex="-1"></a>                      <span class="fu">abs</span>(f0) <span class="kw">as</span> f0, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">as</span> f1</span>
<span id="cb3-443"><a href="#cb3-443" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">FROM</span></span>
<span id="cb3-444"><a href="#cb3-444" aria-hidden="true" tabindex="-1"></a>                      t21</span>
<span id="cb3-445"><a href="#cb3-445" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">AS</span> _</span>
<span id="cb3-446"><a href="#cb3-446" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">WHERE</span></span>
<span id="cb3-447"><a href="#cb3-447" aria-hidden="true" tabindex="-1"></a>                      f0 <span class="op">&lt;</span> <span class="dv">0</span>)</span>
<span id="cb3-448"><a href="#cb3-448" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">AS</span> _</span>
<span id="cb3-449"><a href="#cb3-449" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">UNION</span></span>
<span id="cb3-450"><a href="#cb3-450" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-451"><a href="#cb3-451" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">FROM</span></span>
<span id="cb3-452"><a href="#cb3-452" aria-hidden="true" tabindex="-1"></a>                     (<span class="kw">SELECT</span> <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">as</span> f0, f0 <span class="kw">as</span> f1 <span class="kw">FROM</span> t21 <span class="kw">AS</span> _ <span class="kw">WHERE</span> f0 <span class="op">&gt;=</span> <span class="dv">0</span>)</span>
<span id="cb3-453"><a href="#cb3-453" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">AS</span> _)</span>
<span id="cb3-454"><a href="#cb3-454" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">AS</span> _)</span>
<span id="cb3-455"><a href="#cb3-455" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">AS</span> _)</span>
<span id="cb3-456"><a href="#cb3-456" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">AS</span> _</span>
<span id="cb3-457"><a href="#cb3-457" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">CROSS</span> <span class="kw">JOIN</span></span>
<span id="cb3-458"><a href="#cb3-458" aria-hidden="true" tabindex="-1"></a>                  (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f2, f1 <span class="kw">AS</span> f3, f2 <span class="kw">AS</span> f4, f3 <span class="kw">AS</span> f5 <span class="kw">FROM</span> t18 <span class="kw">AS</span> _))</span>
<span id="cb3-459"><a href="#cb3-459" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">AS</span> _)</span>
<span id="cb3-460"><a href="#cb3-460" aria-hidden="true" tabindex="-1"></a>                <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-461"><a href="#cb3-461" aria-hidden="true" tabindex="-1"></a>                <span class="kw">FROM</span></span>
<span id="cb3-462"><a href="#cb3-462" aria-hidden="true" tabindex="-1"></a>                (<span class="kw">WITH</span> t23 <span class="kw">AS</span></span>
<span id="cb3-463"><a href="#cb3-463" aria-hidden="true" tabindex="-1"></a>                 (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-464"><a href="#cb3-464" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">FROM</span></span>
<span id="cb3-465"><a href="#cb3-465" aria-hidden="true" tabindex="-1"></a>                  (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-466"><a href="#cb3-466" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">FROM</span></span>
<span id="cb3-467"><a href="#cb3-467" aria-hidden="true" tabindex="-1"></a>                   (<span class="kw">SELECT</span></span>
<span id="cb3-468"><a href="#cb3-468" aria-hidden="true" tabindex="-1"></a>                    f0 <span class="kw">AS</span> f0, f1 <span class="kw">AS</span> f1</span>
<span id="cb3-469"><a href="#cb3-469" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">FROM</span></span>
<span id="cb3-470"><a href="#cb3-470" aria-hidden="true" tabindex="-1"></a>                    (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f0, f1 <span class="kw">AS</span> f1 <span class="kw">FROM</span> t20 <span class="kw">AS</span> _)</span>
<span id="cb3-471"><a href="#cb3-471" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">AS</span> _)</span>
<span id="cb3-472"><a href="#cb3-472" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">AS</span> _</span>
<span id="cb3-473"><a href="#cb3-473" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">CROSS</span> <span class="kw">JOIN</span></span>
<span id="cb3-474"><a href="#cb3-474" aria-hidden="true" tabindex="-1"></a>                   (<span class="kw">SELECT</span></span>
<span id="cb3-475"><a href="#cb3-475" aria-hidden="true" tabindex="-1"></a>                    f0 <span class="kw">AS</span> f2, f1 <span class="kw">AS</span> f3, f2 <span class="kw">AS</span> f4, f3 <span class="kw">AS</span> f5, f4 <span class="kw">AS</span> f6, f5 <span class="kw">AS</span> f7</span>
<span id="cb3-476"><a href="#cb3-476" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">FROM</span></span>
<span id="cb3-477"><a href="#cb3-477" aria-hidden="true" tabindex="-1"></a>                    t20</span>
<span id="cb3-478"><a href="#cb3-478" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">AS</span> _))</span>
<span id="cb3-479"><a href="#cb3-479" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">AS</span> _)</span>
<span id="cb3-480"><a href="#cb3-480" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-481"><a href="#cb3-481" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">FROM</span></span>
<span id="cb3-482"><a href="#cb3-482" aria-hidden="true" tabindex="-1"></a>                 (<span class="kw">WITH</span> t24 <span class="kw">AS</span></span>
<span id="cb3-483"><a href="#cb3-483" aria-hidden="true" tabindex="-1"></a>                  (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-484"><a href="#cb3-484" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">FROM</span></span>
<span id="cb3-485"><a href="#cb3-485" aria-hidden="true" tabindex="-1"></a>                   (<span class="co">-- dist</span></span>
<span id="cb3-486"><a href="#cb3-486" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-487"><a href="#cb3-487" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">FROM</span></span>
<span id="cb3-488"><a href="#cb3-488" aria-hidden="true" tabindex="-1"></a>                    (<span class="kw">SELECT</span></span>
<span id="cb3-489"><a href="#cb3-489" aria-hidden="true" tabindex="-1"></a>                     f0 <span class="kw">AS</span> f0, f2 <span class="kw">AS</span> f1, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f10, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f11, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f12, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f13, f3 <span class="kw">AS</span> f2, f4 <span class="kw">AS</span> f3, f5 <span class="kw">AS</span> f4, f6 <span class="kw">AS</span> f5, f7 <span class="kw">AS</span> f6, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f7, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f8, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f9</span>
<span id="cb3-490"><a href="#cb3-490" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">FROM</span></span>
<span id="cb3-491"><a href="#cb3-491" aria-hidden="true" tabindex="-1"></a>                     (<span class="co">-- dist1</span></span>
<span id="cb3-492"><a href="#cb3-492" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t23 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f0&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-493"><a href="#cb3-493" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">AS</span> _)</span>
<span id="cb3-494"><a href="#cb3-494" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">AS</span> _</span>
<span id="cb3-495"><a href="#cb3-495" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">UNION</span></span>
<span id="cb3-496"><a href="#cb3-496" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-497"><a href="#cb3-497" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">FROM</span></span>
<span id="cb3-498"><a href="#cb3-498" aria-hidden="true" tabindex="-1"></a>                    (<span class="kw">SELECT</span></span>
<span id="cb3-499"><a href="#cb3-499" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f0, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f1, f4 <span class="kw">AS</span> f10, f5 <span class="kw">AS</span> f11, f6 <span class="kw">AS</span> f12, f7 <span class="kw">AS</span> f13, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f2, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f3, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f4, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f5, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f6, f1 <span class="kw">AS</span> f7, f2 <span class="kw">AS</span> f8, f3 <span class="kw">AS</span> f9</span>
<span id="cb3-500"><a href="#cb3-500" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">FROM</span></span>
<span id="cb3-501"><a href="#cb3-501" aria-hidden="true" tabindex="-1"></a>                     (<span class="co">-- dist2</span></span>
<span id="cb3-502"><a href="#cb3-502" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t23 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f1&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-503"><a href="#cb3-503" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">AS</span> _)</span>
<span id="cb3-504"><a href="#cb3-504" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">AS</span> _)</span>
<span id="cb3-505"><a href="#cb3-505" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">AS</span> _)</span>
<span id="cb3-506"><a href="#cb3-506" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-507"><a href="#cb3-507" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">FROM</span></span>
<span id="cb3-508"><a href="#cb3-508" aria-hidden="true" tabindex="-1"></a>                  (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-509"><a href="#cb3-509" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">FROM</span></span>
<span id="cb3-510"><a href="#cb3-510" aria-hidden="true" tabindex="-1"></a>                   (<span class="kw">SELECT</span></span>
<span id="cb3-511"><a href="#cb3-511" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f0, f0 <span class="kw">AS</span> f1</span>
<span id="cb3-512"><a href="#cb3-512" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">FROM</span></span>
<span id="cb3-513"><a href="#cb3-513" aria-hidden="true" tabindex="-1"></a>                    (<span class="kw">SELECT</span></span>
<span id="cb3-514"><a href="#cb3-514" aria-hidden="true" tabindex="-1"></a>                     f0 <span class="op">+</span> f1 <span class="kw">AS</span> f0</span>
<span id="cb3-515"><a href="#cb3-515" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">FROM</span></span>
<span id="cb3-516"><a href="#cb3-516" aria-hidden="true" tabindex="-1"></a>                     (<span class="kw">WITH</span> t25 <span class="kw">AS</span></span>
<span id="cb3-517"><a href="#cb3-517" aria-hidden="true" tabindex="-1"></a>                      (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-518"><a href="#cb3-518" aria-hidden="true" tabindex="-1"></a>                       <span class="kw">FROM</span></span>
<span id="cb3-519"><a href="#cb3-519" aria-hidden="true" tabindex="-1"></a>                       (<span class="kw">SELECT</span></span>
<span id="cb3-520"><a href="#cb3-520" aria-hidden="true" tabindex="-1"></a>                        f0 <span class="kw">AS</span> f0, f1 <span class="kw">AS</span> f1, f2 <span class="kw">AS</span> f2, f3 <span class="kw">AS</span> f3, f4 <span class="kw">AS</span> f4, f5 <span class="kw">AS</span> f5, f6 <span class="kw">AS</span> f6</span>
<span id="cb3-521"><a href="#cb3-521" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">FROM</span></span>
<span id="cb3-522"><a href="#cb3-522" aria-hidden="true" tabindex="-1"></a>                        (<span class="co">-- join1</span></span>
<span id="cb3-523"><a href="#cb3-523" aria-hidden="true" tabindex="-1"></a>                         <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t24 <span class="kw">AS</span> _</span>
<span id="cb3-524"><a href="#cb3-524" aria-hidden="true" tabindex="-1"></a>                         <span class="kw">WHERE</span></span>
<span id="cb3-525"><a href="#cb3-525" aria-hidden="true" tabindex="-1"></a>                         (<span class="ot">&quot;f0&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">AND</span> (((<span class="ot">&quot;f1&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">OR</span> (<span class="ot">&quot;f2&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)) <span class="kw">AND</span> ((<span class="ot">&quot;f3&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">AND</span> (((<span class="ot">&quot;f4&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">OR</span> (<span class="ot">&quot;f5&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)) <span class="kw">AND</span> (<span class="ot">&quot;f6&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)))))</span>
<span id="cb3-526"><a href="#cb3-526" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">AS</span> _)</span>
<span id="cb3-527"><a href="#cb3-527" aria-hidden="true" tabindex="-1"></a>                       <span class="kw">AS</span> _)</span>
<span id="cb3-528"><a href="#cb3-528" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-529"><a href="#cb3-529" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">FROM</span></span>
<span id="cb3-530"><a href="#cb3-530" aria-hidden="true" tabindex="-1"></a>                      (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-531"><a href="#cb3-531" aria-hidden="true" tabindex="-1"></a>                       <span class="kw">FROM</span></span>
<span id="cb3-532"><a href="#cb3-532" aria-hidden="true" tabindex="-1"></a>                       (<span class="kw">SELECT</span></span>
<span id="cb3-533"><a href="#cb3-533" aria-hidden="true" tabindex="-1"></a>                        f0 <span class="kw">AS</span> f0</span>
<span id="cb3-534"><a href="#cb3-534" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">FROM</span></span>
<span id="cb3-535"><a href="#cb3-535" aria-hidden="true" tabindex="-1"></a>                        (<span class="kw">SELECT</span></span>
<span id="cb3-536"><a href="#cb3-536" aria-hidden="true" tabindex="-1"></a>                         f0 <span class="kw">AS</span> f0</span>
<span id="cb3-537"><a href="#cb3-537" aria-hidden="true" tabindex="-1"></a>                         <span class="kw">FROM</span></span>
<span id="cb3-538"><a href="#cb3-538" aria-hidden="true" tabindex="-1"></a>                         (<span class="kw">SELECT</span></span>
<span id="cb3-539"><a href="#cb3-539" aria-hidden="true" tabindex="-1"></a>                          f2 <span class="kw">AS</span> f0, f3 <span class="kw">AS</span> f1, f4 <span class="kw">AS</span> f2, f5 <span class="kw">AS</span> f3</span>
<span id="cb3-540"><a href="#cb3-540" aria-hidden="true" tabindex="-1"></a>                          <span class="kw">FROM</span></span>
<span id="cb3-541"><a href="#cb3-541" aria-hidden="true" tabindex="-1"></a>                          (<span class="kw">SELECT</span></span>
<span id="cb3-542"><a href="#cb3-542" aria-hidden="true" tabindex="-1"></a>                           f1 <span class="kw">AS</span> f0, f2 <span class="kw">AS</span> f1, f3 <span class="kw">AS</span> f2, f4 <span class="kw">AS</span> f3, f5 <span class="kw">AS</span> f4, f6 <span class="kw">AS</span> f5</span>
<span id="cb3-543"><a href="#cb3-543" aria-hidden="true" tabindex="-1"></a>                           <span class="kw">FROM</span></span>
<span id="cb3-544"><a href="#cb3-544" aria-hidden="true" tabindex="-1"></a>                           t25</span>
<span id="cb3-545"><a href="#cb3-545" aria-hidden="true" tabindex="-1"></a>                           <span class="kw">AS</span> _)</span>
<span id="cb3-546"><a href="#cb3-546" aria-hidden="true" tabindex="-1"></a>                          <span class="kw">AS</span> _)</span>
<span id="cb3-547"><a href="#cb3-547" aria-hidden="true" tabindex="-1"></a>                         <span class="kw">AS</span> _)</span>
<span id="cb3-548"><a href="#cb3-548" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">AS</span> _)</span>
<span id="cb3-549"><a href="#cb3-549" aria-hidden="true" tabindex="-1"></a>                       <span class="kw">AS</span> _</span>
<span id="cb3-550"><a href="#cb3-550" aria-hidden="true" tabindex="-1"></a>                       <span class="kw">CROSS</span> <span class="kw">JOIN</span></span>
<span id="cb3-551"><a href="#cb3-551" aria-hidden="true" tabindex="-1"></a>                       (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f1 <span class="kw">FROM</span> (<span class="kw">SELECT</span> <span class="dv">1</span> <span class="kw">as</span> f0 <span class="kw">FROM</span> t25 <span class="kw">AS</span> _) <span class="kw">AS</span> _))</span>
<span id="cb3-552"><a href="#cb3-552" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">AS</span> _)</span>
<span id="cb3-553"><a href="#cb3-553" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">AS</span> _)</span>
<span id="cb3-554"><a href="#cb3-554" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">AS</span> _)</span>
<span id="cb3-555"><a href="#cb3-555" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">AS</span> _</span>
<span id="cb3-556"><a href="#cb3-556" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">UNION</span></span>
<span id="cb3-557"><a href="#cb3-557" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-558"><a href="#cb3-558" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">FROM</span></span>
<span id="cb3-559"><a href="#cb3-559" aria-hidden="true" tabindex="-1"></a>                   (<span class="kw">SELECT</span></span>
<span id="cb3-560"><a href="#cb3-560" aria-hidden="true" tabindex="-1"></a>                    f0 <span class="kw">AS</span> f0, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f1</span>
<span id="cb3-561"><a href="#cb3-561" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">FROM</span></span>
<span id="cb3-562"><a href="#cb3-562" aria-hidden="true" tabindex="-1"></a>                    (<span class="kw">SELECT</span></span>
<span id="cb3-563"><a href="#cb3-563" aria-hidden="true" tabindex="-1"></a>                     f0 <span class="kw">AS</span> f0</span>
<span id="cb3-564"><a href="#cb3-564" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">FROM</span></span>
<span id="cb3-565"><a href="#cb3-565" aria-hidden="true" tabindex="-1"></a>                     (<span class="kw">SELECT</span></span>
<span id="cb3-566"><a href="#cb3-566" aria-hidden="true" tabindex="-1"></a>                      f2 <span class="kw">AS</span> f0, f3 <span class="kw">AS</span> f1, f4 <span class="kw">AS</span> f2, f5 <span class="kw">AS</span> f3</span>
<span id="cb3-567"><a href="#cb3-567" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">FROM</span></span>
<span id="cb3-568"><a href="#cb3-568" aria-hidden="true" tabindex="-1"></a>                      (<span class="kw">SELECT</span></span>
<span id="cb3-569"><a href="#cb3-569" aria-hidden="true" tabindex="-1"></a>                       f1 <span class="kw">AS</span> f0, f2 <span class="kw">AS</span> f1, f3 <span class="kw">AS</span> f2, f4 <span class="kw">AS</span> f3, f5 <span class="kw">AS</span> f4, f6 <span class="kw">AS</span> f5</span>
<span id="cb3-570"><a href="#cb3-570" aria-hidden="true" tabindex="-1"></a>                       <span class="kw">FROM</span></span>
<span id="cb3-571"><a href="#cb3-571" aria-hidden="true" tabindex="-1"></a>                       (<span class="kw">SELECT</span></span>
<span id="cb3-572"><a href="#cb3-572" aria-hidden="true" tabindex="-1"></a>                        f7 <span class="kw">AS</span> f0, f8 <span class="kw">AS</span> f1, f9 <span class="kw">AS</span> f2, f10 <span class="kw">AS</span> f3, f11 <span class="kw">AS</span> f4, f12 <span class="kw">AS</span> f5, f13 <span class="kw">AS</span> f6</span>
<span id="cb3-573"><a href="#cb3-573" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">FROM</span></span>
<span id="cb3-574"><a href="#cb3-574" aria-hidden="true" tabindex="-1"></a>                        (<span class="co">-- join2</span></span>
<span id="cb3-575"><a href="#cb3-575" aria-hidden="true" tabindex="-1"></a>                         <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t24 <span class="kw">AS</span> _</span>
<span id="cb3-576"><a href="#cb3-576" aria-hidden="true" tabindex="-1"></a>                         <span class="kw">WHERE</span></span>
<span id="cb3-577"><a href="#cb3-577" aria-hidden="true" tabindex="-1"></a>                         (<span class="ot">&quot;f7&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">AND</span> (((<span class="ot">&quot;f8&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">OR</span> (<span class="ot">&quot;f9&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)) <span class="kw">AND</span> ((<span class="ot">&quot;f10&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">AND</span> (((<span class="ot">&quot;f11&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">OR</span> (<span class="ot">&quot;f12&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)) <span class="kw">AND</span> (<span class="ot">&quot;f13&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)))))</span>
<span id="cb3-578"><a href="#cb3-578" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">AS</span> _)</span>
<span id="cb3-579"><a href="#cb3-579" aria-hidden="true" tabindex="-1"></a>                       <span class="kw">AS</span> _)</span>
<span id="cb3-580"><a href="#cb3-580" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">AS</span> _)</span>
<span id="cb3-581"><a href="#cb3-581" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">AS</span> _)</span>
<span id="cb3-582"><a href="#cb3-582" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">AS</span> _)</span>
<span id="cb3-583"><a href="#cb3-583" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">AS</span> _)</span>
<span id="cb3-584"><a href="#cb3-584" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">AS</span> _)</span>
<span id="cb3-585"><a href="#cb3-585" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">AS</span> _)</span>
<span id="cb3-586"><a href="#cb3-586" aria-hidden="true" tabindex="-1"></a>                <span class="kw">AS</span> _)</span>
<span id="cb3-587"><a href="#cb3-587" aria-hidden="true" tabindex="-1"></a>               <span class="kw">AS</span> _)</span>
<span id="cb3-588"><a href="#cb3-588" aria-hidden="true" tabindex="-1"></a>              <span class="kw">AS</span> _)</span>
<span id="cb3-589"><a href="#cb3-589" aria-hidden="true" tabindex="-1"></a>             <span class="kw">AS</span> _)</span>
<span id="cb3-590"><a href="#cb3-590" aria-hidden="true" tabindex="-1"></a>            <span class="kw">AS</span> _</span>
<span id="cb3-591"><a href="#cb3-591" aria-hidden="true" tabindex="-1"></a>            <span class="kw">CROSS</span> <span class="kw">JOIN</span></span>
<span id="cb3-592"><a href="#cb3-592" aria-hidden="true" tabindex="-1"></a>            (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f2 <span class="kw">FROM</span> (<span class="kw">SELECT</span> f2 <span class="kw">AS</span> f0 <span class="kw">FROM</span> t15 <span class="kw">AS</span> _) <span class="kw">AS</span> _))</span>
<span id="cb3-593"><a href="#cb3-593" aria-hidden="true" tabindex="-1"></a>           <span class="kw">AS</span> _)</span>
<span id="cb3-594"><a href="#cb3-594" aria-hidden="true" tabindex="-1"></a>          <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-595"><a href="#cb3-595" aria-hidden="true" tabindex="-1"></a>          <span class="kw">FROM</span></span>
<span id="cb3-596"><a href="#cb3-596" aria-hidden="true" tabindex="-1"></a>          (<span class="co">-- dist</span></span>
<span id="cb3-597"><a href="#cb3-597" aria-hidden="true" tabindex="-1"></a>           <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-598"><a href="#cb3-598" aria-hidden="true" tabindex="-1"></a>           <span class="kw">FROM</span></span>
<span id="cb3-599"><a href="#cb3-599" aria-hidden="true" tabindex="-1"></a>           (<span class="kw">SELECT</span></span>
<span id="cb3-600"><a href="#cb3-600" aria-hidden="true" tabindex="-1"></a>            f0 <span class="kw">AS</span> f0, f2 <span class="kw">AS</span> f1, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f2, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f3</span>
<span id="cb3-601"><a href="#cb3-601" aria-hidden="true" tabindex="-1"></a>            <span class="kw">FROM</span></span>
<span id="cb3-602"><a href="#cb3-602" aria-hidden="true" tabindex="-1"></a>            (<span class="co">-- dist1</span></span>
<span id="cb3-603"><a href="#cb3-603" aria-hidden="true" tabindex="-1"></a>             <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t16 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f0&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-604"><a href="#cb3-604" aria-hidden="true" tabindex="-1"></a>            <span class="kw">AS</span> _)</span>
<span id="cb3-605"><a href="#cb3-605" aria-hidden="true" tabindex="-1"></a>           <span class="kw">AS</span> _</span>
<span id="cb3-606"><a href="#cb3-606" aria-hidden="true" tabindex="-1"></a>           <span class="kw">UNION</span></span>
<span id="cb3-607"><a href="#cb3-607" aria-hidden="true" tabindex="-1"></a>           <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-608"><a href="#cb3-608" aria-hidden="true" tabindex="-1"></a>           <span class="kw">FROM</span></span>
<span id="cb3-609"><a href="#cb3-609" aria-hidden="true" tabindex="-1"></a>           (<span class="kw">SELECT</span></span>
<span id="cb3-610"><a href="#cb3-610" aria-hidden="true" tabindex="-1"></a>            <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f0, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f1, f1 <span class="kw">AS</span> f2, f2 <span class="kw">AS</span> f3</span>
<span id="cb3-611"><a href="#cb3-611" aria-hidden="true" tabindex="-1"></a>            <span class="kw">FROM</span></span>
<span id="cb3-612"><a href="#cb3-612" aria-hidden="true" tabindex="-1"></a>            (<span class="co">-- dist2</span></span>
<span id="cb3-613"><a href="#cb3-613" aria-hidden="true" tabindex="-1"></a>             <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t16 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f1&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-614"><a href="#cb3-614" aria-hidden="true" tabindex="-1"></a>            <span class="kw">AS</span> _)</span>
<span id="cb3-615"><a href="#cb3-615" aria-hidden="true" tabindex="-1"></a>           <span class="kw">AS</span> _)</span>
<span id="cb3-616"><a href="#cb3-616" aria-hidden="true" tabindex="-1"></a>          <span class="kw">AS</span> _)</span>
<span id="cb3-617"><a href="#cb3-617" aria-hidden="true" tabindex="-1"></a>         <span class="kw">AS</span> _)</span>
<span id="cb3-618"><a href="#cb3-618" aria-hidden="true" tabindex="-1"></a>        <span class="kw">AS</span> _)</span>
<span id="cb3-619"><a href="#cb3-619" aria-hidden="true" tabindex="-1"></a>       <span class="kw">AS</span> _</span>
<span id="cb3-620"><a href="#cb3-620" aria-hidden="true" tabindex="-1"></a>       <span class="kw">WHERE</span></span>
<span id="cb3-621"><a href="#cb3-621" aria-hidden="true" tabindex="-1"></a>       (<span class="ot">&quot;f2&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">AND</span> (<span class="ot">&quot;f3&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>))</span>
<span id="cb3-622"><a href="#cb3-622" aria-hidden="true" tabindex="-1"></a>      <span class="kw">AS</span> _)</span>
<span id="cb3-623"><a href="#cb3-623" aria-hidden="true" tabindex="-1"></a>     <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> recursion <span class="kw">ORDER</span> <span class="kw">BY</span> step <span class="kw">DESC</span> <span class="kw">LIMIT</span> <span class="dv">1</span>)</span>
<span id="cb3-624"><a href="#cb3-624" aria-hidden="true" tabindex="-1"></a>    <span class="kw">AS</span> _)</span>
<span id="cb3-625"><a href="#cb3-625" aria-hidden="true" tabindex="-1"></a>   <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-626"><a href="#cb3-626" aria-hidden="true" tabindex="-1"></a>   <span class="kw">FROM</span></span>
<span id="cb3-627"><a href="#cb3-627" aria-hidden="true" tabindex="-1"></a>   (<span class="kw">WITH</span> t26 <span class="kw">AS</span></span>
<span id="cb3-628"><a href="#cb3-628" aria-hidden="true" tabindex="-1"></a>    (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-629"><a href="#cb3-629" aria-hidden="true" tabindex="-1"></a>     <span class="kw">FROM</span></span>
<span id="cb3-630"><a href="#cb3-630" aria-hidden="true" tabindex="-1"></a>     (<span class="co">-- undist</span></span>
<span id="cb3-631"><a href="#cb3-631" aria-hidden="true" tabindex="-1"></a>      <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-632"><a href="#cb3-632" aria-hidden="true" tabindex="-1"></a>      <span class="kw">FROM</span></span>
<span id="cb3-633"><a href="#cb3-633" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">SELECT</span></span>
<span id="cb3-634"><a href="#cb3-634" aria-hidden="true" tabindex="-1"></a>       f0 <span class="kw">AS</span> f0, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f1, f1 <span class="kw">AS</span> f2</span>
<span id="cb3-635"><a href="#cb3-635" aria-hidden="true" tabindex="-1"></a>       <span class="kw">FROM</span></span>
<span id="cb3-636"><a href="#cb3-636" aria-hidden="true" tabindex="-1"></a>       (<span class="co">-- undist1</span></span>
<span id="cb3-637"><a href="#cb3-637" aria-hidden="true" tabindex="-1"></a>        <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t0 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f0&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-638"><a href="#cb3-638" aria-hidden="true" tabindex="-1"></a>       <span class="kw">AS</span> _)</span>
<span id="cb3-639"><a href="#cb3-639" aria-hidden="true" tabindex="-1"></a>      <span class="kw">AS</span> _</span>
<span id="cb3-640"><a href="#cb3-640" aria-hidden="true" tabindex="-1"></a>      <span class="kw">UNION</span></span>
<span id="cb3-641"><a href="#cb3-641" aria-hidden="true" tabindex="-1"></a>      <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-642"><a href="#cb3-642" aria-hidden="true" tabindex="-1"></a>      <span class="kw">FROM</span></span>
<span id="cb3-643"><a href="#cb3-643" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">SELECT</span></span>
<span id="cb3-644"><a href="#cb3-644" aria-hidden="true" tabindex="-1"></a>       <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f0, f2 <span class="kw">AS</span> f1, f3 <span class="kw">AS</span> f2</span>
<span id="cb3-645"><a href="#cb3-645" aria-hidden="true" tabindex="-1"></a>       <span class="kw">FROM</span></span>
<span id="cb3-646"><a href="#cb3-646" aria-hidden="true" tabindex="-1"></a>       (<span class="co">-- dist2</span></span>
<span id="cb3-647"><a href="#cb3-647" aria-hidden="true" tabindex="-1"></a>        <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t0 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f2&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-648"><a href="#cb3-648" aria-hidden="true" tabindex="-1"></a>       <span class="kw">AS</span> _)</span>
<span id="cb3-649"><a href="#cb3-649" aria-hidden="true" tabindex="-1"></a>      <span class="kw">AS</span> _)</span>
<span id="cb3-650"><a href="#cb3-650" aria-hidden="true" tabindex="-1"></a>     <span class="kw">AS</span> _)</span>
<span id="cb3-651"><a href="#cb3-651" aria-hidden="true" tabindex="-1"></a>    <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-652"><a href="#cb3-652" aria-hidden="true" tabindex="-1"></a>    <span class="kw">FROM</span></span>
<span id="cb3-653"><a href="#cb3-653" aria-hidden="true" tabindex="-1"></a>    (<span class="kw">WITH</span> t27 <span class="kw">AS</span></span>
<span id="cb3-654"><a href="#cb3-654" aria-hidden="true" tabindex="-1"></a>     (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-655"><a href="#cb3-655" aria-hidden="true" tabindex="-1"></a>      <span class="kw">FROM</span></span>
<span id="cb3-656"><a href="#cb3-656" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-657"><a href="#cb3-657" aria-hidden="true" tabindex="-1"></a>       <span class="kw">FROM</span></span>
<span id="cb3-658"><a href="#cb3-658" aria-hidden="true" tabindex="-1"></a>       (<span class="kw">SELECT</span></span>
<span id="cb3-659"><a href="#cb3-659" aria-hidden="true" tabindex="-1"></a>        f0 <span class="kw">AS</span> f0, f1 <span class="kw">AS</span> f1</span>
<span id="cb3-660"><a href="#cb3-660" aria-hidden="true" tabindex="-1"></a>        <span class="kw">FROM</span></span>
<span id="cb3-661"><a href="#cb3-661" aria-hidden="true" tabindex="-1"></a>        (<span class="kw">WITH</span> t28 <span class="kw">AS</span></span>
<span id="cb3-662"><a href="#cb3-662" aria-hidden="true" tabindex="-1"></a>         (<span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t26 <span class="kw">AS</span> _)</span>
<span id="cb3-663"><a href="#cb3-663" aria-hidden="true" tabindex="-1"></a>         <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-664"><a href="#cb3-664" aria-hidden="true" tabindex="-1"></a>         <span class="kw">FROM</span></span>
<span id="cb3-665"><a href="#cb3-665" aria-hidden="true" tabindex="-1"></a>         (<span class="kw">WITH</span> t29 <span class="kw">AS</span></span>
<span id="cb3-666"><a href="#cb3-666" aria-hidden="true" tabindex="-1"></a>          (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-667"><a href="#cb3-667" aria-hidden="true" tabindex="-1"></a>           <span class="kw">FROM</span></span>
<span id="cb3-668"><a href="#cb3-668" aria-hidden="true" tabindex="-1"></a>           (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-669"><a href="#cb3-669" aria-hidden="true" tabindex="-1"></a>            <span class="kw">FROM</span></span>
<span id="cb3-670"><a href="#cb3-670" aria-hidden="true" tabindex="-1"></a>            (<span class="kw">SELECT</span></span>
<span id="cb3-671"><a href="#cb3-671" aria-hidden="true" tabindex="-1"></a>             f0 <span class="kw">AS</span> f0</span>
<span id="cb3-672"><a href="#cb3-672" aria-hidden="true" tabindex="-1"></a>             <span class="kw">FROM</span></span>
<span id="cb3-673"><a href="#cb3-673" aria-hidden="true" tabindex="-1"></a>             (<span class="kw">WITH</span> t30 <span class="kw">AS</span></span>
<span id="cb3-674"><a href="#cb3-674" aria-hidden="true" tabindex="-1"></a>              (<span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f0, f1 <span class="kw">AS</span> f1 <span class="kw">FROM</span> t28 <span class="kw">AS</span> _) <span class="kw">AS</span> _)</span>
<span id="cb3-675"><a href="#cb3-675" aria-hidden="true" tabindex="-1"></a>              <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-676"><a href="#cb3-676" aria-hidden="true" tabindex="-1"></a>              <span class="kw">FROM</span></span>
<span id="cb3-677"><a href="#cb3-677" aria-hidden="true" tabindex="-1"></a>              (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-678"><a href="#cb3-678" aria-hidden="true" tabindex="-1"></a>               <span class="kw">FROM</span></span>
<span id="cb3-679"><a href="#cb3-679" aria-hidden="true" tabindex="-1"></a>               (<span class="kw">SELECT</span></span>
<span id="cb3-680"><a href="#cb3-680" aria-hidden="true" tabindex="-1"></a>                f0 <span class="kw">AS</span> f0</span>
<span id="cb3-681"><a href="#cb3-681" aria-hidden="true" tabindex="-1"></a>                <span class="kw">FROM</span></span>
<span id="cb3-682"><a href="#cb3-682" aria-hidden="true" tabindex="-1"></a>                (<span class="co">-- join1</span></span>
<span id="cb3-683"><a href="#cb3-683" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t30 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f0&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-684"><a href="#cb3-684" aria-hidden="true" tabindex="-1"></a>                <span class="kw">AS</span> _)</span>
<span id="cb3-685"><a href="#cb3-685" aria-hidden="true" tabindex="-1"></a>               <span class="kw">AS</span> _</span>
<span id="cb3-686"><a href="#cb3-686" aria-hidden="true" tabindex="-1"></a>               <span class="kw">UNION</span></span>
<span id="cb3-687"><a href="#cb3-687" aria-hidden="true" tabindex="-1"></a>               <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-688"><a href="#cb3-688" aria-hidden="true" tabindex="-1"></a>               <span class="kw">FROM</span></span>
<span id="cb3-689"><a href="#cb3-689" aria-hidden="true" tabindex="-1"></a>               (<span class="kw">SELECT</span></span>
<span id="cb3-690"><a href="#cb3-690" aria-hidden="true" tabindex="-1"></a>                f1 <span class="kw">AS</span> f0</span>
<span id="cb3-691"><a href="#cb3-691" aria-hidden="true" tabindex="-1"></a>                <span class="kw">FROM</span></span>
<span id="cb3-692"><a href="#cb3-692" aria-hidden="true" tabindex="-1"></a>                (<span class="co">-- join2</span></span>
<span id="cb3-693"><a href="#cb3-693" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t30 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f1&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-694"><a href="#cb3-694" aria-hidden="true" tabindex="-1"></a>                <span class="kw">AS</span> _)</span>
<span id="cb3-695"><a href="#cb3-695" aria-hidden="true" tabindex="-1"></a>               <span class="kw">AS</span> _)</span>
<span id="cb3-696"><a href="#cb3-696" aria-hidden="true" tabindex="-1"></a>              <span class="kw">AS</span> _)</span>
<span id="cb3-697"><a href="#cb3-697" aria-hidden="true" tabindex="-1"></a>             <span class="kw">AS</span> _)</span>
<span id="cb3-698"><a href="#cb3-698" aria-hidden="true" tabindex="-1"></a>            <span class="kw">AS</span> _</span>
<span id="cb3-699"><a href="#cb3-699" aria-hidden="true" tabindex="-1"></a>            <span class="kw">CROSS</span> <span class="kw">JOIN</span></span>
<span id="cb3-700"><a href="#cb3-700" aria-hidden="true" tabindex="-1"></a>            (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f1, f1 <span class="kw">AS</span> f2, f2 <span class="kw">AS</span> f3 <span class="kw">FROM</span> t28 <span class="kw">AS</span> _))</span>
<span id="cb3-701"><a href="#cb3-701" aria-hidden="true" tabindex="-1"></a>           <span class="kw">AS</span> _)</span>
<span id="cb3-702"><a href="#cb3-702" aria-hidden="true" tabindex="-1"></a>          <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-703"><a href="#cb3-703" aria-hidden="true" tabindex="-1"></a>          <span class="kw">FROM</span></span>
<span id="cb3-704"><a href="#cb3-704" aria-hidden="true" tabindex="-1"></a>          (<span class="kw">WITH</span> t31 <span class="kw">AS</span></span>
<span id="cb3-705"><a href="#cb3-705" aria-hidden="true" tabindex="-1"></a>           (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-706"><a href="#cb3-706" aria-hidden="true" tabindex="-1"></a>            <span class="kw">FROM</span></span>
<span id="cb3-707"><a href="#cb3-707" aria-hidden="true" tabindex="-1"></a>            (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-708"><a href="#cb3-708" aria-hidden="true" tabindex="-1"></a>             <span class="kw">FROM</span></span>
<span id="cb3-709"><a href="#cb3-709" aria-hidden="true" tabindex="-1"></a>             (<span class="kw">SELECT</span></span>
<span id="cb3-710"><a href="#cb3-710" aria-hidden="true" tabindex="-1"></a>              f0 <span class="kw">AS</span> f0, f1 <span class="kw">AS</span> f1</span>
<span id="cb3-711"><a href="#cb3-711" aria-hidden="true" tabindex="-1"></a>              <span class="kw">FROM</span></span>
<span id="cb3-712"><a href="#cb3-712" aria-hidden="true" tabindex="-1"></a>              (<span class="kw">WITH</span> t32 <span class="kw">AS</span></span>
<span id="cb3-713"><a href="#cb3-713" aria-hidden="true" tabindex="-1"></a>               (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-714"><a href="#cb3-714" aria-hidden="true" tabindex="-1"></a>                <span class="kw">FROM</span></span>
<span id="cb3-715"><a href="#cb3-715" aria-hidden="true" tabindex="-1"></a>                (<span class="kw">SELECT</span></span>
<span id="cb3-716"><a href="#cb3-716" aria-hidden="true" tabindex="-1"></a>                 f0 <span class="op">-</span> f1 <span class="kw">AS</span> f0</span>
<span id="cb3-717"><a href="#cb3-717" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">FROM</span></span>
<span id="cb3-718"><a href="#cb3-718" aria-hidden="true" tabindex="-1"></a>                 (<span class="kw">WITH</span> t33 <span class="kw">AS</span></span>
<span id="cb3-719"><a href="#cb3-719" aria-hidden="true" tabindex="-1"></a>                  (<span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t29 <span class="kw">AS</span> _)</span>
<span id="cb3-720"><a href="#cb3-720" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-721"><a href="#cb3-721" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">FROM</span></span>
<span id="cb3-722"><a href="#cb3-722" aria-hidden="true" tabindex="-1"></a>                  (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-723"><a href="#cb3-723" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">FROM</span></span>
<span id="cb3-724"><a href="#cb3-724" aria-hidden="true" tabindex="-1"></a>                   (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f0 <span class="kw">FROM</span> (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f0 <span class="kw">FROM</span> t33 <span class="kw">AS</span> _) <span class="kw">AS</span> _)</span>
<span id="cb3-725"><a href="#cb3-725" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">AS</span> _</span>
<span id="cb3-726"><a href="#cb3-726" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">CROSS</span> <span class="kw">JOIN</span></span>
<span id="cb3-727"><a href="#cb3-727" aria-hidden="true" tabindex="-1"></a>                   (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f1 <span class="kw">FROM</span> (<span class="kw">SELECT</span> <span class="dv">100</span> <span class="kw">as</span> f0 <span class="kw">FROM</span> t33 <span class="kw">AS</span> _) <span class="kw">AS</span> _))</span>
<span id="cb3-728"><a href="#cb3-728" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">AS</span> _)</span>
<span id="cb3-729"><a href="#cb3-729" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">AS</span> _)</span>
<span id="cb3-730"><a href="#cb3-730" aria-hidden="true" tabindex="-1"></a>                <span class="kw">AS</span> _)</span>
<span id="cb3-731"><a href="#cb3-731" aria-hidden="true" tabindex="-1"></a>               <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-732"><a href="#cb3-732" aria-hidden="true" tabindex="-1"></a>               <span class="kw">FROM</span></span>
<span id="cb3-733"><a href="#cb3-733" aria-hidden="true" tabindex="-1"></a>               (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-734"><a href="#cb3-734" aria-hidden="true" tabindex="-1"></a>                <span class="kw">FROM</span></span>
<span id="cb3-735"><a href="#cb3-735" aria-hidden="true" tabindex="-1"></a>                (<span class="kw">SELECT</span></span>
<span id="cb3-736"><a href="#cb3-736" aria-hidden="true" tabindex="-1"></a>                 <span class="fu">abs</span>(f0) <span class="kw">as</span> f0, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">as</span> f1</span>
<span id="cb3-737"><a href="#cb3-737" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">FROM</span></span>
<span id="cb3-738"><a href="#cb3-738" aria-hidden="true" tabindex="-1"></a>                 t32</span>
<span id="cb3-739"><a href="#cb3-739" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">AS</span> _</span>
<span id="cb3-740"><a href="#cb3-740" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">WHERE</span></span>
<span id="cb3-741"><a href="#cb3-741" aria-hidden="true" tabindex="-1"></a>                 f0 <span class="op">&lt;</span> <span class="dv">0</span>)</span>
<span id="cb3-742"><a href="#cb3-742" aria-hidden="true" tabindex="-1"></a>                <span class="kw">AS</span> _</span>
<span id="cb3-743"><a href="#cb3-743" aria-hidden="true" tabindex="-1"></a>                <span class="kw">UNION</span></span>
<span id="cb3-744"><a href="#cb3-744" aria-hidden="true" tabindex="-1"></a>                <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-745"><a href="#cb3-745" aria-hidden="true" tabindex="-1"></a>                <span class="kw">FROM</span></span>
<span id="cb3-746"><a href="#cb3-746" aria-hidden="true" tabindex="-1"></a>                (<span class="kw">SELECT</span> <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">as</span> f0, f0 <span class="kw">as</span> f1 <span class="kw">FROM</span> t32 <span class="kw">AS</span> _ <span class="kw">WHERE</span> f0 <span class="op">&gt;=</span> <span class="dv">0</span>)</span>
<span id="cb3-747"><a href="#cb3-747" aria-hidden="true" tabindex="-1"></a>                <span class="kw">AS</span> _)</span>
<span id="cb3-748"><a href="#cb3-748" aria-hidden="true" tabindex="-1"></a>               <span class="kw">AS</span> _)</span>
<span id="cb3-749"><a href="#cb3-749" aria-hidden="true" tabindex="-1"></a>              <span class="kw">AS</span> _)</span>
<span id="cb3-750"><a href="#cb3-750" aria-hidden="true" tabindex="-1"></a>             <span class="kw">AS</span> _</span>
<span id="cb3-751"><a href="#cb3-751" aria-hidden="true" tabindex="-1"></a>             <span class="kw">CROSS</span> <span class="kw">JOIN</span></span>
<span id="cb3-752"><a href="#cb3-752" aria-hidden="true" tabindex="-1"></a>             (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f2, f1 <span class="kw">AS</span> f3, f2 <span class="kw">AS</span> f4, f3 <span class="kw">AS</span> f5 <span class="kw">FROM</span> t29 <span class="kw">AS</span> _))</span>
<span id="cb3-753"><a href="#cb3-753" aria-hidden="true" tabindex="-1"></a>            <span class="kw">AS</span> _)</span>
<span id="cb3-754"><a href="#cb3-754" aria-hidden="true" tabindex="-1"></a>           <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-755"><a href="#cb3-755" aria-hidden="true" tabindex="-1"></a>           <span class="kw">FROM</span></span>
<span id="cb3-756"><a href="#cb3-756" aria-hidden="true" tabindex="-1"></a>           (<span class="kw">WITH</span> t34 <span class="kw">AS</span></span>
<span id="cb3-757"><a href="#cb3-757" aria-hidden="true" tabindex="-1"></a>            (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-758"><a href="#cb3-758" aria-hidden="true" tabindex="-1"></a>             <span class="kw">FROM</span></span>
<span id="cb3-759"><a href="#cb3-759" aria-hidden="true" tabindex="-1"></a>             (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-760"><a href="#cb3-760" aria-hidden="true" tabindex="-1"></a>              <span class="kw">FROM</span></span>
<span id="cb3-761"><a href="#cb3-761" aria-hidden="true" tabindex="-1"></a>              (<span class="kw">SELECT</span></span>
<span id="cb3-762"><a href="#cb3-762" aria-hidden="true" tabindex="-1"></a>               f0 <span class="kw">AS</span> f0, f1 <span class="kw">AS</span> f1</span>
<span id="cb3-763"><a href="#cb3-763" aria-hidden="true" tabindex="-1"></a>               <span class="kw">FROM</span></span>
<span id="cb3-764"><a href="#cb3-764" aria-hidden="true" tabindex="-1"></a>               (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f0, f1 <span class="kw">AS</span> f1 <span class="kw">FROM</span> t31 <span class="kw">AS</span> _)</span>
<span id="cb3-765"><a href="#cb3-765" aria-hidden="true" tabindex="-1"></a>               <span class="kw">AS</span> _)</span>
<span id="cb3-766"><a href="#cb3-766" aria-hidden="true" tabindex="-1"></a>              <span class="kw">AS</span> _</span>
<span id="cb3-767"><a href="#cb3-767" aria-hidden="true" tabindex="-1"></a>              <span class="kw">CROSS</span> <span class="kw">JOIN</span></span>
<span id="cb3-768"><a href="#cb3-768" aria-hidden="true" tabindex="-1"></a>              (<span class="kw">SELECT</span></span>
<span id="cb3-769"><a href="#cb3-769" aria-hidden="true" tabindex="-1"></a>               f0 <span class="kw">AS</span> f2, f1 <span class="kw">AS</span> f3, f2 <span class="kw">AS</span> f4, f3 <span class="kw">AS</span> f5, f4 <span class="kw">AS</span> f6, f5 <span class="kw">AS</span> f7</span>
<span id="cb3-770"><a href="#cb3-770" aria-hidden="true" tabindex="-1"></a>               <span class="kw">FROM</span></span>
<span id="cb3-771"><a href="#cb3-771" aria-hidden="true" tabindex="-1"></a>               t31</span>
<span id="cb3-772"><a href="#cb3-772" aria-hidden="true" tabindex="-1"></a>               <span class="kw">AS</span> _))</span>
<span id="cb3-773"><a href="#cb3-773" aria-hidden="true" tabindex="-1"></a>             <span class="kw">AS</span> _)</span>
<span id="cb3-774"><a href="#cb3-774" aria-hidden="true" tabindex="-1"></a>            <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-775"><a href="#cb3-775" aria-hidden="true" tabindex="-1"></a>            <span class="kw">FROM</span></span>
<span id="cb3-776"><a href="#cb3-776" aria-hidden="true" tabindex="-1"></a>            (<span class="kw">WITH</span> t35 <span class="kw">AS</span></span>
<span id="cb3-777"><a href="#cb3-777" aria-hidden="true" tabindex="-1"></a>             (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-778"><a href="#cb3-778" aria-hidden="true" tabindex="-1"></a>              <span class="kw">FROM</span></span>
<span id="cb3-779"><a href="#cb3-779" aria-hidden="true" tabindex="-1"></a>              (<span class="co">-- dist</span></span>
<span id="cb3-780"><a href="#cb3-780" aria-hidden="true" tabindex="-1"></a>               <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-781"><a href="#cb3-781" aria-hidden="true" tabindex="-1"></a>               <span class="kw">FROM</span></span>
<span id="cb3-782"><a href="#cb3-782" aria-hidden="true" tabindex="-1"></a>               (<span class="kw">SELECT</span></span>
<span id="cb3-783"><a href="#cb3-783" aria-hidden="true" tabindex="-1"></a>                f0 <span class="kw">AS</span> f0, f2 <span class="kw">AS</span> f1, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f10, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f11, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f12, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f13, f3 <span class="kw">AS</span> f2, f4 <span class="kw">AS</span> f3, f5 <span class="kw">AS</span> f4, f6 <span class="kw">AS</span> f5, f7 <span class="kw">AS</span> f6, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f7, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f8, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f9</span>
<span id="cb3-784"><a href="#cb3-784" aria-hidden="true" tabindex="-1"></a>                <span class="kw">FROM</span></span>
<span id="cb3-785"><a href="#cb3-785" aria-hidden="true" tabindex="-1"></a>                (<span class="co">-- dist1</span></span>
<span id="cb3-786"><a href="#cb3-786" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t34 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f0&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-787"><a href="#cb3-787" aria-hidden="true" tabindex="-1"></a>                <span class="kw">AS</span> _)</span>
<span id="cb3-788"><a href="#cb3-788" aria-hidden="true" tabindex="-1"></a>               <span class="kw">AS</span> _</span>
<span id="cb3-789"><a href="#cb3-789" aria-hidden="true" tabindex="-1"></a>               <span class="kw">UNION</span></span>
<span id="cb3-790"><a href="#cb3-790" aria-hidden="true" tabindex="-1"></a>               <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-791"><a href="#cb3-791" aria-hidden="true" tabindex="-1"></a>               <span class="kw">FROM</span></span>
<span id="cb3-792"><a href="#cb3-792" aria-hidden="true" tabindex="-1"></a>               (<span class="kw">SELECT</span></span>
<span id="cb3-793"><a href="#cb3-793" aria-hidden="true" tabindex="-1"></a>                <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f0, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f1, f4 <span class="kw">AS</span> f10, f5 <span class="kw">AS</span> f11, f6 <span class="kw">AS</span> f12, f7 <span class="kw">AS</span> f13, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f2, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f3, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f4, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f5, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f6, f1 <span class="kw">AS</span> f7, f2 <span class="kw">AS</span> f8, f3 <span class="kw">AS</span> f9</span>
<span id="cb3-794"><a href="#cb3-794" aria-hidden="true" tabindex="-1"></a>                <span class="kw">FROM</span></span>
<span id="cb3-795"><a href="#cb3-795" aria-hidden="true" tabindex="-1"></a>                (<span class="co">-- dist2</span></span>
<span id="cb3-796"><a href="#cb3-796" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t34 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f1&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-797"><a href="#cb3-797" aria-hidden="true" tabindex="-1"></a>                <span class="kw">AS</span> _)</span>
<span id="cb3-798"><a href="#cb3-798" aria-hidden="true" tabindex="-1"></a>               <span class="kw">AS</span> _)</span>
<span id="cb3-799"><a href="#cb3-799" aria-hidden="true" tabindex="-1"></a>              <span class="kw">AS</span> _)</span>
<span id="cb3-800"><a href="#cb3-800" aria-hidden="true" tabindex="-1"></a>             <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-801"><a href="#cb3-801" aria-hidden="true" tabindex="-1"></a>             <span class="kw">FROM</span></span>
<span id="cb3-802"><a href="#cb3-802" aria-hidden="true" tabindex="-1"></a>             (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-803"><a href="#cb3-803" aria-hidden="true" tabindex="-1"></a>              <span class="kw">FROM</span></span>
<span id="cb3-804"><a href="#cb3-804" aria-hidden="true" tabindex="-1"></a>              (<span class="kw">SELECT</span></span>
<span id="cb3-805"><a href="#cb3-805" aria-hidden="true" tabindex="-1"></a>               <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f0, f0 <span class="kw">AS</span> f1</span>
<span id="cb3-806"><a href="#cb3-806" aria-hidden="true" tabindex="-1"></a>               <span class="kw">FROM</span></span>
<span id="cb3-807"><a href="#cb3-807" aria-hidden="true" tabindex="-1"></a>               (<span class="kw">SELECT</span></span>
<span id="cb3-808"><a href="#cb3-808" aria-hidden="true" tabindex="-1"></a>                f0 <span class="op">+</span> f1 <span class="kw">AS</span> f0</span>
<span id="cb3-809"><a href="#cb3-809" aria-hidden="true" tabindex="-1"></a>                <span class="kw">FROM</span></span>
<span id="cb3-810"><a href="#cb3-810" aria-hidden="true" tabindex="-1"></a>                (<span class="kw">WITH</span> t36 <span class="kw">AS</span></span>
<span id="cb3-811"><a href="#cb3-811" aria-hidden="true" tabindex="-1"></a>                 (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-812"><a href="#cb3-812" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">FROM</span></span>
<span id="cb3-813"><a href="#cb3-813" aria-hidden="true" tabindex="-1"></a>                  (<span class="kw">SELECT</span></span>
<span id="cb3-814"><a href="#cb3-814" aria-hidden="true" tabindex="-1"></a>                   f0 <span class="kw">AS</span> f0, f1 <span class="kw">AS</span> f1, f2 <span class="kw">AS</span> f2, f3 <span class="kw">AS</span> f3, f4 <span class="kw">AS</span> f4, f5 <span class="kw">AS</span> f5, f6 <span class="kw">AS</span> f6</span>
<span id="cb3-815"><a href="#cb3-815" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">FROM</span></span>
<span id="cb3-816"><a href="#cb3-816" aria-hidden="true" tabindex="-1"></a>                   (<span class="co">-- join1</span></span>
<span id="cb3-817"><a href="#cb3-817" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t35 <span class="kw">AS</span> _</span>
<span id="cb3-818"><a href="#cb3-818" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">WHERE</span></span>
<span id="cb3-819"><a href="#cb3-819" aria-hidden="true" tabindex="-1"></a>                    (<span class="ot">&quot;f0&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">AND</span> (((<span class="ot">&quot;f1&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">OR</span> (<span class="ot">&quot;f2&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)) <span class="kw">AND</span> ((<span class="ot">&quot;f3&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">AND</span> (((<span class="ot">&quot;f4&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">OR</span> (<span class="ot">&quot;f5&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)) <span class="kw">AND</span> (<span class="ot">&quot;f6&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)))))</span>
<span id="cb3-820"><a href="#cb3-820" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">AS</span> _)</span>
<span id="cb3-821"><a href="#cb3-821" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">AS</span> _)</span>
<span id="cb3-822"><a href="#cb3-822" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-823"><a href="#cb3-823" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">FROM</span></span>
<span id="cb3-824"><a href="#cb3-824" aria-hidden="true" tabindex="-1"></a>                 (<span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-825"><a href="#cb3-825" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">FROM</span></span>
<span id="cb3-826"><a href="#cb3-826" aria-hidden="true" tabindex="-1"></a>                  (<span class="kw">SELECT</span></span>
<span id="cb3-827"><a href="#cb3-827" aria-hidden="true" tabindex="-1"></a>                   f0 <span class="kw">AS</span> f0</span>
<span id="cb3-828"><a href="#cb3-828" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">FROM</span></span>
<span id="cb3-829"><a href="#cb3-829" aria-hidden="true" tabindex="-1"></a>                   (<span class="kw">SELECT</span></span>
<span id="cb3-830"><a href="#cb3-830" aria-hidden="true" tabindex="-1"></a>                    f0 <span class="kw">AS</span> f0</span>
<span id="cb3-831"><a href="#cb3-831" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">FROM</span></span>
<span id="cb3-832"><a href="#cb3-832" aria-hidden="true" tabindex="-1"></a>                    (<span class="kw">SELECT</span></span>
<span id="cb3-833"><a href="#cb3-833" aria-hidden="true" tabindex="-1"></a>                     f2 <span class="kw">AS</span> f0, f3 <span class="kw">AS</span> f1, f4 <span class="kw">AS</span> f2, f5 <span class="kw">AS</span> f3</span>
<span id="cb3-834"><a href="#cb3-834" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">FROM</span></span>
<span id="cb3-835"><a href="#cb3-835" aria-hidden="true" tabindex="-1"></a>                     (<span class="kw">SELECT</span></span>
<span id="cb3-836"><a href="#cb3-836" aria-hidden="true" tabindex="-1"></a>                      f1 <span class="kw">AS</span> f0, f2 <span class="kw">AS</span> f1, f3 <span class="kw">AS</span> f2, f4 <span class="kw">AS</span> f3, f5 <span class="kw">AS</span> f4, f6 <span class="kw">AS</span> f5</span>
<span id="cb3-837"><a href="#cb3-837" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">FROM</span></span>
<span id="cb3-838"><a href="#cb3-838" aria-hidden="true" tabindex="-1"></a>                      t36</span>
<span id="cb3-839"><a href="#cb3-839" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">AS</span> _)</span>
<span id="cb3-840"><a href="#cb3-840" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">AS</span> _)</span>
<span id="cb3-841"><a href="#cb3-841" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">AS</span> _)</span>
<span id="cb3-842"><a href="#cb3-842" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">AS</span> _)</span>
<span id="cb3-843"><a href="#cb3-843" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">AS</span> _</span>
<span id="cb3-844"><a href="#cb3-844" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">CROSS</span> <span class="kw">JOIN</span></span>
<span id="cb3-845"><a href="#cb3-845" aria-hidden="true" tabindex="-1"></a>                  (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f1 <span class="kw">FROM</span> (<span class="kw">SELECT</span> <span class="dv">1</span> <span class="kw">as</span> f0 <span class="kw">FROM</span> t36 <span class="kw">AS</span> _) <span class="kw">AS</span> _))</span>
<span id="cb3-846"><a href="#cb3-846" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">AS</span> _)</span>
<span id="cb3-847"><a href="#cb3-847" aria-hidden="true" tabindex="-1"></a>                <span class="kw">AS</span> _)</span>
<span id="cb3-848"><a href="#cb3-848" aria-hidden="true" tabindex="-1"></a>               <span class="kw">AS</span> _)</span>
<span id="cb3-849"><a href="#cb3-849" aria-hidden="true" tabindex="-1"></a>              <span class="kw">AS</span> _</span>
<span id="cb3-850"><a href="#cb3-850" aria-hidden="true" tabindex="-1"></a>              <span class="kw">UNION</span></span>
<span id="cb3-851"><a href="#cb3-851" aria-hidden="true" tabindex="-1"></a>              <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-852"><a href="#cb3-852" aria-hidden="true" tabindex="-1"></a>              <span class="kw">FROM</span></span>
<span id="cb3-853"><a href="#cb3-853" aria-hidden="true" tabindex="-1"></a>              (<span class="kw">SELECT</span></span>
<span id="cb3-854"><a href="#cb3-854" aria-hidden="true" tabindex="-1"></a>               f0 <span class="kw">AS</span> f0, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f1</span>
<span id="cb3-855"><a href="#cb3-855" aria-hidden="true" tabindex="-1"></a>               <span class="kw">FROM</span></span>
<span id="cb3-856"><a href="#cb3-856" aria-hidden="true" tabindex="-1"></a>               (<span class="kw">SELECT</span></span>
<span id="cb3-857"><a href="#cb3-857" aria-hidden="true" tabindex="-1"></a>                f0 <span class="kw">AS</span> f0</span>
<span id="cb3-858"><a href="#cb3-858" aria-hidden="true" tabindex="-1"></a>                <span class="kw">FROM</span></span>
<span id="cb3-859"><a href="#cb3-859" aria-hidden="true" tabindex="-1"></a>                (<span class="kw">SELECT</span></span>
<span id="cb3-860"><a href="#cb3-860" aria-hidden="true" tabindex="-1"></a>                 f2 <span class="kw">AS</span> f0, f3 <span class="kw">AS</span> f1, f4 <span class="kw">AS</span> f2, f5 <span class="kw">AS</span> f3</span>
<span id="cb3-861"><a href="#cb3-861" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">FROM</span></span>
<span id="cb3-862"><a href="#cb3-862" aria-hidden="true" tabindex="-1"></a>                 (<span class="kw">SELECT</span></span>
<span id="cb3-863"><a href="#cb3-863" aria-hidden="true" tabindex="-1"></a>                  f1 <span class="kw">AS</span> f0, f2 <span class="kw">AS</span> f1, f3 <span class="kw">AS</span> f2, f4 <span class="kw">AS</span> f3, f5 <span class="kw">AS</span> f4, f6 <span class="kw">AS</span> f5</span>
<span id="cb3-864"><a href="#cb3-864" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">FROM</span></span>
<span id="cb3-865"><a href="#cb3-865" aria-hidden="true" tabindex="-1"></a>                  (<span class="kw">SELECT</span></span>
<span id="cb3-866"><a href="#cb3-866" aria-hidden="true" tabindex="-1"></a>                   f7 <span class="kw">AS</span> f0, f8 <span class="kw">AS</span> f1, f9 <span class="kw">AS</span> f2, f10 <span class="kw">AS</span> f3, f11 <span class="kw">AS</span> f4, f12 <span class="kw">AS</span> f5, f13 <span class="kw">AS</span> f6</span>
<span id="cb3-867"><a href="#cb3-867" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">FROM</span></span>
<span id="cb3-868"><a href="#cb3-868" aria-hidden="true" tabindex="-1"></a>                   (<span class="co">-- join2</span></span>
<span id="cb3-869"><a href="#cb3-869" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t35 <span class="kw">AS</span> _</span>
<span id="cb3-870"><a href="#cb3-870" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">WHERE</span></span>
<span id="cb3-871"><a href="#cb3-871" aria-hidden="true" tabindex="-1"></a>                    (<span class="ot">&quot;f7&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">AND</span> (((<span class="ot">&quot;f8&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">OR</span> (<span class="ot">&quot;f9&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)) <span class="kw">AND</span> ((<span class="ot">&quot;f10&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">AND</span> (((<span class="ot">&quot;f11&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">OR</span> (<span class="ot">&quot;f12&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)) <span class="kw">AND</span> (<span class="ot">&quot;f13&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)))))</span>
<span id="cb3-872"><a href="#cb3-872" aria-hidden="true" tabindex="-1"></a>                   <span class="kw">AS</span> _)</span>
<span id="cb3-873"><a href="#cb3-873" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">AS</span> _)</span>
<span id="cb3-874"><a href="#cb3-874" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">AS</span> _)</span>
<span id="cb3-875"><a href="#cb3-875" aria-hidden="true" tabindex="-1"></a>                <span class="kw">AS</span> _)</span>
<span id="cb3-876"><a href="#cb3-876" aria-hidden="true" tabindex="-1"></a>               <span class="kw">AS</span> _)</span>
<span id="cb3-877"><a href="#cb3-877" aria-hidden="true" tabindex="-1"></a>              <span class="kw">AS</span> _)</span>
<span id="cb3-878"><a href="#cb3-878" aria-hidden="true" tabindex="-1"></a>             <span class="kw">AS</span> _)</span>
<span id="cb3-879"><a href="#cb3-879" aria-hidden="true" tabindex="-1"></a>            <span class="kw">AS</span> _)</span>
<span id="cb3-880"><a href="#cb3-880" aria-hidden="true" tabindex="-1"></a>           <span class="kw">AS</span> _)</span>
<span id="cb3-881"><a href="#cb3-881" aria-hidden="true" tabindex="-1"></a>          <span class="kw">AS</span> _)</span>
<span id="cb3-882"><a href="#cb3-882" aria-hidden="true" tabindex="-1"></a>         <span class="kw">AS</span> _)</span>
<span id="cb3-883"><a href="#cb3-883" aria-hidden="true" tabindex="-1"></a>        <span class="kw">AS</span> _)</span>
<span id="cb3-884"><a href="#cb3-884" aria-hidden="true" tabindex="-1"></a>       <span class="kw">AS</span> _</span>
<span id="cb3-885"><a href="#cb3-885" aria-hidden="true" tabindex="-1"></a>       <span class="kw">CROSS</span> <span class="kw">JOIN</span></span>
<span id="cb3-886"><a href="#cb3-886" aria-hidden="true" tabindex="-1"></a>       (<span class="kw">SELECT</span> f0 <span class="kw">AS</span> f2 <span class="kw">FROM</span> (<span class="kw">SELECT</span> f2 <span class="kw">AS</span> f0 <span class="kw">FROM</span> t26 <span class="kw">AS</span> _) <span class="kw">AS</span> _))</span>
<span id="cb3-887"><a href="#cb3-887" aria-hidden="true" tabindex="-1"></a>      <span class="kw">AS</span> _)</span>
<span id="cb3-888"><a href="#cb3-888" aria-hidden="true" tabindex="-1"></a>     <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-889"><a href="#cb3-889" aria-hidden="true" tabindex="-1"></a>     <span class="kw">FROM</span></span>
<span id="cb3-890"><a href="#cb3-890" aria-hidden="true" tabindex="-1"></a>     (<span class="co">-- dist</span></span>
<span id="cb3-891"><a href="#cb3-891" aria-hidden="true" tabindex="-1"></a>      <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-892"><a href="#cb3-892" aria-hidden="true" tabindex="-1"></a>      <span class="kw">FROM</span></span>
<span id="cb3-893"><a href="#cb3-893" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">SELECT</span></span>
<span id="cb3-894"><a href="#cb3-894" aria-hidden="true" tabindex="-1"></a>       f0 <span class="kw">AS</span> f0, f2 <span class="kw">AS</span> f1, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f2, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f3</span>
<span id="cb3-895"><a href="#cb3-895" aria-hidden="true" tabindex="-1"></a>       <span class="kw">FROM</span></span>
<span id="cb3-896"><a href="#cb3-896" aria-hidden="true" tabindex="-1"></a>       (<span class="co">-- dist1</span></span>
<span id="cb3-897"><a href="#cb3-897" aria-hidden="true" tabindex="-1"></a>        <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t27 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f0&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-898"><a href="#cb3-898" aria-hidden="true" tabindex="-1"></a>       <span class="kw">AS</span> _)</span>
<span id="cb3-899"><a href="#cb3-899" aria-hidden="true" tabindex="-1"></a>      <span class="kw">AS</span> _</span>
<span id="cb3-900"><a href="#cb3-900" aria-hidden="true" tabindex="-1"></a>      <span class="kw">UNION</span></span>
<span id="cb3-901"><a href="#cb3-901" aria-hidden="true" tabindex="-1"></a>      <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb3-902"><a href="#cb3-902" aria-hidden="true" tabindex="-1"></a>      <span class="kw">FROM</span></span>
<span id="cb3-903"><a href="#cb3-903" aria-hidden="true" tabindex="-1"></a>      (<span class="kw">SELECT</span></span>
<span id="cb3-904"><a href="#cb3-904" aria-hidden="true" tabindex="-1"></a>       <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f0, <span class="kw">NULL</span>:<span class="ch">:integer</span> <span class="kw">AS</span> f1, f1 <span class="kw">AS</span> f2, f2 <span class="kw">AS</span> f3</span>
<span id="cb3-905"><a href="#cb3-905" aria-hidden="true" tabindex="-1"></a>       <span class="kw">FROM</span></span>
<span id="cb3-906"><a href="#cb3-906" aria-hidden="true" tabindex="-1"></a>       (<span class="co">-- dist2</span></span>
<span id="cb3-907"><a href="#cb3-907" aria-hidden="true" tabindex="-1"></a>        <span class="kw">SELECT</span> <span class="op">*</span> <span class="kw">FROM</span> t27 <span class="kw">AS</span> _ <span class="kw">WHERE</span> <span class="ot">&quot;f1&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>)</span>
<span id="cb3-908"><a href="#cb3-908" aria-hidden="true" tabindex="-1"></a>       <span class="kw">AS</span> _)</span>
<span id="cb3-909"><a href="#cb3-909" aria-hidden="true" tabindex="-1"></a>      <span class="kw">AS</span> _)</span>
<span id="cb3-910"><a href="#cb3-910" aria-hidden="true" tabindex="-1"></a>     <span class="kw">AS</span> _)</span>
<span id="cb3-911"><a href="#cb3-911" aria-hidden="true" tabindex="-1"></a>    <span class="kw">AS</span> _)</span>
<span id="cb3-912"><a href="#cb3-912" aria-hidden="true" tabindex="-1"></a>   <span class="kw">AS</span> _)</span>
<span id="cb3-913"><a href="#cb3-913" aria-hidden="true" tabindex="-1"></a>  <span class="kw">AS</span> _</span>
<span id="cb3-914"><a href="#cb3-914" aria-hidden="true" tabindex="-1"></a>  <span class="kw">WHERE</span></span>
<span id="cb3-915"><a href="#cb3-915" aria-hidden="true" tabindex="-1"></a>  (<span class="ot">&quot;f0&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>) <span class="kw">AND</span> (<span class="ot">&quot;f1&quot;</span> <span class="kw">IS</span> <span class="kw">NOT</span> <span class="kw">NULL</span>))</span>
<span id="cb3-916"><a href="#cb3-916" aria-hidden="true" tabindex="-1"></a> <span class="kw">AS</span> _)</span>
<span id="cb3-917"><a href="#cb3-917" aria-hidden="true" tabindex="-1"></a><span class="kw">AS</span> _;</span></code></pre></div>
</details>
<p>It’s not pretty, rather amazingly, running the above query in postgres 17 will in fact return a single row with a single column whose value is 100. And you’d better believe it does it by <em>actually looping its way up to 100.</em> If you don’t believe me, make the following change:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="st">-     SELECT * FROM recursion ORDER BY step DESC LIMIT 1)</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="va">+     SELECT * FROM recursion ORDER BY step DESC)</span></span></code></pre></div>
<p>which will instead return a row for each step of the iteration.</p>
<p>There are some obvious optimizations I could make to the generated SQL, but it didn’t seem worth my time, since that’s not the interesting part of the project.</p>
<h2 id="what-the-hell-is-going-on">What the Hell Is Going On?</h2>
<p>Let’s take some time to discuss the underlying category theory here. I am by no means an expert, but what I have learned after a decade of bashing my head against this stuff is that a little goes a long way.</p>
<p>For our intents and purposes, we have types, and arrows (functions) between types. We always have the identity “do nothing arrow” <code>id</code>:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">id</span><span class="ot">  ::</span> a <span class="op">~&gt;</span> a</span></code></pre></div>
<p>and we can compose arrows by lining up one end to another:<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>(⨟)<span class="ot"> ::</span> (a <span class="op">~&gt;</span> b) <span class="ot">-&gt;</span> (b <span class="op">~&gt;</span> c) <span class="ot">-&gt;</span> (a <span class="op">~&gt;</span> c)</span></code></pre></div>
<p>Unlike Haskell (or really any programming language, for that matter), we DO NOT have the notion of function application. That is, there is no arrow:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- doesn&#39;t exist!</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="ot">($) ::</span> (a <span class="op">~&gt;</span> b) <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> b</span></code></pre></div>
<p>You can only compose arrows, you can’t apply them. That’s why we call these things “arrows” rather than “functions.”</p>
<p>There are a bundle of arrows for working with product types. The two projection functions correspond to <code>fst</code> and <code>snd</code>, taking individual components out of pairs:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>prj₁<span class="ot"> ::</span> (a, b) <span class="op">~&gt;</span> a</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>prj₂<span class="ot"> ::</span> (a, b) <span class="op">~&gt;</span> b</span></code></pre></div>
<p>How do we get things into pairs in the first place? We can use the “fork” operation, which takes two arrows computing <code>b</code> and <code>c</code>, and generates a new arrow which generates a pair of <code>(b, c)</code>:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>(△)<span class="ot">  ::</span> (a <span class="op">~&gt;</span> b) <span class="ot">-&gt;</span> (a <span class="op">~&gt;</span> c) <span class="ot">-&gt;</span> (a <span class="op">~&gt;</span> (b, c))</span></code></pre></div>
<p>If you’re coming from a Haskell background, it’s tempting to think of this operation <em>merely</em> as the <code>(,)</code> pair constructor. But you’ll notice from the type of the computation that there can be no data dependency between <code>b</code> and <code>c</code>, thus we are free to parallelize each side of the pair.</p>
<p>In category theory, the distinction between left and right sides of an arrow is rather arbitrary. This gives rise to a notion called <em>duality</em> where we can flip the arrows around, and get cool new behavior. If we dualize all of our product machinery, we get the <em>coproduct</em> machinery, where a coproduct of <code>a</code> and <code>b</code> is “either <code>a</code> or <code>b</code>, but definitely not both nor neither.”</p>
<p>Swapping the arrow direction of <code>prj₁</code> and <code>prj₂</code>, and replacing <code>(,)</code> with <code>Either</code> gives us the following injections:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ot">inl ::</span> a <span class="op">~&gt;</span> <span class="dt">Either</span> a b</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="ot">inr ::</span> b <span class="op">~&gt;</span> <span class="dt">Either</span> a b</span></code></pre></div>
<p>and the following “join” operation for eliminating coproducts:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>(▽)<span class="ot"> ::</span> (a <span class="op">~&gt;</span> c) <span class="ot">-&gt;</span> (b <span class="op">~&gt;</span> c) <span class="ot">-&gt;</span> (<span class="dt">Either</span> a b <span class="op">~&gt;</span> c)</span></code></pre></div>
<p>Again, coming from Haskell this is just the standard <code>either</code> function. It corresponds to a branch between one of two cases.</p>
<p>As you can see, with just these eight operations, we already have a tremendous amount of expressivity. We can express data dependencies via <code>⨟</code> and branching via <code>▽</code>. With <code>△</code> we automatically encode opportunities for parallelism, and gain the ability to build complicated data structures, with <code>prj₁</code> and <code>prj₂</code> allowing us to get the information <em>back out</em> of the data structures.</p>
<p>You’ll notice in the IL that there are no variable names anywhere to be found. The desugaring of the source language builds a stack (via the <code>something to allocate △ id</code> pattern), and replaces subsequent variable lookups with a series of projections on the stack to find the value again. On one hand, this makes the categorical IL rather hard to read, but it makes it very easy to re-target! Many domains do have a notion of grouping, but don’t have a native notion of naming.</p>
<p>For example, in an electronic circuit, I can have a ribbon of 32 wires which represents an <code>Int32</code>. If I have another ribbon of 32 wires, I can trivially route both wires into a 64-wire ribbon corresponding to a pair of <code>(Int32, Int32)</code>.</p>
<p>By eliminating names before we get to the IL, it means no compiler backend ever needs to deal with names. They can just work on a stack representation, and are free to special-case optimize series of projections if they are able to.</p>
<p>Of particular interest to this discussion is how we desugar loops in catlang. The underlying primitive is <code>cochoice</code>:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ot">cochoice ::</span> (<span class="dt">Either</span> a c <span class="op">~&gt;</span> <span class="dt">Either</span> b c) <span class="ot">-&gt;</span> (a <span class="op">~&gt;</span> b)</span></code></pre></div>
<p>which magically turns an arrow on <code>Either</code>s into an arrow without the eithers. We obviously must <em>run</em> that arrow on eithers. If that function returns <code>inl</code>, then we’re happy and we can just output that. But if the function returns <code>inr</code>, we have no choice but to pass it back in to the eithered arrow. In Haskell, cochoice is implemented as:</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ot">cochoiceHask ::</span> (<span class="dt">Either</span> a c <span class="ot">-&gt;</span> <span class="dt">Either</span> b c) <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> c</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>cochoiceHask f <span class="ot">=</span> go <span class="op">.</span> <span class="dt">Left</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">where</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="ot">    go ::</span> <span class="dt">Either</span> a c <span class="ot">-&gt;</span> b</span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>    go eac <span class="ot">=</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>      <span class="kw">case</span> f eac <span class="kw">of</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Left</span> b <span class="ot">-&gt;</span> b</span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>        <span class="dt">Right</span> c <span class="ot">-&gt;</span> go (<span class="dt">Right</span> c)</span></code></pre></div>
<p>which as you can see, will loop until <code>f</code> finally returns a <code>Left</code>. What’s neat about this formulation of a loop is that we can statically differentiate between our first and subsequent passes through the loop body. The first time through <code>eac</code> is <code>Left</code>, while for all other times it is <code>Right</code>. We don’t take advantage of it in the original <code>count</code> program, but how many times have you written loop code that needs to initialize something its first time through?</p>
<h2 id="compiling-to-sql">Compiling to SQL</h2>
<p>So that’s the underlying theory behind the IL. How can we compile this to SQL now?</p>
<p>As alluded to before, we simply need to give SQL implementations for each of the operations in the intermediary language. As a simple example, <code>id</code> compiles to <code>SELECT * FROM {}</code>, where <code>{}</code> is the input of the arrow.</p>
<p>The hardest part here was working out a data representation. It seems obvious to encode each element of a product as a new column, but what do we do about coproducts? After much work thought, I decided to flatten out the coproducts. So, for example, the type:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>(<span class="dt">Int</span>, <span class="dt">Either</span> <span class="dt">Int</span> <span class="dt">Int</span>)</span></code></pre></div>
<p>would be represented as three columns:</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>( f1 <span class="dt">INT</span> <span class="kw">NOT</span> <span class="kw">NULL</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>, f2 <span class="dt">INT</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>, f3 <span class="dt">INT</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>)</span></code></pre></div>
<p>with the constraint that exactly one of <code>f2</code> or <code>f3</code> would be <code>IS NOT NULL</code> at any given point in time.</p>
<p>With this hammered out, almost everything else is pretty trivial. Composition corresponds to a nested query. Forks are <code>CROSS JOIN</code>s which concatenate the columns of each sub-query. Joins are <code>UNION</code>s, where we add a <code>WHERE field IS NOT NULL</code> clause to enforce we’re looking at the correct coproduct constructor.</p>
<p>Cochoice is the only really tricky thing, but it corresponds to a <a href="https://www.postgresql.org/docs/current/queries-with.html#QUERIES-WITH-RECURSIVE">recursive CTE</a>. Generating a recursive CTE table for the computation isn’t too hard, but getting the final value out of it was surprisingly tricky. The semantics of SQL tables is that they are multisets and come with an arbitrary greatest element. Which is to say, you need an column structured in a relevant way in order to query the final result. Due to some quirks in what postgres accepts, and in how I structured my queries, it was prohibitively hard to insert a “how many times have I looped” column and order by that. So instead I cheated and added a <code>clock_timestamp() as step</code> column which looks at the processor clock and ordered by that.</p>
<p>This is clearly a hack, and presumably will cause problems if I ever add some primitives which generate more than one row, but again, this is just for fun and who cares. Send me a <a href="https://github.com/isovector/catlang">pull request</a> if you’re offended by my chicanery!</p>
<h2 id="stupid-directions-to-go-in-the-future">Stupid Directions To Go In the Future</h2>
<p>I’ve run out of vacation time to work on this project, so I’m probably not going to get around to the meta-circular stupidity I was planning.</p>
<p>The compiler still needs a few string-crunching primitives (which are easy to add), but then it would be simple to write a little <a href="https://en.wikipedia.org/wiki/Brainfuck">brainfuck</a> interpreter in catlang. Which I could then compile to SQL. Now we’ve got a brainfuck interpreter running in postgres. Of course, this has been done by hand before, but to my knowledge, never via compilation.</p>
<p>There exist C to brainfuck compilers. And postgres is written in C. So in a move that would make Xzibit proud, we could run postgres in postgres. And of course, it would be fun to run brainfuck in brainfuck. That’d be a cool catlang backend if someone wanted to contribute such a thing.</p>
<h2 id="notes-and-due-diligence-and-what-have-you">Notes and Due Diligence and What Have You</h2>
<p>I am not the first person to do anything like this. The source language of catlang is heavily inspired by <a href="https://www.staff.city.ac.uk/~ross/papers/notation.pdf">Haskell’s arrow syntax</a>, which in turn is essentially a desugaring algorithm for <a href="https://www.cse.chalmers.se/~rjmh/afp-arrows.pdf">Arrows</a>. Arrows are slightly the wrong abstraction because they require an operation <code>arr :: (a -&gt; b) -&gt; (a ~&gt; b)</code>—which requires you to be able to embed Haskell functions in your category, something which is <em>almost never possible.</em></p>
<p>Unfortunately, arrow syntax in Haskell desugars down to <code>arr</code> for almost everything it does, which in turn makes arrow notation effectively useless. In an ideal world, everything I described in this blog post would be a tiny little Haskell library, with arrow notation doing the heavy lifting. But that is just not the world we live in.</p>
<p>Nor am I the first person to notice that there are categorical semantics behind programming languages. I don’t actually know whom to cite on this one, but it is well-established folklore that the lambda calculus corresponds to <a href="https://en.wikipedia.org/wiki/Cartesian_closed_category">cartesian-closed categories</a>. The “closed” part of “cartesian-closed” means we have an operation <code>eval :: (a ~&gt; b, a) ~&gt; b</code>, but everyone and their dog has implemented the lambda calculus, so I thought it would be fun to see how far we can get without it. This is not a limitation on catlang’s turing completeness (since <code>cochoice</code> gives us everything we need.)</p>
<p>I’ve been thinking about writing a <em>category-first</em> programming language for the better part of a decade, ever since I read <a href="http://conal.net/papers/compiling-to-categories/compiling-to-categories.pdf">Compiling to Categories</a>. That paper takes Haskell and desugars it back down to categories. I stole many of the tricks here from that paper.</p>
<p>Anyway. All of the code is available on <a href="https://github.com/isovector/catlang">github</a> if you’re interested in taking a look. The repo isn’t up to my usual coding standards, for which you have my apologies. Of note is the template-haskell backend which can spit out Haskell code; meaning it wouldn’t be very hard to make a quasiquoter to compile catlang into what Haskell’s arrow desugaring <em>ought to be.</em> If there’s enough clamor for such a thing, I’ll see about turning this part into a library.</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>When looking at the types of arrows in this essay, we make the distinction that <code>~&gt;</code> are arrows that we can write in catlang, while <code>-&gt;</code> exist in the metatheory.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
        ]]>
      </content>
    </entry>
    <entry>
      <title>Theorems for Free Redux</title>
      <id>blog/theorems-for-free-redux/index.html</id>
      <link href='blog/theorems-for-free-redux/index.html'/>
      <published>2025-10-09T11:27:00Z</published>
      <updated>2025-10-09T11:27:00Z</updated>

      <content type="html" xml:base="https://reasonablypolymorphic.com">
        <![CDATA[
        <p>A reader recently got in touch with me regarding my 2017 blog post <a href="/blog/theorems-for-free/">Review: Theorems for Free</a>. He had some questions about the paper/my review, and upon revisiting it, I realized that I had no idea how the paper worked anymore.</p>
<p>So I decided to rehash my understanding, and came up with something much conceptually clearer about what is happening and why.</p>
<p>A quick summary of <em>Theorems for Free</em>:</p>
<blockquote>
<p>For any polymorphic type, we can generate a law that must hold for any value of that type.</p>
</blockquote>
<p>One the examples given is for the function <code>length :: forall a. [a] -&gt; Int</code>, which states that <code>forall f l. length (fmap f l) = length l</code>—namely, that <code>fmap</code> doesn’t change the length of the list.</p>
<p><em>Theorems for Free</em> gives a roundabout and obtuse set of rules for computing these free theorems. But, as usual, the clarity of the idea is obscured by the encoding details.</p>
<p>The actual idea is this:</p>
<blockquote>
<p>Parametrically-polymorphic functions can’t branch on the specific types they are instantiated at.</p>
</blockquote>
<p>Because of this fact, functions must behave the same way, regardless of the type arguments passed to them. So all of the free theorems have the form “replacing the type variables <em>before</em> calling the function is the same as replacing the type variables <em>after</em> calling the function.”</p>
<p>What does it mean to replace a type variable? Well, if we want to replace a type variable <code>a</code> with <code>a'</code>, we will generate a fresh function <code>f :: a -&gt; a'</code>, and then stick it wherever we need to.</p>
<p>For example, given the function <code>id :: a -&gt; a</code>, we generate the free theorem:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">forall</span> f a<span class="op">.</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  f (<span class="fu">id</span> a) <span class="ot">=</span> <span class="fu">id</span> (f a)</span></code></pre></div>
<p>or, for the function <code>fromJust :: Maybe a -&gt; a</code>, we get:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">forall</span> f ma<span class="op">.</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  f (fromJust ma) <span class="ot">=</span> fromJust (<span class="fu">fmap</span> f ma)</span></code></pre></div>
<p>This scheme also works for functions in multiple type parameters. Given the function <code>swap :: (a, b) -&gt; (b, a)</code>, we must replace both <code>a</code> and <code>b</code>, giving the free theorem:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">forall</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    (<span class="ot">f ::</span> a <span class="ot">-&gt;</span> a&#39;)</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    (<span class="ot">g ::</span> b <span class="ot">-&gt;</span> b&#39;)</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    (<span class="ot">p ::</span> (a, b))</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>  swap (bimap f g p) <span class="ot">=</span> bimap g f (swap p)</span></code></pre></div>
<p>In the special case where there are no type parameters, we don’t need to do anything. This is what’s happening in the <code>length</code> example given in the introduction.</p>
<p>Simple stuff, right? The obfuscation in the paper comes from the actual technique given to figure out where to apply these type substitutions. The paper is not fully general here, in that it only gives rules for the <code>[]</code> and <code>(-&gt;)</code> type constructors (if I recall correctly.) These rules are further obscured in that they inline the definitions of <code>fmap</code>, rather than writing <code>fmap</code> directly.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> But for types in one variable, <code>fmap</code> is exactly the function that performs type substitution.</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Perhaps this paper predates typeclasses? Very possible.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
        ]]>
      </content>
    </entry>
    <entry>
      <title>Analyzing API Design via Algebraic Laws</title>
      <id>blog/api-analysis/index.html</id>
      <link href='blog/api-analysis/index.html'/>
      <published>2025-05-05T07:33:00Z</published>
      <updated>2025-05-05T07:33:00Z</updated>

      <content type="html" xml:base="https://reasonablypolymorphic.com">
        <![CDATA[
        <p>The other day, someone asked:</p>
<blockquote>
<p>Why doesn’t [the Data.Map function] <code>unionWith :: (a -&gt; a -&gt; a) -&gt; Map k a -&gt; Map k a -&gt; Map k a</code> allow for different value types the way <code>intersectionWith :: (a -&gt; b -&gt; c) -&gt; Map k a -&gt; Map k b -&gt; Map k c</code> does?</p>
</blockquote>
<p>This is a very reasonable question, and it lead down an interesting rabbit hole of at the intersection of API design and efficient implementation.</p>
<p>To answer the original question, what would the type of a different value type of <code>unionWith</code> look like? It would be something in the flavor of:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">unionWith ::</span> (<span class="dt">Maybe</span> a <span class="ot">-&gt;</span> <span class="dt">Maybe</span> b <span class="ot">-&gt;</span> c) <span class="ot">-&gt;</span> <span class="dt">Map</span> k a <span class="ot">-&gt;</span> <span class="dt">Map</span> k b <span class="ot">-&gt;</span> <span class="dt">Map</span> k c</span></code></pre></div>
<p>But this new <code>Maybe a -&gt; Maybe b -&gt; c</code> parameter is somewhat lossy, in that it gives the impression that it could be called with <code>Nothing Nothing</code> as parameters, which doesn’t fit into the vibe of being a “union.”</p>
<p>So instead we could restrict that possibility by using <code>These a b</code>:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">These</span> a b <span class="ot">=</span> <span class="dt">This</span> a <span class="op">|</span> <span class="dt">That</span> b <span class="op">|</span> <span class="dt">These</span> a b</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="ot">unionWith ::</span> (<span class="dt">These</span> a b <span class="ot">-&gt;</span> c) <span class="ot">-&gt;</span> <span class="dt">Map</span> k a <span class="ot">-&gt;</span> <span class="dt">Map</span> k b <span class="ot">-&gt;</span> <span class="dt">Map</span> k c</span></code></pre></div>
<p>which seems reasonable enough.</p>
<hr />
<p>But let’s take <em>reasonableness</em> out of the picture and start again from first principles. Instead let’s ask ourselves the deep philsophical question of <em>what even IS a map?</em></p>
<p>A <code>Map k v</code> is a particularly efficient implementation of functions with type <code>k -&gt; Maybe v</code>. But why is this <code>Maybe</code> here? It’s really only to encode the “default” value of performing a lookup. Nothing goes wrong if we generalize this to be <code>Monoid v =&gt; k -&gt; v</code>. In fact, it helps us make sense of the right bias present in <code>Data.Map</code>, where we see:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="fu">lookup</span> k (singleton k v1 <span class="op">&lt;&gt;</span> singleton k v2) <span class="ot">=</span> <span class="dt">Just</span> v2</span></code></pre></div>
<p>This equality is hard to justify under the normal understanding of <code>Map k v</code> being an encoding of a function <code>k -&gt; Maybe v</code>. But under the general monoid interpretation, we get a nice semigroup homomorphism:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="fu">lookup</span> k (m1 <span class="op">&lt;&gt;</span> m2) <span class="ot">=</span> <span class="fu">lookup</span> k m1 <span class="op">&lt;&gt;</span> <span class="fu">lookup</span> k m2</span></code></pre></div>
<p>where the monoid in question has been specialized to be <a href="https://hackage.haskell.org/package/base-4.21.0.0/docs/Data-Monoid.html#t:Last"><code>Last</code></a>.</p>
<p>Of course, we also have a monoid homomorphism:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">lookup</span> k <span class="fu">mempty</span> <span class="ot">=</span> <span class="fu">mempty</span></span></code></pre></div>
<p>Let’s re-evaluate the original question in terms of this newly-generalized <code>Map</code>. Now that we’ve removed all of the unnecessary baggage of <code>Maybe</code>, we can again think about the desired type of <code>unionWith</code>:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>unionWith</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="ot">    ::</span> (a <span class="ot">-&gt;</span> b <span class="ot">-&gt;</span> c)</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> <span class="dt">Map</span> k a</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> <span class="dt">Map</span> k b</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> <span class="dt">Map</span> k c</span></code></pre></div>
<p>which looks <a href="https://hackage.haskell.org/package/base-4.21.0.0/docs/Prelude.html#v:liftA2">awfully familiar</a>. This new type signature automatically resolves our original concerns about “what should we do if the key isn’t present?”—just call the function with <code>mempty</code> as a parameter!</p>
<p>We can give some semantics as to what <code>unionWith</code> ought to do again by relating it to the observation <code>lookup</code>. The relevant law here seems like it ought to be:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="fu">lookup</span> k (unionWith f m n) <span class="ot">=</span> f (<span class="fu">lookup</span> k m) (<span class="fu">lookup</span> k n)</span></code></pre></div>
<p>By choosing a degenerate function <code>f</code>, say, <code>\_ _ -&gt; nontrivial</code>, where <code>nontrivial</code> is some value that is <em>not</em> <code>mempty</code>, we can see the beginnings of a problem:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>  <span class="fu">lookup</span> k (unionWith f m n)</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>  f (<span class="fu">lookup</span> k m) (<span class="fu">lookup</span> k n)</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span> <span class="op">&lt;</span><span class="kw">let</span> f <span class="ot">=</span> \_ _ <span class="ot">-&gt;</span> nontrivial<span class="op">&gt;</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>  nontrivial</span></code></pre></div>
<p>Regardless of the key we lookup in our <code>unionWith</code>ed <code>Map</code>, we need to get back <code>nontrivial</code>. How can we implement such a thing? I see only two ways:</p>
<ol type="1">
<li>explicitly associate every key in the map with <code>nontrivial</code>, or</li>
<li>keep <code>nontrivial</code> around as a default value in the map</li>
</ol>
<p>#1 is clearly a non-starter, given that we want our <code>Map</code>s to be <em>efficient</em> encodings of functions, which leaves us with only #2. This is actually a pretty common construction, which stems immediately from the fact that a pair of monoids is itself a monoid. The construction would look something like this:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Map</span> k v <span class="ot">=</span> <span class="dt">Map</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>  {<span class="ot"> defaultValue ::</span> v</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>  ,<span class="ot"> implementation ::</span> <span class="dt">Data.Map.Map</span> k v</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> stock <span class="dt">Generic</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> (<span class="dt">Semigroup</span>, <span class="dt">Monoid</span>) via (<span class="dt">Generically</span> (<span class="dt">Map</span> k v))</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>unionWith</span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a><span class="ot">    ::</span> (a <span class="ot">-&gt;</span> b <span class="ot">-&gt;</span> c)</span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> <span class="dt">Map</span> k a</span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> <span class="dt">Map</span> k b</span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> <span class="dt">Map</span> k c</span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a>unionWith f (<span class="dt">Map</span> def1 imp1) (<span class="dt">Map</span> def2 imp2) <span class="ot">=</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Map</span> (f def1 def2) (liftA2 f imp1 imp2)</span></code></pre></div>
<p>Seems fine, right? The nail in the coffin comes from when we reintroduce our semigroup homomorphism:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="fu">lookup</span> k (m1 <span class="op">&lt;&gt;</span> m2) <span class="ot">=</span> <span class="fu">lookup</span> k m1 <span class="op">&lt;&gt;</span> <span class="fu">lookup</span> k m2</span></code></pre></div>
<p>Without loss of generalization, take <code>m2 = pure nontrivial</code> (where <code>pure</code> is just <code>unionWith</code> with a constant function.) This gives us:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="fu">lookup</span> k (m1 <span class="op">&lt;&gt;</span> <span class="fu">pure</span> nontrivial) <span class="ot">=</span> <span class="fu">lookup</span> k m1 <span class="op">&lt;&gt;</span> nontrivial</span></code></pre></div>
<p>Making this thing efficient is a further complication! We again have two options:</p>
<ol type="1">
<li>modify the value at every key by multiplying in <code>nontrivial</code>, or</li>
<li>finding a way of suspending this computation</li>
</ol>
<p>#1 clearly requires <span class="math inline">\(O(n)\)</span> work, which again forces us to look at #2. But #2 seems very challenging, because the monoidal values we need to suspend <em>need not</em> span the entire <code>Map</code>. For example, consider a <code>Map</code> constructed a la:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>((<span class="fu">pure</span> prefix1 <span class="op">&lt;&gt;</span> ((<span class="fu">pure</span> prefix2 <span class="op">&lt;&gt;</span> m) <span class="op">&lt;&gt;</span> n)) <span class="op">&lt;&gt;</span> (p <span class="op">&lt;&gt;</span> <span class="fu">pure</span> suffix)</span></code></pre></div>
<p>Representing this thing efficiently certainly isn’t impossible, but you’re not going to be able to do it on the balanced binary search trees that underlie the implementation of <code>Data.Map.Map</code>.</p>
<hr />
<p>I find this quite an interesting result. I always assumed that <code>Data.Map.Map</code> (or at least, <code>Data.Map.Monoidal.MonoidalMap</code>) didn’t have an <code>Applicative</code> instance because it would require a <code>Monoid</code> constraint on its output—but that’s not the sort of thing we can express in Haskell.</p>
<p>But the analysis above says that’s not actually the reason! It’s that there can be no efficient implementation of <code>Applicative</code>, even if we <em>could</em> constrain the result.</p>
<p>What I find so cool about this style of analysis is that we didn’t actually write any code, nor did we peek into the implementation of <code>Data.Map</code> (except to know that it’s implemented as a balanced BST.) All we did was look at the obvious laws, instantiate them with degenerate inputs, and think about what would be required to to efficiently get the right answer.</p>
        ]]>
      </content>
    </entry>
    <entry>
      <title>Using Obscure Graph Theory to solve PL Problems</title>
      <id>blog/solving-lcsa/index.html</id>
      <link href='blog/solving-lcsa/index.html'/>
      <published>2025-05-04T08:05:00Z</published>
      <updated>2025-05-04T08:05:00Z</updated>

      <content type="html" xml:base="https://reasonablypolymorphic.com">
        <![CDATA[
        <p>Usually I write about <em>solutions</em> to problems I’ve worked out, but I’ve found myself increasingly becoming interesting in <em>where solutions come from.</em> Maybe it’s because I’ve been reading Boorstin’s excellent <a href="https://en.wikipedia.org/wiki/The_Discoverers">The Discoverers</a>, which I’d strongly recommend.</p>
<p>Regardless of why, I thought I’d switch up the usual dance step today, and discuss what solving my most-recent-big-problem actually looked like, in terms of what I tried, where I looked, and what the timeline was.</p>
<h2 id="the-problem">The Problem</h2>
<p>The problem is to serialize a program graph into a series of let-bindings. For example, given the following graph:</p>
<pre><code>      +
    /   \
  f ---&gt; g
  |     / \
  a     \ /
      expensive</code></pre>
<p>which represents the program:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>f a (g expensive expensive) <span class="op">+</span> g expensive expensive</span></code></pre></div>
<p>Unfortunately, this is a naive representation of the program, since it duplicates the work required to compute <code>expensive</code> four times, and <code>g expensive expensive</code> twice. Instead, we would prefer to generate the equivalent-but-more-efficient program:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> <span class="op">$</span><span class="dv">0</span> <span class="ot">=</span> expensive</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">$</span><span class="dv">1</span> <span class="ot">=</span> g <span class="op">$</span><span class="dv">0</span> <span class="op">$</span><span class="dv">0</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">in</span> f a <span class="op">$</span><span class="dv">1</span> <span class="op">+</span> <span class="op">$</span><span class="dv">1</span></span></code></pre></div>
<p>This transformation is affectionately known as <em>sharing</em>, since it shares the computed answer whenever there is repeated work to be done.</p>
<p>So this is what we’re trying to do. Given the original graph, determine the best place to insert these let-bindings, for some reasonable definition of “best.” We can assume there are no side effects involved, so any place that an expression is well-scoped is an acceptable solution.</p>
<p>In order to understand some of my attempted solutions, it’s worth noting that our final solution should build something of type <code>Expr</code>, and the original graph is represented as a <code>IntMap (ExprF Int)</code>. <code>ExprF</code> is the <a href="https://hackage.haskell.org/package/recursion-schemes-5.2.3/docs/Data-Functor-Foldable.html#t:Base"><code>Base</code></a> functor of <code>Expr</code>, with all of its self-references replaced by some type variable, in this case <code>Int</code>. Thus, the graph above looks much more like:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>_ <span class="op">:</span> <span class="dt">IntMap</span> (<span class="dt">ExprF</span> <span class="dt">Int</span>)</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>_ <span class="ot">=</span> IM.fromList</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  [ (<span class="dv">0</span>, <span class="dt">Apply</span> <span class="st">&quot;+&quot;</span> [<span class="dv">1</span>, <span class="dv">3</span>])</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  , (<span class="dv">1</span>, <span class="dt">Apply</span> <span class="st">&quot;f&quot;</span> [<span class="dv">2</span>, <span class="dv">3</span>]</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>  , (<span class="dv">2</span>, <span class="op">...</span>)  <span class="co">-- a</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>  , (<span class="dv">3</span>, <span class="dt">Apply</span> <span class="st">&quot;g&quot;</span> [<span class="dv">4</span>, <span class="dv">4</span>])</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>  , (<span class="dv">4</span>, <span class="op">...</span>)  <span class="co">-- expensive</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>  ]</span></code></pre></div>
<h2 id="the-original-solution">The Original Solution</h2>
<p>I spent over a year trying to solve this problem, with various mostly-working solutions during that time. My strategy here was to think really hard, write up some algorithm that seemed plausible, and then run it against our (small) battery of integration tests to make sure it got the same answer as before.</p>
<p>Why not property test it? I tried, but found it very challenging to implement well-typed generators that would reliably introduce shared thunks. But maybe there’s a different lesson to be learned here about writing good generators.</p>
<p>Anyway. For eight months, one of these think-really-hard algorithms fit the bill and didn’t give us any problems. It was a weird, bespoke solution to the problem that independetly kept track of all of the free variables in every graph fragment, and tried to let-bind a fragment as soon as we landed in a context where all of the free variables were in scope. It seemed to work, but it was extremely messy and unmaintainable.</p>
<p>At the time of writing, this sharing algorithm was the only source of let-binds in our entire language, which meant that it didn’t need to account for let-binds <em>in</em> the program.</p>
<p>Of course, that invariant eventually changed. We added a way in the source langauge to introduce <code>let</code>s, which meant my algorithm was wrong. And I had written it sufficiently long ago that I no longer remembered <em>exactly why it worked.</em> Which meant the <a href="https://pages.cs.wisc.edu/~remzi/Naur.pdf">theory of my program was lost, and thus that we ought to rewrite it.</a></p>
<h2 id="unfolding-a-solution">Unfolding a Solution</h2>
<p>I went back to the problem statement, and stared at it for a long time (back to the think-really-hard algorithm!) Upon staring at the problem, I realized that what I was really trying to do was determine where diamond patterns arose in the propgram graph.</p>
<p>Recall our original graph:</p>
<pre><code>      +
    /   \
  f ---&gt; g
  |     / \
  a     \ /
      expensive</code></pre>
<p>If we redraw it such that <code>g</code> is on a different rank than <code>f</code>, then the two diamond patterns become much clearer:</p>
<pre><code>      +
    /  \
  f     |
  | \   |
  a  \ /
      g
     / \
     \ /
   expensive</code></pre>
<p>The insight I came up with is that if a node <code>n</code> is the source of a diamond, then we must let-bind the sink of the diamond immediately before inlining the definition of <code>n</code>.</p>
<p>This gives rise to the question of “how do we identify a diamond?” What we can do is give a mapping from each node to its reachable set of nodes. For example, in the above, we’d compute the map:</p>
<pre><code>+         -&gt; {+, f, a, g, expensive}
f         -&gt; {f, a, g, expensive}
a         -&gt; {a}
g         -&gt; {g, expensive}
expensive -&gt; {expensive}</code></pre>
<p>Then when we go to inline a node, say, <code>+</code>, we can look for any nodes that are reachable via more than one of its immediate subterms. Since the immediate subterms of <code>+</code> are <code>f</code> and <code>g</code>, we can take the intersections of their reachable sets:</p>
<pre><code>{f, a, g, expensive} union {g, expensive}</code></pre>
<p>giving us</p>
<pre><code>{g, expensive}</code></pre>
<p>which is exactly the set of nodes that we need to perform sharing on. If you topologically sort this set, it gives you the order that you should perform your let bindings.</p>
<p>EXCEPT there’s a kink in the whole thing. What happens if one of the terms in this diamond contains free variables? In particular, we might have something like this:</p>
<pre><code>      +
    /  \
  f     |
  | \   |
  a  \ /
      λx
     / \
     \ /
   expensive
      |
      x</code></pre>
<p>This gives us an analogous set of reachable nodes when we look at <code>+</code>, but we obviously can’t lift <code>expensive x</code> above the lambda.</p>
<p>Resolving this problem required giving up on the notion of memoizing the entire reachable set of nodes, and to instead crawl the graph ensuring that everything is well-scoped.</p>
<h2 id="performance-woes">Performance Woes</h2>
<p>My algorithm looked fine, and, importantly, got the right answer in a reasonable amount of time on our (small) battery of integration tests. So I shipped it, commended myself on a job well done, and thought nothing more about it. For about a week, until a bug report came in saying that our compiler now seemed to hang on big programs.</p>
<p>Which was something I hadn’t noticed, since we didn’t have any big programs in our integration tests.</p>
<p>Damn!</p>
<p>Upon digging in to what exactly was so slow, I noticed that my algorithm was <a href="https://accidentallyquadratic.tumblr.com/">accidentally quadratic</a>. I needed to fold over every node in the graph, and that required looking at the entire reachable set underneath it. I had put in some of the obvious safeguards, hoping that they would prune the search tree early, but it wasn’t enough sacrifice for the Great God of Asymptotes.</p>
<p>Did I mention that at this point in the story, having this algorithm working fast was on the critical path of the company? Everybody else was blocked on me figuring this out. Talk about pressure!</p>
<p>Anyway. You’ll notice above that in my description of the algorithm, everything sounds fine. But the juice is in the details, as the common saying goes. Computing reachability isn’t quite the right thing to be using here, as it gave us the wrong answer for the lambda example above. Which is unfortunate because reachability is something we can do in linear time.</p>
<p>And then when reachability didn’t work, I just threw away the fast performance and hoped my bespoke algorithm would do the job. My only redemption comes from the fact that at least it got the right answer, even if it did so very slowly.</p>
<h2 id="finding-the-kernel">Finding the Kernel</h2>
<p>Back to the drawing board.</p>
<p>Whenever I have graph theory problems, I call up my boy Vikrem. He’s good at nerd stuff like this.</p>
<p>We <a href="https://en.wikipedia.org/wiki/Rubber_duck_debugging">rubberducked</a> the problem, and tried to reframe the problem in the language of graph theory. We had a Merkiv–Maguire moment where we indepdently realized that the goal was somehow related to finding the <em>lowest common ancestor</em> (LCA) of a node.</p>
<p>Which is to say, roughly, that we are looking for forks in the diamond diagram. Which we already knew, but it was nice to have some language for.</p>
<p>Our new problem is that LCA is defined only over trees. There are some extensions to DAGs, but none of them seem to be particularly well founded. However, searching for exactly that brought me to <a href="https://stackoverflow.com/questions/14865081/algorithm-to-find-lowest-common-ancestor-in-directed-acyclic-graph">this stackoverflow question</a>, where nestled in the comments is someone suggesting that the poster isn’t looking for LCA, but instead for a related notion the <em>lowest <strong>single</strong> common ancestor.</em> LSCA is defined in a 2010 paper <a href="https://www.sciencedirect.com/science/article/abs/pii/S0020019010000487">New common ancestor problems in trees and directed acyclic graphs</a>.</p>
<p>The standard definition of <code>LCA(x, y) = l</code> is that “<code>l</code> is an ancestor of <code>x</code> and of <code>y</code>, and that no descendent of <code>l</code> has this property.”</p>
<p>But the definition of <code>LSCA(x, y) = l</code> is that “<code>l</code> lies on all root-to-<code>x</code> paths, and that <code>l</code> lies on all root-to-<code>y</code> paths, and that no descendent of <code>l</code> has this property.”</p>
<p>The distinction between the two is easily seen in the following graph:</p>
<pre><code>  0
 / \
1   2
| X |
3   4</code></pre>
<p>Under the standard definition, LCA is not uniquely defined for DAGs. That is, <code>LCA(3, 4) = {1, 2}</code>. But neither 1 nor 2 lies on <em>all</em> paths from the root. Under LSCA therefore we get <code>LSCA(3, 4) = 0</code>, which is the obviously-correct place to let-bind 3 and 4.</p>
<p>The paper gives a preprocessing scheme for computing LSCA by building a “lowest single ancestor” (LSA) tree. The LSA of a node is the LSCA of all of its in-edges. This definition cashes out to mean “the most immediate diamond above any node.” Finally! This is exactly what we’re looking for, since this is where we must insert our let-bindings! Even better, the paper gives us an algorithm for computing the LSA tree in linear time!</p>
<h2 id="the-first-implementer">The First Implementer</h2>
<p>Of course, I’m lazy and would prefer not to implement this thing. So instead I searched on hackage for <code>lsca</code>, and found nothing. But then I searched for <code>lca</code> and found that, like always, <a href="https://hackage.haskell.org/package/lca">Ed Kmett was 13 years ahead of me.</a></p>
<p>The <code>lca</code> package implements an <span class="math inline">\(O(log n)\)</span> algorithm for computing the LCA of any two nodes in a graph. Which is very convenient for me, since the LSCA algorithm requires being able to do this.</p>
<p>Time to roll up the sleeves and get cracking I suppose.</p>
<p>The paper was surprisingly straightforward, and my first attempt implemented the (imperative) algorithms as given (imperatively.) The first step is to do a topological sort on the DAG in order to know in which order one ought to unfold the LSA tree.</p>
<p>But as is so often the case, this topological sort isn’t actually relevant to the algorithm; it’s just an encoding detail of expressing the algorithm imperatively. But you don’t need that when you’ve got laziness on your side! Instead you can just tie the know and do something cool like this:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ot">lsaTree ::</span> <span class="dt">Ord</span> v <span class="ot">=&gt;</span> <span class="dt">Map</span> v (<span class="dt">Set</span> v) <span class="ot">-&gt;</span> <span class="dt">Map</span> v (<span class="dt">Path</span> v)</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>lsaTree input <span class="ot">=</span> fix <span class="op">$</span> \result <span class="ot">-&gt;</span> M.fromList <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>  (node, parents) <span class="ot">&lt;-</span> M.toList input</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">let</span> parentResults <span class="ot">=</span> <span class="fu">fmap</span> (result <span class="op">M.!</span>) parents</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span></code></pre></div>
<p>Notice how we use <code>fix</code> to bind the eventual result of the final computation. Then we can chase pointers by looking them up in <code>result</code>—even though it’s not yet “computed.” Who cares what order the computer does it in. Why is that a thing I should need to specify?</p>
<p>Anyway. The exact details of implementing LSA are not particularly important for the remainder of this blog post. If you’re interested, you can peep the PR, which is <a href="https://github.com/ekmett/lca/pull/8">delightfully small</a>.</p>
<h2 id="tying-it-all-back-together">Tying It All Back Together</h2>
<p>Equipped with my LSA tree, I was now ready to go back and solve the original problem of figuring out where to stick let-bindings. It’s easy now. Given the original program graph, find the LSA for each node. The LSA is the place you should insert the let binding.</p>
<p>So given the map of nodes to their LSAs, invert that map and get back a map of nodes to descendents who have this node as an LSA. Now when you go to inline a node, just look up everything in this map and inline it first.</p>
<p>It turns out to be a very elegant solution. It’s one third of the length of my horrible ad-hoc implementations, and it runs in linear time of the number of nodes in the graph. All in all, very good.</p>
<p>More often than I’m comfortable about, people will ask me how I can have so many good ideas. And what I like about this story is that it’s pretty typical of how I actually “have” “good” ideas. I’m reminded of the fact that <a href="https://fs.blog/great-talks/richard-hamming-your-research/">luck favors the prepared mind</a>. Attentive readers will notice that <em>none</em> of this process was due to brilliance on my part. I happened to know Vikrem who’s a genius. Together we pulled at some ancient graph theory strings and remembered a fact that someone else had thought important to teach us. That wasn’t actually the right path, but it lead us to stackoverflow where someone had linked to a relevant paper. I implemented the paper using a library that someone else had done the heavy lifting on, and simplified the implementation using this knot-tying trick I picked up somewhere along the way.</p>
<p>Also, I’m just really pleased that the solution came from trying to reverse engineer the relevant graph-theory search terms. Maybe that’s the actual takeaway here.</p>
        ]]>
      </content>
    </entry>
    <entry>
      <title>Bidirectional Instance Contexts</title>
      <id>blog/bidirectional-instance-contexts/index.html</id>
      <link href='blog/bidirectional-instance-contexts/index.html'/>
      <published>2025-02-15T02:15:00Z</published>
      <updated>2025-02-15T02:15:00Z</updated>

      <content type="html" xml:base="https://reasonablypolymorphic.com">
        <![CDATA[
        <p>Just a quick one today, but I wanted to point out a little trick you can do with Haskell’s typeclass inference.</p>
<p>Imagine we have some little class, the details of which matter not in the least:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Foo</span><span class="ot"> ::</span> <span class="dt">Type</span> <span class="ot">-&gt;</span> <span class="dt">Constraint</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="dt">Foo</span> a <span class="kw">where</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span></code></pre></div>
<p>We can give some instances of this type:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Foo</span> <span class="dt">Int</span> <span class="kw">where</span> <span class="op">...</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Foo</span> <span class="dt">Bool</span> <span class="kw">where</span> <span class="op">...</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Foo</span> () <span class="kw">where</span> <span class="op">...</span></span></code></pre></div>
<p>Regular, everyday stuff. But the instances for type constructors are more interesting, because they come with an instance context:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">Foo</span> a, <span class="dt">Foo</span> b) <span class="ot">=&gt;</span> <span class="dt">Foo</span> (a, b) <span class="kw">where</span> <span class="op">...</span></span></code></pre></div>
<p>Then, of course, if we know both <code>Foo a</code> and <code>Foo b</code>, we can infer <code>Foo (a, b)</code>. To make this fact overwhelmingly explicit, we can reify the usual constraint-solving logic by using the <code>Dict</code> type, and thus the following program will typecheck:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Constraint</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>forwards</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">Dict</span> (<span class="dt">Foo</span> a)</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> <span class="dt">Dict</span> (<span class="dt">Foo</span> b)</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> <span class="dt">Dict</span> (<span class="dt">Foo</span> (a, b))</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>forwards <span class="dt">Dict</span> <span class="dt">Dict</span> <span class="ot">=</span> <span class="dt">Dict</span></span></code></pre></div>
<p>Perhaps tipped off by the name here, the gentle reader is asked to notice the asymmetry here, since the converse program will not typecheck:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>backwards</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">Dict</span> (<span class="dt">Foo</span> (a, b))</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> (<span class="dt">Dict</span> (<span class="dt">Foo</span> a), <span class="dt">Dict</span> (<span class="dt">Foo</span> b))</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>backwards <span class="dt">Dict</span> <span class="ot">=</span> (<span class="dt">Dict</span>, <span class="dt">Dict</span>)</span></code></pre></div>
<p>But why should it not typecheck?<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> Recall from the relevant instance definition that these instances must, in fact, exist:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">Foo</span> a, <span class="dt">Foo</span> b) <span class="ot">=&gt;</span> <span class="dt">Foo</span> (a, b)</span></code></pre></div>
<p>As a testament to <em>just</em> how good GHC is, we can support this bidirectionality via a minor tweak to the definition of class and its instances.</p>
<p>The trick is to add an associated type family to <code>Foo</code>, and to <em>use it as a superclass constraint:</em></p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Foo</span><span class="ot"> ::</span> <span class="dt">Type</span> <span class="ot">-&gt;</span> <span class="dt">Constraint</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="dt">Evidence</span> a <span class="ot">=&gt;</span> <span class="dt">Foo</span> a <span class="kw">where</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">type</span> <span class="dt">Evidence</span><span class="ot"> a ::</span> <span class="dt">Constraint</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">type</span> <span class="dt">Evidence</span> a <span class="ot">=</span> ()</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span></code></pre></div>
<p>Because we’ve given a default implementation of the type family, our existing simple instances work as before:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Foo</span> <span class="dt">Int</span> <span class="kw">where</span> <span class="op">...</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Foo</span> <span class="dt">Bool</span> <span class="kw">where</span> <span class="op">...</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Foo</span> () <span class="kw">where</span> <span class="op">...</span></span></code></pre></div>
<p>with the only change required coming from the type constructor instances:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">Foo</span> a, <span class="dt">Foo</span> b) <span class="ot">=&gt;</span> <span class="dt">Foo</span> (a, b) <span class="kw">where</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">type</span> <span class="dt">Evidence</span> (a, b) <span class="ot">=</span> (<span class="dt">Foo</span> a, <span class="dt">Foo</span> b)</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span></code></pre></div>
<p>or, if we you want to be cute about it:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Evidence</span> (a, b) <span class="ot">=&gt;</span> <span class="dt">Foo</span> (a, b) <span class="kw">where</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">type</span> <span class="dt">Evidence</span> (a, b) <span class="ot">=</span> (<span class="dt">Foo</span> a, <span class="dt">Foo</span> b)</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span></code></pre></div>
<p>By sticking <code>Evidence</code> into the superclass constraint, GHC knows that this dictionary is always available when you’ve got a <code>Foo</code> dictionary around. And our earlier <code>backwards</code> program now typechecks as expected.</p>
<p><a href="https://play.haskell.org/saved/YjCfxwNy">This is all available in a play session</a> if you’d like to fool around with it.</p>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Rhetorical question. I don’t want to hear about orphans or overlapping instances or whatever.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
        ]]>
      </content>
    </entry>
    <entry>
      <title>Use Monoids for Construction</title>
      <id>blog/use-monoids/index.html</id>
      <link href='blog/use-monoids/index.html'/>
      <published>2025-01-24T09:35:00Z</published>
      <updated>2025-01-24T09:35:00Z</updated>

      <content type="html" xml:base="https://reasonablypolymorphic.com">
        <![CDATA[
        <p>There’s a common anti-pattern I see in beginner-to-intermediate Haskell programmers that I wanted to discuss today. It’s the tendency to conceptualize the <em>creation</em> of an object by <em>repeated mutation.</em> Often this takes the form of repeated insertion into an empty container, but comes up under many other guises as well.</p>
<p>This anti-pattern isn’t particularly surprising in its prevalence; after all, if you’ve got the usual imperative brainworms, this is just <em>how things get built.</em> The gang of four “builder pattern” is exactly this; you can build an empty object, and setters on such a thing change the state <em>but return the object itself.</em> Thus, you build things by chaning together setter methods:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>Foo myFoo <span class="op">=</span> <span class="kw">new</span> <span class="fu">Foo</span><span class="op">().</span><span class="fu">setBar</span><span class="op">().</span><span class="fu">setQux</span><span class="op">(</span><span class="dv">17</span><span class="op">).</span><span class="fu">setZap</span><span class="op">(</span><span class="kw">true</span><span class="op">);</span></span></code></pre></div>
<p>Even if you don’t ascribe to the whole OOP design principle thing, you’re still astronomically likely to think about building data structures like this:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>Doodad doodad <span class="op">=</span> <span class="kw">new</span> Doodad<span class="op">;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="fu">foreach</span> <span class="op">(</span>Widget widget in widgets<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  doodad<span class="op">.</span><span class="fu">addWidget</span><span class="op">(</span>widget<span class="op">);</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>To be more concrete, maybe instead of doodads and widgets you have <code>BST</code>s and <code>Node</code>s. Or dictionaries and key-value pairs. Or graphs and edges. Anywhere you look, you’ll probably find examples of this sort of code.</p>
<p>Maybe you’re thinking to yourself “I’m a hairy-chested functional programmer and I scoff at patterns like these.” That might be true, but perhaps you too are guilty of writing code that looks like:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="fu">foldr</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    (\(k, v) m <span class="ot">-&gt;</span> Map.insert k v m)</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    Map.empty</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">$</span> toKVPairs something</span></code></pre></div>
<p>Just because it’s dressed up with functional combinators <em>doesn’t mean</em> you’re not still writing C code. To my eye, the great promise of functional programming is its potential for conceptual clarity, and repeated mutation will always fall short of the mark.</p>
<p>The complaint, as usual, is that repeated mutation tells you <em>how</em> to build something, rather than focusing on <em>what</em> it is you’re building. An algorithm cannot be correct in the absence of intention—after all, you must know what you’re trying to accomplish in order to know if you succeeded. What these builder patterns, for loops, and <code>foldr</code>s all have in common is that they are algorithms for strategies for building something.</p>
<p>But you’ll notice none of them come with comments. And therefore we can only ever guess at what the original author intended, based on the context of the code we’re looking at.</p>
<p>I’m sure this all sounds like splitting hairs, but that’s because the examples so far have been extremely simple. But what about this one?</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ot">cgo ::</span> (a <span class="ot">-&gt;</span> (<span class="dt">UInt</span>, <span class="dt">UInt</span>)) <span class="ot">-&gt;</span> [a] <span class="ot">-&gt;</span> [<span class="dt">NonEmpty</span> a]</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>cgo f <span class="ot">=</span> <span class="fu">foldr</span> step []</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">where</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    step a [] <span class="ot">=</span> [<span class="fu">pure</span> a]</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>    step a bss0<span class="op">@</span>((b <span class="op">:|</span> bs) <span class="op">:</span> bss)</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>      <span class="op">|</span> <span class="kw">let</span> (al, ac) <span class="ot">=</span> f a</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>      , <span class="kw">let</span> (bl, bc) <span class="ot">=</span> f b</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>      , al <span class="op">+</span> <span class="dv">1</span> <span class="op">==</span> bl <span class="op">&amp;&amp;</span> ac <span class="op">==</span> bc</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>            <span class="ot">=</span> (a <span class="op">:|</span> b <span class="op">:</span> bs) <span class="op">:</span> bss</span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>      <span class="op">|</span> <span class="fu">otherwise</span> <span class="ot">=</span> <span class="fu">pure</span> a <span class="op">:</span> bss0</span></code></pre></div>
<p>which I found by grepping through <code>haskell-language-server</code> for <code>foldr</code>, and then mangled to remove the suggestive variable names. What does this one do? Based solely on the type we can presume it’s using that function to partition the list somehow. But how? And is it correct? We’ll never know—and the function doesn’t even come with any tests!</p>
<h2 id="its-always-monoids">It’s Always Monoids</h2>
<p>The shift in perspective necessary here is to reconceptualize building-by-repeated-mutation as building-by-combining. Rather than chiseling out the object you want, instead find a way of gluing it together from simple, obviously-correct pieces.</p>
<p>The notion of “combining together” should evoke in you a cozy warm fuzzy feeling. Much like being in a secret pillow form. You must come to be one with the monoid. Once you have come to embrace monoids, you will have found inner programming happiness. Monoids are a sacred, safe place, at the fantastic intersection of “overwhelming powerful” and yet “hard to get wrong.”</p>
<p>As an amazingly fast recap, a monoid is a collection of three things: some type <code>m</code>, some value of that type <code>mempty</code>, and binary operation over that type <code>(&lt;&gt;) :: m -&gt; m -&gt; m</code>, subject to a bunch of laws:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>∀a<span class="op">.</span> <span class="fu">mempty</span> <span class="op">&lt;&gt;</span> a <span class="ot">=</span> a <span class="ot">=</span> a <span class="op">&lt;&gt;</span> <span class="fu">mempty</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>∀a b c<span class="op">.</span> (a <span class="op">&lt;&gt;</span> b) <span class="op">&lt;&gt;</span> c <span class="ot">=</span> a <span class="op">&lt;&gt;</span> (b <span class="op">&lt;&gt;</span> c)</span></code></pre></div>
<p>which is to say, <code>mempty</code> does nothing and <code>(&lt;&gt;)</code> doesn’t care where you stick the parentheses.</p>
<p>If you’re going to memorize any two <em>particular</em> examples of monoids, it had better be these two:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Monoid</span> [a] <span class="kw">where</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>  <span class="fu">mempty</span> <span class="ot">=</span> []</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  a <span class="op">&lt;&gt;</span> b <span class="ot">=</span> a <span class="op">++</span> b</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">Monoid</span> a, <span class="dt">Monoid</span> b) <span class="ot">=&gt;</span> <span class="dt">Monoid</span> (a, b) <span class="kw">where</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>  <span class="fu">mempty</span> <span class="ot">=</span> (<span class="fu">mempty</span>, <span class="fu">mempty</span>)</span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>  (a1, b1) <span class="op">&lt;&gt;</span> (a2, b2) <span class="ot">=</span> (a1 <span class="op">&lt;&gt;</span> a2, b1 <span class="op">&lt;&gt;</span> b2)</span></code></pre></div>
<p>The first says that lists form a monoid under the empty list and concatenation. The second says that products preserve monoids.</p>
<p>The list monoid instance is responsible for the semantics of the ordered, “sequency” data structures. That is, if I have some sequential flavor of data structure, its monoid instance should probably satisfy the equation <code>toList a &lt;&gt; toList b = toList (a &lt;&gt; b)</code>. Sequency data structures are things like lists, vectors, queues, deques, that sort of thing. Data structures where, when you combine them, you assume there is no overlap.</p>
<p>The second monoid instance here, over products, is responsible for pretty much all the other data structures. The first thing we can do with it is remember that functions are just really, really big product types, with one “slot” for every value in the domain. We can show an isomorphism between pairs and functions out of booleans, for example:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ot">from ::</span> (<span class="dt">Bool</span> <span class="ot">-&gt;</span> a) <span class="ot">-&gt;</span> (a, a)</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>from f <span class="ot">=</span> (f <span class="dt">False</span>, f <span class="dt">True</span>)</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="ot">to ::</span> (a, a) <span class="ot">-&gt;</span> (<span class="dt">Bool</span> <span class="ot">-&gt;</span> a)</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>to (a, _) <span class="dt">False</span> <span class="ot">=</span> a</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>to (_, a) <span class="dt">True</span>  <span class="ot">=</span> a</span></code></pre></div>
<p>and under this isomorphism, we should thereby expect the <code>Monoid a =&gt; Monoid (Bool -&gt; a)</code> instance to agree with <code>Monoid a =&gt; Monoid (a, a)</code>. If you generalize this out, you get the following instance:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Monoid</span> a <span class="ot">=&gt;</span> <span class="dt">Monoid</span> (x <span class="ot">-&gt;</span> a) <span class="kw">where</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>  <span class="fu">mempty</span> <span class="ot">=</span> \_ <span class="ot">-&gt;</span> <span class="fu">mempty</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>  f <span class="op">&lt;&gt;</span> g <span class="ot">=</span> \x <span class="ot">-&gt;</span> f x <span class="op">&lt;&gt;</span> g x</span></code></pre></div>
<p>which combines values in the codomain monoidally. We can show the equivalence between this monoid instance and our original product preservation:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>  from f <span class="op">&lt;&gt;</span> from g</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span> (f <span class="dt">False</span>,  f <span class="dt">True</span>) <span class="op">&lt;&gt;</span> (g <span class="dt">False</span>, g <span class="dt">True</span>)</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span> (f <span class="dt">False</span> <span class="op">&lt;&gt;</span> g <span class="dt">False</span>, f <span class="dt">True</span> <span class="op">&lt;&gt;</span> g <span class="dt">True</span>)</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span> ((f <span class="op">&lt;&gt;</span> g) <span class="dt">False</span>, (f <span class="op">&lt;&gt;</span> g) <span class="dt">True</span>)</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span> from (f <span class="op">&lt;&gt;</span> g)</span></code></pre></div>
<p>and</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>  to (a11, a12) <span class="op">&lt;&gt;</span> to (a21, a22)</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span> \x <span class="ot">-&gt;</span> to (a11, a12) x <span class="op">&lt;&gt;</span> to (a21, a22) x</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span> \x <span class="ot">-&gt;</span> <span class="kw">case</span> x <span class="kw">of</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">False</span> <span class="ot">-&gt;</span> to (a11, a12) <span class="dt">False</span> <span class="op">&lt;&gt;</span> to (a21, a22) <span class="dt">False</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">True</span>  <span class="ot">-&gt;</span> to (a11, a12) <span class="dt">True</span>  <span class="op">&lt;&gt;</span> to (a21, a22) <span class="dt">True</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span> \x <span class="ot">-&gt;</span> <span class="kw">case</span> x <span class="kw">of</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">False</span> <span class="ot">-&gt;</span> a11 <span class="op">&lt;&gt;</span> a21</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">True</span>  <span class="ot">-&gt;</span> a12 <span class="op">&lt;&gt;</span> a22</span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span> \x <span class="ot">-&gt;</span> to (a11 <span class="op">&lt;&gt;</span> a21, a12 <span class="op">&lt;&gt;</span> a22) x</span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a><span class="ot">=</span> to (a11 <span class="op">&lt;&gt;</span> a21, a12 <span class="op">&lt;&gt;</span> a22)</span></code></pre></div>
<p>which is a little proof that our function monoid agrees with the preservation-of-products monoid. The same argument works for any type <code>x</code> in the domain of the function, but showing it generically is challenging.</p>
<p>Anyway, I digresss.</p>
<p>The reason to memorize <em>this</em> <code>Monoid</code> instance is that it’s the monoid instance that every data structure is trying to be. Recall that <em>almost all</em> data structures are merely different encodings of functions, designed to make some operations more efficient than they would otherwise be.</p>
<p>Don’t believe me? A <code>Map k v</code> is an encoding of the function <code>k -&gt; Maybe v</code> optimized to efficiently query which <code>k</code> values map to <code>Just</code> something. That is to say, it’s a sparse representation of a function.</p>
<h2 id="from-theory-to-practice">From Theory to Practice</h2>
<p>What does all of this look like in practice? Stuff like worrying about <code>foldr</code> is surely programming-in-the-small, which is worth knowing, but isn’t the sort of thing that turns the tides of a successful application.</p>
<p>The reason I’ve been harping on about the function and product monoids is that they are compositional. The uninformed programmer will be surprised by just far one can get by composing these things.</p>
<p>At work, we need to reduce a tree (+ nonlocal references) into an honest-to-goodness graph. While we’re doing it, we need to collect certain nodes. And the tree has a few constructors which semantically change the scope of their subtrees, so we need to preserve that information as well.</p>
<p>It’s actually quite the exercise to sketch out an algorithm that will accomplish all of these goals when you’re thinking about explicit mutation. Our initial attempts at implementing this were clumsy. We’d fold the tree into a graph, adding fake nodes for the <code>Scope</code> construcotrs. Then we’d filter all the nodes in the graph, trying to find the ones we needed to collect. Then we’d do a graph traversal from the root, trying to find these <code>Scope</code> nodes, and propagating their information downstream.</p>
<p>Rather amazingly, this implementation kinda sorta worked! But it was slow, and took <span class="math inline">\(O(10k)\)</span> SLOC to implement.</p>
<p>The insight here is that everything we needed to collect was monoidal:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Solution</span> <span class="ot">=</span> <span class="dt">Solution</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>  {<span class="ot"> graph ::</span> <span class="dt">Graph</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>  ,<span class="ot"> collectedNodes ::</span> <span class="dt">Set</span> <span class="dt">Node</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>  ,<span class="ot"> metadata ::</span> <span class="dt">Map</span> <span class="dt">Node</span> <span class="dt">Metadata</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> stock (<span class="dt">Generic</span>)</span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> (<span class="dt">Semigroup</span>, <span class="dt">Monoid</span>) via <span class="dt">Generically</span> <span class="dt">Solution</span></span></code></pre></div>
<p>where the <code>deriving (Semigroup, Monoid) via Generically Solution</code> stanza gives us the semigroup and monoid instances that we’d expect from <code>Solution</code> being the product of a bunch of other monoids.</p>
<p>And now for the <em>coup de grace</em>: we hook everything up with the <code>Writer</code> monad. <code>Writer</code> is a chronically slept-on type, because most people seem to think it’s useful only for logging, and, underwhelming at doing logging compared to a real logger type. But the charm is in the details:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Monoid</span> w <span class="ot">=&gt;</span> <span class="dt">Monad</span> (<span class="dt">Writer</span> w)</span></code></pre></div>
<p><code>Writer w</code> is a <em>monad</em> whenever <code>w</code> is a <em>monoid</em>, which makes it the perfect monad for solving data-structure-creation problems like the one we’ve got in mind. Such a thing gives rise to a few helper functions:</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ot">collectNode ::</span> <span class="dt">MonadWriter</span> <span class="dt">Solution</span> m <span class="ot">=&gt;</span> <span class="dt">Node</span> <span class="ot">-&gt;</span> m ()</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>collectNode n <span class="ot">=</span> tell <span class="op">$</span> <span class="fu">mempty</span> { collectedNodes <span class="ot">=</span> Set.singleton n }</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="ot">addMetadata ::</span> <span class="dt">MonadWriter</span> <span class="dt">Solution</span> m <span class="ot">=&gt;</span> <span class="dt">Node</span> <span class="ot">-&gt;</span> <span class="dt">Metadata</span> <span class="ot">-&gt;</span> m ()</span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>addMetadata n m <span class="ot">=</span> tell <span class="op">$</span> <span class="fu">mempty</span> { metadata <span class="ot">=</span> Map.singleton n m }</span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a><span class="ot">emitGraphFragment ::</span> <span class="dt">MonadWriter</span> <span class="dt">Solution</span> m <span class="ot">=&gt;</span> <span class="dt">Graph</span> <span class="ot">-&gt;</span> m ()</span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>emitGraphFragment g <span class="ot">=</span> tell <span class="op">$</span> <span class="fu">mempty</span> { graph <span class="ot">=</span> g }</span></code></pre></div>
<p>each of which is responsible for adding a little piece to the final solution. Our algorithm is thus a function of the type:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>algorithm</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="ot">  ::</span> <span class="dt">Metadata</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- ^ the current scope</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> <span class="dt">Tree</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- ^ the tree we&#39;re reducing</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>  <span class="ot">-&gt;</span> <span class="dt">Writer</span> <span class="dt">Solution</span> <span class="dt">Node</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- ^ our partial solution, and the node corresponding to the root of the tree</span></span></code></pre></div>
<p>which traverses the <code>Tree</code>, recursing with a different <code>Metadata</code> whenever it comes across a <code>Scope</code> constructor, and calling our helper functions as it goes. At each step of the way, the only thing it needs to return is the root <code>Node</code> of the section of the graph it just built, which recursing calls can use to break up the problem into inductive pieces.</p>
<p>This new implementation is roughly 20x smaller, coming in at <span class="citation" data-cites="O">@O</span>(500)@ SLOC, and was free of all the bugs we’d been dilligently trying to squash under the previous implementation.</p>
<p>Chalk it down to another win for induction!</p>
        ]]>
      </content>
    </entry>
</feed>

