<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Some personal notes turned into a blog</title>
    <link href="https://zanzix.github.io/atom.xml" rel="self" type="application/rss+xml" />
  <updated>2025-02-17T21:02:07Z</updated>
  <author>
      <name>Zanzi</name>
  </author>
  <id>https://zanzix.github.io/</id>

  <entry>
      <title>Compiler Engineering for Substructural Languages I: Day Convolution for
Covers</title>
      <link href="https://zanzix.github.io/posts/6-promonoidal-covers.html"/>
      <id>https://zanzix.github.io/posts/6-promonoidal-covers.html</id>
      <updated>2025-02-17T00:00:00Z</updated>
      <summary>Lets define some combinators</summary>
      <content type="html"><![CDATA[<p>In the <a href="">previous post</a> we've posed the problem of
defining substructural polymorphism, but while we've defined
substitution for a polymorphic language, we did not do so for the
substructural one. We will rectify this in the current blogpost, as well
as introduce some nice combinators for working with covers.</p>
<h3 id="substitution-in-the-linear-lambda-calculus">Substitution in the
Linear Lambda Calculus</h3>
<p>First let's define substitution in the linear lambda calculus the way
we'd do normally, then try to introduce some more general machinery.</p>
<p>Just as in the last post, we'll start by defining relevant covers,
well-scoped lambda terms, and substitutions</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Cover</span> <span class="ot">:</span> (k, l, m <span class="ot">:</span> <span class="dt">List</span> a) <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Done</span>   <span class="ot">:</span>                <span class="dt">Cover</span>      []      []      []</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Left</span>   <span class="ot">:</span> <span class="dt">Cover</span> k l m <span class="ot">-&gt;</span> <span class="dt">Cover</span> (a <span class="ot">::</span> k)     l  (a <span class="ot">::</span> m)</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Right</span>  <span class="ot">:</span> <span class="dt">Cover</span> k l m <span class="ot">-&gt;</span> <span class="dt">Cover</span>       k  (a<span class="ot">::</span>l) (a <span class="ot">::</span> m)</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Both</span>   <span class="ot">:</span> <span class="dt">Cover</span> k l m <span class="ot">-&gt;</span> <span class="dt">Cover</span> (a <span class="ot">::</span> k) (a<span class="ot">::</span>l) (a <span class="ot">::</span> m)</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="co">--  Binary operators like &#39;App&#39; have a Cover wrapped around them</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Term</span> <span class="ot">:</span> <span class="dt">List</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Var</span> <span class="ot">:</span> {s <span class="ot">:</span> <span class="dt">String</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> [s]</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Lam</span> <span class="ot">:</span> {s <span class="ot">:</span> <span class="dt">String</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> (s<span class="ot">::</span>g) <span class="ot">-&gt;</span> <span class="dt">Term</span> g</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>  <span class="dt">App</span>  <span class="ot">:</span> <span class="dt">Cover</span> g1 g2 g <span class="ot">-&gt;</span> <span class="dt">Term</span> g1 <span class="ot">-&gt;</span> <span class="dt">Term</span> g2 <span class="ot">-&gt;</span> <span class="dt">Term</span> g</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Sub</span> <span class="ot">:</span> <span class="dt">List</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">List</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Nil</span> <span class="ot">:</span> <span class="dt">Sub</span> [] []</span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- ^the empty substitution</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Cons</span> <span class="ot">:</span> {a <span class="ot">:</span> <span class="dt">String</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> g1 <span class="ot">-&gt;</span> <span class="dt">Cover</span> g1 g2 g <span class="ot">-&gt;</span> <span class="dt">Sub</span> g2 d <span class="ot">-&gt;</span> <span class="dt">Sub</span> g (a<span class="ot">::</span>d)</span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- add a term in context g1 to a substitution with context g2,</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- and append their contexts</span></span></code></pre></div>
<p>But now, let's actually see what the guts of substitution look
like.</p>
<p>TODO: Substitution in plan</p>
<h3 id="substitution-using-day-convolution">Substitution using Day
Convolution</h3>
<p>TODO: cleaned up substitution</p>
<h3 id="factor-out-covers">Factor out covers</h3>
<p>Now, what happens if we factor out the cover outside of Sub? This
means that, what if instead of combining each individual context using
Sub, we collect them into a list of contexts, and only have one outer
cover?</p>]]></content>
  </entry>
  <entry>
      <title>Compiler Engineering for Substructural Languages I: The Problem with
Polymorphism</title>
      <link href="https://zanzix.github.io/posts/5-substructural-polymorphism.html"/>
      <id>https://zanzix.github.io/posts/5-substructural-polymorphism.html</id>
      <updated>2025-02-14T00:00:00Z</updated>
      <summary>Can a correct-by-construction implementation of a substructural language
be extended to a polymorphic lambda calculus?</summary>
      <content type="html"><![CDATA[<p>We've been working hard at <a
href="https://glaive-research.org/">Glaive</a> to develop a language
based on the classical sequent calculus, ie. a type theory with
first-class support for continuations and call-cc. I will make a proper
announcement of the language soon, but for now I just want to discuss a
particularly subtle problem that came up in our development. (In the
meantime, you can read <a href="https://arxiv.org/abs/2406.14719">this
excellent paper by Binder et al</a> to get a taste of what programming
in this class of languages is like).</p>
<p>For very subtle theoretical reasons, the core language that we're
developing needs to be substructural. The problem isn't with
copying/deleting by itself - we can still copy and delete variables -
this just needs to be done explicitly, at least in the core language.
Jules wrote about <a
href="https://zanzix.github.io/posts/4-substructural.html">representing
explicitly cartesian languages</a> on this blog before.</p>
<p>So the current intention is that the concrete syntax will be
cartesian as normal, but it will desugar to a substructural core
language with explicit copy and delete, aka. the Co-de-Bruijn
representation. (Though now that we're working on a substructural core,
we've actually been talking about experimenting with the design space of
languages like Rust).</p>
<p>The problem we're facing, however, is that it's entirely unclear how
to adapt a correct-by-construction implementation of a polymorphic
language to a substructural discipline.</p>
<p>So the purpose of this blog series is two-fold:</p>
<p>On one hand, I would like to document the current progress of our
language implementation in Idris - this will both be a showcase of using
dependent types for general compiler engineering, as well as a
collection of various folklore around implementing substructural
languages specifically.</p>
<p>On the other hand, there are still many open questions that we have
in this space, and there are practically no publications on this topic.
So we would like to solicit feedback and see if anyone has some ideas
that we've overlooked.</p>
<p>In this blog post I will introduce the problem by defining two
separate lambda calculi - one with substructural variables, and one with
polymorphism. The question of how to combine the two will be one of the
main things that we'd like to answer by the time the series
finishes.</p>
<h3
id="substructural-languages-from-a-dependently-typed-point-of-view">Substructural
Languages from a Dependently-Typed Point of View</h3>
<p>Let's start with the simply-typed substructural lambda calculus.</p>
<p>The main thing that happens when switching from a cartesian to a
linear syntax is that we can no longer implicitly share contexts. This
means that variables become singletons - only one thing can be in scope
at the leaves, and that each term has its own context, so rules that
involve more than one term (such as <code>App</code>) now need to
explicitly combine them.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Naive representation of linear terms</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Term</span> <span class="ot">:</span> <span class="dt">List</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Var</span> <span class="ot">:</span> {s <span class="ot">:</span> <span class="dt">String</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> [s]</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Lam</span> <span class="ot">:</span> {s <span class="ot">:</span> <span class="dt">String</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> (s<span class="ot">::</span>g) <span class="ot">-&gt;</span> <span class="dt">Term</span> g</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">App</span>  <span class="ot">:</span> <span class="dt">Term</span> g1 <span class="ot">-&gt;</span> <span class="dt">Term</span> g2 <span class="ot">-&gt;</span> <span class="dt">Term</span> (g1 <span class="fu">++</span> g2)</span></code></pre></div>
<p>This of course creates the dreaded green slime in the domain of
<code>App</code> - we now have a function in our data-type definition,
which will cause problems later.</p>
<p>Because of this, the standard solution is to use 'covers', which
represent the function (++) as a proof-relevant relation. This gives us
a way to pattern-match on the Cover when needed, thus avoiding the
unifier from getting stuck in such cases.</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- A relation for splitting relevant terms.</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="co">-- Each variable either goes into one of the contexts, or both.</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Cover</span> <span class="ot">:</span> (k, l, m <span class="ot">:</span> <span class="dt">List</span> a) <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Done</span>   <span class="ot">:</span>                <span class="dt">Cover</span>      []      []      []</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Left</span>   <span class="ot">:</span> <span class="dt">Cover</span> k l m <span class="ot">-&gt;</span> <span class="dt">Cover</span> (a <span class="ot">::</span> k)     l  (a <span class="ot">::</span> m)</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Right</span>  <span class="ot">:</span> <span class="dt">Cover</span> k l m <span class="ot">-&gt;</span> <span class="dt">Cover</span>       k  (a<span class="ot">::</span>l) (a <span class="ot">::</span> m)</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Both</span>   <span class="ot">:</span> <span class="dt">Cover</span> k l m <span class="ot">-&gt;</span> <span class="dt">Cover</span> (a <span class="ot">::</span> k) (a<span class="ot">::</span>l) (a <span class="ot">::</span> m)</span></code></pre></div>
<p>Given a context <code>m</code>, the cover shows how to decompose it
into the contexts <code>k</code> and <code>l</code>, by putting each
variable into either one or both of the contexts.</p>
<p>Our term representation now looks like this.</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co">--  Binary operators like &#39;App&#39; have a Cover wrapped around them</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Term</span> <span class="ot">:</span> <span class="dt">List</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Var</span> <span class="ot">:</span> {s <span class="ot">:</span> <span class="dt">String</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> [s]</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Lam</span> <span class="ot">:</span> {s <span class="ot">:</span> <span class="dt">String</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> (s<span class="ot">::</span>g) <span class="ot">-&gt;</span> <span class="dt">Term</span> g</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">App</span>  <span class="ot">:</span> <span class="dt">Cover</span> g1 g2 g <span class="ot">-&gt;</span> <span class="dt">Term</span> g1 <span class="ot">-&gt;</span> <span class="dt">Term</span> g2 <span class="ot">-&gt;</span> <span class="dt">Term</span> g</span></code></pre></div>
<p>This won't be a full introduction to Co-de-Bruijn, for more details I
recommend <a
href="https://jesper.sikanda.be/posts/1001-syntax-representations.html">this
blog post by Jesper Cockx</a> (Ctrl+F for 'Co-de-Bruijn'), <a
href="https://arxiv.org/abs/1807.04085">Conor's original paper</a>, or
<a
href="https://studenttheses.uu.nl/bitstream/handle/20.500.12932/44219/thesis-final-matthias-heinzel.pdf?sequence=1&amp;isAllowed=y">this
great Masters thesis by Matthias Heinzel</a>.</p>
<p>In this blog post I'd like to focus on one of the reasons for
<em>why</em> we care about Co-de-Bruijn, which is that it eliminates one
of the biggest sources of inefficiency when it comes to implemeting
substitution.</p>
<p>Regardless of which representation of substitution we use, we will
inevitably need to perform substitution under binders. Traditionally,
this is done by introducing the concept of a <em>renaming</em>, or
<em>thinning</em>. The idea is that as we substitute under binders we
additionally perform a renaming of a term, extending its context with a
new variable. <a
href="https://gist.github.com/AndrasKovacs/bd6a6333e4eecd7acb0eb9d98f7e0cb8">András
Kovacs has a great reference implementation here</a>.</p>
<p>Semantically, this is nice - renaming forms a functor, substitution
forms a (relative) monad on that functor. (We will look at this semantic
perspective in more detail in a future series, but for now we'll just
focus on the syntax).</p>
<p>Operationally, this is a nightmare - we now need to traverse each
term twice, and moreover, the renaming doesn't <em>do</em> anything
beyond keeping the contexts of sub-terms in sync with each other.
Context sharing was meant to be a simplification, but now it induces a
major operational cost on our implementation.</p>
<p>The beautiful thing about substructural languages is that they forego
the need for renaming - because contexts are split, there's no need to
keep them in sync. And because the variables are now singletons, there
is no need to traverse the entire term just to update its context about
all the variables it won't be using anyway.</p>
<p>In practice, our substitution datatype would look like this.</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- A substitution for a substructural language</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Sub</span> <span class="ot">:</span> <span class="dt">List</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">List</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Nil</span> <span class="ot">:</span> <span class="dt">Sub</span> [] []</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- ^the empty substitution</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Cons</span> <span class="ot">:</span> {a <span class="ot">:</span> <span class="dt">String</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> g1 <span class="ot">-&gt;</span> <span class="dt">Cover</span> g1 g2 g <span class="ot">-&gt;</span> <span class="dt">Sub</span> g2 d <span class="ot">-&gt;</span> <span class="dt">Sub</span> g (a<span class="ot">::</span>d)</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- add a term in context g1 to a substitution with context g2,</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- and append their contexts</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a><span class="co">-- Substitution traverses the term and applies the environment to each subterm</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a><span class="fu">subst</span> <span class="ot">:</span> <span class="dt">Term</span> g <span class="ot">-&gt;</span> <span class="dt">Sub</span> d g <span class="ot">-&gt;</span> <span class="dt">Term</span> d</span></code></pre></div>
<p>(Compare it to <a
href="https://gist.github.com/AndrasKovacs/bd6a6333e4eecd7acb0eb9d98f7e0cb8#file-stlcsubst-agda-L162">this
definition in Kovac's implementation which uses implcit
context-sharing</a>). The only difference is that whenever we Cons a new
term on the environment, we need to explicitly add its context using a
cover.</p>
<p>This works well, modulo some wrangling of covers, for which we've
come up with some helpful combinators with the help of Vikraman
Choudhury, and that I'll show in the next blog post.</p>
<p>For now, the main point is that the most expensive operation -
extending the context by a new variable - is now entirely free, <a
href="https://gist.github.com/AndrasKovacs/bd6a6333e4eecd7acb0eb9d98f7e0cb8#file-stlcsubst-agda-L179">rather
than requiring us to individually weaken each term in the
environment</a>.</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">ext</span> <span class="ot">:</span> {g&#39; <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Sub</span> g g&#39; <span class="ot">-&gt;</span> <span class="dt">Sub</span> (s <span class="ot">::</span> g) (s <span class="ot">::</span> g&#39;)</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>ext lift e <span class="fu">=</span> <span class="dt">Cons</span> <span class="dt">Var</span> (<span class="dt">Left</span> coverRightId) e</span></code></pre></div>
<p>All we do is Cons a variable to an existing environment
<code>e</code>, and our cover is a proof that the new variable goes on
the left-most context, while all the other variables go on the right
(this is what <code>coverRightId</code> does). None of the actual terms
in <code>e</code> are touched at any point.</p>
<p>Now, unfortunately... I don't think this substitution datatype
generalises to the polymorphic case, at least not in an obvious way.</p>
<p>To see that, let's first sketch out what a polymorphic language with
shared contexts looks like.</p>
<h3 id="a-quick-introduction-to-polymorphic-lambda-calculi">A Quick
Introduction to Polymorphic Lambda Calculi</h3>
<p>András Kovacs has us covered once again, as he has a <a
href="https://github.com/AndrasKovacs/system-f-omega/blob/master/Term.agda">great
reference implementation</a>.</p>
<p>Unlike András, we will be going with a well scoped rather than well
typed representation, in order to avoid the buckets of green slime that
a typical intrinsically typed implementation of System F will saddle us
with.</p>
<p>First we will define types, which are now indexed by a list of type
variables.</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Ty</span> <span class="ot">:</span> (typeVars <span class="ot">:</span> <span class="dt">List</span> <span class="dt">String</span>) <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">VarT</span> <span class="ot">:</span> <span class="dt">Elem</span> a g <span class="ot">-&gt;</span> <span class="dt">Ty</span> g</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- ^ Type variables</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Forall</span> <span class="ot">:</span> <span class="dt">Ty</span> (s<span class="ot">::</span>g) <span class="ot">-&gt;</span> <span class="dt">Ty</span> g</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- ^ Type quantification</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Mu</span> <span class="ot">:</span> <span class="dt">Ty</span> (s<span class="ot">::</span>g) <span class="ot">-&gt;</span> <span class="dt">Ty</span> g</span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- ^ Least fixpoint of a datatype</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>  <span class="fu">(~&gt;)</span> <span class="ot">:</span> <span class="dt">Ty</span> g <span class="ot">-&gt;</span> <span class="dt">Ty</span> g <span class="ot">-&gt;</span> <span class="dt">Ty</span> g</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- ^ Function type</span></span></code></pre></div>
<p>For terms contexts, the simplest approach is to define them as being
indexed by two independent lists, one for type variables and one for
term variables, as is <a
href="https://github.com/sstucki/system-f-agda/blob/master/src/SystemF/Term.agda">done
by Sandro Stucki here</a>:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Term</span> <span class="ot">:</span> (typeVars <span class="ot">:</span> <span class="dt">List</span> <span class="dt">String</span>) <span class="ot">-&gt;</span> (termVars <span class="ot">:</span> <span class="dt">List</span> <span class="dt">String</span>) <span class="ot">-&gt;</span> <span class="dt">Type</span></span></code></pre></div>
<p>This representation is convenient to work with, but misses an
important connection between the two contexts - term variables can refer
to type variables in their types! So a more informative representation
would allow the term context to be synced with the type context, and the
standard solution to this is to index the latter by the former.</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- a list indexed by another list</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">IxList</span> <span class="ot">:</span> (a <span class="ot">:</span> <span class="dt">Type</span>) <span class="ot">-&gt;</span> <span class="dt">List</span> a <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Nil</span> <span class="ot">:</span> <span class="dt">IxList</span> a []</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- ^the empty IxList is indexed by the empty List</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>  <span class="fu">(::)</span> <span class="ot">:</span> a <span class="ot">-&gt;</span> <span class="dt">IxList</span> a ls <span class="ot">-&gt;</span> <span class="dt">IxList</span> a ls</span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- ^add a new term variable without touching the index</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>  <span class="fu">(:::)</span> <span class="ot">:</span> (el <span class="ot">:</span> a) <span class="ot">-&gt;</span> <span class="dt">IxList</span> a as <span class="ot">-&gt;</span> <span class="dt">IxList</span> a (el<span class="ot">::</span>as)</span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- ^add a new type variable,</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- increasing the type context by which future term variables will be indexed</span></span></code></pre></div>
<p>We now need a version of the <a
href="https://www.idris-lang.org/docs/idris2/0.6.0/base_docs/docs/Data.List.Elem.html"><code>Elem</code>
data-type</a> for indexed list, ie. a proof-relevant variable that keeps
track of its position in the context.</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">IxElem</span> <span class="ot">:</span> a <span class="ot">-&gt;</span> <span class="dt">IxList</span> a ks <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Here</span>    <span class="ot">:</span> <span class="dt">IxElem</span> a (a <span class="ot">::</span> as)</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">There</span>   <span class="ot">:</span> <span class="dt">IxElem</span> a as <span class="ot">-&gt;</span> <span class="dt">IxElem</span> a (b <span class="ot">::</span> as)</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">ThereK</span>  <span class="ot">:</span> <span class="dt">IxElem</span> a as <span class="ot">-&gt;</span> <span class="dt">IxElem</span> a (b <span class="ot">:::</span> as)</span></code></pre></div>
<p>We've now got everything to define a well scoped fragment of System
F.</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Term</span> <span class="ot">:</span> (tyVars <span class="ot">:</span> <span class="dt">List</span> <span class="dt">String</span>)</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>         <span class="ot">-&gt;</span> (trmVars <span class="ot">:</span> <span class="dt">IxList</span> <span class="dt">String</span> tyVars) <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Var</span>  <span class="ot">:</span> (var <span class="ot">:</span> <span class="dt">String</span>) <span class="ot">-&gt;</span> <span class="dt">IxElem</span> {tyVars} var termVars <span class="ot">-&gt;</span> <span class="dt">Term</span> tyVars termVars</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Proof that the variable var is in the IxList termvars</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Lam</span>  <span class="ot">:</span> (a <span class="ot">:</span> <span class="dt">String</span>) <span class="ot">-&gt;</span> (tya <span class="ot">:</span> <span class="dt">Ty</span> tyVars)</span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>      <span class="ot">-&gt;</span> <span class="dt">Term</span> tyVars (a <span class="ot">::</span> trmVars) <span class="ot">-&gt;</span> <span class="dt">Term</span> tyVars trmVars</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Lambda abstraction is standard, and includes a type annotation `ty`</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">App</span> <span class="ot">:</span> <span class="dt">Term</span> tyVars trmVars <span class="ot">-&gt;</span> <span class="dt">Term</span> tyVars trmVars</span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a>     <span class="ot">-&gt;</span> <span class="dt">Term</span> tyVars trmVars</span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- lambda application is standard</span></span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a>  <span class="dt">In</span>   <span class="ot">:</span> (f <span class="ot">:</span> <span class="dt">Ty</span> (tyVar <span class="ot">::</span> tyVars)) <span class="ot">-&gt;</span> <span class="dt">Term</span> tyVars trmVars <span class="ot">-&gt;</span> <span class="dt">Term</span> tyVars trmVars</span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a>    <span class="co">-- inject into a term of a recursive type `f`</span></span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Out</span>  <span class="ot">:</span> (f <span class="ot">:</span> <span class="dt">Ty</span> (tyVar <span class="ot">::</span> tyVars)) <span class="ot">-&gt;</span> <span class="dt">Term</span> tyVars trmVars <span class="ot">-&gt;</span> <span class="dt">Term</span> tyVars trmVars</span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a>    <span class="co">-- project from a term of a recursive type `f`</span></span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true" tabindex="-1"></a>  <span class="dt">TLam</span> <span class="ot">:</span> (tyVar <span class="ot">:</span> <span class="dt">String</span>) <span class="ot">-&gt;</span> <span class="dt">Term</span> (tyVar <span class="ot">::</span> tyVars) (tyVar <span class="ot">:::</span> trmVars)</span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true" tabindex="-1"></a>      <span class="ot">-&gt;</span> <span class="dt">Term</span> tyVars trmVars</span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- type abstraction now binds a type variable `k` in both contexts</span></span>
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true" tabindex="-1"></a>  <span class="dt">TApp</span>  <span class="ot">:</span> <span class="dt">Term</span> tyVars trmVars <span class="ot">-&gt;</span> <span class="dt">Ty</span> tyVars <span class="ot">-&gt;</span> <span class="dt">Term</span> tyVars trmVars</span>
<span id="cb10-25"><a href="#cb10-25" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Type application applies a type to a term with a type lambda</span></span></code></pre></div>
<p>For now we will assume some familiarity with System F, so I won't go
into too much detail into what each constructor does, but we can rectify
that in a future blog post. I recommend <a
href="https://homepages.inf.ed.ac.uk/wadler/papers/mpc-2019/system-f-in-agda.pdf">this
paper by Chapman et al</a> (aptly called "System F in Agda, for Fun and
Profit") in the meantime.</p>
<p>At this point, we have enough to start defining renaming and
substitution, but before that we should take note of something
interesting: because we designed our term contexts to be indexed by type
contexts, this decision will propagate across all context operations. So
term renamings are indexed by type renamings, and term substitutions are
indexed by type substitutions.</p>
<p>For our purposes, we only care about substitution, since a
substructural type system side-steps renaming.</p>
<p>In order to define term substitutions we first need to define type
substitutions:</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- type substitution with implicitly shared contexts &#39;g&#39;</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">TySub</span> <span class="ot">:</span> <span class="dt">List</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">List</span> <span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">NilTy</span> <span class="ot">:</span> <span class="dt">TySub</span> g []</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- ^empty type substitution.</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">ConsTy</span> <span class="ot">:</span> (tyVar <span class="ot">:</span> <span class="dt">String</span>) <span class="ot">-&gt;</span> <span class="dt">Ty</span> g <span class="ot">-&gt;</span> <span class="dt">TySub</span> g d <span class="ot">-&gt;</span> <span class="dt">TySub</span> g (tyVar<span class="ot">::</span>d)</span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- ^extend the type substitution with a new variable</span></span></code></pre></div>
<p>Contrast this to the earlier implementation of <code>Sub</code> which
used a cover to concatenate contexts - we are now assuming that the
context <code>g</code> is the same across all terms. While this
simplifies the datatype, it comes at the cost of requiring any operation
on term contexts (such as weakening) to apply to <em>all</em> terms in
the substitution.</p>
<p>We can see this once we define substitution, which is no different to
substitution in any well scoped syntax.</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- projection from the environment</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="fu">indexEnv</span> <span class="ot">:</span> <span class="dt">TySub</span> g d <span class="ot">-&gt;</span> <span class="dt">Elem</span> a d <span class="ot">-&gt;</span> <span class="dt">Ty</span> g</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>indexEnv (<span class="dt">ConsTy</span> a x y) <span class="dt">Here</span> <span class="fu">=</span> x</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>indexEnv (<span class="dt">ConsTy</span> a x y) (<span class="dt">There</span> t) <span class="fu">=</span> indexEnv y t</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="co">-- Traverse a type and substitute all the type variables</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a><span class="fu">tySubst</span> <span class="ot">:</span> <span class="dt">TySub</span> g d <span class="ot">-&gt;</span> <span class="dt">Ty</span> d <span class="ot">-&gt;</span> <span class="dt">Ty</span> g</span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>tySubst sub (<span class="dt">VarT</span> x) <span class="fu">=</span> indexEnv sub x</span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>tySubst sub (<span class="dt">Forall</span> s x) <span class="fu">=</span> <span class="dt">Forall</span> s <span class="fu">$</span> tySubst (tyExt sub) x</span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>tySubst sub (<span class="dt">Mu</span> s x) <span class="fu">=</span> <span class="dt">Mu</span> s <span class="fu">$</span> tySubst (tyExt sub) x</span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>tySubst sub (<span class="dt">Imp</span> x y) <span class="fu">=</span> <span class="dt">Imp</span> (tySubst sub x) (tySubst sub y)</span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a><span class="co">-- extending the type environment</span></span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a><span class="fu">extTy</span> <span class="ot">:</span> <span class="dt">TySub</span> g d <span class="ot">-&gt;</span> <span class="dt">TySub</span> (s <span class="ot">::</span> g) (s <span class="ot">::</span> d)</span></code></pre></div>
<p>Just as before, we rely on the extension operation <code>tyExt</code>
when dealing with binders such as Forall or Mu. This operation weakens
the context of each value in the substitution, thus requiring a full
traversal of each value. Unlike with the substructural case, where we
get this operation for free, defining it here requires us to also define
renaming, and so we'll elide this definition for now (but it can be
found in any of the reference implementations above).</p>
<p>What we're really interested in is term substitutions, so lets see
what our new datatype looks like.</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">TrmSub</span> <span class="ot">:</span> (g <span class="ot">:</span> <span class="dt">IxList</span> <span class="dt">String</span> as) <span class="ot">-&gt;</span> (sub <span class="ot">:</span> <span class="dt">TySub</span> as bs)</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>           <span class="ot">-&gt;</span> (d <span class="ot">:</span> <span class="dt">IxList</span> <span class="dt">String</span> bs) <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">NilTrm</span> <span class="ot">:</span> <span class="dt">TrmSub</span> g <span class="dt">NilTy</span> []</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- an empty term substitution indexed by an empty type substitution</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="dt">ConsTrm</span> <span class="ot">:</span> (trmVar <span class="ot">:</span> <span class="dt">String</span>) <span class="ot">-&gt;</span> <span class="dt">Term</span> tyVars g</span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>         <span class="ot">-&gt;</span> <span class="dt">TrmSub</span> g sub d <span class="ot">-&gt;</span> <span class="dt">TrmSub</span> g sub (trmVar<span class="ot">::</span>d)</span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- extend the term variable context by `trmVar` without affecting the type variables</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">ConsTrmTy</span> <span class="ot">:</span> (tyVar <span class="ot">:</span> <span class="dt">String</span>) <span class="ot">-&gt;</span> (ty <span class="ot">:</span> <span class="dt">Ty</span> tyVars)</span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>         <span class="ot">-&gt;</span> <span class="dt">TrmSub</span> g sub d <span class="ot">-&gt;</span> <span class="dt">TrmSub</span> g (<span class="dt">ConsTy</span> tyVar ty sub) (tyVar <span class="ot">:::</span> d)</span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- extend both the term and type variable contexts by a type variable `tyVar`</span></span></code></pre></div>
<p>This is... a lot, so let's break it down into components.</p>
<p>The first thing we notice is that the type of TrmSub is indexed by an
instance of TySub - ie. in order to map a term context <code>g</code>,
which is indexed by a type context <code>as</code>, into <code>d</code>,
which is indexed by <code>bs</code>, we need to explain how to map
<code>as</code> to <code>bs</code>. (Jules tells me that this means that
we're probably dealing with a fibration).</p>
<p>The rules for NilTrm and ConsTrm are just as before, except that
NilTrm is indexed by the empty type substitution, and ConsTrm is indexed
by an arbitrary type substitution <code>sub</code>, which it does not
interact with.</p>
<p>The interesting case is <code>ConsTrmTy</code> - it extends the term
substitution by a <em>type</em> variable - which in turn means that it
needs to extend the indexing type substitution <code>sub</code> with the
same variable.</p>
<p>We can now define the action of substitution on terms, and just like
with term contexts and term substitutions it will be indexed by a
corresponding action of type substitutions on types. Unlike before, I'll
work through the full definition here:</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Lookup a term in an environment</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="fu">lookupTrm</span> <span class="ot">:</span> <span class="dt">TrmSub</span> d tySub g <span class="ot">-&gt;</span> <span class="dt">IxElem</span> as g <span class="ot">-&gt;</span> <span class="dt">Term</span> bs d</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>lookupTrm (<span class="dt">ConsTrm</span> a x y) <span class="dt">Here</span> <span class="fu">=</span> x</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>lookupTrm (<span class="dt">ConsTrm</span> b y z) (<span class="dt">There</span> x) <span class="fu">=</span> indexTrmEnv z x</span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>lookupTrm (<span class="dt">ConsTrmTy</span> b y z) (<span class="dt">ThereK</span> x) <span class="fu">=</span> indexTrmEnv z x</span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a><span class="co">-- Substitute a term</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a><span class="fu">trmSubst</span> <span class="ot">:</span> (tySub <span class="ot">:</span> <span class="dt">TySub</span> as bs) <span class="ot">-&gt;</span> (trmSub <span class="ot">:</span> <span class="dt">TrmSub</span> g tySub d)</span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>        <span class="ot">-&gt;</span> <span class="dt">Term</span> bs d <span class="ot">-&gt;</span> <span class="dt">Term</span> as g</span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>trmSubst tySub trmSub (<span class="dt">Var</span> a x)</span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a>  <span class="fu">=</span> lookupTerm trmSub x</span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a>trmSubst tySub trmSub (<span class="dt">Lam</span> a tya x)</span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a>  <span class="fu">=</span> <span class="dt">Lam</span> a (tySubst tySub tya) (trmSubst tySub (extTrm trmSub) x)</span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a>trmSubst tySub trmSub (<span class="dt">App</span> x y)</span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a>  <span class="fu">=</span> <span class="dt">App</span> (trmSubst tySub trmSub x) (trmSubst tySub trmSub y)</span>
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true" tabindex="-1"></a>trmSubst tySub trmSub (<span class="dt">In</span> ty trm)</span>
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true" tabindex="-1"></a>  <span class="fu">=</span> <span class="dt">In</span> (tySubst (extTy tySub) ty) (trmSubst tySub trmSub trm)</span>
<span id="cb14-18"><a href="#cb14-18" aria-hidden="true" tabindex="-1"></a>trmSubst tySub trmSub (<span class="dt">Out</span> ty trm)</span>
<span id="cb14-19"><a href="#cb14-19" aria-hidden="true" tabindex="-1"></a>  <span class="fu">=</span> <span class="dt">Out</span> (tySubst (extTy tySub) ty) (trmSubst tySub trmSub trm)</span>
<span id="cb14-20"><a href="#cb14-20" aria-hidden="true" tabindex="-1"></a>trmSubst tySub trmSub (<span class="dt">TLam</span> k trm)</span>
<span id="cb14-21"><a href="#cb14-21" aria-hidden="true" tabindex="-1"></a>  <span class="fu">=</span> <span class="dt">TLam</span> k <span class="fu">$</span> trmSubst (extTy tySub) (extTrmTy trmSub) trm</span>
<span id="cb14-22"><a href="#cb14-22" aria-hidden="true" tabindex="-1"></a>trmSubst tySub trmSub (<span class="dt">TApp</span> trm ty)</span>
<span id="cb14-23"><a href="#cb14-23" aria-hidden="true" tabindex="-1"></a>  <span class="fu">=</span> <span class="dt">TApp</span> (trmSubst tySub trmSub trm) (tySubst tySub ty)</span></code></pre></div>
<p>Let's work through these one by one.</p>
<p><code>Var</code> is unchanged beyond looking up the value in a more
complicated environment.</p>
<p><code>Lam</code> extends the term substitution just as in the simply
typed case, but now performs an additional type substitution on its type
annotation.</p>
<p><code>App</code> is the same as with the STLC.</p>
<p>Both <code>In</code> and <code>Out</code> involve a binder in the
datatype that we're taking the fixpoint over, so they require us to
perform an extension of the type substitution, but they substitute the
term itself as normal.</p>
<p><code>TLam</code> is the most interesting case because it binds a
type variable inside a term. This means that we need to extend the type
substitution, as well as extend the term substitution by a new
<em>type</em> variable. This is the reason why <code>TrmSub</code> has
the shape it does.</p>
<p><code>TApp</code> is not much more complicated than <code>App</code>,
except that one of the things it substitutes is a term and the other is
the type that we're applying to it.</p>
<p>Of note is the fact that term substitutions now have two extension
operations:</p>
<div class="sourceCode" id="cb15"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- extend the term substitution by a new term variable</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="fu">extTrm</span> <span class="ot">:</span> <span class="dt">TrmSub</span> g tySub d <span class="ot">-&gt;</span> <span class="dt">TrmSub</span> (a <span class="ot">::</span> g) tySub (a <span class="ot">::</span> d)</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- extend the term substitution by a new *type* variable</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a><span class="fu">extTrmTy</span> <span class="ot">:</span> <span class="dt">TrmSub</span> g tySub d <span class="ot">-&gt;</span> <span class="dt">TrmSub</span> (k <span class="ot">:::</span> g) (extTy tySub) (k <span class="ot">:::</span> d)</span></code></pre></div>
<p><code>extTrm</code> leaves the type substitution alone, but
<code>extTrmTy</code> extends both the term substitution and the type
substitution that it's indexed by with the same variable</p>
<p>And just as before, in order to implement <code>extTrm</code> and
<code>extTrmTy</code> we would need to implement term renamings which
are indexed by type renamings. This is standard, and is included in all
of the earlier references.</p>
<h3 id="towards-substructural-polymorphism">Towards substructural
polymorphism</h3>
<p>At this point we have two generalisations of the simply typed lambda
calculus - one takes us into substructural types, the other into
polymorphism. It would be really nice if we could combine the two, and
define a substructural polymorphic language. Unfortunately though, it's
<em>extremely</em> not obvious how to do this.</p>
<p>The usual answer provided in the literature is to keep the type
contexts cartesian, and only make the term contexts linear. After all,
what does it even <em>mean</em> for a type context to be linear?</p>
<p>While this works on paper, this would make the implementation quite
cumbersome. What makes the implementation above as slick as it is, is
the fact that the inductive structure of type-indexed-terms closely
matches the inductive structure of the types indexing them. Letting
types have implicitly shared contexts while enforcing a linear
discipline on terms would not work so well (or at all?). And moreover,
if one of the reasons for working substructurally is to avoid the
expensive renaming operation, it would be a job-half-done if we
eliminated term renamings while keeping renamings of types.</p>
<p>So while it's true that it doesn't quite make sense to talk about
"linear type contexts", we could still talk about 'explicitly cartesian
contexts', ie. Co-de-Bruijn-style contexts which allow copying and
deleting of type variables so long as that's done explicitly, rather
than implicitly through context-sharing.</p>
<p>But this still begs the question - what should the right definition
of a polymorphic substructural lambda calculus even be?</p>
<p>Defining polymorphic covers would not be such a big deal - working by
analogy with the other polymorphic operations, we can guess that a cover
that handles term contexts will be indexed by a cover for type
contexts.</p>
<p>But where things break down is when we need to define linear term
substitutions, ie. this data-type:</p>
<div class="sourceCode" id="cb16"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">LinTrmSub</span> <span class="ot">:</span> (g <span class="ot">:</span> <span class="dt">IxList</span> <span class="dt">String</span> as) <span class="ot">-&gt;</span> (sub <span class="ot">:</span> <span class="dt">LinTySub</span> as bs)</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>              <span class="ot">-&gt;</span> (d <span class="ot">:</span> <span class="dt">IxList</span> <span class="dt">String</span> bs) <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span></code></pre></div>
<p>I have attempted this a few times now, but each time I reached a
dead-end.</p>
<p>Jules suspects that this is because monoidal fibrations are much less
obvious to work with than cartesian fibrations, but I have not figured
out how to translate the extra data needed in the definition of a
monoidal fibration into code.</p>
<p>So this is the problem that we're currently facing, and I'd be
interested if anyone has some ideas here.</p>
<p>In the meantime, the blog series will explore the things that we
<em>do</em> know how to do well. In the next few posts I'll show you how
to work with covers more generally, how to define scope-checkers and
type-checkers for substructural languages, and how to put all the pieces
together into a full compiler pipeline using <a
href="https://cybercat.institute/2025/01/13/program-pipelines.idr/">Andre
Videla's library for dependent compiler pipelines</a>.</p>]]></content>
  </entry>
  <entry>
      <title>Well-Typed Substructural Languages</title>
      <link href="https://zanzix.github.io/posts/4-substructural.html"/>
      <id>https://zanzix.github.io/posts/4-substructural.html</id>
      <updated>2024-08-26T00:00:00Z</updated>
      <summary>Implementing well-typed by construction substructural languages</summary>
      <content type="html"><![CDATA[<p>Guest post by <a href="https://julesh.com/">Jules Hedges</a></p>
<p>In this post I'll explain how to build well-typed by construction
implementations of substructural languages, that is, languages in which
our ability to delete, copy and/or swap variables in scope is
restricted. I will begin by recounting the folklore that I learned from
Conor Mc Bride and Zanzi, and then I will explain a useful trick that I
invented: terms that are parametrised by an action of a category of
context morphisms.</p>
<p>Personally, my main interest in this topic comes from my plans to
implement a bidirectional programming language in which all programs are
<a href="https://arxiv.org/abs/1703.10857">optics</a>, so they can be
run in both a forwards mode and a backwards mode. Due to the subtle
categorical structure of optics, such a programming language is
substructural in a very unique and complicated way. I have found in
practice that actions of context morphisms help a lot to make this
problem tractable. I'll be continuing to document my development of this
language on the <a href="https://cybercat.institute/">CyberCat Institute
blog</a>.</p>
<p>We begin with a tiny language for types, with monoidal products (a
neutral name because later we will be making it behave like different
kinds of product), a unit type to be the neutral element of the monoidal
product, and a "ground" type that is intended to contain some nontrivial
values.</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">Ty</span> <span class="op">:</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Unit</span> <span class="op">:</span> <span class="dt">Ty</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Ground</span> <span class="op">:</span> <span class="dt">Ty</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Tensor</span> <span class="op">:</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span></span></code></pre></div>
<h2 id="cartesian-terms">Cartesian terms</h2>
<p>Although we have used the name "tensor", suppose we want to make an
ordinary cartesian language where variables can be implicitly copied and
discarded. Here is a standard way to do it: it is an intuitionistic
natural deduction calculus.</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">Term</span> <span class="op">:</span> <span class="dt">List</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- A variable is a term if we can point to it in scope</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Var</span> <span class="op">:</span> <span class="dt">Elem</span> x xs <span class="ot">-&gt;</span> <span class="dt">Term</span> xs x</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Unit is always a term in every scope</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">UnitIntro</span> <span class="op">:</span> <span class="dt">Term</span> xs <span class="dt">Unit</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Pattern matching on Unit, redunant here but kept for comparison to later</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">UnitElim</span> <span class="op">:</span> <span class="dt">Term</span> xs <span class="dt">Unit</span> <span class="ot">-&gt;</span> <span class="dt">Term</span> xs x <span class="ot">-&gt;</span> <span class="dt">Term</span> xs x</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- A pair is a term if each side is a term</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">TensorIntro</span> <span class="op">:</span> <span class="dt">Term</span> xs x <span class="ot">-&gt;</span> <span class="dt">Term</span> xs y <span class="ot">-&gt;</span> <span class="dt">Term</span> xs (<span class="dt">Tensor</span> x y)</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Pattern matching on a pair, adding both sides to the scope</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>  <span class="dt">TensorElim</span> <span class="op">:</span> <span class="dt">Term</span> xs (<span class="dt">Tensor</span> x y) <span class="ot">-&gt;</span> <span class="dt">Term</span> (<span class="ot">x :: y ::</span> xs) z <span class="ot">-&gt;</span> <span class="dt">Term</span> xs z</span></code></pre></div>
<p>The constructor for <code>Var</code> uses <code>Elem</code>, a
standard library type that defines pointers into a list:</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">data</span> <span class="dt">Elem</span> <span class="op">:</span> a <span class="ot">-&gt;</span> <span class="dt">List</span> a <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Here</span> <span class="op">:</span> <span class="dt">Elem</span> x (<span class="ot">x ::</span> xs)</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">There</span> <span class="op">:</span> <span class="dt">Elem</span> x xs <span class="ot">-&gt;</span> <span class="dt">Elem</span> x (<span class="ot">x&#39; ::</span> xs)</span></code></pre></div>
<p>Here are some examples of programs we can write in this language:</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="co">-- \x =&gt; ()</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>delete <span class="op">:</span> <span class="dt">CartesianTerm</span> [a] <span class="dt">Unit</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>delete <span class="ot">=</span> <span class="dt">UnitIntro</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="co">-- \(x, y) =&gt; x</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>prjl <span class="op">:</span> <span class="dt">CartesianTerm</span> [a, b] a</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>prjl <span class="ot">=</span> <span class="dt">Var</span> <span class="dt">Here</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a><span class="co">-- \(x, y) =&gt; y</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>prjr <span class="op">:</span> <span class="dt">CartesianTerm</span> [a, b] b</span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>prjr <span class="ot">=</span> <span class="dt">Var</span> (<span class="dt">There</span> <span class="dt">Here</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="co">-- \x =&gt; (x, x)</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>copy <span class="op">:</span> <span class="dt">CartesianTerm</span> [a] (<span class="dt">Tensor</span> a a)</span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>copy <span class="ot">=</span> <span class="dt">TensorIntro</span> (<span class="dt">Var</span> <span class="dt">Here</span>) (<span class="dt">Var</span> <span class="dt">Here</span>)</span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a><span class="co">-- \(x, y) =&gt; (y, x)</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>swap <span class="op">:</span> <span class="dt">CartesianTerm</span> [a, b] (<span class="dt">Tensor</span> b a)</span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a>swap <span class="ot">=</span> <span class="dt">TensorIntro</span> (<span class="dt">Var</span> (<span class="dt">There</span> <span class="dt">Here</span>)) (<span class="dt">Var</span> <span class="dt">Here</span>)</span></code></pre></div>
<p>The thing that makes this language cartesian and allows us to write
these 3 terms is the way that the context <code>xs</code> gets shared by
the inputs of the different term constructors. In the next section we
will define terms a different way, and then none of these examples will
typecheck.</p>
<h2 id="planar-terms">Planar terms</h2>
<p>Next let's go to the opposite extreme and build a fully substructural
language, in which we cannot delete or copy or swap. I learned how to do
this from Conor Mc Bride and Zanzi. Here is the idea:</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">data</span> <span class="dt">Term</span> <span class="op">:</span> <span class="dt">List</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</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="co">-- A variable is a term only if it is the only thing in scope</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Var</span> <span class="op">:</span> <span class="dt">Term</span> [x] x</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Unit is a term only in the empty scope</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">UnitIntro</span> <span class="op">:</span> <span class="dt">Term</span> [] <span class="dt">Unit</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Pattern matching on Unit consumes its scope</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">UnitElim</span> <span class="op">:</span> <span class="dt">Term</span> xs <span class="dt">Unit</span> <span class="ot">-&gt;</span> <span class="dt">Term</span> ys y <span class="ot">-&gt;</span> <span class="dt">Term</span> (xs <span class="op">++</span> ys) y</span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Constructing a pair consumes the scopes of both sides</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">TensorIntro</span> <span class="op">:</span> <span class="dt">Term</span> xs x <span class="ot">-&gt;</span> <span class="dt">Term</span> ys y <span class="ot">-&gt;</span> <span class="dt">Term</span> (xs <span class="op">++</span> ys) (<span class="dt">Tensor</span> x y)</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Pattern matching on a pair consumes its scope</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>  <span class="dt">TensorElim</span> <span class="op">:</span> <span class="dt">Term</span> xs (<span class="dt">Tensor</span> x y) <span class="ot">-&gt;</span> <span class="dt">Term</span> (<span class="ot">x :: y ::</span> ys) z <span class="ot">-&gt;</span> <span class="dt">Term</span> (xs <span class="op">++</span> ys) z</span></code></pre></div>
<p>This is a semantically correct definition of planar terms and it
would work if we had a sufficiently smart typechecker, but for the
current generation of dependent typecheckers we can't use this
definition because it suffers from what's called <em>green slime</em>.
The problem is that we have types containing terms that involve the
recursive function <code>++</code>, and the typechecker will get stuck
when this function tries to pattern match on a free variable. (I have no
idea how you learn this if you don't happen to drink in the same pubs as
Conor. Dependently typed programming has a catastrophic lack of books
that teach it.)</p>
<p>The fix is that we need to define a datatype that witnesses that the
concatenation of two lists is equal to a third list - a witness that the
composition of two things is equal to a third thing is called a
<em>simplex</em>. The key idea is that this datatype exactly reflects
the recursive structure of <code>++</code>, but as a relation rather
than a function:</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">data</span> <span class="dt">Simplex</span> <span class="op">:</span> <span class="dt">List</span> a <span class="ot">-&gt;</span> <span class="dt">List</span> a <span class="ot">-&gt;</span> <span class="dt">List</span> a <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Right</span> <span class="op">:</span> <span class="dt">Simplex</span> [] ys ys</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Left</span> <span class="op">:</span> <span class="dt">Simplex</span> xs ys zs <span class="ot">-&gt;</span> <span class="dt">Simplex</span> (<span class="ot">x ::</span> xs) ys (<span class="ot">x ::</span> zs)</span></code></pre></div>
<p>Now we can write a definition of planar terms that we can work
with:</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">data</span> <span class="dt">Term</span> <span class="op">:</span> <span class="dt">List</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Var</span> <span class="op">:</span> <span class="dt">Term</span> [x] x</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">UnitIntro</span> <span class="op">:</span> <span class="dt">Term</span> [] <span class="dt">Unit</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">UnitElim</span> <span class="op">:</span> <span class="dt">Simplex</span> xs ys zs </span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>          <span class="ot">-&gt;</span> <span class="dt">Term</span> xs <span class="dt">Unit</span> <span class="ot">-&gt;</span> <span class="dt">Term</span> ys y <span class="ot">-&gt;</span> <span class="dt">Term</span> zs y</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">TensorIntro</span> <span class="op">:</span> <span class="dt">Simplex</span> xs ys zs </span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>             <span class="ot">-&gt;</span> <span class="dt">Term</span> xs x <span class="ot">-&gt;</span> <span class="dt">Term</span> ys y <span class="ot">-&gt;</span> <span class="dt">Term</span> zs (<span class="dt">Tensor</span> x y)</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">TensorElim</span> <span class="op">:</span> <span class="dt">Simplex</span> xs ys zs </span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>            <span class="ot">-&gt;</span> <span class="dt">Term</span> xs (<span class="dt">Tensor</span> x y) <span class="ot">-&gt;</span> <span class="dt">Term</span> (<span class="ot">x :: y ::</span> ys) z <span class="ot">-&gt;</span> <span class="dt">Term</span> zs z</span></code></pre></div>
<p>This language is so restricted that it's hard to show it doing
anything, but here is one example of a term we can write:</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">-- \(x, y) =&gt; (x, y)</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>foo <span class="op">:</span> <span class="dt">Term</span> [a, b] (<span class="dt">Tensor</span> a b)</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>foo <span class="ot">=</span> <span class="dt">TensorIntro</span> (<span class="dt">Left</span> <span class="dt">Right</span>) <span class="dt">Var</span> <span class="dt">Var</span></span></code></pre></div>
<p>Manually defining simplicies, which cut a context into two halves, is
very good as a learning exercise but eventually gets irritating. We can
direct Idris to search for the simplex automatically:</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">Term</span> <span class="op">:</span> <span class="dt">List</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Var</span> <span class="op">:</span> <span class="dt">Term</span> [x] x</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">UnitIntro</span> <span class="op">:</span> <span class="dt">Term</span> [] <span class="dt">Unit</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">UnitElim</span> <span class="op">:</span> {auto prf <span class="op">:</span> <span class="dt">Simplex</span> xs ys zs} </span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>          <span class="ot">-&gt;</span> <span class="dt">Term</span> xs <span class="dt">Unit</span> <span class="ot">-&gt;</span> <span class="dt">Term</span> ys y <span class="ot">-&gt;</span> <span class="dt">Term</span> zs y</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">TensorIntro</span> <span class="op">:</span> {auto prf <span class="op">:</span> <span class="dt">Simplex</span> xs ys zs} </span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>             <span class="ot">-&gt;</span> <span class="dt">Term</span> xs x <span class="ot">-&gt;</span> <span class="dt">Term</span> ys y <span class="ot">-&gt;</span> <span class="dt">Term</span> zs (<span class="dt">Tensor</span> x y)</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">TensorElim</span> <span class="op">:</span> {auto prf <span class="op">:</span> <span class="dt">Simplex</span> xs ys zs} </span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>            <span class="ot">-&gt;</span> <span class="dt">Term</span> xs (<span class="dt">Tensor</span> x y) <span class="ot">-&gt;</span> <span class="dt">Term</span> (<span class="ot">x :: y ::</span> ys) z <span class="ot">-&gt;</span> <span class="dt">Term</span> zs z</span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>foo <span class="op">:</span> <span class="dt">Term</span> [a, b] (<span class="dt">Tensor</span> a b)</span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>foo <span class="ot">=</span> <span class="dt">TensorIntro</span> <span class="dt">Var</span> <span class="dt">Var</span></span></code></pre></div>
<p>This works, but I find that the proof search gets confused easily
(although it works fine for the baby examples in this post), so let's
pull out the big guns and write a tactic:</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">concat</span> <span class="op">:</span> (xs, ys <span class="op">:</span> <span class="dt">List</span> a) <span class="ot">-&gt;</span> (zs <span class="op">:</span> <span class="dt">List</span> a <span class="op">**</span> <span class="dt">Simplex</span> xs ys zs)</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="fu">concat</span> [] ys <span class="ot">=</span> (ys <span class="op">**</span> <span class="dt">Right</span>)</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="fu">concat</span> (<span class="ot">x ::</span> xs) ys <span class="ot">=</span> <span class="kw">let</span> (zs <span class="op">**</span> s) <span class="ot">=</span> <span class="fu">concat</span> xs ys <span class="kw">in</span> (<span class="ot">x ::</span> zs <span class="op">**</span> <span class="dt">Left</span> s)</span></code></pre></div>
<p>This function takes two lists and returns their concatenation
together with a simplex that witnesses this fact. Here <code>**</code>
is Idris syntax for both the type former and term former for dependent
pair (aka. Sigma) types.</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">Term</span> <span class="op">:</span> <span class="dt">List</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Var</span> <span class="op">:</span> <span class="dt">Term</span> [x] x</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">UnitIntro</span> <span class="op">:</span> <span class="dt">Term</span> [] <span class="dt">Unit</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">UnitElim</span> <span class="op">:</span> {xs, ys <span class="op">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} </span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>          <span class="ot">-&gt;</span> {default (<span class="fu">concat</span> xs ys) prf <span class="op">:</span> (zs <span class="op">:</span> <span class="dt">List</span> <span class="dt">Ty</span> <span class="op">**</span> <span class="dt">Simplex</span> xs ys zs)}</span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>          <span class="ot">-&gt;</span> <span class="dt">Term</span> xs <span class="dt">Unit</span> <span class="ot">-&gt;</span> <span class="dt">Term</span> ys y <span class="ot">-&gt;</span> <span class="dt">Term</span> prf<span class="op">.</span><span class="fu">fst</span> y</span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">TensorIntro</span> <span class="op">:</span> {xs, ys <span class="op">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} </span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>              <span class="ot">-&gt;</span> {default (<span class="fu">concat</span> xs ys) prf <span class="op">:</span> (zs <span class="op">:</span> <span class="dt">List</span> <span class="dt">Ty</span> <span class="op">**</span> <span class="dt">Simplex</span> xs ys zs)}</span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>              <span class="ot">-&gt;</span> <span class="dt">Term</span> xs x <span class="ot">-&gt;</span> <span class="dt">Term</span> ys y <span class="ot">-&gt;</span> <span class="dt">Term</span> prf<span class="op">.</span><span class="fu">fst</span> (<span class="dt">Tensor</span> x y)</span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">TensorElim</span> <span class="op">:</span> {xs, ys <span class="op">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} </span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>            <span class="ot">-&gt;</span> {default (<span class="fu">concat</span> xs ys) prf <span class="op">:</span> (zs <span class="op">:</span> <span class="dt">List</span> <span class="dt">Ty</span> <span class="op">**</span> <span class="dt">Simplex</span> xs ys zs)} </span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>            <span class="ot">-&gt;</span> <span class="dt">Term</span> xs (<span class="dt">Tensor</span> x y) <span class="ot">-&gt;</span> <span class="dt">Term</span> (<span class="ot">x :: y ::</span> ys) z <span class="ot">-&gt;</span> <span class="dt">Term</span> prf<span class="op">.</span><span class="fu">fst</span> z</span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a>foo <span class="op">:</span> {a, b <span class="op">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> [a, b] (<span class="dt">Tensor</span> a b)</span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a>foo <span class="ot">=</span> <span class="dt">TensorIntro</span> <span class="dt">Var</span> <span class="dt">Var</span></span></code></pre></div>
<p>I find Idris' <code>default</code> syntax to be a bit awkward, but it
feels to me like a potentially very powerful tool, and something I wish
Haskell had for scripting instance search.</p>
<h2 id="context-morphisms">Context morphisms</h2>
<p>Unfortunately, going from a planar language to a linear one - that
is, ruling out copy and delete but allowing swaps - is much harder. I
figured out a technique for doing this that turns out to be very
powerful and give very fine control over the scoping rules of a
language.</p>
<p>The idea is to isolate a category of context morphisms (technically a
coloured <a href="https://ncatlab.org/nlab/show/PRO">pro</a>, that is a
strict monoidal category whose monoid of objects is free). Then we will
parametrise a planar language by an action of this category. The good
news is that this is the final iteration of the definition of
<code>Term</code>, and we'll be working with it for the rest of this
blog post.</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="dt">Structure</span> <span class="op">:</span> <span class="dt">Type</span> <span class="ot">-&gt;</span> <span class="dt">Type</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Structure</span> a <span class="ot">=</span> <span class="dt">List</span> a <span class="ot">-&gt;</span> <span class="dt">List</span> a <span class="ot">-&gt;</span> <span class="dt">Type</span></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 class="kw">data</span> <span class="dt">Term</span> <span class="op">:</span> <span class="dt">Structure</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">List</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Var</span> <span class="op">:</span> <span class="dt">Term</span> hom [x] x</span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Act</span> <span class="op">:</span> hom xs ys <span class="ot">-&gt;</span> <span class="dt">Term</span> hom ys x <span class="ot">-&gt;</span> <span class="dt">Term</span> hom xs x</span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">UnitIntro</span> <span class="op">:</span> <span class="dt">Term</span> hom [] <span class="dt">Unit</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">UnitElim</span> <span class="op">:</span> {xs, ys <span class="op">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} </span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>          <span class="ot">-&gt;</span> {default (<span class="fu">concat</span> xs ys) prf <span class="op">:</span> (zs <span class="op">:</span> <span class="dt">List</span> <span class="dt">Ty</span> <span class="op">**</span> <span class="dt">Simplex</span> xs ys zs)}</span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>          <span class="ot">-&gt;</span> <span class="dt">Term</span> hom xs <span class="dt">Unit</span> <span class="ot">-&gt;</span> <span class="dt">Term</span> hom ys y <span class="ot">-&gt;</span> <span class="dt">Term</span> hom prf<span class="op">.</span><span class="fu">fst</span> y</span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>  <span class="dt">TensorIntro</span> <span class="op">:</span> {xs, ys <span class="op">:</span> <span class="dt">List</span> <span class="dt">Ty</span>}</span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a>             <span class="ot">-&gt;</span> {default (<span class="fu">concat</span> xs ys) prf <span class="op">:</span> (zs <span class="op">:</span> <span class="dt">List</span> <span class="dt">Ty</span> <span class="op">**</span> <span class="dt">Simplex</span> xs ys zs)}</span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a>             <span class="ot">-&gt;</span> <span class="dt">Term</span> hom xs x <span class="ot">-&gt;</span> <span class="dt">Term</span> hom ys y <span class="ot">-&gt;</span> <span class="dt">Term</span> hom prf<span class="op">.</span><span class="fu">fst</span> (<span class="dt">Tensor</span> x y)</span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a>  <span class="dt">TensorElim</span> <span class="op">:</span> {xs, ys <span class="op">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} </span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a>            <span class="ot">-&gt;</span> {default (<span class="fu">concat</span> xs ys) prf <span class="op">:</span> (zs <span class="op">:</span> <span class="dt">List</span> <span class="dt">Ty</span> <span class="op">**</span> <span class="dt">Simplex</span> xs ys zs)} </span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a>            <span class="ot">-&gt;</span> <span class="dt">Term</span> hom xs (<span class="dt">Tensor</span> x y) <span class="ot">-&gt;</span> <span class="dt">Term</span> hom (<span class="ot">x :: y ::</span> ys) z </span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a>            <span class="ot">-&gt;</span> <span class="dt">Term</span> hom prf<span class="op">.</span><span class="fu">fst</span> z</span></code></pre></div>
<p>First, let's recover planar terms. To do this, we want to define a
<code>Structure</code> where <code>hom xs ys</code> is a proof that
<code>xs = ys</code>:</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">data</span> <span class="dt">Planar</span> <span class="op">:</span> <span class="dt">Structure</span> a <span class="kw">where</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Empty</span> <span class="op">:</span> <span class="dt">Planar</span> [] []</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Whisker</span> <span class="op">:</span> <span class="dt">Planar</span> xs ys <span class="ot">-&gt;</span> <span class="dt">Planar</span> (<span class="ot">x ::</span> xs) (<span class="ot">x ::</span> ys)</span></code></pre></div>
<p>Now let's deal with linear terms. For that, we want to define a
<code>Structure</code> where <code>hom xs ys</code> is a proof that
<code>ys</code> is a permutation of <code>xs</code>. We can do this in
two steps:</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="co">-- Insertion x xs ys is a witness that ys consists of xs with x inserted somewhere</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Insertion</span> <span class="op">:</span> a <span class="ot">-&gt;</span> <span class="dt">List</span> a <span class="ot">-&gt;</span> <span class="dt">List</span> a <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- The insertion is at the head of the list</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Here</span> <span class="op">:</span> <span class="dt">Insertion</span> x xs (<span class="ot">x ::</span> xs)</span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- The insertion is somewhere in the tail of the list</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">There</span> <span class="op">:</span> <span class="dt">Insertion</span> x xs ys <span class="ot">-&gt;</span> <span class="dt">Insertion</span> x (<span class="ot">y ::</span> xs) (<span class="ot">y ::</span> ys)</span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Symmetric</span> <span class="op">:</span> <span class="dt">Structure</span> a <span class="kw">where</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- The empty list has a unique permutation to itself</span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Empty</span> <span class="op">:</span> <span class="dt">Symmetric</span> [] []</span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Extend a permutation by inserting the head element into the permuted tail</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Insert</span> <span class="op">:</span> <span class="dt">Insertion</span> x ys zs <span class="ot">-&gt;</span> <span class="dt">Symmetric</span> xs ys <span class="ot">-&gt;</span> <span class="dt">Symmetric</span> (<span class="ot">x ::</span> xs) zs</span></code></pre></div>
<p>(Incidentally, this is the point where I realised that although Idris
<em>looks</em> like Haskell, programming in it feels a lot closer to
programming in Prolog.)</p>
<p>Now we write swap as term:</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>swap <span class="op">:</span> {a, b <span class="op">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> <span class="dt">Symmetric</span> [a, b] (<span class="dt">Tensor</span> b a)</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>swap <span class="ot">=</span> <span class="dt">Act</span> (<span class="dt">Insert</span> (<span class="dt">There</span> <span class="dt">Here</span>) (<span class="dt">Insert</span> <span class="dt">Here</span> <span class="dt">Empty</span>)) (<span class="dt">TensorIntro</span> <span class="dt">Var</span> <span class="dt">Var</span>)</span></code></pre></div>
<h2 id="explicitly-cartesian-terms">Explicitly cartesian terms</h2>
<p>Now we can come full circle and redefine cartesian terms in a way
that uniformly matches the way we do substructural terms.</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="kw">data</span> <span class="dt">Cartesian</span> <span class="op">:</span> <span class="dt">Structure</span> a <span class="kw">where</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Delete everything in scope</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Delete</span> <span class="op">:</span> <span class="dt">Cartesian</span> xs []</span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Point to a variable in scope and make a copy on top</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Copy</span> <span class="op">:</span> <span class="dt">Elem</span> y xs <span class="ot">-&gt;</span> <span class="dt">Cartesian</span> xs ys <span class="ot">-&gt;</span> <span class="dt">Cartesian</span> xs (<span class="ot">y ::</span> ys)</span></code></pre></div>
<p>With this, we can rewrite all the terms we started with:</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>delete <span class="op">:</span> {a <span class="op">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> <span class="dt">Cartesian</span> [a] <span class="dt">Unit</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>delete <span class="ot">=</span> <span class="dt">Act</span> <span class="dt">Delete</span> <span class="dt">UnitIntro</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>prjl <span class="op">:</span> {a, b <span class="op">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> <span class="dt">Cartesian</span> [a, b] a</span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>prjl <span class="ot">=</span> <span class="dt">Act</span> (<span class="dt">Copy</span> <span class="dt">Here</span> <span class="dt">Delete</span>) <span class="dt">Var</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>prjr <span class="op">:</span> {a, b <span class="op">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> <span class="dt">Cartesian</span> [a, b] b</span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>prjr <span class="ot">=</span> <span class="dt">Act</span> (<span class="dt">Copy</span> (<span class="dt">There</span> <span class="dt">Here</span>) <span class="dt">Delete</span>) <span class="dt">Var</span></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a>copy <span class="op">:</span> {a <span class="op">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> <span class="dt">Cartesian</span> [a] (<span class="dt">Tensor</span> a a)</span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a>copy <span class="ot">=</span> <span class="dt">Act</span> (<span class="dt">Copy</span> <span class="dt">Here</span> (<span class="dt">Copy</span> <span class="dt">Here</span> <span class="dt">Delete</span>)) (<span class="dt">TensorIntro</span> <span class="dt">Var</span> <span class="dt">Var</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>swap <span class="op">:</span> {a, b <span class="op">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> <span class="dt">Cartesian</span> [a, b] (<span class="dt">Tensor</span> b a)</span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a>swap <span class="ot">=</span> <span class="dt">Act</span> (<span class="dt">Copy</span> (<span class="dt">There</span> <span class="dt">Here</span>) (<span class="dt">Copy</span> <span class="dt">Here</span> <span class="dt">Delete</span>)) (<span class="dt">TensorIntro</span> <span class="dt">Var</span> <span class="dt">Var</span>)</span></code></pre></div>
<p>Let's end with a party trick. What would a <em>cocartesian</em>
language look like - one where we can't delete or copy, but we can spawn
and merge?</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><span class="dt">Co</span> <span class="op">:</span> <span class="dt">Structure</span> a <span class="ot">-&gt;</span> <span class="dt">Structure</span> a</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Co</span> hom xs ys <span class="ot">=</span> hom ys xs</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- spawn : Void -&gt; a</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a><span class="co">-- spawn = \case {}</span></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>spawn <span class="op">:</span> {a <span class="op">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> (<span class="dt">Co</span> <span class="dt">Cartesian</span>) [] a</span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a>spawn <span class="ot">=</span> <span class="dt">Act</span> <span class="dt">Delete</span> <span class="dt">Var</span></span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a><span class="co">-- merge : Either a a -&gt; a</span></span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a><span class="co">-- merge = \case {Left x =&gt; x; Right x =&gt; x}</span></span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>merge <span class="op">:</span> {a <span class="op">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> (<span class="dt">Co</span> <span class="dt">Cartesian</span>) [a, a] a</span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a>merge <span class="ot">=</span> <span class="dt">Act</span> (<span class="dt">Copy</span> <span class="dt">Here</span> (<span class="dt">Copy</span> <span class="dt">Here</span> <span class="dt">Delete</span>)) <span class="dt">Var</span></span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a><span class="co">-- injl : a -&gt; Either a b</span></span>
<span id="cb18-15"><a href="#cb18-15" aria-hidden="true" tabindex="-1"></a><span class="co">-- injl = \x =&gt; Left x</span></span>
<span id="cb18-16"><a href="#cb18-16" aria-hidden="true" tabindex="-1"></a>injl <span class="op">:</span> {a, b <span class="op">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> (<span class="dt">Co</span> <span class="dt">Cartesian</span>) [a] (<span class="dt">Tensor</span> a b)</span>
<span id="cb18-17"><a href="#cb18-17" aria-hidden="true" tabindex="-1"></a>injl <span class="ot">=</span> <span class="dt">Act</span> (<span class="dt">Copy</span> <span class="dt">Here</span> <span class="dt">Delete</span>) (<span class="dt">TensorIntro</span> <span class="dt">Var</span> <span class="dt">Var</span>)</span>
<span id="cb18-18"><a href="#cb18-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-19"><a href="#cb18-19" aria-hidden="true" tabindex="-1"></a><span class="co">-- injr : b -&gt; Either a b</span></span>
<span id="cb18-20"><a href="#cb18-20" aria-hidden="true" tabindex="-1"></a><span class="co">-- injr = \y =&gt; Right y</span></span>
<span id="cb18-21"><a href="#cb18-21" aria-hidden="true" tabindex="-1"></a>injr <span class="op">:</span> {a, b <span class="op">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> (<span class="dt">Co</span> <span class="dt">Cartesian</span>) [b] (<span class="dt">Tensor</span> a b)</span>
<span id="cb18-22"><a href="#cb18-22" aria-hidden="true" tabindex="-1"></a>injr <span class="ot">=</span> <span class="dt">Act</span> (<span class="dt">Copy</span> (<span class="dt">There</span> <span class="dt">Here</span>) <span class="dt">Delete</span>) (<span class="dt">TensorIntro</span> <span class="dt">Var</span> <span class="dt">Var</span>)</span></code></pre></div>
<p>Since at the very beginning we added a single generating type
<code>Ground</code>, and the category generated by one object and finite
coproducts is finite sets and functions, this language can define
exactly the functions between finite sets. For example, there are
exactly 4 functions from booleans to booleans:</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="fu">id</span>, false, true, <span class="fu">not</span> <span class="op">:</span> <span class="dt">Term</span> (<span class="dt">Co</span> <span class="dt">Cartesian</span>) [<span class="dt">Ground</span>, <span class="dt">Ground</span>] (<span class="dt">Tensor</span> <span class="dt">Ground</span> <span class="dt">Ground</span>)</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="fu">id</span> <span class="ot">=</span> <span class="dt">Act</span> (<span class="dt">Copy</span> <span class="dt">Here</span> (<span class="dt">Copy</span> (<span class="dt">There</span> <span class="dt">Here</span>) <span class="dt">Delete</span>)) (<span class="dt">TensorIntro</span> <span class="dt">Var</span> <span class="dt">Var</span>)</span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>false <span class="ot">=</span> <span class="dt">Act</span> (<span class="dt">Copy</span> <span class="dt">Here</span> (<span class="dt">Copy</span> <span class="dt">Here</span> <span class="dt">Delete</span>)) (<span class="dt">TensorIntro</span> <span class="dt">Var</span> <span class="dt">Var</span>)</span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>true <span class="ot">=</span> <span class="dt">Act</span> (<span class="dt">Copy</span> (<span class="dt">There</span> <span class="dt">Here</span>) (<span class="dt">Copy</span> (<span class="dt">There</span> <span class="dt">Here</span>) <span class="dt">Delete</span>)) (<span class="dt">TensorIntro</span> <span class="dt">Var</span> <span class="dt">Var</span>)</span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a><span class="fu">not</span> <span class="ot">=</span> <span class="dt">Act</span> (<span class="dt">Copy</span> (<span class="dt">There</span> <span class="dt">Here</span>) (<span class="dt">Copy</span> <span class="dt">Here</span> <span class="dt">Delete</span>)) (<span class="dt">TensorIntro</span> <span class="dt">Var</span> <span class="dt">Var</span>)</span></code></pre></div>
<p>That's enough for today, but next time I will continue using this
style of term language to start dealing with the difficult issues of
building a programming language for optics.</p>]]></content>
  </entry>
  <entry>
      <title>Introduction to Recursion Schemes with Idris</title>
      <link href="https://zanzix.github.io/posts/3-rec-idris.html"/>
      <id>https://zanzix.github.io/posts/3-rec-idris.html</id>
      <updated>2024-04-04T00:00:00Z</updated>
      <summary>Refactoring Algebraic Datatypes with Recursion Schemes</summary>
      <content type="html"><![CDATA[<h2 id="fixpoints-over-functors">Fixpoints over Functors</h2>
<p>In the previous two blog posts we've looked at a <a
href="https://zanzix.github.io/posts/1-bcc.html">combinator language for
categories</a>, as well as a <a
href="https://zanzix.github.io/posts/2-stlc-idris.html">data type for
simply typed lambda terms</a>. We've also had a look at translating from
one to the other. Both blog posts assumed quite a bit of background
knowledge, so our goal today will be to start at the very beginning and
introduce recursion schemes step by step.</p>
<h2 id="semirings">Semirings</h2>
<p>To start, let's look at how we'd normally implement a datatype for
semirings, along with an evaluator for it, and then see how we can
generalise it using recursion schemes.</p>
<p>First, we'll add a constructor for each operation.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> <span class="dt">Simple</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">data</span> <span class="dt">Semiring</span> <span class="ot">:</span> <span class="dt">Type</span> <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Val</span> <span class="ot">:</span> value <span class="ot">-&gt;</span> <span class="dt">Semiring</span> value</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="dt">One</span> <span class="ot">:</span> <span class="dt">Semiring</span> value</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Zero</span> <span class="ot">:</span> <span class="dt">Semiring</span> value</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Mult</span> <span class="ot">:</span> <span class="dt">Semiring</span> value <span class="ot">-&gt;</span> <span class="dt">Semiring</span> value <span class="ot">-&gt;</span> <span class="dt">Semiring</span> value</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Add</span> <span class="ot">:</span> <span class="dt">Semiring</span> value <span class="ot">-&gt;</span> <span class="dt">Semiring</span> value <span class="ot">-&gt;</span> <span class="dt">Semiring</span> value</span></code></pre></div>
<p>Now we would like to implement an evaluator for each of the
constructors of the semiring.</p>
<p>Following the Haskell tradition of writing folds, it would look
something like this:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>  <span class="fu">eval</span> <span class="ot">:</span> (add <span class="ot">:</span> a <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> a) <span class="ot">-&gt;</span> (mult <span class="ot">:</span> a <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> a)</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>      <span class="ot">-&gt;</span> (zero <span class="ot">:</span> a) <span class="ot">-&gt;</span> (one <span class="ot">:</span> a) <span class="ot">-&gt;</span> <span class="dt">Semiring</span> a <span class="ot">-&gt;</span> a</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  eval <span class="fu">_</span> <span class="fu">_</span> <span class="fu">_</span> <span class="fu">_</span> (<span class="dt">Val</span> v) <span class="fu">=</span> v</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>  eval <span class="fu">_</span> <span class="fu">_</span> <span class="fu">_</span> one <span class="dt">One</span> <span class="fu">=</span> one</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>  eval <span class="fu">_</span> <span class="fu">_</span> zero <span class="fu">_</span> <span class="dt">Zero</span> <span class="fu">=</span> zero</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>  eval add mult zero one (<span class="dt">Mult</span> x y) <span class="fu">=</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    mult (eval add mult zero one x) (eval add mult zero one y)</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>  eval add mult zero one (<span class="dt">Add</span> x y) <span class="fu">=</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>    add (eval add mult zero one x) (eval add mult zero one y)</span></code></pre></div>
<p>This function, <a
href="https://www.cs.nott.ac.uk/~pszgmh/fold.pdf">known as a fold</a>,
is capable of expressing any interpreter that consumes this data type.
However, while folds are interesting theoretically, the function itself
is fairly boilerplate - all it's doing is matching constructors of the
datatype to individual functions that consume them.</p>
<p>Since we're going to be writing a lot of datatypes, we want to avoid
writing an individual evaluator for each of them - we'd rather get them
for free. If we had macros in our language, we could use them for this.
But we don't need macros where we're going, as we've got category
theory.</p>
<p>The starting idea is that the same way that we bundle up our
constructors into a single datatype, we can bundle up our consumers
together as well.</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>  <span class="kw">record</span> <span class="dt">SemiringAlgebra</span> (a <span class="ot">:</span> <span class="dt">Type</span>) <span class="kw">where</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="fu">add</span> <span class="ot">:</span> a <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> a</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    <span class="fu">mult</span> <span class="ot">:</span> a <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> a</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    <span class="fu">zero</span> <span class="ot">:</span> a</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    <span class="fu">one</span> <span class="ot">:</span> a</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="co">-- if we uncurry we can see that these are all just morphisms of a category</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">record</span> <span class="dt">SemiringAlgebra&#39;</span> (a <span class="ot">:</span> <span class="dt">Type</span>) <span class="kw">where</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>    <span class="fu">add</span> <span class="ot">:</span> (a, a) <span class="ot">-&gt;</span> a</span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>    <span class="fu">mult</span> <span class="ot">:</span> (a, a) <span class="ot">-&gt;</span> a</span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>    <span class="fu">zero</span> <span class="ot">:</span> () <span class="ot">-&gt;</span> a</span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>    <span class="fu">one</span> <span class="ot">:</span> () <span class="ot">-&gt;</span> a</span></code></pre></div>
<p>Using SemiringAlgebra we can get a slightly cleaner looking
evaluator:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>  <span class="fu">eval&#39;</span> <span class="ot">:</span> <span class="dt">SemiringAlgebra</span> a <span class="ot">-&gt;</span> <span class="dt">Semiring</span> a <span class="ot">-&gt;</span> a</span></code></pre></div>
<p>But it would involve the same amount of boilerplate as before.</p>
<p>The problem is that we are essentially declaring each concept twice -
once as a constructor, and once as a function consuming it. What we
would like is to do declare it once, and derive the rest from that
single declaration.</p>
<p>Now, Semiring has the type <code>Type -&gt; Type</code>, and so does
SemiringAlgebra. So we want something of the type
<code>(Type -&gt; Type) -&gt; (Type -&gt; Type)</code>. This turns out
to be fairly straightforward:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Algebra</span> <span class="ot">:</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="ot">-&gt;</span> <span class="dt">Type</span>)</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Algebra</span> f a <span class="fu">=</span> f a <span class="ot">-&gt;</span> a</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="dt">SemiringAlgebra&#39;</span> <span class="ot">:</span> <span class="dt">Type</span> <span class="ot">-&gt;</span> <span class="dt">Type</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="dt">SemiringAlgebra&#39;</span> a <span class="fu">=</span> <span class="dt">Algebra</span> <span class="dt">Semiring</span> a</span></code></pre></div>
<p>But how would we use such a thing? Naively, it seems that our
evaluator has now become trivial:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="fu">evalNope</span> <span class="ot">:</span> <span class="dt">Algebra</span> <span class="dt">Semiring</span> a <span class="ot">-&gt;</span> <span class="dt">Semiring</span> a <span class="ot">-&gt;</span> a</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>evalNope alg s <span class="fu">=</span> alg s</span></code></pre></div>
<p>This type checks, however it does not do anything interesting, it
merely applies the function that we've supplied to it, and we still need
to define that function manually. What we really want is for this
function to be derived for us from smaller pieces.</p>
<p>To resolve this, we notice that our original SemiringAlgebra record
does not actually tell us how to tear down a full semiring. All it does
is tell us how to tear down each individual layer. So let's start by
describing these layers as a data type.</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">SemiringLayer</span> <span class="ot">:</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="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Val</span> <span class="ot">:</span> value <span class="ot">-&gt;</span> <span class="dt">SemiringLayer</span> value expression</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">One</span> <span class="ot">:</span> <span class="dt">SemiringLayer</span> value expression</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Zero</span> <span class="ot">:</span> <span class="dt">SemiringLayer</span> value expression</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Mult</span> <span class="ot">:</span> expression <span class="ot">-&gt;</span> expression <span class="ot">-&gt;</span> <span class="dt">SemiringLayer</span> value expression</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Add</span> <span class="ot">:</span> expression <span class="ot">-&gt;</span> expression <span class="ot">-&gt;</span> <span class="dt">SemiringLayer</span> value expression</span></code></pre></div>
<p>The structure of this datatype is very similar to our original
Semiring. But whereas Semiring was inductive - we defined complex
expressions in terms of simpler ones - our new SemiringLayer only
defines the contents of a <em>single</em> layer. And rather than being
parametrised by a single type of values <code>Type -&gt; Type</code>, we
now take two parameters <code>Type -&gt; Type -&gt; Type</code>: one for
values, and one for complex expressions.</p>
<p>The result is that our ideal evaluator would now look like this:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="fu">evalAlg</span> <span class="ot">:</span> <span class="dt">Algebra</span> (<span class="dt">SemiringLayer</span> val) val <span class="ot">-&gt;</span> <span class="dt">Algebra</span> <span class="dt">Semiring</span> val</span></code></pre></div>
<p>In other words, we lift an algebra over a layer of a semiring to an
algebra over the entire semiring. The final piece of the puzzle is that
we would like to derive <code>Semiring</code> from
<code>SemiringLayer</code>, rather than defining them separately.</p>
<p>We do this by using a type-level fixpoint that operates on
datatypes.</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Fix</span> <span class="ot">:</span> (layer <span class="ot">:</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="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">In</span> <span class="ot">:</span> {layer <span class="ot">:</span> <span class="dt">Type</span> <span class="ot">-&gt;</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> layer (<span class="dt">Fix</span> layer) <span class="ot">-&gt;</span> <span class="dt">Fix</span> layer</span></code></pre></div>
<p>It is not unlike a standard fixpoint operator that works on
functions:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">partial</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="fu">fix</span> <span class="ot">:</span> (a <span class="ot">-&gt;</span> a) <span class="ot">-&gt;</span> a</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>fix f <span class="fu">=</span> f (fix f)</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="co">-- Don&#39;t try this at home:</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a><span class="co">-- SemiringBoom : Type -&gt; Type</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="co">-- SemiringBoom value = fix (SemiringLayer value)</span></span></code></pre></div>
<p>Using <code>Fix</code>, we can now define <code>Semiring</code>
inductively in terms of <code>SemiringLayer</code> - each time that
<code>SemiringLayer</code> expects an expression, <code>Fix</code> will
fill that in with <code>Fix SemiringLayer</code> as a subexpression:</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Semiring</span> <span class="ot">:</span> <span class="dt">Type</span> <span class="ot">-&gt;</span> <span class="dt">Type</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Semiring</span> value <span class="fu">=</span> <span class="dt">Fix</span> (<span class="dt">SemiringLayer</span> value)</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- example expression</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a><span class="fu">ex1</span> <span class="ot">:</span> <span class="dt">Semiring</span> <span class="dt">Nat</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>ex1 <span class="fu">=</span> <span class="dt">In</span> (<span class="dt">Mult</span> (<span class="dt">In</span> <span class="dt">One</span>) (<span class="dt">In</span> <span class="fu">$</span> <span class="dt">Val</span> <span class="dv">2</span>))</span></code></pre></div>
<p>The small downside is that we now have <code>In</code> around our
code, however this can be avoided using smart constructors.</p>
<p>Now we can finally define our evaluator uniformly without mentioning
any individual constructor:</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- We&#39;ll need a functor constraint for what&#39;s to come:</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Functor</span> (<span class="dt">SemiringLayer</span> a) <span class="kw">where</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>  map f (<span class="dt">Val</span> x) <span class="fu">=</span> <span class="dt">Val</span> x</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>  map f <span class="dt">One</span> <span class="fu">=</span> <span class="dt">One</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>  map f <span class="dt">Zero</span> <span class="fu">=</span> <span class="dt">Zero</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>  map f (<span class="dt">Mult</span> x y) <span class="fu">=</span> <span class="dt">Mult</span> (f x) (f y)</span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>  map f (<span class="dt">Add</span> x y) <span class="fu">=</span> <span class="dt">Add</span> (f x) (f y)</span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a><span class="co">-- Lift an algebra of a semiring layer to a semiring</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a><span class="fu">eval</span> <span class="ot">:</span> <span class="dt">Algebra</span> (<span class="dt">SemiringLayer</span> val) a <span class="ot">-&gt;</span> <span class="dt">Fix</span> (<span class="dt">SemiringLayer</span> val) <span class="ot">-&gt;</span> a</span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>eval alg (<span class="dt">In</span> op) <span class="fu">=</span> alg (map (eval alg) op)</span></code></pre></div>
<p>And since our <code>eval</code> makes no reference to the
constructors of <code>Semiring</code>, this means that we can generalise
it to an arbitrary functor.</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Mission accomplished.</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="fu">cata</span> <span class="ot">:</span> <span class="dt">Functor</span> f <span class="ot">=&gt;</span> <span class="dt">Algebra</span> f a <span class="ot">-&gt;</span> <span class="dt">Fix</span> f <span class="ot">-&gt;</span> a</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>cata alg (<span class="dt">In</span> op) <span class="fu">=</span> alg (map (cata alg) op)</span></code></pre></div>
<p>We can now apply our <code>cata</code> to arbitrary datatypes (with
some restrictions, that we will talk about later in the blog), and
provided that we give them a functor constraint.</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">ListLayer</span> <span class="ot">:</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="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Nil</span> <span class="ot">:</span> <span class="dt">ListLayer</span> val expr</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Cons</span> <span class="ot">:</span> val <span class="ot">-&gt;</span> expr <span class="ot">-&gt;</span> <span class="dt">ListLayer</span> val expr</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a><span class="dt">Functor</span> (<span class="dt">ListLayer</span> a) <span class="kw">where</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>  map f [] <span class="fu">=</span> []</span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>  map f (<span class="dt">Cons</span> x y) <span class="fu">=</span> <span class="dt">Cons</span> x (f y)</span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a><span class="dt">List</span> <span class="ot">:</span> <span class="dt">Type</span> <span class="ot">-&gt;</span> <span class="dt">Type</span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a><span class="dt">List</span> a <span class="fu">=</span> <span class="dt">Fix</span> (<span class="dt">ListLayer</span> a)</span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a><span class="co">-- we get the evaluator for free!</span></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a><span class="fu">foldr</span> <span class="ot">:</span> <span class="dt">Algebra</span> (<span class="dt">ListLayer</span> a) a <span class="ot">-&gt;</span> <span class="dt">Fix</span> (<span class="dt">ListLayer</span> a) <span class="ot">-&gt;</span> a</span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a>foldr <span class="fu">=</span> cata</span></code></pre></div>
<p>It's worth tracing out what exactly happens when we use
<code>eval</code> - the gist of it is that there are two things that we
need to do: use <code>map</code> to go under an <code>f</code> to turn
<code>f (Fix f)</code> into <code>f a</code>, and then use
<code>alg</code> to turn an <code>f a</code> into <code>a</code>.</p>
<p>We can split <code>cata</code> into two mutually-inductive functions,
each of which is responsible for one of these steps. As a bonus, this
makes it structurally recursive over Fix f.</p>
<div class="sourceCode" id="cb15"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">mutual</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- take a layer of `f a` to an `a`</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>  <span class="fu">fold</span> <span class="ot">:</span> <span class="dt">Functor</span> f <span class="ot">=&gt;</span> (f a <span class="ot">-&gt;</span> a) <span class="ot">-&gt;</span> <span class="dt">Fix</span> f <span class="ot">-&gt;</span> a</span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>  fold alg (<span class="dt">In</span> x) <span class="fu">=</span> alg (mapFold alg x)</span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- go underneath an f to turn Fix f to a</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>  <span class="fu">mapFold</span> <span class="ot">:</span> <span class="dt">Functor</span> f <span class="ot">=&gt;</span> (f a <span class="ot">-&gt;</span> a) <span class="ot">-&gt;</span> f (<span class="dt">Fix</span> f) <span class="ot">-&gt;</span> f a</span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>  mapFold alg op <span class="fu">=</span> map (fold alg) op</span></code></pre></div>
<p>It can get tedious writing all these functor constraints after a
while. If we had macros, we could automate this, but once again we can
get away without macros with the help of category theory - using what is
known as the Coyoneda trick.</p>
<h2 id="the-coyoneda-trick">The Coyoneda Trick</h2>
<p>A lot has been written about the Yoneda lemma, and its dual cousin,
Coyoneda. Personally, I find that it's one of those concepts that you
don't so much "understand" as "get used to". And the best way to get
used to something is to use it, which - luckily for us - we'll have
plenty of opportunity to do.</p>
<p>The datatype representing Coyoneda is simple, it is a pair of a value
inside of a functor, and a function that will map this value.
Essentially, it is nothing more than a suspended map operation:</p>
<div class="sourceCode" id="cb16"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Coyoneda</span> <span class="ot">:</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="ot">-&gt;</span> <span class="dt">Type</span>  <span class="kw">where</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Map</span> <span class="ot">:</span> {<span class="dv">0</span> a <span class="ot">:</span> <span class="fu">_</span>} <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> f a <span class="ot">-&gt;</span> <span class="dt">Coyoneda</span> f b</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- map :             (a -&gt; b) -&gt; f a -&gt;          f b</span></span></code></pre></div>
<p>In other words, Coyoneda is to functors as SemiringLayer is to
semirings - it's a data type that holds the contents of a functorial
map, the same way that SemiringLayer holds values of some semiring. Like
SemiringLayer, Coyoneda comes with its own notion of algebra, and we
will make this precise in a futre blog post.</p>
<div class="sourceCode" id="cb17"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- When `f` is a functor, we can tear down a layer of Coyoneda</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="fu">mapCoyo</span> <span class="ot">:</span> <span class="dt">Functor</span> f <span class="ot">=&gt;</span> <span class="dt">Coyoneda</span> f b <span class="ot">-&gt;</span> f b</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>mapCoyo (<span class="dt">Map</span> f fa) <span class="fu">=</span> map f fa</span></code></pre></div>
<p>Using this trick, we can modify our generic evaluator to no longer
need a functor constraint:</p>
<div class="sourceCode" id="cb18"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="fu">mcata</span> <span class="ot">:</span> <span class="dt">Algebra</span> (<span class="dt">Coyoneda</span> f) c <span class="ot">-&gt;</span> <span class="dt">Fix</span> f <span class="ot">-&gt;</span> c</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>mcata alg (<span class="dt">In</span> op) <span class="fu">=</span> alg (<span class="dt">Map</span> (mcata alg) op)</span></code></pre></div>
<p>The <code>m</code> in <code>mcata</code> stands for
<code>Mendler</code>, and <code>Algebra (Coyoneda f) a</code> is
commonly known as a <code>Mendler Algebra</code>.</p>
<div class="sourceCode" id="cb19"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="dt">MAlgebra</span> <span class="ot">:</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="ot">-&gt;</span> <span class="dt">Type</span>)</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="dt">MAlgebra</span> f a <span class="fu">=</span> <span class="dt">Algebra</span> (<span class="dt">Coyoneda</span> f) a</span></code></pre></div>
<p>Kmett wrote a <a
href="https://www.schoolofhaskell.com/user/edwardk/recursion-schemes/catamorphisms">great
post about catamorphisms and Mendler catamorphisms</a>, and it includes
how to go from <code>cata</code> to <code>mcata</code> and vice
versa.</p>
<h2 id="algebra-transformers">Algebra Transformers</h2>
<p>The downside of using Mendler-style recursion schemes is that our
algebras become a tad more involved. Compare the following:</p>
<div class="sourceCode" id="cb20"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- monoid of natural numbers, standard algebra style</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a><span class="fu">algPlus</span> <span class="ot">:</span> <span class="dt">Algebra</span> (<span class="dt">ListLayer</span> <span class="dt">Nat</span>) <span class="dt">Nat</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>algPlus [] <span class="fu">=</span> <span class="dv">0</span></span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>algPlus (<span class="dt">Cons</span> x y) <span class="fu">=</span> x <span class="fu">+</span> y</span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a><span class="co">-- monoid of natural numbers, Mendler style</span></span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a><span class="fu">malgPlus</span> <span class="ot">:</span> <span class="dt">MAlgebra</span> (<span class="dt">ListLayer</span> <span class="dt">Nat</span>) <span class="dt">Nat</span></span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a>malgPlus (<span class="dt">Map</span> f []) <span class="fu">=</span> <span class="dv">0</span></span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a>malgPlus (<span class="dt">Map</span> f (<span class="dt">Cons</span> x y)) <span class="fu">=</span> x <span class="fu">+</span> f y</span></code></pre></div>
<p>Whereas a normal algebra merely accesses the values of each
constructor, a Mendler algebra carries around an extra function that we
need to apply before accessing sub-expressions.</p>
<p>One way around this is to use algebra transformers, ie. a way to turn
a simple algebra into a more complex one. In this case, we can derive a
Mendler algebra from a standard one:</p>
<div class="sourceCode" id="cb21"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="fu">malgToAlg</span> <span class="ot">:</span> <span class="dt">Algebra</span> (<span class="dt">ListLayer</span> v) a <span class="ot">-&gt;</span> <span class="dt">MAlgebra</span> (<span class="dt">ListLayer</span> v) a</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>malgToAlg alg (<span class="dt">Map</span> f []) <span class="fu">=</span> alg []</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>malgToAlg alg (<span class="dt">Map</span> f (<span class="dt">Cons</span> x y)) <span class="fu">=</span> alg (<span class="dt">Cons</span> x (f y))</span></code></pre></div>
<p>We can now use standard algebras with <code>mcata</code>, as if they
were Mendler algebras:</p>
<div class="sourceCode" id="cb22"><pre
class="sourceCode idris"><code class="sourceCode idris"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="fu">listEval&#39;</span> <span class="ot">:</span> <span class="dt">Algebra</span> (<span class="dt">ListLayer</span> v) a <span class="ot">-&gt;</span> <span class="dt">Fix</span> (<span class="dt">ListLayer</span> v) <span class="ot">-&gt;</span> a</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>listEval&#39; alg <span class="fu">=</span> mcata (malgToAlg alg)</span></code></pre></div>
<p>What's interesting is that if we look at <code>malgToAlg</code>
closely, we'll see that it's nothing other than an inside out functor
interface for ListLayer. So in the end we did about the same amount of
work as before, but at least with Mendler algebras we could choose when
to do it, and we were not forced to write all of our interfaces up
front.</p>
<p>If we had macros at our disposal, we could actually derive malgToAlg
automatically. And... well, now I actually wish that I had macros at my
disposal here. (Or at least that I had a working knowledge of <a
href="https://github.com/stefan-hoeck/idris2-elab-util/blob/main/src/Doc/Index.md">elaborator
reflection</a>, which could accomplish the same thing).</p>
<p>At this point, we might wonder if going through Mendler algebras is
worth it if they are equally expressive to standard algebras. As we will
soon see, the answer is yes, as a small generalisation to Mendler
algebras - leading to what I call "Kan algebras" - will give us a vast
amount of expressive power that can capture many datatypes of interest
besides those representable as functors on sets.</p>
<p>But before we get to that, let us talk about monads.</p>]]></content>
  </entry>
  <entry>
      <title>From Lambda Calculus to Bicartesian Closed Categories</title>
      <link href="https://zanzix.github.io/posts/2-stlc-idris.html"/>
      <id>https://zanzix.github.io/posts/2-stlc-idris.html</id>
      <updated>2023-09-23T00:00:00Z</updated>
      <summary>Converting the simply typed lambda calculus into typed combinators</summary>
      <content type="html"><![CDATA[<h2 id="introduction">Introduction</h2>
<p>In the <a href="/posts/bcc">previous post</a> we've defined a typed
combinator language for bicartesian closed categories. In this post, we
will define the Simply Typed Lambda Calculus and translate it into our
combinator language.</p>
<p>The reason why we'd want to do this is that while combinators allow
us to work with the primitives of some categorical structure, they make
for a very austere programming language - one with no variables or
binding. So while it's possible to program entirely in combinators, we
would be limiting ourselves to writing point-free programs. Instead, we
will write our programs in the STLC and compile the code into
combinators.</p>
<p>But while the translation from lambda terms to closed cartesian
categories is standard, there is a slight impedance mismatch between
variable contexts and products that we will encounter again and again.
So in addition to showing the translation itself, the goal of this blog
post is to start introducing the idea of categories with a first-class
notion of context, aka multicategories.</p>
<h2 id="types">Types</h2>
<p>Just as before, we start by defining a type for our STLC types, as
well as infix type synonyms for each type constructor.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Ty</span> <span class="ot">:</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Unit</span> <span class="ot">:</span> <span class="dt">Ty</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Prod</span> <span class="ot">:</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Sum</span> <span class="ot">:</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Exp</span> <span class="ot">:</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">N</span> <span class="ot">:</span> <span class="dt">Ty</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="kw">infixr</span> <span class="dv">5</span> <span class="fu">~&gt;</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="fu">(~&gt;)</span> <span class="ot">:</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>(<span class="fu">~&gt;</span>) <span class="fu">=</span> <span class="dt">Exp</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="kw">infixr</span> <span class="dv">5</span> <span class="ot">:</span><span class="fu">*:</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="fu">(:*:)</span> <span class="ot">:</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>(<span class="ot">:</span><span class="fu">*:</span>) <span class="fu">=</span> <span class="dt">Prod</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a><span class="kw">infixr</span> <span class="dv">5</span> <span class="ot">:</span><span class="fu">+:</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="fu">(:+:)</span> <span class="ot">:</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>(<span class="ot">:</span><span class="fu">+:</span>) <span class="fu">=</span> <span class="dt">Sum</span></span></code></pre></div>
<p>As we can see, the types stay the same as before. In fact, looking at
the STLC and our <a href="/posts/bcc">combinator language</a> side by
side reveals that a lot of structure is carried over with little
modification.</p>
<p>Let's start by looking at the core language, and then add the rest of
the constructors.</p>
<h2 id="core-language">Core language</h2>
<div class="sourceCode" id="cb2"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Terms of the Simply Typed Lambda Calculus</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Term</span> <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Variables</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Var</span> <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> {a <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Elem</span> a g <span class="ot">-&gt;</span> <span class="dt">Term</span> g a</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Primitives</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Prim</span> <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> {a <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Prims</span> g a <span class="ot">-&gt;</span> <span class="dt">Term</span> g a</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Lambda abstraction</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Lam</span> <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> {a, b <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> (a<span class="ot">::</span>g) b <span class="ot">-&gt;</span> <span class="dt">Term</span> g (a <span class="fu">~&gt;</span> b)</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Lambda application</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">App</span> <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> {a, b <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> g (a <span class="fu">~&gt;</span> b) <span class="ot">-&gt;</span> <span class="dt">Term</span> g a <span class="ot">-&gt;</span> <span class="dt">Term</span> g b</span></code></pre></div>
<p>The first thing we notice is that our type signature has changed.
While combinators take a single input to a single output
<code>Ty -&gt; Ty -&gt; Type</code>, we are now working with a list of
inputs - aka our variable context - which is then taken to an output
<code>List Ty -&gt; Ty -&gt; Type</code>. Since we will use the latter
type a lot, we'll define a type synonym for it, and call it a
multigraph.</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Graph</span> <span class="ot">:</span> <span class="dt">Type</span> <span class="ot">-&gt;</span> <span class="dt">Type</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Graph</span> obj <span class="fu">=</span> obj <span class="ot">-&gt;</span> obj <span class="ot">-&gt;</span> <span class="dt">Type</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="dt">Multigraph</span> <span class="ot">:</span> <span class="dt">Type</span> <span class="ot">-&gt;</span> <span class="dt">Type</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="dt">Multigraph</span> obj <span class="fu">=</span> <span class="dt">List</span> obj <span class="ot">-&gt;</span> obj <span class="ot">-&gt;</span> <span class="dt">Type</span></span></code></pre></div>
<p>Since we now have a list of inputs as opposed to a single input, we
need some way of embedding variables into our variable context. This is
done using the <code>Var</code> constructor. It kind of looks like the
identity arrow from the combinator language if you squint, and indeed
the correspondence would become a lot more precise if we were working
with a linear lambda calculus:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Id</span>   <span class="ot">:</span> {a <span class="ot">:</span> <span class="dt">Ty</span>}                              <span class="ot">-&gt;</span> <span class="dt">Comb</span> <span class="fu">_</span> a  a</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="dt">LVar</span> <span class="ot">:</span> {a <span class="ot">:</span> <span class="dt">Ty</span>}                              <span class="ot">-&gt;</span> <span class="dt">Term</span>  [a] a</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="dt">Var</span>  <span class="ot">:</span> {a <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> {g <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Elem</span> a g <span class="ot">-&gt;</span> <span class="dt">Term</span>   g  a</span></code></pre></div>
<p>So <code>Id</code> takes a single input to a single output,
<code>Var</code> embeds a variable into a larger context, while
<code>LVar</code> embeds the variable into a singleton context. From
this we can see the difference between linear and cartesian variables -
cartesian variables can be projected out of a larger context, ignoring
the rest, while linear variables must be used without anything else
remaining.</p>
<p>Here <a
href="https://www.idris-lang.org/docs/idris2/current/base_docs/docs/Data.List.Elem.html">Elem</a>
is taken from the Idris standard library, it's kind of proof-relevant
membership relation, which guarantees that the variable <code>a</code>
will be inside of the larger context <code>g</code>.</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Elem</span> <span class="ot">:</span> a <span class="ot">-&gt;</span> <span class="dt">List</span> a <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="co">||| A proof that the element is at the head of the list</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Here</span> <span class="ot">:</span> <span class="dt">Elem</span> x (x <span class="ot">::</span> xs)</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">||| A proof that the element is in the tail of the list</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">There</span> <span class="ot">:</span> <span class="dt">Elem</span> x xs <span class="ot">-&gt;</span> <span class="dt">Elem</span> x (y <span class="ot">::</span> xs)</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="co">-- Find the variable corresponding to Elem t g, from an environment Env g</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a><span class="fu">lookup</span> <span class="ot">:</span> <span class="dt">Elem</span> t g <span class="ot">-&gt;</span> <span class="dt">Env</span> g <span class="ot">-&gt;</span> evalTy t</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>lookup <span class="dt">Here</span> (x <span class="ot">::</span><span class="fu">-</span> xs) <span class="fu">=</span> x</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>lookup (<span class="dt">There</span> t) (y <span class="ot">::</span><span class="fu">-</span> xs) <span class="fu">=</span> lookup t xs</span></code></pre></div>
<p>We can also see that lambda abstraction looks kind of like currying,
but flipped. If we were to work with Snoc-lists instead of Cons-lists
then we would see the correspondence between the two constructors a lot
clearer:</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Snoc List</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">SList</span> a <span class="fu">=</span> <span class="dt">Lin</span> <span class="fu">|</span> <span class="dt">Snoc</span> (<span class="dt">SList</span> a) a</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="kw">infixr</span> <span class="dv">5</span> <span class="fu">-:</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="fu">(-:)</span> <span class="ot">:</span> <span class="dt">SList</span> a <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> <span class="dt">SList</span> a</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>(<span class="fu">-:</span>) <span class="fu">=</span> <span class="dt">Snoc</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="dt">Lam</span>   <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">SList</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span>   (g  <span class="fu">-:</span> a) b <span class="ot">-&gt;</span> <span class="dt">Term</span>   g (a <span class="fu">~&gt;</span> b)</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a><span class="dt">Curry</span> <span class="ot">:</span> {c <span class="ot">:</span>       <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Comb</span> <span class="fu">_</span> (c <span class="ot">:</span><span class="fu">*:</span> a) b <span class="ot">-&gt;</span> <span class="dt">Comb</span> <span class="fu">_</span> c (a <span class="fu">~&gt;</span> b)</span></code></pre></div>
<p>We can see that the two line-up very closely, except that Curry takes
as an input a morphism from a tuple <code>(c :*: a)</code>, while Lam
takes as an input a term with the context <code>g -: a</code>. Lambda
abstraction then takes the free variable <code>a</code>, and binds it
inside the function <code>(a ~&gt; b)</code>. So in a way, a context is
just a convenient representation for an n-ary tuple.</p>
<p>Unfortunately, while the Snoc-list representation makes working with
lambda abstraction much easier, it will complicate working with the rest
of our binding operators, so we will not be using it in the full
language.</p>
<p>We've also split Apply into multiple terms. Whereas previously the
entire operation was expressed as a single combinator, we are now
defining it as a meta-operation on terms, each with their own
context:</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="dt">App</span>   <span class="ot">:</span> <span class="dt">Term</span>   g  (a <span class="fu">~&gt;</span> b) <span class="ot">-&gt;</span> <span class="dt">Term</span> g a <span class="ot">-&gt;</span> <span class="dt">Term</span> g b</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Apply</span> <span class="ot">:</span> <span class="dt">Comb</span> <span class="fu">_</span>   ((a <span class="fu">~&gt;</span> b) <span class="ot">:</span><span class="fu">*:</span>       a)          b</span></code></pre></div>
<p>This will be a recurring pattern in the translation, and many other
combinators will be split this way.</p>
<h2 id="primitives">Primitives</h2>
<p>We can also see that just as we've changed the type of our term
language to be a multigraph, we've done the same to our primitives
<code>Prims : List Ty -&gt; Ty -&gt; Type</code>. Similar to Lam, each
primitive will take a number of variables from the context and bind them
to a primitive expression.</p>
<p>Let's define some primitives. Just like before, we'd like to work
with the generators of a monoid. There are a few choices of
representation that we can take here, depending on how we want our
primitives to interact with the context.</p>
<p>The easiest thing to do would be to say that our generators take a
number of variables from some larger context, and leave the rest of the
context unchanged, implicitly discarding it. The unit of the monoid
takes no variables from the context <code>g</code>, and leaves the
entire thing unchanged, while the multiplication takes two variables
<code>N :: N :: g</code>, and leaves the rest.</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Primitives with &quot;cartesian&quot; contexts</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">CPrims</span> <span class="ot">:</span> <span class="dt">Multigraph</span> <span class="dt">Ty</span> <span class="kw">where</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">CZ</span> <span class="ot">:</span> <span class="dt">CPrims</span> g <span class="dt">N</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">CMult</span> <span class="ot">:</span> <span class="dt">CPrims</span> (<span class="dt">N</span> <span class="ot">::</span> <span class="dt">N</span> <span class="ot">::</span> g) <span class="dt">N</span></span></code></pre></div>
<p>This would be convenient to program with, since we could embed our
primitives inside terms with an arbitrary context.</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="fu">ex</span> <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> g (<span class="dt">N</span> <span class="fu">~&gt;</span> (<span class="dt">N</span> <span class="fu">~&gt;</span> <span class="dt">N</span>))</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>ex <span class="fu">=</span> <span class="dt">Lam</span> (<span class="dt">Lam</span> (<span class="dt">Prim</span> <span class="dt">CMult</span>))</span></code></pre></div>
<p>Unfortunately - as we will see below - this would make the
translation to combinators a lot more cumbersome. So instead, we will
use primitives with a more careful context discipline, only admitting
contexts with the exact number of variables that will be used.</p>
<p>So the monoid unit will require an empty context <code>[]</code>,
which is equivalent to a morphism from the unit object, and the monoid
multiplication will use a context with exactly two free variables, which
is equivalent to a morphism from a tuple. This will make the translation
to the set of primitives from the last post almost trivial. Almost.</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Primitives with &quot;linear&quot; contexts</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">LinPrims</span> <span class="ot">:</span> <span class="dt">Multigraph</span> <span class="dt">Ty</span> <span class="kw">where</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">LZ</span> <span class="ot">:</span> <span class="dt">LinPrims</span> [] <span class="dt">N</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">LMult</span> <span class="ot">:</span> <span class="dt">LinPrims</span> [<span class="dt">N</span>, <span class="dt">N</span>] <span class="dt">N</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a><span class="co">-- the context needs to be empty, or the expression won&#39;t type-check</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="fu">ex&#39;</span> <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> <span class="dt">Nil</span> (<span class="dt">N</span> <span class="fu">~&gt;</span> (<span class="dt">N</span> <span class="fu">~&gt;</span> <span class="dt">N</span>))</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>ex&#39; <span class="fu">=</span> <span class="dt">Lam</span> (<span class="dt">Lam</span> (<span class="dt">Prim</span> <span class="dt">LMult</span>))</span></code></pre></div>
<p>Alternatively, we could have defined our set of primitives within the
language itself:</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">STLC</span> <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- ... stlc constructors</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">E</span> <span class="ot">:</span> <span class="dt">STLC</span> g <span class="dt">N</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Mult</span> <span class="ot">:</span> <span class="dt">STLC</span> g <span class="dt">N</span> <span class="ot">-&gt;</span> <span class="dt">STLC</span> g <span class="dt">N</span> <span class="ot">-&gt;</span> <span class="dt">STLC</span> g <span class="dt">N</span></span></code></pre></div>
<p>But this would not maintain the clean separation between the
primitives and the terms built on top of them, like we did in our
combinator language.</p>
<p>Our presentation also gives us an insight into a more subtle
relationship between lambda terms and combinators - combinators are
defined over an underlying graph, while terms are defined over an
underlying multigraph.</p>
<h2 id="stlc-with-products-and-sums">STLC with Products and Sums</h2>
<p>Having looked at the core language, let's now turn our attention to
the full language:</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Term</span> <span class="ot">:</span> <span class="dt">Multigraph</span> <span class="dt">Ty</span> <span class="kw">where</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Variables</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Var</span> <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> {a <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Elem</span> a g <span class="ot">-&gt;</span> <span class="dt">Term</span> g a</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Primitives</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">LPrim</span> <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> {a <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">LPrims</span> g a <span class="ot">-&gt;</span> <span class="dt">Term</span> g a</span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Lambda abstraction: (a::g → b) → (g → (a ⇨ b))</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Lam</span> <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> {a, b <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> (a<span class="ot">::</span>g) b <span class="ot">-&gt;</span> <span class="dt">Term</span> g (a <span class="fu">~&gt;</span> b)</span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Lambda application: (g → (a ~&gt; b)) → (g → a) → (g → a)</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">App</span> <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> {a, b <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Term</span> g (a <span class="fu">~&gt;</span> b) <span class="ot">-&gt;</span> <span class="dt">Term</span> g a <span class="ot">-&gt;</span> <span class="dt">Term</span> g b</span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- First projection: (g → (a * b)) → (g → a)</span></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Fst</span> <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> {a, b <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> g (<span class="dt">Prod</span> a b) <span class="ot">-&gt;</span> <span class="dt">Term</span> g a</span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Second projection: (g → (a * b)) → (g → b)</span></span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Snd</span> <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> {a, b <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> g (<span class="dt">Prod</span> a b) <span class="ot">-&gt;</span> <span class="dt">Term</span> g b</span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Product introduction: (g → a) → (g → b) → (g → (a * b))</span></span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Pair</span> <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> {a, b <span class="ot">:</span> <span class="dt">Ty</span>}</span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> <span class="dt">Term</span> g a <span class="ot">-&gt;</span> <span class="dt">Term</span> g b <span class="ot">-&gt;</span> <span class="dt">Term</span> g (<span class="dt">Prod</span> a b)</span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Left injection: (g → a) → (g → a + b)</span></span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true" tabindex="-1"></a>  <span class="dt">InL</span> <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> {a, b <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> g a <span class="ot">-&gt;</span> <span class="dt">Term</span> g (<span class="dt">Sum</span> a b)</span>
<span id="cb12-20"><a href="#cb12-20" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Right injection: (g → b) → (g → a + b)</span></span>
<span id="cb12-21"><a href="#cb12-21" aria-hidden="true" tabindex="-1"></a>  <span class="dt">InR</span> <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> {a, b <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> g b <span class="ot">-&gt;</span> <span class="dt">Term</span> g (<span class="dt">Sum</span> a b)</span>
<span id="cb12-22"><a href="#cb12-22" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Case matching: (g → a + b) → (a::g → c) → (b::g → c) → (g → c)</span></span>
<span id="cb12-23"><a href="#cb12-23" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Case</span> <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> {a, b, c <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span></span>
<span id="cb12-24"><a href="#cb12-24" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Term</span> g (<span class="dt">Sum</span> a b) <span class="ot">-&gt;</span> <span class="dt">Term</span> (a<span class="ot">::</span>g) c <span class="ot">-&gt;</span> <span class="dt">Term</span> (b<span class="ot">::</span>g) c <span class="ot">-&gt;</span> <span class="dt">Term</span> g c</span>
<span id="cb12-25"><a href="#cb12-25" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Let binding: (g → s) → (s::g → t) → (g → t)</span></span>
<span id="cb12-26"><a href="#cb12-26" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Let</span> <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> {s <span class="ot">:</span> <span class="dt">Ty</span>}</span>
<span id="cb12-27"><a href="#cb12-27" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> <span class="dt">Term</span> g s <span class="ot">-&gt;</span> <span class="dt">Term</span> (s<span class="ot">::</span>g) t <span class="ot">-&gt;</span> <span class="dt">Term</span> g t</span></code></pre></div>
<p>We can see that just as with the core language, the new connectives
fall into two categories - they either interact with the context, such
as Case and Let, or they do not.</p>
<h2 id="let-is-all-you-need">Let is all you need</h2>
<p><code>Let</code> is often seen as redundant since it can be defined
using <code>Lam</code>, but doing so is only valid in a category with
exponentials. While this is obviously true in our full language, our
goal is to mix-and-match the syntax as needed. So keeping the Let
operator will allow us to retain the ability to bind variables even if
we move to a subset of the language without lambda abstraction.</p>
<p>In fact, if we look closely at the Let connective, we'll notice that
it's possible to work in a language with <em>nothing but</em> variables
and Let.</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Let</span>         <span class="ot">:</span> <span class="dt">Term</span>    g s <span class="ot">-&gt;</span> <span class="dt">Term</span>   (s <span class="ot">::</span> g) t <span class="ot">-&gt;</span> <span class="dt">Term</span>   g t</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>(flip <span class="dt">Comp</span>) <span class="ot">:</span> <span class="dt">Comb</span> <span class="fu">_</span>  c s <span class="ot">-&gt;</span> <span class="dt">Comb</span> <span class="fu">_</span>  s       t <span class="ot">-&gt;</span> <span class="dt">Comb</span> <span class="fu">_</span> c t</span></code></pre></div>
<p>So <code>Let</code> is nothing other than composition! Or to be more
precise, it's a notion of composition for morphisms that contain
variable contexts. We will call these 'multi-morphisms'. Meanwhile, the
constructor for linear variables <code>LVar</code> that we've seen
earlier is a notion of an identity arrow for multi-morphisms.</p>
<p>Taking this a step further, we can see a correspondence between a
free category on a graph, and a free "multicategory" on a
multigraph.</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Free category over a graph &#39;g&#39;.</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Cat</span> <span class="ot">:</span> {obj <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> <span class="dt">Graph</span> obj <span class="ot">-&gt;</span> <span class="dt">Graph</span> obj <span class="kw">where</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Id</span> <span class="ot">:</span> {a <span class="ot">:</span> obj} <span class="ot">-&gt;</span> <span class="dt">Cat</span> g a a</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Cons</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> obj} <span class="ot">-&gt;</span> g b c <span class="ot">-&gt;</span> <span class="dt">Cat</span> g a b <span class="ot">-&gt;</span> <span class="dt">Cat</span> g a c</span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a><span class="co">-- Free multicategory over the multigraph &#39;m&#39;.</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Multicat</span> <span class="ot">:</span> {obj <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> <span class="dt">Multigraph</span> obj <span class="ot">-&gt;</span> <span class="dt">Multigraph</span> obj <span class="kw">where</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">LVar</span> <span class="ot">:</span> {a <span class="ot">:</span> obj} <span class="ot">-&gt;</span> <span class="dt">Multicat</span> m [a] a</span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Let</span> <span class="ot">:</span> {ctx <span class="ot">:</span> <span class="dt">List</span> obj} <span class="ot">-&gt;</span> {s, t <span class="ot">:</span> obj} <span class="ot">-&gt;</span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>    m ctx s <span class="ot">-&gt;</span> <span class="dt">Multicat</span> m (s <span class="ot">::</span> ctx) t <span class="ot">-&gt;</span> <span class="dt">Multicat</span> m ctx t</span></code></pre></div>
<p>(Strictly speaking, this is a cartesian multicategory, since the
context 'ctx' is shared between terms).</p>
<p>But this is getting ahead of ourselves. We will talk about
multicategories - including non-cartesian ones - in much more detail
later, but for now let's get back to the lambda calculus.</p>
<h2 id="translation-into-idris">Translation into Idris</h2>
<p>Having defined our term language, let's start by translating it into
Idris' types and functions, after which we will do a more general
translation into combinators.</p>
<p>As always, we start by translating the types. This stays exactly as
in our last post:</p>
<div class="sourceCode" id="cb15"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="fu">evalTy</span> <span class="ot">:</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Type</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>evalTy <span class="dt">Unit</span> <span class="fu">=</span> <span class="dt">Unit</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>evalTy <span class="dt">N</span> <span class="fu">=</span> <span class="dt">Nat</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>evalTy (<span class="dt">Exp</span> t1 t2) <span class="fu">=</span> (evalTy t1) <span class="ot">-&gt;</span> (evalTy t2)</span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>evalTy (<span class="dt">Prod</span> t1 t2) <span class="fu">=</span> (evalTy t1, evalTy t2)</span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>evalTy (<span class="dt">Sum</span> t1 t2) <span class="fu">=</span> <span class="dt">Either</span> (evalTy t1) (evalTy t2)</span></code></pre></div>
<p>Next we would like to translate the primitives, however here we face
our first complication. Previously our evaluator converted a primitive
into a function from one input to one output:</p>
<div class="sourceCode" id="cb16"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="fu">evalPrims</span> <span class="ot">:</span> <span class="dt">Prims</span> ty1 ty2 <span class="ot">-&gt;</span> <span class="dt">Idr</span> (evalTy ty1) (evalTy ty2)</span></code></pre></div>
<p>Now we would like to define a function from multiple inputs to an
output:</p>
<div class="sourceCode" id="cb17"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="fu">evalPrims</span> <span class="ot">:</span> <span class="dt">Prims</span> g ty <span class="ot">-&gt;</span> (<span class="dt">Idr</span> (<span class="ot">?evalCtx</span> g) (evalTy t))</span></code></pre></div>
<p>How should we represent these multi-input functions? We can think of
n-ary functions as functions out of an environment, represented as a
heterogeneous list of values.</p>
<p>We will use the following representation of our environment. We can
think of it as a list of values <code>(evalTy t)</code> indexed by our
context <code>List Ty</code>.</p>
<div class="sourceCode" id="cb18"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Cons list, extends environment from the left</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="kw">infixr</span> <span class="dv">5</span> <span class="ot">::</span><span class="fu">-</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Env</span> <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">CNil</span>  <span class="ot">:</span> <span class="dt">Env</span> <span class="dt">Nil</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>  <span class="fu">(::-)</span> <span class="ot">:</span> evalTy t <span class="ot">-&gt;</span> <span class="dt">Env</span> g <span class="ot">-&gt;</span> <span class="dt">Env</span> (t <span class="ot">::</span> g)</span></code></pre></div>
<p>Contrast it to the definition of a list:</p>
<div class="sourceCode" id="cb19"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">List</span> <span class="ot">:</span> <span class="dt">Type</span> <span class="ot">-&gt;</span> <span class="dt">Type</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Nil</span> <span class="ot">:</span> <span class="dt">List</span> a</span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Cons</span> <span class="ot">:</span> t <span class="ot">-&gt;</span> <span class="dt">List</span> t <span class="ot">-&gt;</span> <span class="dt">List</span> t</span></code></pre></div>
<p>We can think of an environment as a kind of "heterogenous list of
values indexed by a list of types of those values".</p>
<p>We will instantiate our monoid as the monoid of natural numbers
<code>Nat</code>. Then our evaluator for primitives becomes as follows.
The monoidal unit does not interact with the environment, creating a 0
out of nothing. The monoidal multiplication pops two natural numbers
from the environment and adds them.</p>
<div class="sourceCode" id="cb20"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="fu">evalPrims</span> <span class="ot">:</span> <span class="dt">LPrims</span> g t <span class="ot">-&gt;</span> <span class="dt">Idr</span> (<span class="dt">Env</span> g) (evalTy t)</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>evalPrims <span class="dt">E</span> <span class="dt">CNil</span> <span class="fu">=</span> <span class="dv">0</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>evalPrims <span class="dt">Mult</span> (m1 <span class="ot">::</span><span class="fu">-</span> m2 <span class="ot">::</span><span class="fu">-</span> <span class="dt">CNil</span>) <span class="fu">=</span> m1 <span class="fu">+</span> m2</span></code></pre></div>
<p>Combining the above, we get our evaluator that takes terms to n-ary
Idris functions. If you compare it to our BCC evaluator from before,
then not a lot changes - the constructors that don't interact with the
context remain almost the same. The constructors that do interact with
the environment - Lam, Case, Let - all involve extending the environment
with a new variable, which then gets bound and used within the
expression.</p>
<div class="sourceCode" id="cb21"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="fu">eval</span> <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> g t <span class="ot">-&gt;</span> <span class="dt">Idr</span> (<span class="dt">Env</span> g) (evalTy t)</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">Var</span> v) env <span class="fu">=</span> lookup v env</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">LPrim</span> e) env <span class="fu">=</span> evalPrims e env</span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">Lam</span> t) env <span class="fu">=</span> <span class="fu">\</span>x <span class="ot">=&gt;</span> eval t (x <span class="ot">::</span><span class="fu">-</span> env)</span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">App</span> t1 t2) env <span class="fu">=</span> (eval t1 env) (eval t2 env)</span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">Pair</span> t1 t2) env <span class="fu">=</span> (eval t1 env, eval t2 env)</span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">Fst</span> t) env <span class="fu">=</span> fst (eval t env)</span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">Snd</span> t) env <span class="fu">=</span> snd (eval t env)</span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">Let</span> t c) env <span class="fu">=</span> eval c ((eval t env) <span class="ot">::</span><span class="fu">-</span> env)</span>
<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">InL</span> t) env <span class="fu">=</span> <span class="dt">Left</span> (eval t env)</span>
<span id="cb21-11"><a href="#cb21-11" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">InR</span> t) env <span class="fu">=</span> <span class="dt">Right</span> (eval t env)</span>
<span id="cb21-12"><a href="#cb21-12" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">Case</span> t1 t2 t3) env <span class="fu">=</span> <span class="kw">case</span> eval t1 env <span class="kw">of</span></span>
<span id="cb21-13"><a href="#cb21-13" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Left</span> l <span class="ot">=&gt;</span> eval t2 (l <span class="ot">::</span><span class="fu">-</span> env)</span>
<span id="cb21-14"><a href="#cb21-14" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Right</span> r <span class="ot">=&gt;</span> eval t3 (r <span class="ot">::</span><span class="fu">-</span> env)</span></code></pre></div>
<p>Finally, we would like to translate our lambda calculus into
bicartesian closed categories. Generalising from Idris functions, our
goal looks something like</p>
<div class="sourceCode" id="cb22"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="fu">eval</span> <span class="ot">:</span> (bcc <span class="ot">:</span> <span class="dt">BCC</span> g) <span class="ot">-&gt;</span> <span class="dt">Term</span> g ty <span class="ot">-&gt;</span> bcc (<span class="dt">Env</span> g) (evalTy t)</span></code></pre></div>
<p>However, our environment Env is defined for Idris types, so we would
need to generalise it. So what we'll do is interpret our context of
types into a product of types, with the empty list being represented by
the Unit type.</p>
<p>At first glance, we might want to simply fold over our context:</p>
<div class="sourceCode" id="cb23"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="fu">ctxF</span> <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>ctxF tys <span class="fu">=</span> foldr <span class="dt">Prod</span> <span class="dt">Unit</span> tys</span></code></pre></div>
<p>However, this would create awkward-looking types such as
<code>(Prod a (Prod b) Unit)</code>. So a more nicer alternative would
be to convert the empty List into Unit, but not use that as a base case,
and instead treat the embedding <code>[a]</code> of a type into a list
as the base case instead. This would give us nicer-looking types without
trailing units at the end.</p>
<div class="sourceCode" id="cb24"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="fu">ctxEv</span> <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>ctxEv <span class="dt">Nil</span> <span class="fu">=</span> <span class="dt">Unit</span></span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>ctxEv [t] <span class="fu">=</span> t</span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>ctxEv (t<span class="ot">::</span>ts) <span class="fu">=</span> <span class="dt">Prod</span> t (ctxEv ts)</span></code></pre></div>
<p>Using this evaluator, our translation between primitives would be
trivial.</p>
<div class="sourceCode" id="cb25"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Translating from LPrims to Typed.Prims</span></span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a><span class="fu">evalPrim</span> <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">LPrims</span> g t <span class="ot">-&gt;</span> <span class="dt">Prims</span> (ctxEv g) t</span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a>evalPrim <span class="dt">LZ</span> <span class="fu">=</span> <span class="dt">Typed</span><span class="fu">.</span><span class="dt">Z</span></span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a>evalPrim <span class="dt">LMult</span> <span class="fu">=</span> <span class="dt">Typed</span><span class="fu">.</span><span class="dt">Mult</span></span></code></pre></div>
<p>Unfortunately, using this much nicer evaluator would complicate type
unification immensely, and make the translation much harder to write. So
we will use the messier fold instead and just put up with trailing
units.</p>
<p>This means that while the monoidal unit translates correctly to
<code>Prims Unit N</code>, the monoidal multiplication becomes
<code>Prims (Pair N (Pair N Unit)) N</code>. We could fix this by using
the structural rules of the combinator language to rearrange the
expression and drop the trailing Unit, but this means that we need to
first embed our primitives into the combinator language, rather than
translating between two sets of primitives directly.</p>
<p>First, let's add some new structural rules to the combinator
language.</p>
<div class="sourceCode" id="cb26"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Syntactic sugar for composing arrows:</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a><span class="fu">(&gt;&gt;&gt;)</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Comb</span> k a b <span class="ot">-&gt;</span> <span class="dt">Comb</span> k b c <span class="ot">-&gt;</span> <span class="dt">Comb</span> k a c</span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a>(<span class="fu">&gt;&gt;&gt;</span>) f g <span class="fu">=</span> <span class="dt">Comp</span> g f</span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a><span class="co">-- | New Combinators</span></span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a><span class="co">-- Bifunctor for products</span></span>
<span id="cb26-8"><a href="#cb26-8" aria-hidden="true" tabindex="-1"></a><span class="dt">BifP</span> <span class="ot">:</span> {a, b, c, d <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span></span>
<span id="cb26-9"><a href="#cb26-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Comb</span> k a c <span class="ot">-&gt;</span> <span class="dt">Comb</span> k b d <span class="ot">-&gt;</span> <span class="dt">Comb</span> k (a <span class="ot">:</span><span class="fu">*:</span> b) (c <span class="ot">:</span><span class="fu">*:</span> d)</span>
<span id="cb26-10"><a href="#cb26-10" aria-hidden="true" tabindex="-1"></a><span class="co">-- Unit elimination</span></span>
<span id="cb26-11"><a href="#cb26-11" aria-hidden="true" tabindex="-1"></a><span class="dt">UnitL</span> <span class="ot">:</span> {a <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Comb</span> g (a <span class="ot">:</span><span class="fu">*:</span> <span class="dt">Unit</span>) a</span></code></pre></div>
<p>Now we can do the translation:</p>
<div class="sourceCode" id="cb27"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Won&#39;t work without embedding into Comb</span></span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a><span class="fu">evalPrim</span> <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">LPrims</span> g t <span class="ot">-&gt;</span> <span class="dt">Prims</span> (ctxF g) t</span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a>evalPrim <span class="dt">LZ</span> <span class="fu">=</span> <span class="dt">Typed</span><span class="fu">.</span><span class="dt">Z</span></span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a>evalPrim <span class="dt">LMult</span> <span class="fu">=</span> <span class="ot">?sadness</span></span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-6"><a href="#cb27-6" aria-hidden="true" tabindex="-1"></a><span class="co">-- Works</span></span>
<span id="cb27-7"><a href="#cb27-7" aria-hidden="true" tabindex="-1"></a><span class="fu">evalPrimF</span> <span class="ot">:</span> {ctx <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">LPrims</span> ctx t <span class="ot">-&gt;</span> <span class="dt">Comb</span> <span class="dt">Prims</span> (ctxF ctx) t</span>
<span id="cb27-8"><a href="#cb27-8" aria-hidden="true" tabindex="-1"></a>evalPrimF <span class="dt">LZ</span> <span class="fu">=</span> <span class="dt">Prim</span> <span class="dt">Typed</span><span class="fu">.</span><span class="dt">Z</span></span>
<span id="cb27-9"><a href="#cb27-9" aria-hidden="true" tabindex="-1"></a>evalPrimF <span class="dt">LMult</span> <span class="fu">=</span> <span class="dt">BifP</span> <span class="dt">Id</span> <span class="dt">UnitL</span> <span class="fu">&gt;&gt;&gt;</span> <span class="dt">Prim</span> <span class="dt">Typed</span><span class="fu">.</span><span class="dt">Mult</span></span></code></pre></div>
<p>Had we chosen to work with cartesian contexts instead, we would have
needed to deal with the trailing context of unused variables. The
monoidal unit would be <code>Prims (ctxF g) N</code>, with
multiplication <code>Prims (Pair N (Pair N (ctxF g)))</code>. This would
mean that for each primitive we'd have to zoom into the nested tuple and
drop the remaining context by composing it with the terminal morphism:
<code>Terminal : {a : Ty} -&gt; Comb k a Unit</code>.</p>
<div class="sourceCode" id="cb28"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Works, but messy</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a><span class="fu">evalPrim&#39;</span> <span class="ot">:</span> {ctx <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">CPrims</span> ctx t <span class="ot">-&gt;</span> <span class="dt">Comb</span> <span class="dt">Prims</span> (ctxF ctx) t</span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a>evalPrim&#39; <span class="dt">CZ</span> <span class="fu">=</span> <span class="dt">Terminal</span> <span class="fu">&gt;&gt;&gt;</span> <span class="dt">Prim</span> <span class="dt">Typed</span><span class="fu">.</span><span class="dt">Z</span></span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a>evalPrim&#39; <span class="dt">CMult</span> <span class="fu">=</span> <span class="dt">BifP</span> <span class="dt">Id</span> <span class="dt">Fst</span> <span class="fu">&gt;&gt;&gt;</span> <span class="dt">Prim</span> <span class="dt">Typed</span><span class="fu">.</span><span class="dt">Mult</span></span></code></pre></div>
<p>In addition to translating the primitives, we also want to translate
variables. When working with contexts, a variable is an index into an
environment, pointing at a specific value. When working with tuples, a
variable is translated into a sequence of projections from a nested
tuple.</p>
<div class="sourceCode" id="cb29"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="fu">var</span> <span class="ot">:</span> {g <span class="ot">:</span> <span class="dt">Graph</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> {ctx <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> {ty <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Elem</span> ty ctx <span class="ot">-&gt;</span> <span class="dt">Comb</span> g (ctxF ctx) ty</span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a>var <span class="dt">Here</span> <span class="fu">=</span> <span class="dt">Fst</span></span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a>var (<span class="dt">There</span> t) <span class="fu">=</span> <span class="dt">Comp</span> (var t) <span class="dt">Snd</span></span></code></pre></div>
<p>We're either taking the left-most component with Fst, or traversing
the nested tuple with a sequence of Snd's.</p>
<p>Finally, we get our evaluator from terms to combinators. Just like
earlier, the only constructors that require special care are the ones
that interact with the context. Usually these involve some manner of
re-arrangement of nested tuples using the structural rules of
bicartesian closed categories. For instance, had we used Snoc-lists, the
evaluator for <code>Lam</code> would be trivial, but instead we will
re-arrange the context a bit to make it work.</p>
<p>First, we'll go back to our combinator language and add a few more
structural combinators to make it work.</p>
<div class="sourceCode" id="cb30"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- | New Combinators</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- Distributivity of sums over products</span></span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a><span class="dt">Distrib</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Comb</span> k ((a <span class="ot">:</span><span class="fu">+:</span> b) <span class="ot">:</span><span class="fu">*:</span> c) ((a <span class="ot">:</span><span class="fu">*:</span> c) <span class="ot">:</span><span class="fu">+:</span> (b <span class="ot">:</span><span class="fu">*:</span> c))</span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a><span class="co">-- Bifunctor for sums</span></span>
<span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a><span class="dt">BifC</span> <span class="ot">:</span> {a, b, c, d <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span></span>
<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Comb</span> k a c <span class="ot">-&gt;</span> <span class="dt">Comb</span> k b d <span class="ot">-&gt;</span> <span class="dt">Comb</span> k (a <span class="ot">:</span><span class="fu">+:</span> b) (c <span class="ot">:</span><span class="fu">+:</span> d)</span>
<span id="cb30-8"><a href="#cb30-8" aria-hidden="true" tabindex="-1"></a><span class="co">-- Symmetry for products</span></span>
<span id="cb30-9"><a href="#cb30-9" aria-hidden="true" tabindex="-1"></a><span class="dt">SwapP</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Comb</span> k (a <span class="ot">:</span><span class="fu">*:</span> b) (b <span class="ot">:</span><span class="fu">*:</span> a)</span>
<span id="cb30-10"><a href="#cb30-10" aria-hidden="true" tabindex="-1"></a><span class="co">-- Symmetry for sums</span></span>
<span id="cb30-11"><a href="#cb30-11" aria-hidden="true" tabindex="-1"></a><span class="dt">SwapC</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Comb</span> k (a <span class="ot">:</span><span class="fu">+:</span> b) (b <span class="ot">:</span><span class="fu">+:</span> a)</span>
<span id="cb30-12"><a href="#cb30-12" aria-hidden="true" tabindex="-1"></a><span class="co">-- Unit elimination</span></span>
<span id="cb30-13"><a href="#cb30-13" aria-hidden="true" tabindex="-1"></a><span class="dt">UnitL</span> <span class="ot">:</span> {a <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Comb</span> g (a <span class="ot">:</span><span class="fu">*:</span> <span class="dt">Unit</span>) a</span>
<span id="cb30-14"><a href="#cb30-14" aria-hidden="true" tabindex="-1"></a><span class="co">-- Copy: (a → a * a)</span></span>
<span id="cb30-15"><a href="#cb30-15" aria-hidden="true" tabindex="-1"></a><span class="dt">Copy</span> <span class="ot">:</span> {a <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Comb</span> g a (a <span class="ot">:</span><span class="fu">*:</span> a)</span>
<span id="cb30-16"><a href="#cb30-16" aria-hidden="true" tabindex="-1"></a><span class="co">-- Cocopy: (a + a → a)</span></span>
<span id="cb30-17"><a href="#cb30-17" aria-hidden="true" tabindex="-1"></a><span class="dt">Cocopy</span> <span class="ot">:</span> {a <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Comb</span> b (a <span class="ot">:</span><span class="fu">+:</span> a) a</span></code></pre></div>
<p>Now we can do the translation itself. The most involved case is that
of case matching, which I had <a href="https://julesh.com/">Jules</a>
help me with. We have a morphism from the context into a sum, as well as
two morphisms out of a product of a variable and the context. We need to
combine them to get a morphism out of the context.</p>
<pre><code>m1 : g -&gt; a + b
m2 : (a * g) -&gt; ty
m3 : (b * g) -&gt; ty
----------------------
g -&gt; ty</code></pre>
<p>As an Idris expression, it would look like this:</p>
<div class="sourceCode" id="cb32"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="fu">match</span> <span class="ot">:</span> (g <span class="ot">-&gt;</span> <span class="dt">Either</span> a b) <span class="ot">-&gt;</span> ((a, g) <span class="ot">-&gt;</span> t) <span class="ot">-&gt;</span> ((b, g) <span class="ot">-&gt;</span> t) <span class="ot">-&gt;</span> g <span class="ot">-&gt;</span> t</span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>match m1 m2 m3 g <span class="fu">=</span> <span class="kw">case</span> m1 g <span class="kw">of</span></span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Left</span> a <span class="ot">=&gt;</span> m2 (a, g)</span>
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Right</span> b <span class="ot">=&gt;</span> m3 (b, g)</span></code></pre></div>
<p>Translating this into combinators, we will need the following
sequence of transformations:</p>
<div class="sourceCode" id="cb33"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- g -&gt; (g * g) -&gt; ((a + b) * g) ~= ((a * g) + (b * g)) -&gt; ty + ty -&gt; ty</span></span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a>sem (<span class="dt">Case</span> t1 t2 t3) <span class="fu">=</span> <span class="dt">Copy</span> <span class="fu">&gt;&gt;&gt;</span> <span class="dt">BifP</span> (sem t1) <span class="dt">Id</span> <span class="fu">&gt;&gt;&gt;</span></span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Distrib</span> <span class="fu">&gt;&gt;&gt;</span> <span class="dt">BifC</span> (sem t2) (sem t3) <span class="fu">&gt;&gt;&gt;</span> <span class="dt">Cocopy</span></span></code></pre></div>
<p>Putting it all together, our compiler to combinators becomes the
following:</p>
<div class="sourceCode" id="cb34"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Translation into combinators</span></span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a><span class="fu">sem</span> <span class="ot">:</span> {ctx <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> {ty <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Term</span> ctx ty <span class="ot">-&gt;</span> <span class="dt">Comb</span> <span class="dt">Prims</span> (ctxF ctx) ty</span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a>sem (<span class="dt">Var</span> v) <span class="fu">=</span> var v</span>
<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a>sem (<span class="dt">LPrim</span> e) <span class="fu">=</span> evalPrimF e</span>
<span id="cb34-5"><a href="#cb34-5" aria-hidden="true" tabindex="-1"></a>sem (<span class="dt">Pair</span> t1 t2) <span class="fu">=</span> <span class="dt">ProdI</span> (sem t1) (sem t2)</span>
<span id="cb34-6"><a href="#cb34-6" aria-hidden="true" tabindex="-1"></a>sem (<span class="dt">Snd</span> t) <span class="fu">=</span> sem t <span class="fu">&gt;&gt;&gt;</span> <span class="dt">Snd</span></span>
<span id="cb34-7"><a href="#cb34-7" aria-hidden="true" tabindex="-1"></a>sem (<span class="dt">Fst</span> t) <span class="fu">=</span> sem t <span class="fu">&gt;&gt;&gt;</span> <span class="dt">Fst</span></span>
<span id="cb34-8"><a href="#cb34-8" aria-hidden="true" tabindex="-1"></a>sem (<span class="dt">Lam</span> t) <span class="fu">=</span> <span class="kw">let</span> x <span class="fu">=</span> sem t <span class="kw">in</span> (<span class="dt">Curry</span> (<span class="dt">SwapP</span> <span class="fu">&gt;&gt;&gt;</span> x))</span>
<span id="cb34-9"><a href="#cb34-9" aria-hidden="true" tabindex="-1"></a>sem (<span class="dt">App</span> t1 t2) <span class="fu">=</span> (<span class="dt">ProdI</span> (sem t1) (sem t2)) <span class="fu">&gt;&gt;&gt;</span> <span class="dt">Apply</span></span>
<span id="cb34-10"><a href="#cb34-10" aria-hidden="true" tabindex="-1"></a>sem (<span class="dt">Let</span> t c) <span class="fu">=</span> <span class="kw">let</span> evc <span class="fu">=</span> sem (<span class="dt">Lam</span> c)</span>
<span id="cb34-11"><a href="#cb34-11" aria-hidden="true" tabindex="-1"></a>                    evt <span class="fu">=</span> sem t <span class="kw">in</span></span>
<span id="cb34-12"><a href="#cb34-12" aria-hidden="true" tabindex="-1"></a>                      <span class="dt">ProdI</span> evc evt <span class="fu">&gt;&gt;&gt;</span> <span class="dt">Apply</span></span>
<span id="cb34-13"><a href="#cb34-13" aria-hidden="true" tabindex="-1"></a>sem (<span class="dt">InL</span> t) <span class="fu">=</span> sem t <span class="fu">&gt;&gt;&gt;</span> <span class="dt">InL</span></span>
<span id="cb34-14"><a href="#cb34-14" aria-hidden="true" tabindex="-1"></a>sem (<span class="dt">InR</span> t) <span class="fu">=</span> sem t <span class="fu">&gt;&gt;&gt;</span> <span class="dt">InR</span></span>
<span id="cb34-15"><a href="#cb34-15" aria-hidden="true" tabindex="-1"></a>sem (<span class="dt">Case</span> t1 t2 t3) <span class="fu">=</span> <span class="dt">Copy</span> <span class="fu">&gt;&gt;&gt;</span> <span class="dt">BifP</span> (sem t1) <span class="dt">Id</span> <span class="fu">&gt;&gt;&gt;</span></span>
<span id="cb34-16"><a href="#cb34-16" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Distrib</span> <span class="fu">&gt;&gt;&gt;</span> <span class="dt">BifC</span> (sem t2) (sem t3) <span class="fu">&gt;&gt;&gt;</span> <span class="dt">Cocopy</span></span></code></pre></div>
<p>Composing this with the semantic interpreter from combinators to
BCCs, we get:</p>
<div class="sourceCode" id="cb35"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a><span class="fu">interp</span> <span class="ot">:</span> {ctx <span class="ot">:</span> <span class="dt">List</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> {ty <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span></span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a>  (b <span class="ot">:</span> <span class="dt">BCC</span> g) <span class="ot">-&gt;</span> <span class="dt">Term</span> ctx ty <span class="ot">-&gt;</span> g (b<span class="fu">.</span>ty (ctxToProd ctx)) (b<span class="fu">.</span>ty ty)</span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a>interp b t <span class="fu">=</span> eval&#39; b (sem t)</span></code></pre></div>
<h2 id="conclusion">Conclusion</h2>
<p>We have formulated a translation from the STLC into an arbitrary BCC.
This was <em>mostly</em> painless, except for when it came to
translating constructors that involve context manipulation. Even writing
this blog post has fallen to the <del>80:20</del> <del>90:10</del> 95:5
rule, with the majority of the code being straightforward except for the
parts involving shuffling variables and binders.</p>
<p>It's worth reflecting on <em>why</em> this is so difficult.
Categories don't have a first-class notion of variable context or
binding operations, so when we're translating from a calculus that does,
we need some way of turning binders and variables into morphisms. Doing
so, however, makes our semantics more awkward and verbose, and can lead
to an explosion of code size.</p>
<p>But what if there was another way? What if instead of translating
into categorical combinators, we had a way of giving a semantics for the
lambda calculus directly in terms of multicategories? Rather than
dealing with the impedance mismatch between contexts and products, our
semantics would be a homomorphism on the context, preserving its
structure.</p>
<p>This is what we will look at in the next few blog posts, and what
will become one of the main themes of the series. And if the idea of
working with multicategories sounds daunting, then don't worry, the next
blog post will start at the very beginning - with fixpoints of functors
and free monads.</p>]]></content>
  </entry>
  <entry>
      <title>Lambda Calculus and Bicartesian Closed Categories</title>
      <link href="https://zanzix.github.io/posts/1-bcc.html"/>
      <id>https://zanzix.github.io/posts/1-bcc.html</id>
      <updated>2023-08-25T00:00:00Z</updated>
      <summary>Defining a typed combinator syntax, and compile it to an arbitrary
Bicartesian Closed Category</summary>
      <content type="html"><![CDATA[<h2 id="into-the-bibby-zone">Into the Bibby Zone</h2>
<p>As I've recently announced on Twitter, I'm starting a new blog series
at the intersection of type theory, category theory, and functional
programming.</p>
<p>The correspondence between lambda calculus and bicartesian closed
categories is well known, and functional programmers have been using it
to great extent. What is less widely known is how to extend this
correspondence beyond just lambda calculi. In other words:</p>
<ul>
<li>Given an arbitrary DSL, how can we begin thinking about its
categorical semantics?</li>
<li>Given a category-theoretic structure, how can we give it a practical
programming syntax?</li>
</ul>
<p>Our approach to this will be entirely algebraic (for a very general
notion of 'algebraic'). We will represent our syntax using an inductive
type, our semantics as an algebra over the type, and our interpreter as
a fold connecting the two.</p>
<p>This approach is remarkably scalable. We will see how categories,
multicategories, bicategories, and double categories can be all be
represented as (indexed) functors over an appropriately chosen category.
Using tools from recursion schemes, this will give us generic evaluators
for a very wide range of structures.</p>
<p>On the language side, we will start with combinators and build up to
simply typed, polymorphic, and dependently-typed languages. At each step
we will implement an interpreter between the language syntax and its
categorical semantics.</p>
<p>We will use Idris2 as our language, but write our code in a style
accessible to Haskell programmers. (Most of the code in the first part
of the series should be translatable to Haskell too.)</p>
<h2 id="a-free-category-over-idris-types">A free category over Idris
types</h2>
<p>To start, let's retrace some familiar ground and look at a typed
combinator language for bicartesian closed categories. We will interpret
our combinator language into an arbitrary BCC, then show how to
translate from the simply typed lambda calculus into combinators in the
next blog post.</p>
<p>These first two blog posts are meant as a high level introduction to
the basic tools and methodology that we'll be using through the series,
and we will revisit these ideas step-by-step in subsequent posts.</p>
<p>You can find the full code for this post <a
href="https://github.com/zanzix/zanzix.github.io/tree/main/site/code">here</a>.</p>
<p>We'll start with a <a
href="https://hackage.haskell.org/package/free-category-0.0.1.0/docs/Control-Category-Free.html">typical
representation of free categories in Haskell</a> - a free category over
functions.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Path</span> <span class="ot">:</span> (g <span class="ot">:</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="ot">-&gt;</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="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Id</span> <span class="ot">:</span> <span class="dt">Path</span> g a a</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Cons</span> <span class="ot">:</span> g b c <span class="ot">-&gt;</span> <span class="dt">Path</span> g a b <span class="ot">-&gt;</span> <span class="dt">Path</span> g a c</span></code></pre></div>
<p>The first parameter 'g' corresponds to some type of Idris functions.
'a' and 'b' then correspond to the source and target types of the
function, Id is the identity function, and Comp is a formal composite of
functions.</p>
<p>In our case we will use the set of Idris functions</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Idr</span> <span class="ot">:</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>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Idr</span> a b <span class="fu">=</span> a <span class="ot">-&gt;</span> b</span></code></pre></div>
<p>But we can also instantiate it with various useful categories from
functional programming, such as Kleisli categories over a monad.</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Kleisli</span> <span class="ot">:</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="ot">-&gt;</span> <span class="dt">Type</span> <span class="ot">-&gt;</span> <span class="dt">Type</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Kleisli</span> m a b <span class="fu">=</span> a <span class="ot">-&gt;</span> m b</span></code></pre></div>
<p>This representation isn't as general as it could be, though.</p>
<p>And since we have access to dependent types, let's formulate what it
means to be a free category in general, not just free over Idris
types.</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="dt">Graph</span> <span class="ot">:</span> <span class="dt">Type</span> <span class="ot">-&gt;</span> <span class="dt">Type</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Graph</span> obj <span class="fu">=</span> obj <span class="ot">-&gt;</span> obj <span class="ot">-&gt;</span> <span class="dt">Type</span></span></code></pre></div>
<p>The definition of a free category stays the same, but our type
becomes more informative</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Path</span> <span class="ot">:</span> {obj <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> <span class="dt">Graph</span> obj <span class="ot">-&gt;</span> <span class="dt">Graph</span> obj <span class="kw">where</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Id</span> <span class="ot">:</span> {a <span class="ot">:</span> obj} <span class="ot">-&gt;</span> <span class="dt">Path</span> g a a</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Cons</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> obj} <span class="ot">-&gt;</span> g b c <span class="ot">-&gt;</span> <span class="dt">Path</span> g a b <span class="ot">-&gt;</span> <span class="dt">Path</span> g a c</span></code></pre></div>
<p>A term of a free category is nothing other than a path constructed
from composing individual edges of a graph.</p>
<p>You might notice the correspondence between this type, and that of
Lists</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">List</span> <span class="ot">:</span> <span class="dt">Type</span> <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Nil</span> <span class="ot">:</span> <span class="dt">List</span> a</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  <span class="fu">(::)</span> <span class="ot">:</span> a <span class="ot">-&gt;</span> <span class="dt">List</span> a <span class="ot">-&gt;</span> <span class="dt">List</span> a</span></code></pre></div>
<p>Which motivates the idea that a category is a typed monoid.</p>
<p>The evaluator for a free category is very similar to a fold for a
list, except that we replace each edge with a function rather than an
element.</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="fu">eval</span> <span class="ot">:</span> <span class="dt">Path</span> <span class="dt">Idr</span> a b <span class="ot">-&gt;</span> <span class="dt">Idr</span> a b</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>eval <span class="dt">Id</span> <span class="fu">=</span> id</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">Cons</span> f g) <span class="fu">=</span> f <span class="fu">.</span> (eval g)</span></code></pre></div>
<h3 id="the-free-bicartesian-closed-category-over-types">The Free
Bicartesian Closed Category over Types</h3>
<p>We will now go from a free category to a free category with products,
coproducts, and exponentials. For readers new to category theory, we
will go through each of these properties in more granular detail in
subsequent blog posts. But for now we will define them all in one
go.</p>
<p>We can then define our bicartesian category over types as:</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">BCC</span> <span class="ot">:</span> <span class="dt">Graph</span> <span class="dt">Type</span> <span class="ot">-&gt;</span> <span class="dt">Graph</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Embedding a primitive is now a separate operation</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Prim</span> <span class="ot">:</span> k a b <span class="ot">-&gt;</span> <span class="dt">BCC</span> k a b</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Identity arrow: a → a</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Id</span> <span class="ot">:</span> {a <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> <span class="dt">BCC</span> p a a</span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Composition of arrows: (b → c) → (a → b) → (a → c)</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Comp</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> <span class="dt">BCC</span> k b c <span class="ot">-&gt;</span> <span class="dt">BCC</span> k a b <span class="ot">-&gt;</span> <span class="dt">BCC</span> k a c</span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Product introduction: (a → b) → (a → c) → (a → (b * c))</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">ProdI</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> <span class="dt">BCC</span> k a b <span class="ot">-&gt;</span> <span class="dt">BCC</span> k a c</span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> <span class="dt">BCC</span> k a (b, c)</span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- First projection: (a * b) → a</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Fst</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> <span class="dt">BCC</span> k (a, b) a</span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Second projection: (a * b) → b</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Snd</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> <span class="dt">BCC</span> k (a, b) b</span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Coproduct introduction: (b → a) → (c → a) → (b + c → a)</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>  <span class="dt">CoprodI</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> <span class="dt">BCC</span> k b a <span class="ot">-&gt;</span> <span class="dt">BCC</span> k c a</span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> <span class="dt">BCC</span> k (<span class="dt">Either</span> b c) a</span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Left injection: a → (a + b)</span></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true" tabindex="-1"></a>  <span class="dt">InL</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> <span class="dt">BCC</span> k a (<span class="dt">Either</span> a b)</span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Right injection: b → (a + b)</span></span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true" tabindex="-1"></a>  <span class="dt">InR</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> <span class="dt">BCC</span> k b (<span class="dt">Either</span> a b)</span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Exponential elimination:</span></span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Apply</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> <span class="dt">BCC</span> k ((a <span class="ot">-&gt;</span> b), a) b</span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Currying: (a * b → c) → (a → (b ⇨ c))</span></span>
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Curry</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> <span class="dt">BCC</span> k (a, b) c <span class="ot">-&gt;</span> <span class="dt">BCC</span> k a (b <span class="ot">-&gt;</span> c)</span>
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Uncurrying: (a → (b ⇨ c)) → (a * b → c)</span></span>
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Uncurry</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> <span class="dt">BCC</span> k a (b <span class="ot">-&gt;</span> c) <span class="ot">-&gt;</span> <span class="dt">BCC</span> k (a, b) c</span></code></pre></div>
<p>(One important caveat is that our data-type now represents a free
f-algebra rather than a free category in the strict sense. We'll talk
more about the distinction in future posts, but for now I'll abuse
notation and keep calling both concepts by the same name.)</p>
<p>Defining an evaluator is as simple as it was before, we just match
each constructor to the corresponding Idris function</p>
<div class="sourceCode" id="cb9"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="fu">eval</span> <span class="ot">:</span> <span class="dt">BCC</span> <span class="dt">Idr</span> a b <span class="ot">-&gt;</span> <span class="dt">Idr</span> a b</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">Prim</span> f) <span class="fu">=</span> f</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>eval <span class="dt">Id</span> <span class="fu">=</span> id</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">Comp</span> f g) <span class="fu">=</span> (eval f) <span class="fu">.</span> (eval g)</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">ProdI</span> f g) <span class="fu">=</span> <span class="fu">\</span>c <span class="ot">=&gt;</span> ((eval f) c, (eval g) c)</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>eval <span class="dt">Fst</span> <span class="fu">=</span> fst</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>eval <span class="dt">Snd</span> <span class="fu">=</span> snd</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">CoprodI</span> f g) <span class="fu">=</span> <span class="fu">\</span>c <span class="ot">=&gt;</span> <span class="kw">case</span> c <span class="kw">of</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Left</span> l <span class="ot">=&gt;</span> (eval f) l</span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Right</span> r <span class="ot">=&gt;</span> (eval g) r</span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>eval <span class="dt">InL</span> <span class="fu">=</span> <span class="dt">Left</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>eval <span class="dt">InR</span> <span class="fu">=</span> <span class="dt">Right</span></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a>eval <span class="dt">Apply</span> <span class="fu">=</span> uncurry apply</span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">Curry</span> f) <span class="fu">=</span> curry <span class="fu">$</span> eval f</span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">Uncurry</span> f) <span class="fu">=</span> uncurry <span class="fu">$</span> eval f</span></code></pre></div>
<p>Since we'd like to work with more general categories, let's define a
record for storing our evaluator. If we were working in Haskell, we'd be
using a typeclass here.</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">record</span> <span class="dt">Category</span> (g<span class="ot">:</span> <span class="dt">Graph</span> <span class="dt">Type</span>) <span class="kw">where</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constructor</span> <span class="dt">MkCat</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>  <span class="fu">id</span> <span class="ot">:</span> {a <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> g a a</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>  <span class="fu">comp</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> g b c <span class="ot">-&gt;</span> g a b <span class="ot">-&gt;</span> g a c</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>  <span class="fu">prod</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> g c a <span class="ot">-&gt;</span> g c b <span class="ot">-&gt;</span> g c (a, b)</span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>  <span class="fu">fst</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> g (a, b) a</span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>  <span class="fu">snd</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> g (a, b) b</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>  <span class="fu">coprod</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> g a c <span class="ot">-&gt;</span> g b c <span class="ot">-&gt;</span> g (<span class="dt">Either</span> a b) c</span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>  <span class="fu">left</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> g a (<span class="dt">Either</span> a b)</span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>  <span class="fu">right</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> g b (<span class="dt">Either</span> a b)</span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a>  <span class="fu">apply</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> g (a <span class="ot">-&gt;</span> b, a) b</span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a>  <span class="fu">curry</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> g (a, b) c <span class="ot">-&gt;</span> g a (b <span class="ot">-&gt;</span> c)</span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a>  <span class="fu">uncurry</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Type</span>} <span class="ot">-&gt;</span> g a (b <span class="ot">-&gt;</span> c) <span class="ot">-&gt;</span> g (a, b) c</span></code></pre></div>
<p>We adjust our evaluator accordingly to use the new record type:</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="fu">eval&#39;</span> <span class="ot">:</span> <span class="dt">Category</span> g <span class="ot">-&gt;</span> <span class="dt">BCC</span> g s t <span class="ot">-&gt;</span> g s t</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>eval&#39; alg (<span class="dt">Prim</span> f) <span class="fu">=</span> f</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>eval&#39; alg <span class="dt">Id</span>  <span class="fu">=</span> alg<span class="fu">.</span>id</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>eval&#39; alg (<span class="dt">Comp</span> f g) <span class="fu">=</span> alg<span class="fu">.</span>comp (eval&#39; alg f) (eval&#39; alg g)</span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>eval&#39; alg (<span class="dt">ProdI</span> f g) <span class="fu">=</span> alg<span class="fu">.</span>prod (eval&#39; alg f) (eval&#39; alg g)</span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>eval&#39; alg <span class="dt">Fst</span> <span class="fu">=</span> alg<span class="fu">.</span>fst</span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>eval&#39; alg <span class="dt">Snd</span> <span class="fu">=</span> alg<span class="fu">.</span>snd</span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>eval&#39; alg (<span class="dt">CoprodI</span> f g) <span class="fu">=</span> alg<span class="fu">.</span>coprod (eval&#39; alg f) (eval&#39; alg g)</span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>eval&#39; alg <span class="dt">InL</span> <span class="fu">=</span> alg<span class="fu">.</span>left</span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>eval&#39; alg <span class="dt">InR</span> <span class="fu">=</span> alg<span class="fu">.</span>right</span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>eval&#39; alg <span class="dt">Apply</span> <span class="fu">=</span> alg<span class="fu">.</span>apply</span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>eval&#39; alg (<span class="dt">Curry</span> f) <span class="fu">=</span> alg<span class="fu">.</span>curry (eval&#39; alg f)</span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a>eval&#39; alg (<span class="dt">Uncurry</span> f) <span class="fu">=</span> alg<span class="fu">.</span>uncurry (eval&#39; alg f)</span></code></pre></div>
<p>Our new evaluator simply matches each construct with the
corresponding record. Writing out all of these evaluators can become
tiresome after a while, and indeed, in a few posts we will see how to do
this entirely generically using recursion schemes.</p>
<p>As an example, let's create a record that packages up our earlier
definition of the category of Idris functions.</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="dt">IdrCat</span> <span class="ot">:</span> <span class="dt">Category</span> <span class="dt">Idr</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="dt">IdrCat</span> <span class="fu">=</span> <span class="dt">MkCat</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>  id</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>  (<span class="fu">.</span>)</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>  (<span class="fu">\</span>f, g, c <span class="ot">=&gt;</span> (f c, g c))</span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>  fst</span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>  snd</span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>  (<span class="fu">\</span>f, g, c <span class="ot">=&gt;</span> <span class="kw">case</span> c <span class="kw">of</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Left</span> l <span class="ot">=&gt;</span> f l</span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">Right</span> r <span class="ot">=&gt;</span> g r)</span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Left</span></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Right</span></span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a>  (uncurry apply)</span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a>  curry</span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a>  uncurry</span></code></pre></div>
<p>We could also instantiate our record with a few choices of
categories, such as</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Cokleisli category of a comonad</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Cokleisli</span> <span class="ot">:</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="ot">-&gt;</span> <span class="dt">Type</span> <span class="ot">-&gt;</span> <span class="dt">Type</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="dt">Cokleisli</span> m a b <span class="fu">=</span> m a <span class="ot">-&gt;</span> b</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a><span class="co">-- A static effect category over an applicative functor</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a><span class="dt">StaticArrow</span> <span class="ot">:</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="ot">-&gt;</span> <span class="dt">Type</span> <span class="ot">-&gt;</span> <span class="dt">Type</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a><span class="dt">StaticArrow</span> f a b <span class="fu">=</span> f (a <span class="ot">-&gt;</span> b)</span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a><span class="co">-- Freyd category of an arrow</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a><span class="dt">Freyd</span> <span class="ot">:</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="ot">-&gt;</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>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a><span class="dt">Freyd</span> g a b <span class="fu">=</span> g a b</span></code></pre></div>
<p>More on this later!</p>
<p>In general, it's rare that any of these constructions preserve all of
our underlying structure (products, coproducts, exponentials), but we
can always mix and match the syntax as needed.</p>
<h3 id="free-bicartesian-categories-in-general">Free Bicartesian
Categories in General</h3>
<p>Finally, let's step away from the category of Idris types and define
a free bicartesian closed category in general.</p>
<p>Since we can't reuse Idris types, we now need to define a separate
datatype for our type universe.</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Ty</span> <span class="ot">:</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Unit</span> <span class="ot">:</span> <span class="dt">Ty</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Prod</span> <span class="ot">:</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Sum</span> <span class="ot">:</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Exp</span> <span class="ot">:</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">N</span> <span class="ot">:</span> <span class="dt">Ty</span></span></code></pre></div>
<p>And let's define type synonyms for them too</p>
<div class="sourceCode" id="cb15"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">infixr</span> <span class="dv">5</span> <span class="fu">~&gt;</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="fu">(~&gt;)</span> <span class="ot">:</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>(<span class="fu">~&gt;</span>) <span class="fu">=</span> <span class="dt">Exp</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a><span class="kw">infixr</span> <span class="dv">5</span> <span class="ot">:</span><span class="fu">*:</span></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a><span class="fu">(:*:)</span> <span class="ot">:</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>(<span class="ot">:</span><span class="fu">*:</span>) <span class="fu">=</span> <span class="dt">Prod</span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a><span class="kw">infixr</span> <span class="dv">5</span> <span class="ot">:</span><span class="fu">+:</span></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a><span class="fu">(:+:)</span> <span class="ot">:</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a>(<span class="ot">:</span><span class="fu">+:</span>) <span class="fu">=</span> <span class="dt">Sum</span></span></code></pre></div>
<p>Defining the free BCC is just as before, but whereas we previously
defined it over functions of inbuilt types, we now define it over a
graph of our new type universe Ty.</p>
<div class="sourceCode" id="cb16"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Comb</span> <span class="ot">:</span> <span class="dt">Graph</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Graph</span> <span class="dt">Ty</span> <span class="kw">where</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Primitives</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Prim</span> <span class="ot">:</span> k a b <span class="ot">-&gt;</span> <span class="dt">Comb</span> k a b</span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Identity arrow: a → a</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Id</span> <span class="ot">:</span> {a <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Comb</span> p a a</span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Composition of arrows: (b → c) → (a → b) → (a → c)</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Comp</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Comb</span> k b c <span class="ot">-&gt;</span> <span class="dt">Comb</span> k a b <span class="ot">-&gt;</span> <span class="dt">Comb</span> k a c</span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Product introduction: (a → b) → (a → c) → (a → (b * c))</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">ProdI</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Comb</span> k a b <span class="ot">-&gt;</span> <span class="dt">Comb</span> k a c</span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> <span class="dt">Comb</span> k a (b <span class="ot">:</span><span class="fu">*:</span> c)</span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- First projection: (a * b) → a</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Fst</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Comb</span> k (a <span class="ot">:</span><span class="fu">*:</span> b) a</span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Second projection: (a * b) → b</span></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Snd</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Comb</span> k (a <span class="ot">:</span><span class="fu">*:</span> b) b</span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Coproduct introduction: (b → a) → (c → a) → (b + c → a)</span></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a>  <span class="dt">CoprodI</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Comb</span> k b a <span class="ot">-&gt;</span> <span class="dt">Comb</span> k c a</span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> <span class="dt">Comb</span> k (b <span class="ot">:</span><span class="fu">+:</span> c) a</span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Left injection: a → (a + b)</span></span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a>  <span class="dt">InL</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Comb</span> k a (a <span class="ot">:</span><span class="fu">+:</span> b)</span>
<span id="cb16-20"><a href="#cb16-20" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Right injection: b → (a + b)</span></span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true" tabindex="-1"></a>  <span class="dt">InR</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Comb</span> k b (a <span class="ot">:</span><span class="fu">+:</span> b)</span>
<span id="cb16-22"><a href="#cb16-22" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Exponential elimination:</span></span>
<span id="cb16-23"><a href="#cb16-23" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Apply</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Comb</span> k ((a <span class="fu">~&gt;</span> b) <span class="ot">:</span><span class="fu">*:</span> a) b</span>
<span id="cb16-24"><a href="#cb16-24" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Currying: (a * b → c) → (a → (b ⇨ c))</span></span>
<span id="cb16-25"><a href="#cb16-25" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Curry</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Comb</span> k (a <span class="ot">:</span><span class="fu">*:</span> b) c <span class="ot">-&gt;</span> <span class="dt">Comb</span> k a (b <span class="fu">~&gt;</span> c)</span>
<span id="cb16-26"><a href="#cb16-26" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Uncurrying: (a → (b ⇨ c)) → (a * b → c)</span></span>
<span id="cb16-27"><a href="#cb16-27" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Uncurry</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> <span class="dt">Comb</span> k a (b <span class="fu">~&gt;</span> c) <span class="ot">-&gt;</span> <span class="dt">Comb</span> k (a <span class="ot">:</span><span class="fu">*:</span> b) c</span></code></pre></div>
<p>The main difference from before is that our primitives are no longer
a simple embedding of Idris functions. Now we need a separate type for
representing them. As an example, let's use the generators of a monoid
over some base type:</p>
<div class="sourceCode" id="cb17"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Prim</span> <span class="ot">:</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Type</span> <span class="kw">where</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Unit</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Z</span> <span class="ot">:</span> <span class="dt">Prim</span> <span class="dt">Unit</span> <span class="dt">Base</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Multiplication</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Mult</span> <span class="ot">:</span> (<span class="dt">Prod</span> <span class="dt">Base</span> <span class="dt">Base</span>) <span class="dt">Base</span></span></code></pre></div>
<p>Most of our remaining definition stays exactly the same! This will
become a running theme in this series, where adding extra generality
will give us more power without too much extra complexity.</p>
<p>We can recover our earlier evaluator once we provide an
interpretation of our type universe into Idris types</p>
<div class="sourceCode" id="cb18"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="fu">evalTy</span> <span class="ot">:</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> <span class="dt">Type</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>evalTy <span class="dt">U</span> <span class="fu">=</span> <span class="dt">Unit</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>evalTy (<span class="dt">Exp</span> t1 t2) <span class="fu">=</span> (evalTy t1) <span class="ot">-&gt;</span> (evalTy t2)</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>evalTy (<span class="dt">Prod</span> t1 t2) <span class="fu">=</span> (evalTy t1, evalTy t2)</span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>evalTy (<span class="dt">Sum</span> t1 t2) <span class="fu">=</span> <span class="dt">Either</span> (evalTy t1) (evalTy t2)</span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a><span class="co">-- We&#39;ll interpret our base type as the type of naturals</span></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a>evalTy <span class="dt">N</span> <span class="fu">=</span> <span class="dt">Nat</span></span></code></pre></div>
<p>We can then define an evaluator. We'll start by interpreting in Idris
functions, then generalise to records again. First we'll need to
interpret the type of primitives.</p>
<div class="sourceCode" id="cb19"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="fu">evalPrims</span> <span class="ot">:</span> <span class="dt">Prims</span> ty1 ty2 <span class="ot">-&gt;</span> <span class="dt">Idr</span> (evalTy ty1) (evalTy ty2)</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>evalPrims <span class="dt">Z</span> <span class="fu">=</span> <span class="fu">\</span>() <span class="ot">=&gt;</span> <span class="dv">0</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>evalPrims <span class="dt">Mult</span> <span class="fu">=</span> uncurry (<span class="fu">+</span>)</span></code></pre></div>
<p>Then we'll write out interpreter for the rest of terms. We could have
parametrised our eval function by evalPrims, but for now we'll keep
things simple.</p>
<div class="sourceCode" id="cb20"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="fu">eval</span> <span class="ot">:</span> <span class="dt">Comb</span> <span class="dt">Prims</span> ty1 ty2 <span class="ot">-&gt;</span> <span class="dt">Idr</span> (evalTy ty1) (evalTy ty2)</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">Prim</span> f) <span class="fu">=</span> evalPrims f</span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>eval <span class="dt">Id</span> <span class="fu">=</span> id</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">Comp</span> f g) <span class="fu">=</span> (eval f) <span class="fu">.</span> (eval g)</span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">ProdI</span> f g) <span class="fu">=</span> <span class="fu">\</span>c <span class="ot">=&gt;</span> ((eval f) c, (eval g) c)</span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a>eval <span class="dt">Fst</span> <span class="fu">=</span> fst</span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a>eval <span class="dt">Snd</span> <span class="fu">=</span> snd</span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">CoprodI</span> f g) <span class="fu">=</span> <span class="fu">\</span>c <span class="ot">=&gt;</span> <span class="kw">case</span> c <span class="kw">of</span></span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Left</span> l <span class="ot">=&gt;</span> (eval f) l</span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">Right</span> r <span class="ot">=&gt;</span> (eval g) r</span>
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true" tabindex="-1"></a>eval <span class="dt">InL</span> <span class="fu">=</span> <span class="dt">Left</span></span>
<span id="cb20-12"><a href="#cb20-12" aria-hidden="true" tabindex="-1"></a>eval <span class="dt">InR</span> <span class="fu">=</span> <span class="dt">Right</span></span>
<span id="cb20-13"><a href="#cb20-13" aria-hidden="true" tabindex="-1"></a>eval <span class="dt">Apply</span> <span class="fu">=</span> uncurry apply</span>
<span id="cb20-14"><a href="#cb20-14" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">Curry</span> f) <span class="fu">=</span> curry <span class="fu">$</span> eval f</span>
<span id="cb20-15"><a href="#cb20-15" aria-hidden="true" tabindex="-1"></a>eval (<span class="dt">Uncurry</span> f) <span class="fu">=</span> uncurry <span class="fu">$</span> eval f</span></code></pre></div>
<p>The main thing that's changed is that now instead of evaluating into
Idris functions directly, we must first evaluate our source and target
types. Thanks to the magic of dependent types, our compiler knows what
the types of our evaluated combinators should be, so it's really hard to
make a mistake here. This is something that will become invaluable once
we start working with languages with more interesting notions of
variable context.</p>
<p>Once again we would like to generalise from evaluating our
combinators into the category of Idris types to evaluating into
morphisms of an arbitrary category. Our types are now evaluated into
objects <code>ty : Ty -&gt; obj</code> and our combinators are evaluated
into morphisms, whose source and target are calculated by first
evaluating the objects
<code>Comb _ ty1 ty2 -&gt; c (ty s) (ty t)</code></p>
<p>We'll package up the evaluator for objects in a more modular way
later, but for now let's just stick the entire thing into our definition
of a BCC:</p>
<div class="sourceCode" id="cb21"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="kw">record</span> <span class="dt">BCC</span> {obj<span class="ot">:</span> <span class="dt">Type</span>} (g<span class="ot">:</span> <span class="dt">Graph</span> obj) <span class="kw">where</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constructor</span> <span class="dt">MkCat</span></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- evaluator for objects</span></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>  <span class="fu">ty</span> <span class="ot">:</span> <span class="dt">Ty</span> <span class="ot">-&gt;</span> obj</span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- evaluator for morphisms</span></span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>  <span class="fu">id</span> <span class="ot">:</span> {a <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> g (ty a) (ty a)</span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>  <span class="fu">comp</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> g (ty b) (ty c) <span class="ot">-&gt;</span> g (ty a) (ty b)</span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> g (ty a) (ty c)</span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a>  <span class="fu">prod</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> g (ty c) (ty a) <span class="ot">-&gt;</span> g (ty c) (ty b)</span>
<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> g (ty c) (ty (a <span class="ot">:</span><span class="fu">*:</span> b))</span>
<span id="cb21-11"><a href="#cb21-11" aria-hidden="true" tabindex="-1"></a>  <span class="fu">fst</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> g (ty (a <span class="ot">:</span><span class="fu">*:</span> b)) (ty a)</span>
<span id="cb21-12"><a href="#cb21-12" aria-hidden="true" tabindex="-1"></a>  <span class="fu">snd</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> g (ty (a <span class="ot">:</span><span class="fu">*:</span> b)) (ty b)</span>
<span id="cb21-13"><a href="#cb21-13" aria-hidden="true" tabindex="-1"></a>  <span class="fu">coprod</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> g (ty a) (ty c) <span class="ot">-&gt;</span> g (ty b) (ty c)</span>
<span id="cb21-14"><a href="#cb21-14" aria-hidden="true" tabindex="-1"></a>    <span class="ot">-&gt;</span> g (ty (a <span class="ot">:</span><span class="fu">+:</span> b)) (ty c)</span>
<span id="cb21-15"><a href="#cb21-15" aria-hidden="true" tabindex="-1"></a>  <span class="fu">left</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> g (ty a) (ty (a <span class="ot">:</span><span class="fu">+:</span> b))</span>
<span id="cb21-16"><a href="#cb21-16" aria-hidden="true" tabindex="-1"></a>  <span class="fu">right</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> g (ty b) (ty (a <span class="ot">:</span><span class="fu">+:</span> b))</span>
<span id="cb21-17"><a href="#cb21-17" aria-hidden="true" tabindex="-1"></a>  <span class="fu">apply</span> <span class="ot">:</span> {a, b <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> g (ty ((a <span class="fu">~&gt;</span> b) <span class="ot">:</span><span class="fu">*:</span> a)) (ty b)</span>
<span id="cb21-18"><a href="#cb21-18" aria-hidden="true" tabindex="-1"></a>  <span class="fu">curry</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> g (ty (a <span class="ot">:</span><span class="fu">*:</span> b)) (ty c) <span class="ot">-&gt;</span> g (ty a) (ty (b <span class="fu">~&gt;</span> c))</span>
<span id="cb21-19"><a href="#cb21-19" aria-hidden="true" tabindex="-1"></a>  <span class="fu">uncurry</span> <span class="ot">:</span> {a, b, c <span class="ot">:</span> <span class="dt">Ty</span>} <span class="ot">-&gt;</span> g (ty a) (ty (b <span class="fu">~&gt;</span> c)) <span class="ot">-&gt;</span> g (ty (a <span class="ot">:</span><span class="fu">*:</span> b)) (ty c)</span>
<span id="cb21-20"><a href="#cb21-20" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- evaluator for primitives</span></span>
<span id="cb21-21"><a href="#cb21-21" aria-hidden="true" tabindex="-1"></a>  <span class="fu">e</span> <span class="ot">:</span> g (ty <span class="dt">Unit</span>) (ty <span class="dt">N</span>)</span>
<span id="cb21-22"><a href="#cb21-22" aria-hidden="true" tabindex="-1"></a>  <span class="fu">mult</span> <span class="ot">:</span> g (ty (<span class="dt">N</span> <span class="ot">:</span><span class="fu">*:</span> <span class="dt">N</span>)) (ty <span class="dt">N</span>)</span></code></pre></div>
<p>We've also included an evaluator for our primitives, in this case the
multiplication and unit of a monoid.</p>
<p>Our final evaluator is then:</p>
<div class="sourceCode" id="cb22"><pre
class="sourceCode idr"><code class="sourceCode idris"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="fu">eval&#39;</span> <span class="ot">:</span> (bcc <span class="ot">:</span> <span class="dt">BCC</span> g) <span class="ot">-&gt;</span> <span class="dt">Comb</span> <span class="dt">Prims</span> ty1 ty2 <span class="ot">-&gt;</span> g (bcc<span class="fu">.</span>ty ty1) (bcc<span class="fu">.</span>ty ty2)</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>eval&#39; alg (<span class="dt">Prim</span> <span class="dt">Z</span>) <span class="fu">=</span> alg<span class="fu">.</span>e</span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>eval&#39; alg (<span class="dt">Prim</span> <span class="dt">Mult</span>) <span class="fu">=</span> alg<span class="fu">.</span>mult</span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>eval&#39; alg <span class="dt">Id</span>  <span class="fu">=</span> alg<span class="fu">.</span>id</span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a>eval&#39; alg (<span class="dt">Comp</span> f g) <span class="fu">=</span> alg<span class="fu">.</span>comp (eval&#39; alg f) (eval&#39; alg g)</span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a>eval&#39; alg (<span class="dt">ProdI</span> f g) <span class="fu">=</span> alg<span class="fu">.</span>prod (eval&#39; alg f) (eval&#39; alg g)</span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a>eval&#39; alg <span class="dt">Fst</span> <span class="fu">=</span> alg<span class="fu">.</span>fst</span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a>eval&#39; alg <span class="dt">Snd</span> <span class="fu">=</span> alg<span class="fu">.</span>snd</span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a>eval&#39; alg (<span class="dt">CoprodI</span> f g) <span class="fu">=</span> alg<span class="fu">.</span>coprod (eval&#39; alg f) (eval&#39; alg g)</span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a>eval&#39; alg <span class="dt">InL</span> <span class="fu">=</span> alg<span class="fu">.</span>left</span>
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a>eval&#39; alg <span class="dt">InR</span> <span class="fu">=</span> alg<span class="fu">.</span>right</span>
<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a>eval&#39; alg <span class="dt">Apply</span> <span class="fu">=</span> alg<span class="fu">.</span>apply</span>
<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a>eval&#39; alg (<span class="dt">Curry</span> f) <span class="fu">=</span> alg<span class="fu">.</span>curry (eval&#39; alg f)</span>
<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a>eval&#39; alg (<span class="dt">Uncurry</span> f) <span class="fu">=</span> alg<span class="fu">.</span>uncurry (eval&#39; alg f)</span></code></pre></div>
<p>Overall, we can see that even as we've increased the complexity of
the language, the structure of our evaluator has stayed the same. This
is because at the core, an evaluator for an inductive type is nothing
more than a homomorphism - a structure preserving map, whose behaviour
is entirely determined by its actions on the generators of our algebraic
theory.</p>
<p>And this is what makes the algebraic approach to programming so
powerful. When we treat our language as an inductive type, we can reuse
the same machinery we've developed for working with simpler algebraic
structures such as monoids and semirings, but now apply it to more
abstract structures, such as a typed combinator language for BCCs. As we
will see through the course of this series, this scales to much more
than just combinator languages, and even variable binding can be handled
algebraically by working with inductive types over an appropriately
chosen category.</p>
<p>In the next blog post we will have our first look at the simply typed
lambda calculus and translate it into our combinator language, thus
showing how to interpret the STLC into an arbitrary bicartesian closed
category. After that, we'll start in earnest, and introduce the main
tool we'll be using throughout the series - recursion schemes.</p>]]></content>
  </entry>
</feed>
