<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"
    xmlns:dc="http://purl.org/dc/elements/1.1/">
    <channel>
        <title>blog :: Brent -> [String]</title>
        <link>http://byorgey.github.io/blog</link>
        <description><![CDATA[Brent Yorgey's academic blog]]></description>
        <atom:link href="http://byorgey.github.io/blog/rss.xml" rel="self"
                   type="application/rss+xml" />
        <lastBuildDate>Fri, 26 Jun 2026 00:00:00 UT</lastBuildDate>
        <item>
    <title>Proving the Fundamental Theorem of Arithmetic in Agda</title>
    <link>http://byorgey.github.io/blog/posts/2026/06/26/FTA.lagda.html</link>
    <description><![CDATA[
<h1>Proving the Fundamental Theorem of Arithmetic in Agda</h1>

<div class="info">
  Posted on June 26, 2026
  
  
  <br />
  Tagged <a title="All pages tagged &#39;agda&#39;." href="/tag/agda.html" rel="tag">agda</a>, <a title="All pages tagged &#39;arithmetic&#39;." href="/tag/arithmetic.html" rel="tag">arithmetic</a>, <a title="All pages tagged &#39;theorem&#39;." href="/tag/theorem.html" rel="tag">theorem</a>, <a title="All pages tagged &#39;proof&#39;." href="/tag/proof.html" rel="tag">proof</a>, <a title="All pages tagged &#39;Agda&#39;." href="/tag/Agda.html" rel="tag">Agda</a>
  
</div>

<a href="https://share.joinmastodon.org/#text=Proving the Fundamental Theorem of Arithmetic in Agda https://byorgey.github.io/blog/posts/2026/06/26/FTA.lagda.html" target="_blank" rel="noopener">Share on <svg role="img" aria-label="Mastodon" height="1em" viewBox="0 0 74 79" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M73.7014 17.4323C72.5616 9.05152 65.1774 2.4469 56.424 1.1671C54.9472 0.950843 49.3518 0.163818 36.3901 0.163818H36.2933C23.3281 0.163818 20.5465 0.950843 19.0697 1.1671C10.56 2.41145 2.78877 8.34604 0.903306 16.826C-0.00357854 21.0022 -0.100361 25.6322 0.068112 29.8793C0.308275 35.9699 0.354874 42.0498 0.91406 48.1156C1.30064 52.1448 1.97502 56.1419 2.93215 60.0769C4.72441 67.3445 11.9795 73.3925 19.0876 75.86C26.6979 78.4332 34.8821 78.8603 42.724 77.0937C43.5866 76.8952 44.4398 76.6647 45.2833 76.4024C47.1867 75.8033 49.4199 75.1332 51.0616 73.9562C51.0841 73.9397 51.1026 73.9184 51.1156 73.8938C51.1286 73.8693 51.1359 73.8421 51.1368 73.8144V67.9366C51.1364 67.9107 51.1302 67.8852 51.1186 67.862C51.1069 67.8388 51.0902 67.8184 51.0695 67.8025C51.0489 67.7865 51.0249 67.7753 50.9994 67.7696C50.9738 67.764 50.9473 67.7641 50.9218 67.7699C45.8976 68.9569 40.7491 69.5519 35.5836 69.5425C26.694 69.5425 24.3031 65.3699 23.6184 63.6327C23.0681 62.1314 22.7186 60.5654 22.5789 58.9744C22.5775 58.9477 22.5825 58.921 22.5934 58.8965C22.6043 58.8721 22.621 58.8505 22.6419 58.8336C22.6629 58.8167 22.6876 58.8049 22.714 58.7992C22.7404 58.7934 22.7678 58.794 22.794 58.8007C27.7345 59.9796 32.799 60.5746 37.8813 60.5733C39.1036 60.5733 40.3223 60.5733 41.5447 60.5414C46.6562 60.3996 52.0437 60.1408 57.0728 59.1694C57.1983 59.1446 57.3237 59.1233 57.4313 59.0914C65.3638 57.5847 72.9128 52.8555 73.6799 40.8799C73.7086 40.4084 73.7803 35.9415 73.7803 35.4523C73.7839 33.7896 74.3216 23.6576 73.7014 17.4323ZM61.4925 47.3144H53.1514V27.107C53.1514 22.8528 51.3591 20.6832 47.7136 20.6832C43.7061 20.6832 41.6988 23.2499 41.6988 28.3194V39.3803H33.4078V28.3194C33.4078 23.2499 31.3969 20.6832 27.3894 20.6832C23.7654 20.6832 21.9552 22.8528 21.9516 27.107V47.3144H13.6176V26.4937C13.6176 22.2395 14.7157 18.8598 16.9118 16.3545C19.1772 13.8552 22.1488 12.5719 25.8373 12.5719C30.1064 12.5719 33.3325 14.1955 35.4832 17.4394L37.5587 20.8853L39.6377 17.4394C41.7884 14.1955 45.0145 12.5719 49.2765 12.5719C52.9614 12.5719 55.9329 13.8552 58.2055 16.3545C60.4017 18.8574 61.4997 22.2371 61.4997 26.4937L61.4925 47.3144Z" fill="inherit"/></svg></a>
<section>
<p><strong>tl;dr</strong>: This is a fully commentated, from-scratch proof of the
Fundamental Theorem of Arithmetic in
<a href="https://wiki.portal.chalmers.se/agda/pmwiki.php?n=Main.HomePage">Agda</a>,
intended for those who already know a bit of Agda but might benefit
from reading and working through a larger example. See the
Introduction and the <a href="#table-of-contents">Table of Contents</a> below for more details.</p>
<section id="introduction" class="level2">
<h2>Introduction</h2>
<p>Earlier this spring, I was idly brainstorming potential final projects
for my <a href="https://hendrix-cs.github.io/csci365/">Functional Programming</a>
students. Having just <a href="http://ozark.hendrix.edu/~yorgey/forest/00EG/index.xml">taught my Discrete Math students the
Fundamental Theorem of
Arithmetic</a>, I
wondered whether formalizing<span class="sidenote-wrapper"><label for="sn-0" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0" class="margin-toggle"/><span class="sidenote">I mean formalizing it <em>from scratch</em>: of
course, the FTA is <a href="https://agda.github.io/agda-stdlib/v2.3/Data.Nat.Primality.Factorisation.html">already in the Agda standard library</a>. As I later
learned, it was added to the standard library by <a href="https://github.com/Taneb">Nathan van Doorn,
aka Taneb</a>.<br />
<br />
</span></span> it in
<a href="https://wiki.portal.chalmers.se/agda/pmwiki.php?n=Main.HomePage">Agda</a>
could make a nice project.</p>
<p>So I decided to spend about an hour trying to prove it in Agda,
to gauge the level of the project. At the end of an hour, I had
learned two things: (1) proving the Fundamental Theorem of Arithmetic is <em>not</em> an appropriate project for
my students (who had only had a few weeks’ practice with Agda); (2) I
was not going to be able to stop until I finished the proof myself!</p>
<p>Over the next week or so, I finished the proof completely from
scratch—without using anything from the standard library, and without
looking up any reference material. I based it only on my experience
in Agda, knowledge of the relevant proofs on an informal level, and
Agda techniques I’ve picked up along the way (from <em>e.g.</em> Conor McBride, Jacques
Carette, colleagues at Penn, and elsewhere).</p>
<p>I decided to publish the proof, with extra commentary, in the hopes
that it can be useful as an intermediate-level reference. That is,
perhaps you’ve learned some basic Agda (if not, I suggest <a href="https://agda.readthedocs.io/en/latest/getting-started/a-taste-of-agda.html">this
tutorial to
start</a>)
and have some basic familiarity
with the Curry-Howard correspondence, but would benefit from seeing an
example of a fully worked out, medium-sized proof.<span class="sidenote-wrapper"><label for="sn-1" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1" class="margin-toggle"/><span class="sidenote">Another good
source of information along these lines is <a href="https://jesper.sikanda.be/posts/formalize-all-the-things.html">this post by Jesper
Cockx</a>.<br />
<br />
</span></span> The resulting blog
post is extremely long, but I make no apologies for that—if you want
an entertaining 5-minute read, you should look elsewhere!</p>
<p>The entire blog post and proof is <a href="https://github.com/byorgey/blog/blob/main/posts/2026/06/26/FTA.lagda.md">available as a literate Agda
document</a>. <strong>Even better, I have also published <a href="http://ozark.hendrix.edu/~yorgey/pub/FTA-holes.lagda.md">another version of this
blog post with holes in place of almost all the proofs</a>.</strong> For a
maximal learning experience, I suggest downloading it and trying to
fill in the holes yourself as you go along.</p>
<p>Below is a table of contents. Depending on your background, you may
of course choose to skip some sections. For example, if you have
already had a good deal of practice dealing with basic natural number
arithmetic, equality, and inequality in Agda, you might wish to skip
over those sections.</p>
</section>
<section id="table-of-contents" class="level2">
<h2>Table of Contents</h2>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#half-of-the-fundamental-theorem-of-arithmetic-constructively">(Half of) The Fundamental Theorem of Arithmetic (Constructively)</a></li>
<li><a href="#preliminaries">Preliminaries</a></li>
<li><a href="#basic-logic">Basic logic</a></li>
<li><a href="#equality">Equality</a></li>
<li><a href="#natural-numbers">Natural numbers</a>
<ul>
<li><a href="#no-confusion">No confusion</a></li>
<li><a href="#decidable-equality">Decidable equality</a></li>
</ul></li>
<li><a href="#addition">Addition</a></li>
<li><a href="#multiplication">Multiplication</a></li>
<li><a href="#inequality">Inequality</a>
<ul>
<li><a href="#relationships-among-equality-and-inequality">Relationships among equality and inequality</a></li>
<li><a href="#arithmetic-and-inequality">Arithmetic and inequality</a></li>
</ul></li>
<li><a href="#divisibility-primes-and-composites">Divisibility, primes, and composites</a>
<ul>
<li><a href="#nontrivial-divisors-come-in-pairs">Nontrivial divisors come in pairs</a></li>
</ul></li>
<li><a href="#division">Division</a></li>
<li><a href="#absolute-difference">Absolute difference</a></li>
<li><a href="#quotient-and-remainder-are-unique">Quotient and remainder are unique</a></li>
<li><a href="#the-division-algorithm-take-1">The division algorithm, take 1</a>
<ul>
<li><a href="#construct-the-evidence-you-would-like-to-pattern-match-on">Construct the evidence you would like to pattern-match on</a></li>
</ul></li>
<li><a href="#well-founded-induction">Well-founded induction</a>
<ul>
<li><a href="#accessibility">Accessibility</a></li>
<li><a href="#well-founded-induction-defined">Well-founded induction, defined</a></li>
<li><a href="#less-than-is-well-founded">Less-than is well-founded</a></li>
</ul></li>
<li><a href="#the-division-algorithm">The division algorithm</a></li>
<li><a href="#primality-testing">Primality testing</a>
<ul>
<li><a href="#counting-up">Counting up</a></li>
<li><a href="#primality-testing-by-trial-division">Primality testing by trial division</a></li>
</ul></li>
<li><a href="#lists">Lists</a></li>
<li><a href="#the-fundamental-theorem-of-arithmetic">The Fundamental Theorem of Arithmetic</a></li>
<li><a href="#further-directions">Further Directions</a></li>
</ul>
</section>
<section id="half-of-the-fundamental-theorem-of-arithmetic-constructively" class="level2">
<h2>(Half of) The Fundamental Theorem of Arithmetic (Constructively)</h2>
<p>The <a href="https://en.wikipedia.org/wiki/Fundamental_theorem_of_arithmetic">Fundamental Theorem of
Arithmetic</a>
(<em>FTA</em> for short) states that any natural number <span class="math inline">\(n \geq 1\)</span> can be
written as a product of zero or more primes, and moreover that this
product is unique up to permutation.</p>
<p>For now, we are only going to prove the <em>existence</em> part (I may write
another blog post with the uniqueness proof later). Since a <em>constructive</em>
existence proof is really an algorithm for constructing the thing that
is claimed to exist, this can also be seen as a <em>formally verified
factorization program</em>: put any number in, get a prime factorization
out. Writing a prime factorization program is not hard, of course;
it’s the formal verification part that is interesting!</p>
<p><strong>Stop!</strong> Before reading on, if you want to get the most out of this tutorial, I
<strong>strongly recommend <a href="http://ozark.hendrix.edu/~yorgey/pub/FTA-holes.lagda.md">downloading the version with
holes</a></strong>
and trying to complete as many of the proofs as you can before reading mine!</p>
</section>
<section id="preliminaries" class="level2">
<h2>Preliminaries</h2>
<p>We will often make use of <code>A</code> and <code>B</code> to stand for arbitrary
sets/types, so we use a <code>variable</code> declaration to tell Agda that it
should implicitly quantify them whenever they show up as free
variables. That way we don’t have to write <code>{A B : Set} → ...</code> all the time.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">variable</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  A B <span class="ot">:</span> <span class="dt">Set</span></span></code></pre></div>
</section>
<section id="basic-logic" class="level2">
<h2>Basic logic</h2>
<p>Since we’re building this completely from scratch, we start with some
types to represent basic logical building blocks (via the
<a href="https://en.wikipedia.org/wiki/Curry%E2%80%93Howard_correspondence">Curry-Howard correspondence</a>). First, the “top” type <code>⊤</code> to stand for truth, <em>i.e.</em> a proposition with trivial evidence:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> ⊤ <span class="ot">:</span> <span class="dt">Set</span> <span class="kw">where</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  tt <span class="ot">:</span> ⊤</span></code></pre></div>
<p><code>tt</code> is declared to be the one and only value of type <code>⊤</code>.</p>
<p>Note that some things we define here—such as <code>⊤</code>—will have the same
names as they do in the <a href="https://agda.github.io/agda-stdlib/v2.3/">Agda standard library</a>. However, many things
won’t, since I either didn’t know the standard name and made up my
own, or (in a few cases) did know the standard name but didn’t like
it, and made up my own anyway.</p>
<p>Next, the “bottom” type <code>⊥</code> with no constructors, representing
falsity, along with a corresponding elimination principle, <code>absurd</code>. The elimination
principle says that anything follows from <code>⊥</code> (“<em><a href="https://en.wikipedia.org/wiki/Principle_of_explosion">ex falso
quodlibet</a></em>”), and is implemented using Agda’s absurd pattern,
written <code>()</code>. If Agda can tell that there are no possible
constructors which could give rise to a value of a certain type, we
can pattern-match on it with <code>()</code>, and are absolved of providing a right-hand side for the definition in that case.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> ⊥ <span class="ot">:</span> <span class="dt">Set</span> <span class="kw">where</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>absurd <span class="ot">:</span> ⊥ <span class="ot">→</span> A</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>absurd <span class="ot">()</span></span></code></pre></div>
<p>We can now define negation as an implication to <code>⊥</code>.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>¬ <span class="ot">:</span> <span class="dt">Set</span> <span class="ot">→</span> <span class="dt">Set</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>¬ P <span class="ot">=</span> P <span class="ot">→</span> ⊥</span></code></pre></div>
<p>Dependent pairs are next: a pair of values where the <em>type</em> of the
second component can depend on the <em>value</em> of the first. That is, a value of type <code>Σ A B</code> is a value <code>a</code> of type
<code>A</code> paired with a value of type <code>B a</code>. Via Curry-Howard, this is used
to represent existential quantification: a (constructive) proof of
<span class="math inline">\(\exists a : A.\; B(a)\)</span> is a value <span class="math inline">\(a\)</span> of type <span class="math inline">\(A\)</span> (the <em>witness</em>)
paired with a proof that <span class="math inline">\(a\)</span> has property <span class="math inline">\(B\)</span> (<em>i.e.</em> a value of type <span class="math inline">\(B(a)\)</span>).</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">infixr</span> <span class="dv">1</span> <span class="ot">_</span>,<span class="ot">_</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> Σ <span class="ot">(</span>A <span class="ot">:</span> <span class="dt">Set</span><span class="ot">)</span> <span class="ot">(</span>B <span class="ot">:</span> A <span class="ot">→</span> <span class="dt">Set</span><span class="ot">)</span> <span class="ot">:</span> <span class="dt">Set</span> <span class="kw">where</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>  <span class="ot">_</span>,<span class="ot">_</span> <span class="ot">:</span> <span class="ot">(</span>a <span class="ot">:</span> A<span class="ot">)</span> <span class="ot">→</span> B a <span class="ot">→</span> Σ A B</span></code></pre></div>
<p>We also define a projection function (we only end up needing <code>fst</code>;
defining <code>snd</code> is left as an exercise for the reader<span class="sidenote-wrapper"><label for="sn-2" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2" class="margin-toggle"/><span class="sidenote">The <em>definition</em>
of <code>snd</code> is trivial; writing down its <em>type</em> is a worthwhile
exercise.<br />
<br />
</span></span>), along with a type of non-dependent pairs, corresponding
to logical conjunction (and).</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>fst <span class="ot">:</span> <span class="ot">∀</span> <span class="ot">{</span>A B<span class="ot">}</span> <span class="ot">→</span> Σ A B <span class="ot">→</span> A</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>fst <span class="ot">(</span>a , <span class="ot">_)</span> <span class="ot">=</span> 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">3</span> <span class="ot">_</span>×<span class="ot">_</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>×<span class="ot">_</span> <span class="ot">:</span> <span class="ot">(</span>A B <span class="ot">:</span> <span class="dt">Set</span><span class="ot">)</span> <span class="ot">→</span> <span class="dt">Set</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>A × B <span class="ot">=</span> Σ A <span class="ot">(λ</span> <span class="ot">_</span> <span class="ot">→</span> B<span class="ot">)</span></span></code></pre></div>
<p>Finally, we define a disjoint (tagged) union type corresponding to
logical disjunction (or).</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">infixr</span> <span class="dv">2</span> <span class="ot">_</span>⊎<span class="ot">_</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="ot">_</span>⊎<span class="ot">_</span> <span class="ot">(</span>A B <span class="ot">:</span> <span class="dt">Set</span><span class="ot">)</span> <span class="ot">:</span> <span class="dt">Set</span> <span class="kw">where</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>  inj₁ <span class="ot">:</span> A <span class="ot">→</span> A ⊎ B</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>  inj₂ <span class="ot">:</span> B <span class="ot">→</span> A ⊎ B</span></code></pre></div>
</section>
<section id="equality" class="level2">
<h2>Equality</h2>
<p>Next, we write down the standard equality (<em>aka</em> identity, <em>aka</em> path) type, with a single
constructor <code>refl</code> that witnesses when its two arguments are
identical.<span class="sidenote-wrapper"><label for="sn-3" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-3" class="margin-toggle"/><span class="sidenote">It still seems somewhat magical to me that this seemingly
too-simple definition encapsulates everything we want in an equality
relation (well, <a href="https://martinescardo.github.io/TypeTopology/UnivalenceFromScratch.html">almost everything</a>).<br />
<br />
</span></span> We also define a convenient
synonym for inequality.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">infix</span> <span class="dv">4</span> <span class="ot">_</span>≡<span class="ot">_</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="ot">_</span>≡<span class="ot">_</span> <span class="ot">(</span>a <span class="ot">:</span> A<span class="ot">)</span> <span class="ot">:</span> A <span class="ot">→</span> <span class="dt">Set</span> <span class="kw">where</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>  refl <span class="ot">:</span> a ≡ a</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>≢<span class="ot">_</span> <span class="ot">:</span> A <span class="ot">→</span> A <span class="ot">→</span> <span class="dt">Set</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>x ≢ y <span class="ot">=</span> ¬ <span class="ot">(</span>x ≡ y<span class="ot">)</span></span></code></pre></div>
<p>Besides reflexivity, equality enjoys various properties that we will
need: symmetry, transitivity, and congruence (<em>i.e.</em>, we can apply any
function to both sides of an equation).</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>sym <span class="ot">:</span> <span class="ot">{</span>x y <span class="ot">:</span> A<span class="ot">}</span> <span class="ot">→</span> x ≡ y <span class="ot">→</span> y ≡ x</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>sym refl <span class="ot">=</span> refl</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>trans <span class="ot">:</span> <span class="ot">{</span>x y z <span class="ot">:</span> A<span class="ot">}</span> <span class="ot">→</span> x ≡ y <span class="ot">→</span> y ≡ z <span class="ot">→</span> x ≡ z</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>trans refl y≡z <span class="ot">=</span> y≡z</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>cong <span class="ot">:</span> <span class="ot">(</span>f <span class="ot">:</span> A <span class="ot">→</span> B<span class="ot">)</span> <span class="ot">→</span> <span class="ot">{</span>x y <span class="ot">:</span> A<span class="ot">}</span> <span class="ot">→</span> x ≡ y <span class="ot">→</span> f x ≡ f y</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>cong <span class="ot">_</span> refl <span class="ot">=</span> refl</span></code></pre></div>
<p>Since we will spend a good amount of time reasoning about equality, it
is worthwhile building up some machinery for writing more readable
equality proofs. Instead of writing, say,</p>
<pre class="text"><code>trans p (trans q (trans (sym r) s))</code></pre>
<p>we will be able to instead write equality proofs like so:</p>
<pre class="text"><code>begin
  v      ≡[ p ⟩≡
  w      ≡[ q ⟩≡
  x      ≡⟨ r ]≡
  y      ≡[ s ⟩≡
  z      ∎</code></pre>
<p>The intention is that this proof shows <code>v ≡ z</code>, by first using <code>p</code> to
show that <code>v ≡ w</code>, then <code>q</code> to show <code>w ≡ x</code>, and so on. This notation
is one of my favorite applications of Agda’s <a href="https://agda.readthedocs.io/en/latest/language/mixfix-operators.html">mixfix operator
syntax</a>,
and has several benefits:</p>
<ul>
<li>We can avoid nested parentheses when chaining uses of transitivity.</li>
<li>We can automatically apply symmetry by using a left-pointing
instead of right-pointing operator.</li>
<li>We get to explicitly mention (and have Agda check for us) all the
intermediate values, making it easier to write the proof
incrementally, and much easier for humans to read.</li>
</ul>
<p>This is one of the places where I deliberately chose different
operator names than the standard library, which uses <code>_≡⟨_⟩_</code> and
<code>_≡⟨_⟨_</code>. The operator names I decided to use are <a href="https://personal.cis.strath.ac.uk/conor.mcbride/PolyTest.pdf">inspired by Conor
McBride</a>. I just like the way they look better.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">infix</span> <span class="dv">1</span> begin<span class="ot">_</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>begin<span class="ot">_</span> <span class="ot">:</span> <span class="ot">{</span>x y <span class="ot">:</span> A<span class="ot">}</span> <span class="ot">→</span> x ≡ y <span class="ot">→</span> x ≡ y</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>begin x≡y <span class="ot">=</span> x≡y</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a><span class="kw">infixr</span> <span class="dv">2</span> <span class="ot">_</span>≡[<span class="ot">_</span>⟩≡<span class="ot">_</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>≡[<span class="ot">_</span>⟩≡<span class="ot">_</span> <span class="ot">:</span> <span class="ot">(</span>x <span class="ot">:</span> A<span class="ot">)</span> <span class="ot">→</span> <span class="ot">{</span>y z <span class="ot">:</span> A<span class="ot">}</span> <span class="ot">→</span> <span class="ot">(</span>x ≡ y<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>y ≡ z<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>x ≡ z<span class="ot">)</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span> ≡[ x≡y ⟩≡ y≡z <span class="ot">=</span> trans x≡y y≡z</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="kw">infixr</span> <span class="dv">2</span> <span class="ot">_</span>≡⟨<span class="ot">_</span>]≡<span class="ot">_</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>≡⟨<span class="ot">_</span>]≡<span class="ot">_</span> <span class="ot">:</span> <span class="ot">(</span>x <span class="ot">:</span> A<span class="ot">)</span> <span class="ot">→</span> <span class="ot">{</span>y z <span class="ot">:</span> A<span class="ot">}</span> <span class="ot">→</span> <span class="ot">(</span>y ≡ x<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>y ≡ z<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>x ≡ z<span class="ot">)</span></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span> ≡⟨ y≡x ]≡ y≡z <span class="ot">=</span> trans <span class="ot">(</span>sym y≡x<span class="ot">)</span> y≡z</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="kw">infixr</span> <span class="dv">5</span> <span class="ot">_</span>∎</span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>∎ <span class="ot">:</span> <span class="ot">(</span>x <span class="ot">:</span> A<span class="ot">)</span> <span class="ot">→</span> x ≡ x</span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span> ∎ <span class="ot">=</span> refl</span></code></pre></div>
<p>Finally, a few <a href="https://hackage-content.haskell.org/package/base-4.22.0.0/docs/Prelude.html#t:Applicative">Applicative</a>-like operators for more conveniently
writing common forms of congruence. For example, instead of writing
<code>cong f x≡y</code>, we can write <code>f $≡ x≡y</code>; or to use congruence on both
arguments of a two-place function at once, we can write <code>f $≡ x≡y ≡$≡ z≡w</code>. (These operators were also inspired by Conor.)</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">infixl</span> <span class="dv">4</span> <span class="ot">_</span>$≡<span class="ot">_</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>$≡<span class="ot">_</span> <span class="ot">:</span> <span class="ot">(</span>f <span class="ot">:</span> A <span class="ot">→</span> B<span class="ot">)</span> <span class="ot">→</span> <span class="ot">{</span>x y <span class="ot">:</span> A<span class="ot">}</span> <span class="ot">→</span> x ≡ y <span class="ot">→</span> f x ≡ f y</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>f $≡ x≡y <span class="ot">=</span> cong f x≡y</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="kw">infixl</span> <span class="dv">4</span> <span class="ot">_</span>≡$<span class="ot">_</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>≡$<span class="ot">_</span> <span class="ot">:</span> <span class="ot">{</span>f g <span class="ot">:</span> A <span class="ot">→</span> B<span class="ot">}</span> <span class="ot">→</span> f ≡ g <span class="ot">→</span> <span class="ot">(</span>x <span class="ot">:</span> A<span class="ot">)</span> <span class="ot">→</span> f x ≡ g x</span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>f≡g ≡$ x <span class="ot">=</span> cong <span class="ot">(λ</span> h <span class="ot">→</span> h x<span class="ot">)</span> f≡g</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="kw">infixl</span> <span class="dv">4</span> <span class="ot">_</span>≡$≡<span class="ot">_</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>≡$≡<span class="ot">_</span> <span class="ot">:</span> <span class="ot">{</span>f g <span class="ot">:</span> A <span class="ot">→</span> B<span class="ot">}</span> <span class="ot">→</span> f ≡ g <span class="ot">→</span> <span class="ot">{</span>x y <span class="ot">:</span> A<span class="ot">}</span> <span class="ot">→</span> x ≡ y <span class="ot">→</span> f x ≡ g y</span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>f≡g ≡$≡ x≡y <span class="ot">=</span> trans <span class="ot">(</span>f≡g ≡$ <span class="ot">_)</span> <span class="ot">(_</span> $≡ x≡y<span class="ot">)</span></span></code></pre></div>
</section>
<section id="natural-numbers" class="level2">
<h2>Natural numbers</h2>
<p>Of course, we will need a type to represent the natural numbers. We
can also tell Agda that our natural number type should correspond to its
built-in notion of natural numbers, so we can use numeric literals
like <code>2 : ℕ</code> instead of having to write <code>suc (suc zero)</code>.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> ℕ <span class="ot">:</span> <span class="dt">Set</span> <span class="kw">where</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>  zero <span class="ot">:</span> ℕ</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>  suc <span class="ot">:</span> ℕ <span class="ot">→</span> ℕ</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a><span class="pp">{-# BUILTIN NATURAL ℕ #-}</span></span></code></pre></div>
<section id="no-confusion" class="level3">
<h3>No confusion</h3>
<p>For our natural number type—and often, for any algebraic data type—we
need to know that the constructors are</p>
<ol type="1">
<li><em>disjoint</em>, meaning that different constructors always generate
different values (so it’s a contradiction to have an equality
between values built with different constructors); and</li>
<li><em>injective</em>, meaning that if we have an equality between values built
with the same constructor, we can decompose it into equalities between
the components.</li>
</ol>
<p>We can prove both of these simultaneously using a property called “no
confusion”. This property and its name is well-known in the
literature; for example, see
<a href="http://strictlypositive.org/concon.ps.gz">McBridge</a> or <a href="https://link.springer.com/chapter/10.1007/3-540-61780-9_64">Cornes +
Terrasse</a>.</p>
<p>For natural numbers <code>m</code> and <code>n</code>, the type <code>NoConf m n</code> should be
thought of as the type of evidence that <code>m ≡ n</code>, based on looking at
the top-level constructors of <code>m</code> and <code>n</code>. If <code>m</code> and <code>n</code> have different
constructors, then no evidence can possibly show that they are equal,
so <code>NoConf m n = ⊥</code> in that case. If <code>m</code> and <code>n</code> are both zero, then
they are evidently equal, so <code>NoConf 0 0 = ⊤</code>. Otherwise, if <code>m</code> and
<code>n</code> are both successors, <code>NoConf m n</code> reduces to a proof of equality
between their predecessors.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>NoConf <span class="ot">:</span> ℕ <span class="ot">→</span> ℕ <span class="ot">→</span> <span class="dt">Set</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>NoConf zero zero <span class="ot">=</span> ⊤</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>NoConf zero <span class="ot">(</span>suc n<span class="ot">)</span> <span class="ot">=</span> ⊥</span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>NoConf <span class="ot">(</span>suc m<span class="ot">)</span> zero <span class="ot">=</span> ⊥</span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>NoConf <span class="ot">(</span>suc m<span class="ot">)</span> <span class="ot">(</span>suc n<span class="ot">)</span> <span class="ot">=</span> m ≡ n</span></code></pre></div>
<p>Now we can prove the no confusion lemma for our natural number type,
which says that <code>NoConf m n</code> always holds whenever <code>m ≡ n</code>.
Since <code>m ≡ n</code>, we only have to deal with the cases when <code>m</code> and <code>n</code>
are both zero or both a successor—but this also justifies assigning a
type of <code>⊥</code> to the cases when the constructors do not match. <code>noConf</code>
can therefore be used to strip <code>suc</code> from both sides of an equation,
<em>or</em> to derive a contradiction when we have an equation between
non-matching constructors.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a>noConf <span class="ot">:</span> <span class="ot">{</span>m n <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> m ≡ n <span class="ot">→</span> NoConf m n</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>noConf <span class="ot">{</span>zero<span class="ot">}</span> refl <span class="ot">=</span> tt</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>noConf <span class="ot">{</span>suc m<span class="ot">}</span> refl <span class="ot">=</span> refl</span></code></pre></div>
<p>As an aside, this definition of the no confusion property uses a
technique I like: defining a <em>type</em> starting with a capital letter,
then defining a <em>term</em> that returns that type starting with a
lowercase letter. This pattern will come up again later. Sometimes
we define named types in this way just for convenience, say, to be
able to refer to the type multiple times in a concise way; or, as in
the above case, sometimes the type is actually defined via some
nontrivial computation.</p>
</section>
<section id="decidable-equality" class="level3">
<h3>Decidable equality</h3>
<p>We can now show how to decide equality of natural numbers. We first
define a simple type representing decidability in general: <code>Dec P</code> represents
either a proof of <code>P</code>, or a proof of <code>¬ P</code>.<span class="sidenote-wrapper"><label for="sn-4" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-4" class="margin-toggle"/><span class="sidenote">You may be aware that the
<a href="https://en.wikipedia.org/wiki/Law_of_excluded_middle">law of excluded middle</a>, which
says that <span class="math inline">\(P \lor \neg P\)</span> for all propositions <span class="math inline">\(P\)</span>, is rejected in constructive logic. However, even
though <span class="math inline">\(P \lor \neg P\)</span> does not hold for <em>all</em> <span class="math inline">\(P\)</span>, it can still hold
for certain specific propositions. Propositions <span class="math inline">\(P\)</span> for which <span class="math inline">\(P \lor
\neg P\)</span> holds constructively are called <em>decidable</em>.<br />
<br />
</span></span> (The <a href="https://agda.github.io/agda-stdlib/v2.3/Relation.Nullary.Decidable.Core.html#1966">standard library
version is much more sophisticated</a>, but this simple version will do
just fine.)</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> Dec <span class="ot">(</span>P <span class="ot">:</span> <span class="dt">Set</span><span class="ot">)</span> <span class="ot">:</span> <span class="dt">Set</span> <span class="kw">where</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>  yes <span class="ot">:</span> P <span class="ot">→</span> Dec P</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>  no <span class="ot">:</span> ¬ P <span class="ot">→</span> Dec P</span></code></pre></div>
<p>We can then prove that for any natural numbers <code>x</code> and <code>y</code>, we can decide
whether <code>x ≡ y</code>. Notice the several different uses of the no
confusion lemma: two to handle impossible situations, and one to strip
<code>suc</code> off both sides of an equality.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>≟<span class="ot">_</span> <span class="ot">:</span> <span class="ot">(</span>x y <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> Dec <span class="ot">(</span>x ≡ y<span class="ot">)</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>zero ≟ zero <span class="ot">=</span> yes refl</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>zero ≟ suc y <span class="ot">=</span> no noConf</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>suc x ≟ zero <span class="ot">=</span> no noConf</span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>suc x ≟ suc y <span class="kw">with</span> x ≟ y</span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> yes x≡y <span class="ot">=</span> yes <span class="ot">(</span>suc $≡ x≡y<span class="ot">)</span></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> no x≢y <span class="ot">=</span> no <span class="ot">(λ</span> sx≡sy <span class="ot">→</span> x≢y <span class="ot">(</span>noConf sx≡sy<span class="ot">))</span></span></code></pre></div>
</section>
</section>
<section id="addition" class="level2">
<h2>Addition</h2>
<p>We next turn to defining addition (by pattern-matching on the
left-hand argument), along with several properties of
addition we will need: zero is a right identity for addition; we can
pull out a <code>suc</code> from the right-hand argument; and addition is
commutative, associative, and left-cancellable.</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">infixl</span> <span class="dv">6</span> <span class="ot">_</span>+<span class="ot">_</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>+<span class="ot">_</span> <span class="ot">:</span> ℕ <span class="ot">→</span> ℕ <span class="ot">→</span> ℕ</span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>zero + y <span class="ot">=</span> y</span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>suc x + y <span class="ot">=</span> suc <span class="ot">(</span>x + y<span class="ot">)</span></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>+0 <span class="ot">:</span> <span class="ot">(</span>n <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>n + <span class="dv">0</span> ≡ n<span class="ot">)</span></span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>zero +0 <span class="ot">=</span> refl</span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a><span class="ot">(</span>suc n<span class="ot">)</span> +0 <span class="ot">=</span> suc $≡ <span class="ot">(</span>n +0<span class="ot">)</span></span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>+suc<span class="ot">_</span> <span class="ot">:</span> <span class="ot">(</span>x y <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>x + suc y<span class="ot">)</span> ≡ suc <span class="ot">(</span>x + y<span class="ot">)</span></span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a>zero +suc y <span class="ot">=</span> refl</span>
<span id="cb19-12"><a href="#cb19-12" aria-hidden="true" tabindex="-1"></a><span class="ot">(</span>suc x<span class="ot">)</span> +suc y <span class="ot">=</span> suc $≡ <span class="ot">(</span>x +suc y<span class="ot">)</span></span>
<span id="cb19-13"><a href="#cb19-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-14"><a href="#cb19-14" aria-hidden="true" tabindex="-1"></a>+-comm <span class="ot">:</span> <span class="ot">(</span>x y <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> x + y ≡ y + x</span>
<span id="cb19-15"><a href="#cb19-15" aria-hidden="true" tabindex="-1"></a>+-comm zero y <span class="ot">=</span> sym <span class="ot">(</span>y +0<span class="ot">)</span></span>
<span id="cb19-16"><a href="#cb19-16" aria-hidden="true" tabindex="-1"></a>+-comm <span class="ot">(</span>suc x<span class="ot">)</span> y <span class="ot">=</span> trans <span class="ot">(</span>suc $≡ <span class="ot">(</span>+-comm x y<span class="ot">))</span> <span class="ot">(</span>sym <span class="ot">(</span>y +suc x<span class="ot">))</span></span>
<span id="cb19-17"><a href="#cb19-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-18"><a href="#cb19-18" aria-hidden="true" tabindex="-1"></a>+-assoc <span class="ot">:</span> <span class="ot">(</span>x y z <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>x + y<span class="ot">)</span> + z ≡ x + <span class="ot">(</span>y + z<span class="ot">)</span></span>
<span id="cb19-19"><a href="#cb19-19" aria-hidden="true" tabindex="-1"></a>+-assoc zero y z <span class="ot">=</span> refl</span>
<span id="cb19-20"><a href="#cb19-20" aria-hidden="true" tabindex="-1"></a>+-assoc <span class="ot">(</span>suc x<span class="ot">)</span> y z <span class="ot">=</span> suc $≡ <span class="ot">(</span>+-assoc x y z<span class="ot">)</span></span>
<span id="cb19-21"><a href="#cb19-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-22"><a href="#cb19-22" aria-hidden="true" tabindex="-1"></a>+-cancelˡ <span class="ot">:</span> <span class="ot">(</span>x y z <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> x + y ≡ x + z <span class="ot">→</span> y ≡ z</span>
<span id="cb19-23"><a href="#cb19-23" aria-hidden="true" tabindex="-1"></a>+-cancelˡ zero y z x+y≡x+z <span class="ot">=</span> x+y≡x+z</span>
<span id="cb19-24"><a href="#cb19-24" aria-hidden="true" tabindex="-1"></a>+-cancelˡ <span class="ot">(</span>suc x<span class="ot">)</span> y z x+y≡x+z <span class="ot">=</span> +-cancelˡ x y z <span class="ot">(</span>noConf x+y≡x+z<span class="ot">)</span></span></code></pre></div>
</section>
<section id="multiplication" class="level2">
<h2>Multiplication</h2>
<p>Multiplication is next: we start by defining the multiplication
operation (by pattern-matching on the left-hand argument) and proving
a few lemmas about multiplying by known arguments on the right. The
proof of <code>*suc</code> is the most involved proof we have seen yet, but it
ultimately just comes down to algebra, and we can make good use of our
notation for writing chained equality proofs.</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">infixl</span> <span class="dv">7</span> <span class="ot">_</span>*<span class="ot">_</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>*<span class="ot">_</span> <span class="ot">:</span> ℕ <span class="ot">→</span> ℕ <span class="ot">→</span> ℕ</span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>zero * y <span class="ot">=</span> zero</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>suc x * y <span class="ot">=</span> y + x * 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="ot">_</span>*0 <span class="ot">:</span> <span class="ot">(</span>n <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>n * <span class="dv">0</span> ≡ <span class="dv">0</span><span class="ot">)</span></span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a>zero *0 <span class="ot">=</span> refl</span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a><span class="ot">(</span>suc n<span class="ot">)</span> *0 <span class="ot">=</span> n *0</span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>*1 <span class="ot">:</span> <span class="ot">(</span>n <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>n * <span class="dv">1</span> ≡ n<span class="ot">)</span></span>
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true" tabindex="-1"></a><span class="dv">0</span> *1 <span class="ot">=</span> refl</span>
<span id="cb20-12"><a href="#cb20-12" aria-hidden="true" tabindex="-1"></a><span class="ot">(</span>suc n<span class="ot">)</span> *1 <span class="ot">=</span> suc $≡ <span class="ot">(</span>n *1<span class="ot">)</span></span>
<span id="cb20-13"><a href="#cb20-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-14"><a href="#cb20-14" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>*suc<span class="ot">_</span> <span class="ot">:</span> <span class="ot">(</span>x y <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>x * suc y ≡ x + x * y<span class="ot">)</span></span>
<span id="cb20-15"><a href="#cb20-15" aria-hidden="true" tabindex="-1"></a>zero *suc y <span class="ot">=</span> refl</span>
<span id="cb20-16"><a href="#cb20-16" aria-hidden="true" tabindex="-1"></a><span class="ot">(</span>suc x<span class="ot">)</span> *suc y <span class="ot">=</span> suc $≡ <span class="ot">(</span></span>
<span id="cb20-17"><a href="#cb20-17" aria-hidden="true" tabindex="-1"></a>  begin</span>
<span id="cb20-18"><a href="#cb20-18" aria-hidden="true" tabindex="-1"></a>  y + x * suc y               ≡[ <span class="ot">(</span>y +<span class="ot">_)</span> $≡ <span class="ot">(</span>x *suc y<span class="ot">)</span> ⟩≡</span>
<span id="cb20-19"><a href="#cb20-19" aria-hidden="true" tabindex="-1"></a>  y + <span class="ot">(</span>x + x * y<span class="ot">)</span>             ≡⟨ +-assoc y x <span class="ot">(</span>x * y<span class="ot">)</span> ]≡</span>
<span id="cb20-20"><a href="#cb20-20" aria-hidden="true" tabindex="-1"></a>  <span class="ot">(</span>y + x<span class="ot">)</span> + x * y             ≡[ <span class="ot">_</span>+<span class="ot">_</span> $≡ +-comm y x ≡$ x * y ⟩≡</span>
<span id="cb20-21"><a href="#cb20-21" aria-hidden="true" tabindex="-1"></a>  <span class="ot">(</span>x + y<span class="ot">)</span> + x * y             ≡[ +-assoc x <span class="ot">_</span> <span class="ot">_</span> ⟩≡</span>
<span id="cb20-22"><a href="#cb20-22" aria-hidden="true" tabindex="-1"></a>  x + <span class="ot">(</span>y + x * y<span class="ot">)</span>             ∎<span class="ot">)</span></span></code></pre></div>
<p>We prove some standard properties of multiplication: commutativity,
distributivity over addition, associativity. Again, the proofs mostly
consist of a whole bunch of algebra, using the special notation for
building chained equality proofs.</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>*-comm <span class="ot">:</span> <span class="ot">(</span>x y <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> x * y ≡ y * x</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>*-comm zero y <span class="ot">=</span> sym <span class="ot">(</span>y *0<span class="ot">)</span></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>*-comm <span class="ot">(</span>suc x<span class="ot">)</span> y <span class="ot">=</span> begin</span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>  y + x * y                   ≡[ y +<span class="ot">_</span> $≡ *-comm x y ⟩≡</span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>  y + y * x                   ≡⟨ y *suc x ]≡</span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>  y * suc x                   ∎</span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a>*-distribˡ <span class="ot">:</span> <span class="ot">(</span>x y z <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> x * <span class="ot">(</span>y + z<span class="ot">)</span> ≡ x * y + x * z</span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a>*-distribˡ zero y z <span class="ot">=</span> refl</span>
<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a>*-distribˡ <span class="ot">(</span>suc x<span class="ot">)</span> y z <span class="ot">=</span> begin</span>
<span id="cb21-11"><a href="#cb21-11" aria-hidden="true" tabindex="-1"></a>  y + z + x * <span class="ot">(</span>y + z<span class="ot">)</span>         ≡[ <span class="ot">(</span>y + z<span class="ot">)</span> +<span class="ot">_</span> $≡ *-distribˡ x y z ⟩≡</span>
<span id="cb21-12"><a href="#cb21-12" aria-hidden="true" tabindex="-1"></a>  y + z + <span class="ot">(</span>x * y + x * z<span class="ot">)</span>     ≡[ +-assoc y <span class="ot">_</span> <span class="ot">_</span> ⟩≡</span>
<span id="cb21-13"><a href="#cb21-13" aria-hidden="true" tabindex="-1"></a>  y + <span class="ot">(</span>z + <span class="ot">(</span>x * y + x * z<span class="ot">))</span>   ≡⟨ y +<span class="ot">_</span> $≡ +-assoc z <span class="ot">_</span> <span class="ot">_</span> ]≡</span>
<span id="cb21-14"><a href="#cb21-14" aria-hidden="true" tabindex="-1"></a>  y + <span class="ot">((</span>z + x * y<span class="ot">)</span> + x * z<span class="ot">)</span>   ≡[ y +<span class="ot">_</span> $≡ <span class="ot">(_</span>+<span class="ot">_</span> $≡ +-comm z <span class="ot">_</span> ≡$ x * z<span class="ot">)</span> ⟩≡</span>
<span id="cb21-15"><a href="#cb21-15" aria-hidden="true" tabindex="-1"></a>  y + <span class="ot">((</span>x * y + z<span class="ot">)</span> + x * z<span class="ot">)</span>   ≡[ y +<span class="ot">_</span> $≡ +-assoc <span class="ot">(</span>x * y<span class="ot">)</span> <span class="ot">_</span> <span class="ot">_</span> ⟩≡</span>
<span id="cb21-16"><a href="#cb21-16" aria-hidden="true" tabindex="-1"></a>  y + <span class="ot">(</span>x * y + <span class="ot">(</span>z + x * z<span class="ot">))</span>   ≡⟨ +-assoc y <span class="ot">_</span> <span class="ot">_</span> ]≡</span>
<span id="cb21-17"><a href="#cb21-17" aria-hidden="true" tabindex="-1"></a>  y + x * y + <span class="ot">(</span>z + x * z<span class="ot">)</span>     ∎</span>
<span id="cb21-18"><a href="#cb21-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-19"><a href="#cb21-19" aria-hidden="true" tabindex="-1"></a>*-distribʳ <span class="ot">:</span> <span class="ot">(</span>x y z <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>x + y<span class="ot">)</span> * z ≡ x * z + y * z</span>
<span id="cb21-20"><a href="#cb21-20" aria-hidden="true" tabindex="-1"></a>*-distribʳ x y z <span class="ot">=</span> begin</span>
<span id="cb21-21"><a href="#cb21-21" aria-hidden="true" tabindex="-1"></a>  <span class="ot">(</span>x + y<span class="ot">)</span> * z                 ≡[ *-comm <span class="ot">(</span>x + y<span class="ot">)</span> <span class="ot">_</span> ⟩≡</span>
<span id="cb21-22"><a href="#cb21-22" aria-hidden="true" tabindex="-1"></a>  z * <span class="ot">(</span>x + y<span class="ot">)</span>                 ≡[ *-distribˡ z <span class="ot">_</span> <span class="ot">_</span> ⟩≡</span>
<span id="cb21-23"><a href="#cb21-23" aria-hidden="true" tabindex="-1"></a>  z * x + z * y               ≡[ <span class="ot">_</span>+<span class="ot">_</span> $≡ *-comm z <span class="ot">_</span> ≡$≡ *-comm z <span class="ot">_</span> ⟩≡</span>
<span id="cb21-24"><a href="#cb21-24" aria-hidden="true" tabindex="-1"></a>  x * z + y * z               ∎</span>
<span id="cb21-25"><a href="#cb21-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-26"><a href="#cb21-26" aria-hidden="true" tabindex="-1"></a>*-assoc <span class="ot">:</span> <span class="ot">(</span>x y z <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>x * y<span class="ot">)</span> * z ≡ x * <span class="ot">(</span>y * z<span class="ot">)</span></span>
<span id="cb21-27"><a href="#cb21-27" aria-hidden="true" tabindex="-1"></a>*-assoc zero y z <span class="ot">=</span> refl</span>
<span id="cb21-28"><a href="#cb21-28" aria-hidden="true" tabindex="-1"></a>*-assoc <span class="ot">(</span>suc x<span class="ot">)</span> y z <span class="ot">=</span> begin</span>
<span id="cb21-29"><a href="#cb21-29" aria-hidden="true" tabindex="-1"></a>  <span class="ot">(</span>y + x * y<span class="ot">)</span> * z             ≡[ *-distribʳ y <span class="ot">_</span> <span class="ot">_</span> ⟩≡</span>
<span id="cb21-30"><a href="#cb21-30" aria-hidden="true" tabindex="-1"></a>  y * z + <span class="ot">(</span>x * y<span class="ot">)</span> * z         ≡[ y * z +<span class="ot">_</span> $≡ *-assoc x <span class="ot">_</span> <span class="ot">_</span> ⟩≡</span>
<span id="cb21-31"><a href="#cb21-31" aria-hidden="true" tabindex="-1"></a>  y * z + x * <span class="ot">(</span>y * z<span class="ot">)</span>         ∎</span></code></pre></div>
<p>Finally, we prove that multiplication is left-cancellative. This
proof is somewhat tricky—in the case that <code>x</code>, <code>y</code>, and <code>z</code> are all
successors, we need to use the induction hypothesis (<em>i.e.</em> a
recursive call to <code>*-cancelˡ</code>) on <code>x</code> and the
predecessors of <code>y</code> and <code>z</code>, using the fact that + is
left-cancellative to construct the required input equality.</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a>*-cancelˡ <span class="ot">:</span> <span class="ot">(</span>x y z <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span><span class="dv">0</span> ≢ x<span class="ot">)</span> <span class="ot">→</span> x * y ≡ x * z <span class="ot">→</span> y ≡ z</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>*-cancelˡ zero y z x≢0 xy≡xz <span class="ot">=</span> absurd <span class="ot">(</span>x≢0 refl<span class="ot">)</span></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>*-cancelˡ <span class="ot">(</span>suc x<span class="ot">)</span> zero zero x≢0 xy≡xz <span class="ot">=</span> refl</span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>*-cancelˡ <span class="ot">(</span>suc x<span class="ot">)</span> zero <span class="ot">(</span>suc z<span class="ot">)</span> x≢0 xy≡xz <span class="ot">=</span> absurd <span class="ot">(</span>noConf <span class="ot">(</span>trans <span class="ot">(</span>sym <span class="ot">(</span>x *0<span class="ot">))</span> xy≡xz<span class="ot">))</span></span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a>*-cancelˡ <span class="ot">(</span>suc x<span class="ot">)</span> <span class="ot">(</span>suc y<span class="ot">)</span> zero x≢0 xy≡xz <span class="ot">=</span> absurd <span class="ot">(</span>noConf <span class="ot">(</span>trans xy≡xz <span class="ot">(</span>x *0<span class="ot">)))</span></span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a>*-cancelˡ <span class="ot">(</span>suc x<span class="ot">)</span> <span class="ot">(</span>suc y<span class="ot">)</span> <span class="ot">(</span>suc z<span class="ot">)</span> x≢0 xy≡xz <span class="ot">=</span> suc $≡</span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a>  <span class="ot">(</span> *-cancelˡ <span class="ot">(</span>suc x<span class="ot">)</span> y z x≢0</span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a>    <span class="ot">(</span> +-cancelˡ <span class="ot">(</span>suc x<span class="ot">)</span> <span class="ot">(</span>suc x * y<span class="ot">)</span> <span class="ot">(</span>suc x * z<span class="ot">)</span></span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a>      <span class="ot">(</span> begin</span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a>          suc x + suc x * y   ≡⟨ <span class="ot">(</span>suc x<span class="ot">)</span> *suc y ]≡</span>
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a>          suc x * suc y       ≡[ xy≡xz ⟩≡</span>
<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a>          suc x * suc z       ≡[ <span class="ot">(</span>suc x<span class="ot">)</span> *suc z ⟩≡</span>
<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a>          suc x + suc x * z   ∎</span>
<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a>      <span class="ot">)</span></span>
<span id="cb22-15"><a href="#cb22-15" aria-hidden="true" tabindex="-1"></a>    <span class="ot">)</span></span>
<span id="cb22-16"><a href="#cb22-16" aria-hidden="true" tabindex="-1"></a>  <span class="ot">)</span></span></code></pre></div>
</section>
<section id="inequality" class="level2">
<h2>Inequality</h2>
<p>Next, we give a standard definition of the “less than or equal to”
relation on natural numbers. Note that the structure of a proof of <span class="math inline">\(x \leq
y\)</span> exactly matches the structure of <span class="math inline">\(x\)</span> itself.</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="ot">_</span>≤<span class="ot">_</span> <span class="ot">:</span> ℕ <span class="ot">→</span> ℕ <span class="ot">→</span> <span class="dt">Set</span> <span class="kw">where</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>  zle <span class="ot">:</span> <span class="ot">{</span>n <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> zero ≤ n</span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>  sle <span class="ot">:</span> <span class="ot">{</span>m n <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> m ≤ n <span class="ot">→</span> suc m ≤ suc n</span></code></pre></div>
<p>We also prove some standard properties of <span class="math inline">\(\leq\)</span>: it is reflexive and
transitive, and is related to <code>suc</code> in various ways.</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a>≤-refl <span class="ot">:</span> <span class="ot">{</span>m <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> m ≤ m</span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>≤-refl <span class="ot">{</span>zero<span class="ot">}</span> <span class="ot">=</span> zle</span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>≤-refl <span class="ot">{</span>suc m<span class="ot">}</span> <span class="ot">=</span> sle ≤-refl</span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a>≤-trans <span class="ot">:</span> <span class="ot">{</span>x y z <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> x ≤ y <span class="ot">→</span> y ≤ z <span class="ot">→</span> x ≤ z</span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a>≤-trans zle y≤z <span class="ot">=</span> zle</span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a>≤-trans <span class="ot">(</span>sle x≤y<span class="ot">)</span> <span class="ot">(</span>sle y≤z<span class="ot">)</span> <span class="ot">=</span> sle <span class="ot">(</span>≤-trans x≤y y≤z<span class="ot">)</span></span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a>≤-sucr <span class="ot">:</span> <span class="ot">{</span>m n <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> m ≤ n <span class="ot">→</span> m ≤ suc n</span>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a>≤-sucr zle <span class="ot">=</span> zle</span>
<span id="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a>≤-sucr <span class="ot">(</span>sle m≤n<span class="ot">)</span> <span class="ot">=</span> sle <span class="ot">(</span>≤-sucr m≤n<span class="ot">)</span></span>
<span id="cb24-12"><a href="#cb24-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-13"><a href="#cb24-13" aria-hidden="true" tabindex="-1"></a>≤-sucl <span class="ot">:</span> <span class="ot">{</span>m n <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> suc m ≤ n <span class="ot">→</span> m ≤ n</span>
<span id="cb24-14"><a href="#cb24-14" aria-hidden="true" tabindex="-1"></a>≤-sucl <span class="ot">(</span>sle sm≤n<span class="ot">)</span> <span class="ot">=</span> ≤-sucr sm≤n</span>
<span id="cb24-15"><a href="#cb24-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-16"><a href="#cb24-16" aria-hidden="true" tabindex="-1"></a>≤-pred <span class="ot">:</span> <span class="ot">{</span>x y <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> suc x ≤ suc y <span class="ot">→</span> x ≤ y</span>
<span id="cb24-17"><a href="#cb24-17" aria-hidden="true" tabindex="-1"></a>≤-pred <span class="ot">(</span>sle sx≤sy<span class="ot">)</span> <span class="ot">=</span> sx≤sy</span></code></pre></div>
<p>For convenience, we define <span class="math inline">\(&lt;\)</span> in terms of <span class="math inline">\(\leq\)</span>, and prove a few
properties: any number is less than its successor, and <span class="math inline">\(&lt;\)</span> is
transitive and non-reflexive.</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>&lt;<span class="ot">_</span> <span class="ot">:</span> ℕ <span class="ot">→</span> ℕ <span class="ot">→</span> <span class="dt">Set</span></span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a>x &lt; y <span class="ot">=</span> suc x ≤ y</span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>&lt;suc <span class="ot">:</span> <span class="ot">(</span>x <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> x &lt; suc x</span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>&lt;suc zero <span class="ot">=</span> sle zle</span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>&lt;suc <span class="ot">(</span>suc x<span class="ot">)</span> <span class="ot">=</span> sle <span class="ot">(</span>x &lt;suc<span class="ot">)</span></span>
<span id="cb25-7"><a href="#cb25-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-8"><a href="#cb25-8" aria-hidden="true" tabindex="-1"></a>&lt;-trans <span class="ot">:</span> <span class="ot">{</span>x y z <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> x &lt; y <span class="ot">→</span> y &lt; z <span class="ot">→</span> x &lt; z</span>
<span id="cb25-9"><a href="#cb25-9" aria-hidden="true" tabindex="-1"></a>&lt;-trans <span class="ot">(</span>sle x&lt;y<span class="ot">)</span> <span class="ot">(</span>sle y&lt;z<span class="ot">)</span> <span class="ot">=</span> ≤-trans <span class="ot">(</span>sle x&lt;y<span class="ot">)</span> <span class="ot">(</span>≤-sucr y&lt;z<span class="ot">)</span></span>
<span id="cb25-10"><a href="#cb25-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-11"><a href="#cb25-11" aria-hidden="true" tabindex="-1"></a>x≮x <span class="ot">:</span> <span class="ot">{</span>x <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> ¬ <span class="ot">(</span>x &lt; x<span class="ot">)</span></span>
<span id="cb25-12"><a href="#cb25-12" aria-hidden="true" tabindex="-1"></a>x≮x <span class="ot">{</span>zero<span class="ot">}</span> <span class="ot">=</span> <span class="ot">λ</span> <span class="ot">()</span></span>
<span id="cb25-13"><a href="#cb25-13" aria-hidden="true" tabindex="-1"></a>x≮x <span class="ot">{</span>suc x<span class="ot">}</span> <span class="ot">=</span> <span class="ot">λ</span> <span class="ot">{</span> <span class="ot">(</span>sle x&lt;x<span class="ot">)</span> <span class="ot">→</span> x≮x x&lt;x<span class="ot">}</span></span></code></pre></div>
<section id="relationships-among-equality-and-inequality" class="level3">
<h3>Relationships among equality and inequality</h3>
<p>Of course, equality, <span class="math inline">\(&lt;\)</span> and <span class="math inline">\(\leq\)</span> have various relationships that we
will need. First, equality implies <span class="math inline">\(\leq\)</span>.</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a>≡→≤ <span class="ot">:</span> <span class="ot">{</span>x y <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> x ≡ y <span class="ot">→</span> x ≤ y</span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>≡→≤ refl <span class="ot">=</span> ≤-refl</span></code></pre></div>
<p>Next, <span class="math inline">\(x &lt; y\)</span> implies that <span class="math inline">\(x\)</span> and <span class="math inline">\(y\)</span> are <em>not</em> related by <span class="math inline">\(\equiv\)</span> or
<span class="math inline">\(\geq\)</span>. The first lemma in particular—that <span class="math inline">\(&lt;\)</span> implies <span class="math inline">\(\not\equiv\)</span>—gets used quite a bit. Note that it can be read in two equivalent
ways: on the surface, it is a way to turn a proof of <span class="math inline">\(x &lt; y\)</span> into a
proof of <span class="math inline">\(x \not\equiv y\)</span>; but
since <span class="math inline">\(x \not\equiv y\)</span> is really an abbreviation for <span class="math inline">\((x \equiv y) \to \bot\)</span>, it can be
used to derive a contradiction if we have proofs that <span class="math inline">\(x &lt; y\)</span> and
also <span class="math inline">\(x \equiv y\)</span>.</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a>&lt;→≢ <span class="ot">:</span> <span class="ot">{</span>x y <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> x &lt; y <span class="ot">→</span> x ≢ y</span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>&lt;→≢ x&lt;y refl <span class="ot">=</span> x≮x x&lt;y</span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a>&lt;→≱ <span class="ot">:</span> <span class="ot">{</span>x y <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> x &lt; y <span class="ot">→</span> ¬ <span class="ot">(</span>y ≤ x<span class="ot">)</span></span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a>&lt;→≱ <span class="ot">(</span>sle x&lt;y<span class="ot">)</span> <span class="ot">(</span>sle y≤x<span class="ot">)</span> <span class="ot">=</span> &lt;→≱ x&lt;y y≤x</span></code></pre></div>
<p>If <span class="math inline">\(x \leq y\)</span> but they are not equal, then <span class="math inline">\(x &lt; y\)</span>.</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a>≤≢→&lt; <span class="ot">:</span> <span class="ot">{</span>x y <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> x ≤ y <span class="ot">→</span> x ≢ y <span class="ot">→</span> x &lt; y</span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>≤≢→&lt; <span class="ot">{</span>y <span class="ot">=</span> zero<span class="ot">}</span> zle x≢y <span class="ot">=</span> absurd <span class="ot">(</span>x≢y refl<span class="ot">)</span></span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a>≤≢→&lt; <span class="ot">{</span>y <span class="ot">=</span> suc y<span class="ot">}</span> zle x≢y <span class="ot">=</span> sle zle</span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a>≤≢→&lt; <span class="ot">(</span>sle x≤y<span class="ot">)</span> x≢y <span class="ot">=</span> sle <span class="ot">(</span>≤≢→&lt; x≤y <span class="ot">(λ</span> m≡n <span class="ot">→</span> x≢y <span class="ot">(</span>suc $≡ m≡n<span class="ot">)))</span></span></code></pre></div>
<p>We will need a form of transitivity that says if <span class="math inline">\(x \leq y\)</span> and <span class="math inline">\(y &lt;
z\)</span>, then <span class="math inline">\(x &lt; z\)</span>, as well as the other way around.</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a>≤-&lt;-trans <span class="ot">:</span> <span class="ot">{</span>x y z <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> x ≤ y <span class="ot">→</span> y &lt; z <span class="ot">→</span> x &lt; z</span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>≤-&lt;-trans x≤y <span class="ot">(</span>sle y&lt;z<span class="ot">)</span> <span class="ot">=</span> ≤-trans <span class="ot">(</span>sle x≤y<span class="ot">)</span> <span class="ot">(</span>sle y&lt;z<span class="ot">)</span></span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a>&lt;-≤-trans <span class="ot">:</span> <span class="ot">{</span>x y z <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> x &lt; y <span class="ot">→</span> y ≤ z <span class="ot">→</span> x &lt; z</span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a>&lt;-≤-trans <span class="ot">(</span>sle x&lt;y<span class="ot">)</span> y≤z <span class="ot">=</span> ≤-trans <span class="ot">(</span>sle x&lt;y<span class="ot">)</span> y≤z</span></code></pre></div>
<p>Finally, a very specific lemma we will need: if a number is not
equal to either 0 or 1, then it must be greater than or equal to 2.</p>
<div class="sourceCode" id="cb30"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a>¬01-is-≥2 <span class="ot">:</span> <span class="ot">(</span>a <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>a ≢ <span class="dv">0</span><span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>a ≢ <span class="dv">1</span><span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span><span class="dv">2</span> ≤ a<span class="ot">)</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>¬01-is-≥2 zero a≢0 a≢1 <span class="ot">=</span> absurd <span class="ot">(</span>a≢0 refl<span class="ot">)</span></span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a>¬01-is-≥2 <span class="ot">(</span>suc zero<span class="ot">)</span> a≢0 a≢1 <span class="ot">=</span> absurd <span class="ot">(</span>a≢1 refl<span class="ot">)</span></span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a>¬01-is-≥2 <span class="ot">(</span>suc <span class="ot">(</span>suc a<span class="ot">))</span> a≢0 a≢1 <span class="ot">=</span> sle <span class="ot">(</span>sle zle<span class="ot">)</span></span></code></pre></div>
</section>
<section id="arithmetic-and-inequality" class="level3">
<h3>Arithmetic and inequality</h3>
<p>The last lemmas we need relate arithmetic operations and inequality.
First, adding and multiplying cannot make anything smaller (unless we
multiply by zero, of course).</p>
<div class="sourceCode" id="cb31"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a>≤+ <span class="ot">:</span> <span class="ot">{</span>x y <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> x ≤ <span class="ot">(</span>x + y<span class="ot">)</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>≤+ <span class="ot">{</span>zero<span class="ot">}</span> <span class="ot">=</span> zle</span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a>≤+ <span class="ot">{</span>suc x<span class="ot">}</span> <span class="ot">=</span> sle ≤+</span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a>≤* <span class="ot">:</span> <span class="ot">{</span>x y <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> <span class="ot">(</span>x ≢ <span class="dv">0</span><span class="ot">)</span> <span class="ot">→</span> y ≤ <span class="ot">(</span>x * y<span class="ot">)</span></span>
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a>≤* <span class="ot">{</span>zero<span class="ot">}</span> x≢0 <span class="ot">=</span> absurd <span class="ot">(</span>x≢0 refl<span class="ot">)</span></span>
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a>≤* <span class="ot">{</span>suc x<span class="ot">}</span> x≢0 <span class="ot">=</span> ≤+</span></code></pre></div>
<p>As a result, if we know that one thing is equal to a sum or product of
other things, we can conclude something about their relative sizes.</p>
<div class="sourceCode" id="cb32"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a>+→≤ <span class="ot">:</span> <span class="ot">{</span>x y z <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> x + y ≡ z <span class="ot">→</span> x ≤ z</span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>+→≤ refl <span class="ot">=</span> ≤+</span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a>+→&lt; <span class="ot">:</span> <span class="ot">{</span>x y z <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> <span class="dv">0</span> &lt; y <span class="ot">→</span> x + y ≡ z <span class="ot">→</span> x &lt; z</span>
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a>+→&lt; <span class="ot">{</span>x<span class="ot">}</span> <span class="ot">{</span>suc y<span class="ot">}</span> <span class="ot">_</span> x+y≡z <span class="ot">=</span> +→≤ <span class="ot">(</span>trans <span class="ot">(</span>sym <span class="ot">(</span>x +suc y<span class="ot">))</span> x+y≡z<span class="ot">)</span></span>
<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a>*→≤ <span class="ot">:</span> <span class="ot">{</span>x y z <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> <span class="ot">(</span>y ≢ <span class="dv">0</span><span class="ot">)</span> <span class="ot">→</span> y * x ≡ z <span class="ot">→</span> x ≤ z</span>
<span id="cb32-8"><a href="#cb32-8" aria-hidden="true" tabindex="-1"></a>*→≤ <span class="ot">{</span>x<span class="ot">}</span> <span class="ot">{</span>y<span class="ot">}</span> y≢0 refl <span class="ot">=</span> ≤* y≢0</span></code></pre></div>
</section>
</section>
<section id="divisibility-primes-and-composites" class="level2">
<h2>Divisibility, primes, and composites</h2>
<p>With the preliminaries out of the way, we can finally get on with the
meat of the problem—and we finally get to make use of a dependent pair! A <em>constructive</em> proof that <code>a</code> divides
<code>b</code> is a specific natural number witness <code>k</code>, along with a proof that <code>k * a ≡ b</code>.</p>
<div class="sourceCode" id="cb33"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>∣<span class="ot">_</span> <span class="ot">:</span> ℕ <span class="ot">→</span> ℕ <span class="ot">→</span> <span class="dt">Set</span></span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a>a ∣ b <span class="ot">=</span> Σ ℕ <span class="ot">(λ</span> k <span class="ot">→</span> k * a ≡ b<span class="ot">)</span></span></code></pre></div>
<p>Proofs of divisibility are unique—that is, for given <span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span> there
is at most one value of <span class="math inline">\(k\)</span> such that <span class="math inline">\(ka = b\)</span>. We won’t need this,
but it follows easily from the fact that multiplication is
cancellative. More interesting is the fact that divisibility is
<em>decidable</em>—that is, for given numbers <span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span> we can calculate
either a proof that <span class="math inline">\(a \mid b\)</span>, or a proof that <span class="math inline">\(\neg (a \mid b)\)</span>.
This will play a starring role later on—to factor a number we need to
be able to try potential divisors and find out whether they work—but proving it is not easy!
It will take us several hundred more lines of Agda to get there.</p>
<p>In any case, using this notion of divisibility, we can now define prime and
composite numbers. A number <span class="math inline">\(n\)</span> is defined to be prime if it is at
least two, and every <span class="math inline">\(2 \leq d &lt; n\)</span> does <em>not</em> divide <span class="math inline">\(n\)</span>.</p>
<div class="sourceCode" id="cb34"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a>Prime <span class="ot">:</span> ℕ <span class="ot">→</span> <span class="dt">Set</span></span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>Prime n <span class="ot">=</span> <span class="ot">(</span><span class="dv">2</span> ≤ n<span class="ot">)</span> × <span class="ot">(∀</span> <span class="ot">(</span>d <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>d &lt; n<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span><span class="dv">2</span> ≤ d<span class="ot">)</span> <span class="ot">→</span> ¬ <span class="ot">(</span>d ∣ n<span class="ot">))</span></span></code></pre></div>
<p>One could equivalently define primality by saying that any divisor of
<span class="math inline">\(n\)</span> must be equal to <span class="math inline">\(1\)</span> or <span class="math inline">\(n\)</span>; I just decided I liked this
formulation better, especially because it directly matches up with the
way we will test a number for primality later.</p>
<p>A composite number is one that has a nontrivial divisor—that is, a number <span class="math inline">\(d\)</span>
such that <span class="math inline">\(2 \leq d &lt; n\)</span> and <span class="math inline">\(d\)</span> divides <span class="math inline">\(n\)</span>.<span class="sidenote-wrapper"><label for="sn-5" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-5" class="margin-toggle"/><span class="sidenote">Note
that we could easily prove that if <span class="math inline">\(n\)</span> is prime then <span class="math inline">\(n\)</span> is not
composite, and likewise if <span class="math inline">\(n\)</span> is composite then it is not prime, but
we won’t end up needing these lemmas.<br />
<br />
</span></span></p>
<div class="sourceCode" id="cb35"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a>Composite <span class="ot">:</span> ℕ <span class="ot">→</span> <span class="dt">Set</span></span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a>Composite n <span class="ot">=</span> Σ ℕ <span class="ot">(λ</span> d <span class="ot">→</span> <span class="dv">2</span> ≤ d × d &lt; n × d ∣ n<span class="ot">)</span></span></code></pre></div>
<p>Unlike proofs of divisibility, proofs of <code>Composite n</code> are <em>not</em>
unique. For example, we could prove <code>Composite 12</code> by showing that
<span class="math inline">\(2\)</span> is a nontrivial divisor of <span class="math inline">\(12\)</span>, or by showing that <span class="math inline">\(3\)</span> is.
Although this does not matter from a purely logical point of view, it
matters computationally; in general, we care which specific proof of
<code>Composite n</code> we have.</p>
<section id="nontrivial-divisors-come-in-pairs" class="level3">
<h3>Nontrivial divisors come in pairs</h3>
<p>Before moving on to other things, we will prove a lemma about
composite numbers. If <span class="math inline">\(n\)</span> is composite, by definition it has a
nontrivial divisor <span class="math inline">\(a\)</span>; but this means it must also have a second
nontrivial divisor <span class="math inline">\(b\)</span> such that <span class="math inline">\(ab = n\)</span>. This fact seems almost
trivial to us. Indeed, it’s easy to show that if <span class="math inline">\(n\)</span> has a divisor
<span class="math inline">\(a\)</span>, then it must have another divisor <span class="math inline">\(b\)</span> such that <span class="math inline">\(ab = n\)</span>. The
tricky part is showing that if <span class="math inline">\(a\)</span> is a <em>nontrivial</em> divisor, then <span class="math inline">\(b\)</span>
is <em>also</em> nontrivial. The proof relies on much of the infrastructure
we have built up about natural numbers, multiplication, and
inequality.</p>
<p>First, we define a type representing two factors of a number <span class="math inline">\(n\)</span>: a
pair of proofs that <span class="math inline">\(n\)</span> is composite (<em>i.e.</em> two nontrivial divisors
of <span class="math inline">\(n\)</span>), along with a proof that the product of those divisors is <span class="math inline">\(n\)</span>.</p>
<div class="sourceCode" id="cb36"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a>FactorsOf <span class="ot">:</span> ℕ <span class="ot">→</span> <span class="dt">Set</span></span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a>FactorsOf n <span class="ot">=</span> Σ <span class="ot">(</span>Composite n × Composite n<span class="ot">)</span> <span class="ot">(λ</span> <span class="ot">{(</span>f₁ , f₂<span class="ot">)</span> <span class="ot">→</span> fst f₁ * fst f₂ ≡ n<span class="ot">})</span></span></code></pre></div>
<p>Now, we prove that if <span class="math inline">\(n\)</span> is composite, then it has two nontrivial
factors. We begin by pattern-matching on the proof that <span class="math inline">\(n\)</span> is
composite, which consists of a divisor <span class="math inline">\(a\)</span>, evidence that <span class="math inline">\(a\)</span> is
nontrivial (<em>i.e.</em> <span class="math inline">\(2 \leq a\)</span> and <span class="math inline">\(a &lt; n\)</span>), and a proof that <span class="math inline">\(a\)</span> is a
divisor of <span class="math inline">\(n\)</span>, which itself consists of a number <span class="math inline">\(b\)</span> paired with a
proof that <span class="math inline">\(ba = n\)</span>.</p>
<div class="sourceCode" id="cb37"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a>factorsOf <span class="ot">:</span> <span class="ot">(</span>n <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> Composite n <span class="ot">→</span> FactorsOf n</span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a>factorsOf n <span class="ot">(</span>a , 2≤a , a&lt;n , b , ba≡n<span class="ot">)</span> <span class="ot">=</span></span></code></pre></div>
<p>To construct the proof of <code>FactorsOf n</code>, we need two proofs of
<code>Composite n</code> along with a proof that the product of the two divisors
is <span class="math inline">\(n\)</span>. We already have a proof that <span class="math inline">\(ba = n\)</span>, so we use that, with
<span class="math inline">\(a\)</span> as the second divisor (replicating the corresponding proof of
<code>Composite n</code>), and <span class="math inline">\(b\)</span> as the first. Proving that <span class="math inline">\(b\)</span> is a divisor of
<span class="math inline">\(n\)</span> is easy: <span class="math inline">\(a\)</span> is the witness, and proving that <span class="math inline">\(ab = n\)</span> is easy
since we already know <span class="math inline">\(ba = n\)</span> and multiplication is commutative. The
only thing left is to prove that <span class="math inline">\(b\)</span> is nontrivial, <em>i.e.</em> that <span class="math inline">\(2
\leq b\)</span> and <span class="math inline">\(b &lt; n\)</span>.</p>
<div class="sourceCode" id="cb38"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a>  <span class="ot">((</span>b , 2≤b , b&lt;n , a , trans <span class="ot">(</span>*-comm a b<span class="ot">)</span> ba≡n<span class="ot">)</span> , <span class="ot">(</span>a , 2≤a , a&lt;n , b , ba≡n<span class="ot">))</span> , ba≡n</span></code></pre></div>
<p>First, we need a lemma that <span class="math inline">\(0 &lt; n\)</span>, which follows because <span class="math inline">\(0 &lt; 1 &lt; a
&lt; n\)</span> (remember that a proof of <span class="math inline">\(1 &lt; a\)</span> is actually defined to be the
same thing as a proof of <span class="math inline">\(2 \leq a\)</span>).</p>
<div class="sourceCode" id="cb39"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a>  0&lt;n <span class="ot">:</span> <span class="dv">0</span> &lt; n</span>
<span id="cb39-3"><a href="#cb39-3" aria-hidden="true" tabindex="-1"></a>  0&lt;n <span class="ot">=</span> &lt;-trans <span class="ot">(</span>sle zle<span class="ot">)</span> <span class="ot">(</span>&lt;-trans 2≤a a&lt;n<span class="ot">)</span></span></code></pre></div>
<p>Next, we tackle <span class="math inline">\(2 \leq b\)</span>, by showing that <span class="math inline">\(b\)</span> can’t possibly be <span class="math inline">\(0\)</span>
or <span class="math inline">\(1\)</span> (using our previous lemma that anything not equal to 0 or 1
must be greater than or equal to 2).</p>
<div class="sourceCode" id="cb40"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a>  2≤b <span class="ot">:</span> <span class="dv">2</span> ≤ b</span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a>  2≤b <span class="ot">=</span> ¬01-is-≥2 b</span></code></pre></div>
<p>If <span class="math inline">\(b\)</span> were <span class="math inline">\(0\)</span>, then <span class="math inline">\(ba = n\)</span> would imply <span class="math inline">\(0 = n\)</span>, but we know
<span class="math inline">\(0 &lt; n\)</span>, so this is a contradiction.</p>
<div class="sourceCode" id="cb41"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a>    <span class="ot">(λ</span> b≡0 <span class="ot">→</span> &lt;→≢ 0&lt;n</span>
<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a>      <span class="ot">(</span>begin</span>
<span id="cb41-3"><a href="#cb41-3" aria-hidden="true" tabindex="-1"></a>        <span class="dv">0</span>                     ≡[ refl ⟩≡</span>
<span id="cb41-4"><a href="#cb41-4" aria-hidden="true" tabindex="-1"></a>        <span class="dv">0</span> * a                 ≡⟨ <span class="ot">_</span>*<span class="ot">_</span> $≡ b≡0 ≡$ a ]≡</span>
<span id="cb41-5"><a href="#cb41-5" aria-hidden="true" tabindex="-1"></a>        b * a                 ≡[ ba≡n ⟩≡</span>
<span id="cb41-6"><a href="#cb41-6" aria-hidden="true" tabindex="-1"></a>        n                     ∎</span>
<span id="cb41-7"><a href="#cb41-7" aria-hidden="true" tabindex="-1"></a>      <span class="ot">)</span></span>
<span id="cb41-8"><a href="#cb41-8" aria-hidden="true" tabindex="-1"></a>    <span class="ot">)</span></span></code></pre></div>
<p>If <span class="math inline">\(b\)</span> were <span class="math inline">\(1\)</span>, then <span class="math inline">\(ba = n\)</span> would imply <span class="math inline">\(a = n\)</span>, but we know
<span class="math inline">\(a &lt; n\)</span>, so this is also a contradiction.</p>
<div class="sourceCode" id="cb42"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb42-1"><a href="#cb42-1" aria-hidden="true" tabindex="-1"></a>    <span class="ot">(λ</span> b≡1 <span class="ot">→</span> &lt;→≢ a&lt;n</span>
<span id="cb42-2"><a href="#cb42-2" aria-hidden="true" tabindex="-1"></a>      <span class="ot">(</span>begin</span>
<span id="cb42-3"><a href="#cb42-3" aria-hidden="true" tabindex="-1"></a>        a                     ≡⟨ a *1 ]≡</span>
<span id="cb42-4"><a href="#cb42-4" aria-hidden="true" tabindex="-1"></a>        a * <span class="dv">1</span>                 ≡[ *-comm a <span class="dv">1</span> ⟩≡</span>
<span id="cb42-5"><a href="#cb42-5" aria-hidden="true" tabindex="-1"></a>        <span class="dv">1</span> * a                 ≡⟨ <span class="ot">_</span>*<span class="ot">_</span> $≡ b≡1 ≡$ a ]≡</span>
<span id="cb42-6"><a href="#cb42-6" aria-hidden="true" tabindex="-1"></a>        b * a                 ≡[ ba≡n ⟩≡</span>
<span id="cb42-7"><a href="#cb42-7" aria-hidden="true" tabindex="-1"></a>        n                     ∎</span>
<span id="cb42-8"><a href="#cb42-8" aria-hidden="true" tabindex="-1"></a>      <span class="ot">)</span></span>
<span id="cb42-9"><a href="#cb42-9" aria-hidden="true" tabindex="-1"></a>    <span class="ot">)</span></span></code></pre></div>
<p>Finally, we prove <span class="math inline">\(b &lt; n\)</span>, by showing <span class="math inline">\(b \leq n\)</span> and <span class="math inline">\(b \neq n\)</span>.</p>
<div class="sourceCode" id="cb43"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb43-1"><a href="#cb43-1" aria-hidden="true" tabindex="-1"></a>  b&lt;n <span class="ot">:</span> b &lt; n</span>
<span id="cb43-2"><a href="#cb43-2" aria-hidden="true" tabindex="-1"></a>  b&lt;n <span class="ot">=</span> ≤≢→&lt;</span></code></pre></div>
<p><span class="math inline">\(b \leq n\)</span> since <span class="math inline">\(ba = n\)</span> and <span class="math inline">\(a\)</span> is not zero (if <span class="math inline">\(a\)</span> were zero it
would contradict the fact that <span class="math inline">\(2 \leq a\)</span>).</p>
<div class="sourceCode" id="cb44"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb44-1"><a href="#cb44-1" aria-hidden="true" tabindex="-1"></a>    <span class="ot">(</span>*→≤ <span class="ot">(λ</span> a≡0 <span class="ot">→</span> &lt;→≢ <span class="ot">(</span>&lt;-trans <span class="ot">(</span>sle zle<span class="ot">)</span> 2≤a<span class="ot">)</span> <span class="ot">(</span>sym a≡0<span class="ot">))</span> <span class="ot">(</span>trans <span class="ot">(</span>*-comm a b<span class="ot">)</span> ba≡n<span class="ot">))</span></span></code></pre></div>
<p><span class="math inline">\(b \neq n\)</span>, since <span class="math inline">\(b = n\)</span> together with <span class="math inline">\(ba = n\)</span> would imply <span class="math inline">\(a = 1\)</span>
(since multiplication is cancellative), but <span class="math inline">\(2 \leq a\)</span> so it cannot
equal 1.</p>
<div class="sourceCode" id="cb45"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb45-1"><a href="#cb45-1" aria-hidden="true" tabindex="-1"></a>    <span class="ot">(λ</span> b≡n <span class="ot">→</span> &lt;→≢ 2≤a</span>
<span id="cb45-2"><a href="#cb45-2" aria-hidden="true" tabindex="-1"></a>      <span class="ot">(</span>sym</span>
<span id="cb45-3"><a href="#cb45-3" aria-hidden="true" tabindex="-1"></a>        <span class="ot">(</span>*-cancelˡ n a <span class="dv">1</span> <span class="ot">(</span>&lt;→≢ 0&lt;n<span class="ot">)</span></span>
<span id="cb45-4"><a href="#cb45-4" aria-hidden="true" tabindex="-1"></a>          <span class="ot">(</span>begin</span>
<span id="cb45-5"><a href="#cb45-5" aria-hidden="true" tabindex="-1"></a>            n * a             ≡⟨ <span class="ot">_</span>*<span class="ot">_</span> $≡ b≡n ≡$ a ]≡</span>
<span id="cb45-6"><a href="#cb45-6" aria-hidden="true" tabindex="-1"></a>            b * a             ≡[ ba≡n ⟩≡</span>
<span id="cb45-7"><a href="#cb45-7" aria-hidden="true" tabindex="-1"></a>            n                 ≡⟨ n *1 ]≡</span>
<span id="cb45-8"><a href="#cb45-8" aria-hidden="true" tabindex="-1"></a>            n * <span class="dv">1</span>             ∎</span>
<span id="cb45-9"><a href="#cb45-9" aria-hidden="true" tabindex="-1"></a>          <span class="ot">)</span></span>
<span id="cb45-10"><a href="#cb45-10" aria-hidden="true" tabindex="-1"></a>        <span class="ot">)</span></span>
<span id="cb45-11"><a href="#cb45-11" aria-hidden="true" tabindex="-1"></a>      <span class="ot">)</span></span>
<span id="cb45-12"><a href="#cb45-12" aria-hidden="true" tabindex="-1"></a>    <span class="ot">)</span></span></code></pre></div>
</section>
</section>
<section id="division" class="level2">
<h2>Division</h2>
<p>Let’s start working our way towards proving that divisibility is
decidable. To check whether <span class="math inline">\(d \mid n\)</span>, the usual idea would be to
divide <span class="math inline">\(n\)</span> by <span class="math inline">\(d\)</span> and check whether we get a remainder of zero. So we
need to formalize this notion of division with remainder.</p>
<p>Specifically, when we divide <span class="math inline">\(n\)</span> by <span class="math inline">\(d\)</span>, we expect to get a <em>quotient</em> <span class="math inline">\(q\)</span>
and a <em>remainder</em> <span class="math inline">\(r\)</span>, such that <span class="math inline">\(r + qd = n\)</span>, and <span class="math inline">\(0 \leq r &lt; d\)</span>.
The first condition, <span class="math inline">\(r + qd = n\)</span>, just defines what we mean by division: <span class="math inline">\(n\)</span> is
<span class="math inline">\(q\)</span> times <span class="math inline">\(d\)</span>, plus a remainder of <span class="math inline">\(r\)</span>. The second condition will ensure
that the result is unique. We wouldn’t want to divide <span class="math inline">\(17\)</span> by <span class="math inline">\(2\)</span> and
end up with a quotient of <span class="math inline">\(6\)</span> and a remainder of <span class="math inline">\(5\)</span>; the remainder should be as small as possible.</p>
<p>The <code>DivMod</code> type simply encodes these requirements.</p>
<div class="sourceCode" id="cb46"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb46-1"><a href="#cb46-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> DivMod <span class="ot">(</span>n d q r <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">:</span> <span class="dt">Set</span> <span class="kw">where</span></span>
<span id="cb46-2"><a href="#cb46-2" aria-hidden="true" tabindex="-1"></a>  DM <span class="ot">:</span> <span class="ot">(</span>r + q * d ≡ n<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>r &lt; d<span class="ot">)</span> <span class="ot">→</span> DivMod n d q r</span></code></pre></div>
<p>We can prove a few lemmas about <code>DivMod</code>. First, whenever we have
<code>DivMod n d q r</code>, then <code>d</code> must be positive, since <span class="math inline">\(r &lt; d\)</span> and <span class="math inline">\(r\)</span> is
a natural number.</p>
<div class="sourceCode" id="cb47"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb47-1"><a href="#cb47-1" aria-hidden="true" tabindex="-1"></a>divMod→0&lt;d <span class="ot">:</span> <span class="ot">{</span>n d q r <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> DivMod n d q r <span class="ot">→</span> <span class="dv">0</span> &lt; d</span>
<span id="cb47-2"><a href="#cb47-2" aria-hidden="true" tabindex="-1"></a>divMod→0&lt;d <span class="ot">(</span>DM <span class="ot">_</span> r&lt;d<span class="ot">)</span> <span class="ot">=</span> ≤-&lt;-trans zle r&lt;d</span></code></pre></div>
<p>We can also show that for nonzero <span class="math inline">\(d\)</span>, the remainder is zero if and only if <span class="math inline">\(d
\mid n\)</span>:</p>
<div class="sourceCode" id="cb48"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb48-1"><a href="#cb48-1" aria-hidden="true" tabindex="-1"></a>mod0→divides <span class="ot">:</span> <span class="ot">(</span>n d <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">{</span>q <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> DivMod n d q <span class="dv">0</span> <span class="ot">→</span> d ∣ n</span>
<span id="cb48-2"><a href="#cb48-2" aria-hidden="true" tabindex="-1"></a>mod0→divides n d <span class="ot">{</span>q<span class="ot">}</span> <span class="ot">(</span>DM eq <span class="ot">_)</span> <span class="ot">=</span> q , eq</span>
<span id="cb48-3"><a href="#cb48-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-4"><a href="#cb48-4" aria-hidden="true" tabindex="-1"></a>divides→mod0 <span class="ot">:</span> <span class="ot">(</span>n d <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span><span class="dv">0</span> &lt; d<span class="ot">)</span> <span class="ot">→</span> d ∣ n <span class="ot">→</span> Σ ℕ <span class="ot">(λ</span> q <span class="ot">→</span> DivMod n d q <span class="dv">0</span><span class="ot">)</span></span>
<span id="cb48-5"><a href="#cb48-5" aria-hidden="true" tabindex="-1"></a>divides→mod0 n d 0&lt;d <span class="ot">(</span>q , qd≡n<span class="ot">)</span> <span class="ot">=</span> q , <span class="ot">(</span>DM qd≡n 0&lt;d<span class="ot">)</span></span></code></pre></div>
<p>We would also like to show that if the remainder when dividing <span class="math inline">\(n\)</span> by
<span class="math inline">\(d\)</span> is <em>not</em> zero, then <span class="math inline">\(d\)</span> does <em>not</em> divide <span class="math inline">\(n\)</span>. This is <em>almost</em>
the contrapositive of <code>divides→mod0</code>—which would be trivial to
show—but not quite: I said “the” remainder, but actually we don’t yet
know that the quotient and remainder are unique! Perhaps we could get
a remainder of 0 and some other remainder for the same <span class="math inline">\(n\)</span> and <span class="math inline">\(d\)</span>, by
choosing different quotients?</p>
<p>Of course, quotients and remainders <em>are</em> unique: that is, if <span class="math inline">\(q_1,
r_1\)</span> and <span class="math inline">\(q_2, r_2\)</span> both satisfy the properties to be the quotient and
remainder of <span class="math inline">\(n\)</span> divided by <span class="math inline">\(d\)</span>, then in fact <span class="math inline">\(q_1 = q_2\)</span> and <span class="math inline">\(r_1 =
r_2\)</span>. But how can we prove this? The usual idea is to look at the
difference <span class="math inline">\(r_1 - r_2 = dq_1 - dq_2\)</span>, which is divisible by <span class="math inline">\(d\)</span>; but
since <span class="math inline">\(r_1 &lt; d\)</span> and <span class="math inline">\(r_2 &lt; d\)</span>, the only way for the difference <span class="math inline">\(r_1 -
r_2\)</span> to be divisible by <span class="math inline">\(d\)</span> is if in fact <span class="math inline">\(r_1 - r_2 = 0\)</span>. From here
we can also derive <span class="math inline">\(q_1 = q_2\)</span> via algebra.</p>
<p>Subtraction, eh? In order to formalize this, it seems as though we might
need to define the integers… but there is a better way!</p>
</section>
<section id="absolute-difference" class="level2">
<h2>Absolute difference</h2>
<p>The previous informal argument mentioned the difference <span class="math inline">\(r_1 - r_2\)</span>.
But we could just as easily have talked about <span class="math inline">\(r_2 - r_1\)</span> instead, and
the same argument would work just as well. This observation shows
that we do not actually care about the (signed) <em>difference</em> between
<span class="math inline">\(r_1\)</span> and <span class="math inline">\(r_2\)</span>, but only the <em>distance</em> between them. This means we
can just stick to our well-loved natural numbers, and define a commutative
<em>absolute difference</em> function which computes the nonnegative distance
between its two arguments, like so:</p>
<div class="sourceCode" id="cb49"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb49-1"><a href="#cb49-1" aria-hidden="true" tabindex="-1"></a>∥<span class="ot">_</span>-<span class="ot">_</span>∥ <span class="ot">:</span> ℕ <span class="ot">→</span> ℕ <span class="ot">→</span> ℕ</span>
<span id="cb49-2"><a href="#cb49-2" aria-hidden="true" tabindex="-1"></a>∥ zero - y ∥ <span class="ot">=</span> y</span>
<span id="cb49-3"><a href="#cb49-3" aria-hidden="true" tabindex="-1"></a>∥ suc x - zero ∥ <span class="ot">=</span> suc x</span>
<span id="cb49-4"><a href="#cb49-4" aria-hidden="true" tabindex="-1"></a>∥ suc x - suc y ∥ <span class="ot">=</span> ∥ x - y ∥</span></code></pre></div>
<p>Of course, we will need a lot of small lemmas about the properties of
this operation. We can start by proving that the distance between two
numbers is 0 if and only if they are equal:</p>
<div class="sourceCode" id="cb50"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb50-1"><a href="#cb50-1" aria-hidden="true" tabindex="-1"></a>diff0 <span class="ot">:</span> <span class="ot">(</span>x <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="dv">0</span> ≡ ∥ x - x ∥</span>
<span id="cb50-2"><a href="#cb50-2" aria-hidden="true" tabindex="-1"></a>diff0 zero <span class="ot">=</span> refl</span>
<span id="cb50-3"><a href="#cb50-3" aria-hidden="true" tabindex="-1"></a>diff0 <span class="ot">(</span>suc x<span class="ot">)</span> <span class="ot">=</span> diff0 x</span>
<span id="cb50-4"><a href="#cb50-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb50-5"><a href="#cb50-5" aria-hidden="true" tabindex="-1"></a>diff0→≡ <span class="ot">:</span> <span class="ot">{</span>x y <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> <span class="dv">0</span> ≡ ∥ x - y ∥ <span class="ot">→</span> x ≡ y</span>
<span id="cb50-6"><a href="#cb50-6" aria-hidden="true" tabindex="-1"></a>diff0→≡ <span class="ot">{</span>zero<span class="ot">}</span> <span class="ot">{</span>zero<span class="ot">}</span> eq <span class="ot">=</span> eq</span>
<span id="cb50-7"><a href="#cb50-7" aria-hidden="true" tabindex="-1"></a>diff0→≡ <span class="ot">{</span>suc x<span class="ot">}</span> <span class="ot">{</span>suc y<span class="ot">}</span> eq <span class="ot">=</span> suc $≡ diff0→≡ eq</span></code></pre></div>
<p>Next, the distance between any number and 0 is the number itself, and
the distance function is commutative.</p>
<div class="sourceCode" id="cb51"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb51-1"><a href="#cb51-1" aria-hidden="true" tabindex="-1"></a>∥x-0∥≡x <span class="ot">:</span> <span class="ot">(</span>x <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> ∥ x - <span class="dv">0</span> ∥ ≡ x</span>
<span id="cb51-2"><a href="#cb51-2" aria-hidden="true" tabindex="-1"></a>∥x-0∥≡x zero <span class="ot">=</span> refl</span>
<span id="cb51-3"><a href="#cb51-3" aria-hidden="true" tabindex="-1"></a>∥x-0∥≡x <span class="ot">(</span>suc x<span class="ot">)</span> <span class="ot">=</span> refl</span>
<span id="cb51-4"><a href="#cb51-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb51-5"><a href="#cb51-5" aria-hidden="true" tabindex="-1"></a>diff-comm <span class="ot">:</span> <span class="ot">{</span>x y <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> ∥ x - y ∥ ≡ ∥ y - x ∥</span>
<span id="cb51-6"><a href="#cb51-6" aria-hidden="true" tabindex="-1"></a>diff-comm <span class="ot">{</span>zero<span class="ot">}</span> <span class="ot">{</span>zero<span class="ot">}</span> <span class="ot">=</span> refl</span>
<span id="cb51-7"><a href="#cb51-7" aria-hidden="true" tabindex="-1"></a>diff-comm <span class="ot">{</span>zero<span class="ot">}</span> <span class="ot">{</span>suc y<span class="ot">}</span> <span class="ot">=</span> refl</span>
<span id="cb51-8"><a href="#cb51-8" aria-hidden="true" tabindex="-1"></a>diff-comm <span class="ot">{</span>suc x<span class="ot">}</span> <span class="ot">{</span>zero<span class="ot">}</span> <span class="ot">=</span> refl</span>
<span id="cb51-9"><a href="#cb51-9" aria-hidden="true" tabindex="-1"></a>diff-comm <span class="ot">{</span>suc x<span class="ot">}</span> <span class="ot">{</span>suc y<span class="ot">}</span> <span class="ot">=</span> diff-comm <span class="ot">{</span>x<span class="ot">}</span> <span class="ot">{</span>y<span class="ot">}</span></span></code></pre></div>
<p>A key lemma supporting the argument outlined in the previous section
is that if <span class="math inline">\(x\)</span> and <span class="math inline">\(y\)</span> are both less than <span class="math inline">\(d\)</span>, so is their absolute difference.</p>
<div class="sourceCode" id="cb52"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb52-1"><a href="#cb52-1" aria-hidden="true" tabindex="-1"></a>diff-&lt; <span class="ot">:</span> <span class="ot">{</span>x y d <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> x &lt; d <span class="ot">→</span> y &lt; d <span class="ot">→</span> ∥ x - y ∥ &lt; d</span>
<span id="cb52-2"><a href="#cb52-2" aria-hidden="true" tabindex="-1"></a>diff-&lt; <span class="ot">{</span>zero<span class="ot">}</span> <span class="ot">{</span>y<span class="ot">}</span> x&lt;d y&lt;d <span class="ot">=</span> y&lt;d</span>
<span id="cb52-3"><a href="#cb52-3" aria-hidden="true" tabindex="-1"></a>diff-&lt; <span class="ot">{</span>suc x<span class="ot">}</span> <span class="ot">{</span>zero<span class="ot">}</span> x&lt;d y&lt;d <span class="ot">=</span> x&lt;d</span>
<span id="cb52-4"><a href="#cb52-4" aria-hidden="true" tabindex="-1"></a>diff-&lt; <span class="ot">{</span>suc x<span class="ot">}</span> <span class="ot">{</span>suc y<span class="ot">}</span> x&lt;d y&lt;d <span class="ot">=</span> diff-&lt; <span class="ot">{</span>x<span class="ot">}</span> <span class="ot">{</span>y<span class="ot">}</span> <span class="ot">(</span>&lt;-trans <span class="ot">(</span>x &lt;suc<span class="ot">)</span> x&lt;d<span class="ot">)</span> <span class="ot">(</span>&lt;-trans <span class="ot">(</span>y &lt;suc<span class="ot">)</span> y&lt;d<span class="ot">)</span></span></code></pre></div>
<p>We can also cancel the same thing being added to both sides, or factor out
the same thing being multiplied on both sides.</p>
<div class="sourceCode" id="cb53"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb53-1"><a href="#cb53-1" aria-hidden="true" tabindex="-1"></a>diff-cancelˡ <span class="ot">:</span> <span class="ot">(</span>a b c <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> ∥ <span class="ot">(</span>a + b<span class="ot">)</span> - <span class="ot">(</span>a + c<span class="ot">)</span> ∥ ≡ ∥ b - c ∥</span>
<span id="cb53-2"><a href="#cb53-2" aria-hidden="true" tabindex="-1"></a>diff-cancelˡ zero b c <span class="ot">=</span> refl</span>
<span id="cb53-3"><a href="#cb53-3" aria-hidden="true" tabindex="-1"></a>diff-cancelˡ <span class="ot">(</span>suc a<span class="ot">)</span> b c <span class="ot">=</span> diff-cancelˡ a b c</span>
<span id="cb53-4"><a href="#cb53-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb53-5"><a href="#cb53-5" aria-hidden="true" tabindex="-1"></a>diff-distribʳ <span class="ot">:</span> <span class="ot">(</span>x y d <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> ∥ x * d - y * d ∥ ≡ ∥ x - y ∥ * d</span>
<span id="cb53-6"><a href="#cb53-6" aria-hidden="true" tabindex="-1"></a>diff-distribʳ zero y d <span class="ot">=</span> refl</span>
<span id="cb53-7"><a href="#cb53-7" aria-hidden="true" tabindex="-1"></a>diff-distribʳ <span class="ot">(</span>suc x<span class="ot">)</span> zero d <span class="ot">=</span> ∥x-0∥≡x <span class="ot">(</span>d + x * d<span class="ot">)</span></span>
<span id="cb53-8"><a href="#cb53-8" aria-hidden="true" tabindex="-1"></a>diff-distribʳ <span class="ot">(</span>suc x<span class="ot">)</span> <span class="ot">(</span>suc y<span class="ot">)</span> d <span class="ot">=</span> begin</span>
<span id="cb53-9"><a href="#cb53-9" aria-hidden="true" tabindex="-1"></a>  ∥ <span class="ot">(</span>d + x * d<span class="ot">)</span> - <span class="ot">(</span>d + y * d<span class="ot">)</span> ∥         ≡[ diff-cancelˡ d <span class="ot">(</span>x * d<span class="ot">)</span> <span class="ot">(</span>y * d<span class="ot">)</span> ⟩≡</span>
<span id="cb53-10"><a href="#cb53-10" aria-hidden="true" tabindex="-1"></a>  ∥ x * d - y * d ∥                     ≡[ diff-distribʳ x y d ⟩≡</span>
<span id="cb53-11"><a href="#cb53-11" aria-hidden="true" tabindex="-1"></a>  ∥ x - y ∥ * d                         ∎</span></code></pre></div>
<p>Another key lemma is that if <span class="math inline">\(w + x = y + z\)</span>, then <span class="math inline">\(\|w - y\| = \|x -
z\|\)</span> (<code>sub₂</code> below). Personally, I found this quite tricky to prove.
The best approach I found was to first prove the simpler lemma that
<span class="math inline">\(x + y = z\)</span> implies <span class="math inline">\(x = \| z - y \|\)</span> (<code>sub₁</code>), which can then be used
in several places in the proof of <code>sub₂</code>.</p>
<div class="sourceCode" id="cb54"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb54-1"><a href="#cb54-1" aria-hidden="true" tabindex="-1"></a>sub₁ <span class="ot">:</span> <span class="ot">{</span>x y z <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> x + y ≡ z <span class="ot">→</span> x ≡ ∥ z - y ∥</span>
<span id="cb54-2"><a href="#cb54-2" aria-hidden="true" tabindex="-1"></a>sub₁ <span class="ot">{</span>zero<span class="ot">}</span> <span class="ot">{</span>y<span class="ot">}</span> <span class="ot">{</span>z<span class="ot">}</span> refl <span class="ot">=</span> diff0 y</span>
<span id="cb54-3"><a href="#cb54-3" aria-hidden="true" tabindex="-1"></a>sub₁ <span class="ot">{</span>suc x<span class="ot">}</span> <span class="ot">{</span>zero<span class="ot">}</span> <span class="ot">{</span>suc z<span class="ot">}</span> x+y≡z <span class="ot">=</span></span>
<span id="cb54-4"><a href="#cb54-4" aria-hidden="true" tabindex="-1"></a>  begin</span>
<span id="cb54-5"><a href="#cb54-5" aria-hidden="true" tabindex="-1"></a>    suc x                     ≡⟨ suc $≡ x +0 ]≡</span>
<span id="cb54-6"><a href="#cb54-6" aria-hidden="true" tabindex="-1"></a>    suc <span class="ot">(</span>x + <span class="dv">0</span><span class="ot">)</span>               ≡[ x+y≡z ⟩≡</span>
<span id="cb54-7"><a href="#cb54-7" aria-hidden="true" tabindex="-1"></a>    suc z                     ∎</span>
<span id="cb54-8"><a href="#cb54-8" aria-hidden="true" tabindex="-1"></a>sub₁ <span class="ot">{</span>suc x<span class="ot">}</span> <span class="ot">{</span>suc y<span class="ot">}</span> <span class="ot">{</span>suc z<span class="ot">}</span> x+y≡z <span class="ot">=</span></span>
<span id="cb54-9"><a href="#cb54-9" aria-hidden="true" tabindex="-1"></a>  sub₁ <span class="ot">{</span>suc x<span class="ot">}</span> <span class="ot">{</span>y<span class="ot">}</span> <span class="ot">{</span>z<span class="ot">}</span></span>
<span id="cb54-10"><a href="#cb54-10" aria-hidden="true" tabindex="-1"></a>    <span class="ot">(</span>noConf <span class="ot">(</span>trans <span class="ot">(</span>suc $≡ sym <span class="ot">(</span>x +suc y<span class="ot">))</span> x+y≡z<span class="ot">))</span></span>
<span id="cb54-11"><a href="#cb54-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb54-12"><a href="#cb54-12" aria-hidden="true" tabindex="-1"></a>sub₂ <span class="ot">:</span> <span class="ot">{</span>w x y z <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> w + x ≡ y + z <span class="ot">→</span> ∥ w - y ∥ ≡ ∥ x - z ∥</span>
<span id="cb54-13"><a href="#cb54-13" aria-hidden="true" tabindex="-1"></a>sub₂ <span class="ot">{</span>zero<span class="ot">}</span> <span class="ot">{</span>x<span class="ot">}</span> <span class="ot">{</span>y<span class="ot">}</span> <span class="ot">{</span>z<span class="ot">}</span> w+x≡y+z <span class="ot">=</span> sub₁ <span class="ot">(</span>sym w+x≡y+z<span class="ot">)</span></span>
<span id="cb54-14"><a href="#cb54-14" aria-hidden="true" tabindex="-1"></a>sub₂ <span class="ot">{</span>suc w<span class="ot">}</span> <span class="ot">{</span>x<span class="ot">}</span> <span class="ot">{</span>zero<span class="ot">}</span> <span class="ot">{</span>z<span class="ot">}</span> w+x≡y+z <span class="ot">=</span> trans <span class="ot">(</span>sub₁ w+x≡y+z<span class="ot">)</span> <span class="ot">(</span>diff-comm <span class="ot">{</span>z<span class="ot">})</span></span>
<span id="cb54-15"><a href="#cb54-15" aria-hidden="true" tabindex="-1"></a>sub₂ <span class="ot">{</span>suc w<span class="ot">}</span> <span class="ot">{</span>x<span class="ot">}</span> <span class="ot">{</span>suc y<span class="ot">}</span> <span class="ot">{</span>z<span class="ot">}</span> w+x≡y+z <span class="ot">=</span> sub₂ <span class="ot">{</span>w<span class="ot">}</span> <span class="ot">(</span>noConf w+x≡y+z<span class="ot">)</span></span></code></pre></div>
</section>
<section id="quotient-and-remainder-are-unique" class="level2">
<h2>Quotient and remainder are unique</h2>
<p>We can now return to prove that quotient and remainder are unique.
First, we show that zero is the only multiple of <span class="math inline">\(d\)</span> which is less than <span class="math inline">\(d\)</span>.</p>
<div class="sourceCode" id="cb55"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb55-1"><a href="#cb55-1" aria-hidden="true" tabindex="-1"></a>∣&lt;→0 <span class="ot">:</span> <span class="ot">{</span>d x <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> d ∣ x <span class="ot">→</span> x &lt; d <span class="ot">→</span> <span class="dv">0</span> ≡ x</span>
<span id="cb55-2"><a href="#cb55-2" aria-hidden="true" tabindex="-1"></a>∣&lt;→0 <span class="ot">(</span>zero , ad≡x<span class="ot">)</span> x&lt;d <span class="ot">=</span> ad≡x</span>
<span id="cb55-3"><a href="#cb55-3" aria-hidden="true" tabindex="-1"></a>∣&lt;→0 <span class="ot">(</span>suc a , ad≡x<span class="ot">)</span> x&lt;d <span class="ot">=</span> absurd <span class="ot">(</span>&lt;→≱ x&lt;d <span class="ot">(</span>+→≤ ad≡x<span class="ot">))</span></span></code></pre></div>
<p>And now for the main event: if we have both <code>DivMod n d q₁ r₁</code> and
<code>DivMod n d q₂ r₂</code>, then in fact the <code>q</code>s and <code>r</code>s must be the same.</p>
<div class="sourceCode" id="cb56"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb56-1"><a href="#cb56-1" aria-hidden="true" tabindex="-1"></a>divModUnique <span class="ot">:</span> <span class="ot">{</span>n d q₁ r₁ q₂ r₂ <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> DivMod n d q₁ r₁ <span class="ot">→</span> DivMod n d q₂ r₂ <span class="ot">→</span> <span class="ot">(</span>q₁ ≡ q₂<span class="ot">)</span> × <span class="ot">(</span>r₁ ≡ r₂<span class="ot">)</span></span>
<span id="cb56-2"><a href="#cb56-2" aria-hidden="true" tabindex="-1"></a>divModUnique <span class="ot">{</span>n<span class="ot">}</span> <span class="ot">{</span>d<span class="ot">}</span> <span class="ot">{</span>q₁<span class="ot">}</span> <span class="ot">{</span>r₁<span class="ot">}</span> <span class="ot">{</span>q₂<span class="ot">}</span> <span class="ot">{</span>r₂<span class="ot">}</span> dm<span class="ot">@(</span>DM r₁+q₁d≡n r₁&lt;d<span class="ot">)</span> <span class="ot">(</span>DM r₂+q₂d≡n r₂&lt;d<span class="ot">)</span> <span class="ot">=</span> q₁≡q₂ , r₁≡r₂</span>
<span id="cb56-3"><a href="#cb56-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span></code></pre></div>
<p>Since <span class="math inline">\(r_1 + q_1d = n\)</span> and <span class="math inline">\(r_2 + q_2d = n\)</span>, by transitivity and
symmetry we have <span class="math inline">\(r_1 + q_1d = r_2 + q_2d\)</span>; then by the <code>sub₂</code> lemma,
<span class="math inline">\(\|r_1 - r_2\| = \|q_1d - q_2d\|\)</span>.</p>
<div class="sourceCode" id="cb57"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb57-1"><a href="#cb57-1" aria-hidden="true" tabindex="-1"></a>  rem-diff <span class="ot">:</span> ∥ r₁ - r₂ ∥ ≡ ∥ q₁ * d - q₂ * d ∥</span>
<span id="cb57-2"><a href="#cb57-2" aria-hidden="true" tabindex="-1"></a>  rem-diff <span class="ot">=</span> sub₂ <span class="ot">{</span>r₁<span class="ot">}</span> <span class="ot">(</span>trans r₁+q₁d≡n <span class="ot">(</span>sym r₂+q₂d≡n<span class="ot">))</span></span></code></pre></div>
<p>Next, we can show that <span class="math inline">\(d\)</span> divides the absolute difference <span class="math inline">\(\|r_1 -
  r_2\|\)</span>, by factoring it out of <span class="math inline">\(\|q_1 d - q_2 d\|\)</span>.</p>
<div class="sourceCode" id="cb58"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb58-1"><a href="#cb58-1" aria-hidden="true" tabindex="-1"></a>  d∣r₁-r₂ <span class="ot">:</span> d ∣ ∥ r₁ - r₂ ∥</span>
<span id="cb58-2"><a href="#cb58-2" aria-hidden="true" tabindex="-1"></a>  d∣r₁-r₂ <span class="ot">=</span> ∥ q₁ - q₂ ∥ ,</span>
<span id="cb58-3"><a href="#cb58-3" aria-hidden="true" tabindex="-1"></a>    <span class="ot">(</span>begin</span>
<span id="cb58-4"><a href="#cb58-4" aria-hidden="true" tabindex="-1"></a>      ∥ q₁ - q₂ ∥ * d         ≡⟨ diff-distribʳ q₁ q₂ d ]≡</span>
<span id="cb58-5"><a href="#cb58-5" aria-hidden="true" tabindex="-1"></a>      ∥ q₁ * d - q₂ * d ∥     ≡⟨ rem-diff ]≡</span>
<span id="cb58-6"><a href="#cb58-6" aria-hidden="true" tabindex="-1"></a>      ∥ r₁ - r₂ ∥             ∎</span>
<span id="cb58-7"><a href="#cb58-7" aria-hidden="true" tabindex="-1"></a>    <span class="ot">)</span></span></code></pre></div>
<p>We can then put three lemmas together to conclude <span class="math inline">\(r_1 = r_2\)</span>: first,
since <span class="math inline">\(r_1\)</span> and <span class="math inline">\(r_2\)</span> are both less than <span class="math inline">\(d\)</span>, so is their absolute
difference; since <span class="math inline">\(d\)</span> also divides the absolute difference, the
absolute difference must be zero; and finally, an absolute difference
of zero means <span class="math inline">\(r_1\)</span> and <span class="math inline">\(r_2\)</span> must be equal.</p>
<div class="sourceCode" id="cb59"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb59-1"><a href="#cb59-1" aria-hidden="true" tabindex="-1"></a>  r₁≡r₂ <span class="ot">:</span> r₁ ≡ r₂</span>
<span id="cb59-2"><a href="#cb59-2" aria-hidden="true" tabindex="-1"></a>  r₁≡r₂ <span class="ot">=</span> diff0→≡ <span class="ot">(</span>∣&lt;→0 d∣r₁-r₂ <span class="ot">(</span>diff-&lt; r₁&lt;d r₂&lt;d<span class="ot">))</span></span></code></pre></div>
<p>From here, proving <span class="math inline">\(q_1 = q_2\)</span> just requires some algebra.</p>
<div class="sourceCode" id="cb60"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb60-1"><a href="#cb60-1" aria-hidden="true" tabindex="-1"></a>  dq₁≡dq₂ <span class="ot">:</span> d * q₁ ≡ d * q₂</span>
<span id="cb60-2"><a href="#cb60-2" aria-hidden="true" tabindex="-1"></a>  dq₁≡dq₂ <span class="ot">=</span> +-cancelˡ r₁ <span class="ot">(</span>d * q₁<span class="ot">)</span> <span class="ot">(</span>d * q₂<span class="ot">)</span></span>
<span id="cb60-3"><a href="#cb60-3" aria-hidden="true" tabindex="-1"></a>    <span class="ot">(</span>begin</span>
<span id="cb60-4"><a href="#cb60-4" aria-hidden="true" tabindex="-1"></a>      r₁ + d * q₁             ≡[ r₁ +<span class="ot">_</span> $≡ *-comm d q₁ ⟩≡</span>
<span id="cb60-5"><a href="#cb60-5" aria-hidden="true" tabindex="-1"></a>      r₁ + q₁ * d             ≡[ r₁+q₁d≡n ⟩≡</span>
<span id="cb60-6"><a href="#cb60-6" aria-hidden="true" tabindex="-1"></a>      n                       ≡⟨ r₂+q₂d≡n ]≡</span>
<span id="cb60-7"><a href="#cb60-7" aria-hidden="true" tabindex="-1"></a>      r₂ + q₂ * d             ≡[ <span class="ot">_</span>+<span class="ot">_</span> $≡ sym r₁≡r₂ ≡$≡ *-comm q₂ d ⟩≡</span>
<span id="cb60-8"><a href="#cb60-8" aria-hidden="true" tabindex="-1"></a>      r₁ + d * q₂             ∎</span>
<span id="cb60-9"><a href="#cb60-9" aria-hidden="true" tabindex="-1"></a>    <span class="ot">)</span></span>
<span id="cb60-10"><a href="#cb60-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb60-11"><a href="#cb60-11" aria-hidden="true" tabindex="-1"></a>  q₁≡q₂ <span class="ot">:</span> q₁ ≡ q₂</span>
<span id="cb60-12"><a href="#cb60-12" aria-hidden="true" tabindex="-1"></a>  q₁≡q₂ <span class="ot">=</span> *-cancelˡ d q₁ q₂ <span class="ot">(</span>&lt;→≢ <span class="ot">(</span>divMod→0&lt;d dm<span class="ot">))</span> dq₁≡dq₂</span></code></pre></div>
<p>Finally, we can use uniqueness of quotients and remainders to show the
lemma we wanted about divisibility and remainders: if <span class="math inline">\(n\)</span> divided by
<span class="math inline">\(d\)</span> has some nonzero number as remainder, then <span class="math inline">\(d\)</span> does not divide
<span class="math inline">\(n\)</span>. If <span class="math inline">\(d\)</span> did divide <span class="math inline">\(n\)</span>, then we know we would get a remainder of
<span class="math inline">\(0\)</span>; but since remainders are unique, we can’t have both a zero and
nonzero remainder.</p>
<div class="sourceCode" id="cb61"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb61-1"><a href="#cb61-1" aria-hidden="true" tabindex="-1"></a>modS→¬divides <span class="ot">:</span> <span class="ot">(</span>n d <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">{</span>q r <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> DivMod n d q <span class="ot">(</span>suc r<span class="ot">)</span> <span class="ot">→</span> ¬ <span class="ot">(</span>d ∣ n<span class="ot">)</span></span>
<span id="cb61-2"><a href="#cb61-2" aria-hidden="true" tabindex="-1"></a>modS→¬divides n d dm d∣n <span class="kw">with</span> divides→mod0 n d <span class="ot">(</span>divMod→0&lt;d dm<span class="ot">)</span> d∣n</span>
<span id="cb61-3"><a href="#cb61-3" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> q₂ , dm₂ <span class="kw">with</span> divModUnique dm dm₂</span>
<span id="cb61-4"><a href="#cb61-4" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> q₁≡q₂ , <span class="ot">()</span></span></code></pre></div>
</section>
<section id="the-division-algorithm-take-1" class="level2">
<h2>The division algorithm, take 1</h2>
<p>So, given natural numbers <span class="math inline">\(n\)</span> and <span class="math inline">\(d\)</span>, how do we compute the quotient
and remainder? We can write down a type <code>DivAlg</code> that expresses what
we want: given some <span class="math inline">\(n\)</span> and <span class="math inline">\(d\)</span>, <code>DivAlg n d</code> represents the result of
the division algorithm, that is, a pair of numbers <span class="math inline">\((q,r)\)</span> such that
<code>DivMod n d q r</code> holds.</p>
<div class="sourceCode" id="cb62"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb62-1"><a href="#cb62-1" aria-hidden="true" tabindex="-1"></a>DivAlg <span class="ot">:</span> ℕ <span class="ot">→</span> ℕ <span class="ot">→</span> <span class="dt">Set</span></span>
<span id="cb62-2"><a href="#cb62-2" aria-hidden="true" tabindex="-1"></a>DivAlg n d <span class="ot">=</span> Σ <span class="ot">(</span>ℕ × ℕ<span class="ot">)</span> <span class="ot">(λ</span> <span class="ot">{</span> <span class="ot">(</span>q , r<span class="ot">)</span> <span class="ot">→</span> DivMod n d q r <span class="ot">})</span></span></code></pre></div>
<p>Then we want a function with a type something like <code>(n d : ℕ) → DivAlg n d</code> (actually this type is not quite correct—can you see why?).
How can we write something with this type?</p>
<p>One simple idea, expressed imperatively, is to start with <span class="math inline">\(q = 0\)</span>.
Now, as long as <span class="math inline">\(n \geq d\)</span>, subtract <span class="math inline">\(d\)</span> from <span class="math inline">\(n\)</span> and add one to
<span class="math inline">\(q\)</span>—if we can find <span class="math inline">\(q\)</span> and <span class="math inline">\(r\)</span> such that <span class="math inline">\(r + qd = n - d\)</span>, then <span class="math inline">\(r +
(q+1)d = n\)</span>. Eventually, <span class="math inline">\(n\)</span> must land in the range <span class="math inline">\(0 \leq n &lt; d\)</span>,
in which case it will be the remainder, and the current value of <span class="math inline">\(q\)</span>
will be the quotient.</p>
<section id="construct-the-evidence-you-would-like-to-pattern-match-on" class="level3">
<h3>Construct the evidence you would like to pattern-match on</h3>
<p>That’s the idea, but turning this into a verified constructive algorithm will take some
work. First, let’s formalize the idea of testing whether <span class="math inline">\(n\)</span> is less
than <span class="math inline">\(d\)</span>, and decreasing it by <span class="math inline">\(d\)</span> if not. We’d rather not actually
deal with subtraction, so the idea is to generate either a proof that
<span class="math inline">\(n &lt; d\)</span>, or another number <span class="math inline">\(n&#39;\)</span> along with a proof that <span class="math inline">\(n&#39; + d = n\)</span>.
We encapsulate this in the following type <code>Cmp</code>:</p>
<div class="sourceCode" id="cb63"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb63-1"><a href="#cb63-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> Cmp <span class="ot">(</span>n d <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">:</span> <span class="dt">Set</span> <span class="kw">where</span></span>
<span id="cb63-2"><a href="#cb63-2" aria-hidden="true" tabindex="-1"></a>  LT <span class="ot">:</span> n &lt; d <span class="ot">→</span> Cmp n d</span>
<span id="cb63-3"><a href="#cb63-3" aria-hidden="true" tabindex="-1"></a>  GE <span class="ot">:</span> <span class="ot">(</span>n′ <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>n′ + d ≡ n<span class="ot">)</span> <span class="ot">→</span> Cmp n d</span></code></pre></div>
<p><code>Cmp n d</code> represents the result of comparing <span class="math inline">\(n\)</span> and <span class="math inline">\(d\)</span>, and is
equivalent to having either <span class="math inline">\(n &lt; d\)</span> or <span class="math inline">\(n \geq d\)</span>, but expressed in a
form that is more directly useful to us. <strong>Construct the evidence you
would like to pattern-match on!</strong> That is, in general, evidence for a
proposition <span class="math inline">\(P\)</span> can take many logically equivalent forms, and you
should pick the form that will make your life easiest at the <em>use
site</em>, even if it means you have to work harder to <em>construct</em> it in
the first place. You can write standalone lemmas for constructing
your evidence; but pattern-matching it will happen in the middle of
some bigger proof which ought not to be cluttered by calls to
conversion lemmas.</p>
<p>To construct evidence for <code>Cmp n d</code>, we write the function
<code>decreaseBy?</code> which decides whether we can decrease <code>n</code> by <code>d</code> or not.
Writing this function is a bit more work than writing something
of type <code>(n d : ℕ) → (n &lt; d) ⊎ (d ≤ n)</code>, but our work will pay off later!</p>
<div class="sourceCode" id="cb64"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb64-1"><a href="#cb64-1" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>decreaseBy?<span class="ot">_</span> <span class="ot">:</span> <span class="ot">(</span>n d <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> Cmp n d</span>
<span id="cb64-2"><a href="#cb64-2" aria-hidden="true" tabindex="-1"></a>zero decreaseBy? zero <span class="ot">=</span> GE <span class="dv">0</span> refl</span>
<span id="cb64-3"><a href="#cb64-3" aria-hidden="true" tabindex="-1"></a>zero decreaseBy? suc d <span class="ot">=</span> LT <span class="ot">(</span>sle zle<span class="ot">)</span></span>
<span id="cb64-4"><a href="#cb64-4" aria-hidden="true" tabindex="-1"></a>suc n decreaseBy? zero <span class="ot">=</span> GE <span class="ot">(</span>suc n<span class="ot">)</span> <span class="ot">((</span>suc n<span class="ot">)</span> +0<span class="ot">)</span></span>
<span id="cb64-5"><a href="#cb64-5" aria-hidden="true" tabindex="-1"></a>suc n decreaseBy? suc d <span class="kw">with</span> n decreaseBy? d</span>
<span id="cb64-6"><a href="#cb64-6" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> LT n&lt;d <span class="ot">=</span> LT <span class="ot">(</span>sle n&lt;d<span class="ot">)</span></span>
<span id="cb64-7"><a href="#cb64-7" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> GE n′ n′+d≡n <span class="ot">=</span> GE n′ <span class="ot">(</span>trans <span class="ot">(</span>n′ +suc d<span class="ot">)</span> <span class="ot">(</span>suc $≡ n′+d≡n<span class="ot">))</span></span></code></pre></div>
<p>We can also write a helper function <code>incDivMod</code> which encodes the
observation from before, that if <span class="math inline">\(r + qd = n-d\)</span>, then <span class="math inline">\(r + (q+1)d =
n\)</span>. Of course we don’t actually want to use subtraction, so instead
of writing <span class="math inline">\(n-d\)</span>, we work in terms of an <span class="math inline">\(n&#39;\)</span> such that <span class="math inline">\(n&#39; + d = n\)</span>.
Proving this requires only some straightforward algebra.</p>
<div class="sourceCode" id="cb65"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb65-1"><a href="#cb65-1" aria-hidden="true" tabindex="-1"></a>incDivMod <span class="ot">:</span> <span class="ot">{</span>n′ n d q r <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> n′ + d ≡ n <span class="ot">→</span> DivMod n′ d q r <span class="ot">→</span> DivMod n d <span class="ot">(</span>suc q<span class="ot">)</span> r</span>
<span id="cb65-2"><a href="#cb65-2" aria-hidden="true" tabindex="-1"></a>incDivMod <span class="ot">{</span>n′<span class="ot">}</span> <span class="ot">{</span>n<span class="ot">}</span> <span class="ot">{</span>d<span class="ot">}</span> <span class="ot">{</span>q<span class="ot">}</span> <span class="ot">{</span>r<span class="ot">}</span> n′+d≡n <span class="ot">(</span>DM r+qd≡n′ r&lt;d<span class="ot">)</span> <span class="ot">=</span> DM r+d+qd≡n r&lt;d</span>
<span id="cb65-3"><a href="#cb65-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb65-4"><a href="#cb65-4" aria-hidden="true" tabindex="-1"></a>  r+d+qd≡n <span class="ot">:</span> r + <span class="ot">(</span>d + q * d<span class="ot">)</span> ≡ n</span>
<span id="cb65-5"><a href="#cb65-5" aria-hidden="true" tabindex="-1"></a>  r+d+qd≡n <span class="ot">=</span> begin</span>
<span id="cb65-6"><a href="#cb65-6" aria-hidden="true" tabindex="-1"></a>    r + <span class="ot">(</span>d + q * d<span class="ot">)</span>           ≡⟨ +-assoc r <span class="ot">_</span> <span class="ot">_</span> ]≡</span>
<span id="cb65-7"><a href="#cb65-7" aria-hidden="true" tabindex="-1"></a>    <span class="ot">(</span>r + d<span class="ot">)</span> + q * d           ≡[ <span class="ot">_</span>+<span class="ot">_</span> $≡ +-comm r <span class="ot">_</span> ≡$ q * d ⟩≡</span>
<span id="cb65-8"><a href="#cb65-8" aria-hidden="true" tabindex="-1"></a>    <span class="ot">(</span>d + r<span class="ot">)</span> + q * d           ≡[ +-assoc d <span class="ot">_</span> <span class="ot">_</span> ⟩≡</span>
<span id="cb65-9"><a href="#cb65-9" aria-hidden="true" tabindex="-1"></a>    d + <span class="ot">(</span>r + q * d<span class="ot">)</span>           ≡[ d +<span class="ot">_</span> $≡ r+qd≡n′ ⟩≡</span>
<span id="cb65-10"><a href="#cb65-10" aria-hidden="true" tabindex="-1"></a>    d + n′                    ≡[ +-comm d <span class="ot">_</span> ⟩≡</span>
<span id="cb65-11"><a href="#cb65-11" aria-hidden="true" tabindex="-1"></a>    n′ + d                    ≡[ n′+d≡n ⟩≡</span>
<span id="cb65-12"><a href="#cb65-12" aria-hidden="true" tabindex="-1"></a>    n                         ∎</span></code></pre></div>
<p>Now it seems like we have everything we need to write the division
algorithm as a recursive algorithm: given <span class="math inline">\(n\)</span> and <span class="math inline">\(d\)</span>, check whether
<span class="math inline">\(n\)</span> can be decreased by <span class="math inline">\(d\)</span> or not. If not, we can return <span class="math inline">\(q = 0\)</span> and
<span class="math inline">\(r = n\)</span>. Otherwise, recurse on <span class="math inline">\(n - d\)</span>, returning the same remainder
and an incremented quotient from whatever the recursive call returns, using
<code>incDivMod</code> to discharge the proof obligation. It’s just a few lines
of code, right?</p>
<div class="sourceCode" id="cb66"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb66-1"><a href="#cb66-1" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> DivModBad <span class="kw">where</span></span>
<span id="cb66-2"><a href="#cb66-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb66-3"><a href="#cb66-3" aria-hidden="true" tabindex="-1"></a>  <span class="pp">{-# NON_TERMINATING #-}</span></span>
<span id="cb66-4"><a href="#cb66-4" aria-hidden="true" tabindex="-1"></a>  divAlg <span class="ot">:</span> <span class="ot">(</span>n d <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> DivAlg n d</span>
<span id="cb66-5"><a href="#cb66-5" aria-hidden="true" tabindex="-1"></a>  divAlg n d <span class="kw">with</span> n decreaseBy? d</span>
<span id="cb66-6"><a href="#cb66-6" aria-hidden="true" tabindex="-1"></a>  <span class="ot">...</span> <span class="ot">|</span> LT n&lt;d <span class="ot">=</span> <span class="ot">(</span><span class="dv">0</span> , n<span class="ot">)</span> , <span class="ot">(</span>DM <span class="ot">(</span>n +0<span class="ot">)</span> n&lt;d<span class="ot">)</span></span>
<span id="cb66-7"><a href="#cb66-7" aria-hidden="true" tabindex="-1"></a>  <span class="ot">...</span> <span class="ot">|</span> GE n′ n′+d≡n <span class="kw">with</span> divAlg n′ d</span>
<span id="cb66-8"><a href="#cb66-8" aria-hidden="true" tabindex="-1"></a>  <span class="ot">...</span> <span class="ot">|</span> <span class="ot">(</span>q , r<span class="ot">)</span> , dm <span class="ot">=</span> <span class="ot">(</span>suc q , r<span class="ot">)</span> , <span class="ot">(</span>incDivMod n′+d≡n dm<span class="ot">)</span></span></code></pre></div>
<p>Well, as you can see, it <em>is</em> just a few lines of code, but all is not
well: although this function typechecks, Agda can’t tell that it is
terminating! (I added the <code>NON_TERMINATING</code> pragma so I could include
this bad version of <code>divAlg</code> in the code without causing an error.)
The problem is that the recursive call to <code>divAlg</code> is on <code>n′</code>,
which is not a subterm of <code>n</code>, but instead comes from the call to
<code>decreaseBy?</code>. Agda has no way of knowing whether the result from
some random function call is going to end up being smaller than the
original input.</p>
<p>Now, you and I can both see that this function does indeed terminate,
but we just need a way to convince Agda of this fact… right?</p>
<p>…have you spotted the flaw? Remember how I mentioned that the type <code>(n d : ℕ) → DivAlg n d</code> is not quite right? In fact, the above bad
implementation of <code>divMod</code> is <em>not</em> terminating, and Agda is quite right to
be worried! In particular, the function recurses infinitely when given an input of <span class="math inline">\(d
= 0\)</span>, since it will keep subtracting <span class="math inline">\(0\)</span> from <span class="math inline">\(n\)</span> forever. This makes sense, of
course: everyone knows you can’t divide by zero <em>because it makes the
universe go into infinite recursion</em>.</p>
<p>The correct type for <code>divAlg</code> is <code>(n d : ℕ) → (0 &lt; d) → DivAlg n d</code>,
but we’re still going to have trouble convincing Agda that our
algorithm is terminating. In order to do so, we need to take a detour
through <em>well-founded induction</em>.</p>
</section>
</section>
<section id="well-founded-induction" class="level2">
<h2>Well-founded induction</h2>
<p>Normally, Agda only allows functions that are <em>structurally
recursive</em>—that is, functions which make recursive calls on syntactic
subterms of their inputs. (Agda’s termination checking is a bit more
sophisticated than that, but that’s the basic idea.) However, we can
use basic structural induction to bootstrap our way into more exotic
forms. In particular, we are going to define something called
<em>well-founded induction</em>.<span class="sidenote-wrapper"><label for="sn-6" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-6" class="margin-toggle"/><span class="sidenote">Note that I will use the terms “recursion”
and “induction” more or less interchangeably. In some contexts, people
make a distinction between the terms (typically a <em>recursion
principle</em> is a less-dependently-typed version of an <em>induction
principle</em>), but in this context, <em>inductive proofs</em> correspond, via
Curry-Howard, to (suitably restricted) <em>recursive functions</em>, so
“induction” and “recursion” describe the same thing from a logical and
computational viewpoint, respectively.<br />
<br />
</span></span></p>
<p>The idea of well-founded induction starts with the general idea of a
<em>relation</em>. A relation on <code>A</code> is just a function that takes two
values of type <code>A</code> and produces a type, representing evidence that the
two values are related (according to whatever kind of relationship we
have in mind).</p>
<div class="sourceCode" id="cb67"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb67-1"><a href="#cb67-1" aria-hidden="true" tabindex="-1"></a>Rel <span class="ot">:</span> <span class="dt">Set</span> <span class="ot">→</span> <span class="dt">Set₁</span></span>
<span id="cb67-2"><a href="#cb67-2" aria-hidden="true" tabindex="-1"></a>Rel A <span class="ot">=</span> A <span class="ot">→</span> A <span class="ot">→</span> <span class="dt">Set</span></span></code></pre></div>
<p>We have already seen quite a few relations, such as equality, <span class="math inline">\(&lt;\)</span>,
<span class="math inline">\(\leq\)</span>, and divisibility.</p>
<p>Suppose we’re writing a recursive function, with some relation <span class="math inline">\(\prec\)</span>
in mind, and for a given input <span class="math inline">\(x\)</span> we’re only allowed to make
recursive calls on values <span class="math inline">\(y\)</span> such that <span class="math inline">\(y \prec x\)</span>. If <span class="math inline">\(\prec\)</span> is the
“is a syntactic subterm of” relation, then we get structural
recursion as usual. But what if <span class="math inline">\(\prec\)</span> is some other relation? What
needs to be true about <span class="math inline">\(\prec\)</span> for this to make sense? In particular, how
can we be sure that the function won’t get stuck in infinite recursion?</p>
<p>One’s first instinct might be to say that <span class="math inline">\(y \prec x\)</span> needs to imply that
<span class="math inline">\(y\)</span> is “smaller than” <span class="math inline">\(x\)</span> somehow. But what does “smaller than” mean?
And in fact, “smaller than” doesn’t always work: for example, if we are
writing a function over the rational numbers, or even just the
integers, the usual “smaller than” relation does <em>not</em> guarantee our
function will terminate; it’s possible to continue choosing smaller
and smaller rational numbers or integers forever.</p>
<p>The key idea is exactly that this can’t happen: it’s not possible to
have an infinite chain of values where each is related to the
previous. That is, there should be no left-infinite chains <span class="math inline">\(\dots
\prec y_3 \prec y_2 \prec y_1 \prec x\)</span>. Then we are guaranteed that if we keep making
recursive calls on values that are related by <span class="math inline">\(\prec\)</span> to the previous
value, we will have to stop eventually: after some finite number of calls
we will hit a value with nothing else related to it.</p>
<p>A relation <span class="math inline">\(\prec\)</span> with this “no left-infinite chains” property is
called <em>well-founded</em>. But how do we encode this idea in Agda?</p>
<section id="accessibility" class="level3">
<h3>Accessibility</h3>
<p>Instead of thinking negatively (<em>no</em> left-infinite
chains), the key is to think positively: <em>all</em> chains to the left of
<em>every</em> value are finite. Call a value <em>accessible</em> if all chains
leading to it are finite. Another way to say this is that a value is
accessible if every value related to it is also accessible:</p>
<div class="sourceCode" id="cb68"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb68-1"><a href="#cb68-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> Acc <span class="ot">(_</span>≺<span class="ot">_</span> <span class="ot">:</span> Rel A<span class="ot">)</span> <span class="ot">:</span> A <span class="ot">→</span> <span class="dt">Set</span> <span class="kw">where</span></span>
<span id="cb68-2"><a href="#cb68-2" aria-hidden="true" tabindex="-1"></a>  acc <span class="ot">:</span> <span class="ot">{</span>x <span class="ot">:</span> A<span class="ot">}</span> <span class="ot">→</span> <span class="ot">((</span>y <span class="ot">:</span> A<span class="ot">)</span> <span class="ot">→</span> y ≺ x <span class="ot">→</span> Acc <span class="ot">_</span>≺<span class="ot">_</span> y<span class="ot">)</span> <span class="ot">→</span> Acc <span class="ot">_</span>≺<span class="ot">_</span> x</span></code></pre></div>
<p><code>Acc _≺_ x</code> defines what it means for a particular value <code>x</code> to be
accessible with respect to a relation <span class="math inline">\(\prec\)</span>. There is only one
constructor, <code>acc</code>, which requires <code>(y : A) → y ≺ x → Acc _≺_ y</code>—that
is, for every value <code>y</code> of type <code>A</code>, if <code>y</code> is related to <code>x</code>, then
<code>y</code> is accessible. In other words, <code>x</code> is accessible if and only if every <code>y ≺ x</code>
is accessible.</p>
<p>This is definitely tricky to wrap your head around! At this point
you may have two objections:</p>
<ol type="1">
<li><p>What about base cases? Shouldn’t we have another constructor which
says <code>x</code> is accessible if <em>nothing</em> is related to it? Actually,
the <code>acc</code> constructor already says that! If nothing is related to
<code>x</code>, then <code>(y : A) → y ≺ x → Acc _≺_ y</code> is trivially true: we can
easily promise anything we want as the output of a function if we
know it can never be called. Every natural number less than zero is a
purple flying weasel.</p></li>
<li><p>Doesn’t this just run into the same problem as before with
left-infinite chains? If we consider the “is one less than”
relation on the integers, isn’t <span class="math inline">\(2\)</span> accessible because <span class="math inline">\(1\)</span> is
accessible because <span class="math inline">\(0\)</span> is accessible because <span class="math inline">\(-1\)</span> is accessible
because … ?</p>
<p>There is something a bit subtle going on here: recursive data types
in Agda (unlike Haskell) are interpreted according to a
<em>least fixed point</em> semantics. Put in plain terms, the only values
of a data type are those which can be built by applications of a
<em>finite</em> number of constructors. So in fact, the “no left-infinite
chain” condition is foundationally built into the way Agda data
types work!</p></li>
</ol>
<p>The idea is that we can turn well-founded induction into structural
induction by <em>pattern-matching on <code>Acc</code> proofs</em>! Starting with some
<span class="math inline">\(x\)</span>, any <span class="math inline">\(y \prec x\)</span> has an accessibility proof which is a subterm of
the accessibility proof for <span class="math inline">\(x\)</span>. This is a bit exotic though: if we
pattern-match on the <code>acc</code> for <span class="math inline">\(x\)</span> we get a <em>function</em> that yields an
accessibility proof for each <span class="math inline">\(y \prec x\)</span>; calling that function
produces another accessibility proof, which <em>counts as a structural
subterm of the original</em>. This seems a bit strange until you think of
a value of type <code>Acc</code> like an big, arbitrarily-branching tree of
finite depth; each node contains a function which really just stores
all the subtrees. In other words, a function of type <code>(y : A) → y ≺ x → Acc _≺_ y</code> can be thought of as a giant tuple of <code>Acc</code> values, one
for each <code>y \prec x</code>.<span class="sidenote-wrapper"><label for="sn-7" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-7" class="margin-toggle"/><span class="sidenote">I am not sure exactly how Agda handles this
internally, but I assume this is well-trodden ground for designers of
proof assistants.<br />
<br />
</span></span></p>
</section>
<section id="well-founded-induction-defined" class="level3">
<h3>Well-founded induction, defined</h3>
<p>Given the definition of accessible elements, we can now give the
definition of a well-founded relation: a relation on <code>A</code> is well-founded if
<em>every</em> value of type <code>A</code> is accessible.</p>
<div class="sourceCode" id="cb69"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb69-1"><a href="#cb69-1" aria-hidden="true" tabindex="-1"></a>WellFounded <span class="ot">:</span> Rel A <span class="ot">→</span> <span class="dt">Set</span></span>
<span id="cb69-2"><a href="#cb69-2" aria-hidden="true" tabindex="-1"></a>WellFounded <span class="ot">{</span>A<span class="ot">}</span> <span class="ot">_</span>≺<span class="ot">_</span> <span class="ot">=</span> <span class="ot">(</span>a <span class="ot">:</span> A<span class="ot">)</span> <span class="ot">→</span> Acc <span class="ot">_</span>≺<span class="ot">_</span> a</span></code></pre></div>
<p>We can now write down the <em>principle of well-founded induction</em>. This
is also quite tricky to wrap your brain around, so we’ll go through it
slowly. Previously, we were just talking about whether functions terminated or
not; but the reason this is important is that a function might be
calculating a <em>proof</em>. A function which purports to calculate a proof
but sometimes goes into infinite recursion is a charlatan, and not
really a proof at all.</p>
<p>So instead of thinking about termination, let’s switch to thinking
about proofs. Given a proposition <span class="math inline">\(P\)</span>, we want to prove that
<span class="math inline">\(P\)</span> holds for every value of type <span class="math inline">\(A\)</span>. The idea is that when trying to
prove <span class="math inline">\(P(y)\)</span> for a particular <span class="math inline">\(y\)</span>, we get to assume that <span class="math inline">\(P(z)\)</span> holds
(<em>i.e.</em> we get to make recursive calls) for all <span class="math inline">\(z \prec y\)</span>.</p>
<p>Here, then, is the statement of the principle of well-founded induction, with
each argument broken out on a separate line so we can explain them as
we go.</p>
<div class="sourceCode" id="cb70"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb70-1"><a href="#cb70-1" aria-hidden="true" tabindex="-1"></a>wf-ind <span class="ot">:</span></span>
<span id="cb70-2"><a href="#cb70-2" aria-hidden="true" tabindex="-1"></a>  <span class="ot">{</span>P <span class="ot">:</span> A <span class="ot">→</span> <span class="dt">Set</span><span class="ot">}</span></span></code></pre></div>
<ul>
<li><code>P</code> represents an arbitrary proposition on <code>A</code>; our goal is to show <code>P</code> holds for
every value of type <code>A</code>.</li>
</ul>
<div class="sourceCode" id="cb71"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb71-1"><a href="#cb71-1" aria-hidden="true" tabindex="-1"></a>  <span class="ot">{_</span>≺<span class="ot">_</span> <span class="ot">:</span> Rel A<span class="ot">}</span> <span class="ot">→</span></span></code></pre></div>
<ul>
<li>An arbitrary relation.</li>
</ul>
<div class="sourceCode" id="cb72"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb72-1"><a href="#cb72-1" aria-hidden="true" tabindex="-1"></a>  WellFounded <span class="ot">_</span>≺<span class="ot">_</span> <span class="ot">→</span></span></code></pre></div>
<ul>
<li>A proof that <code>≺</code> is a well-founded relation.</li>
</ul>
<div class="sourceCode" id="cb73"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb73-1"><a href="#cb73-1" aria-hidden="true" tabindex="-1"></a>  <span class="ot">((</span>y <span class="ot">:</span> A<span class="ot">)</span> <span class="ot">→</span> <span class="ot">((</span>z <span class="ot">:</span> A<span class="ot">)</span> <span class="ot">→</span> z ≺ y <span class="ot">→</span> P z<span class="ot">)</span> <span class="ot">→</span> P y<span class="ot">)</span> <span class="ot">→</span></span></code></pre></div>
<ul>
<li>This is the trickiest
argument to understand. Intuitively, it says “For any
<code>y</code>, if we know <code>P z</code> holds for all <code>z ≺ y</code>, then we can show <code>P y</code>
also holds.”</li>
</ul>
<div class="sourceCode" id="cb74"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb74-1"><a href="#cb74-1" aria-hidden="true" tabindex="-1"></a>  <span class="ot">(</span>x <span class="ot">:</span> A<span class="ot">)</span> <span class="ot">→</span> P x</span></code></pre></div>
<ul>
<li>The principle of well-founded induction says that all of this is
enough to show that <code>P x</code> holds for <em>all</em> <code>x : A</code>.</li>
</ul>
<p>So, how do we implement this? If we try something
straightforward, as in <code>wf-ind-bad</code> below—just call <code>ind</code> on <code>x</code>, then call <code>wf-ind</code> recursively
to fill in the proofs for <code>P z</code>—of course it does not work; Agda cannot
tell that this is terminating.<span class="sidenote-wrapper"><label for="sn-8" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-8" class="margin-toggle"/><span class="sidenote">As an aside, Agda complains that this definition of <code>wf-ind-bad</code>
is not terminating—which makes sense—but it continues to complain even
when I include the <code>NON_TERMINATING</code> pragma, which I don’t
understand. Perhaps this has been fixed in a more recent version of Agda.<br />
<br />
</span></span> And this makes sense, because we are
not even using the fact that the relation is well-founded at all!</p>
<pre class="plain"><code>module WFIndBad where

  {-# NON_TERMINATING #-}
  wf-ind-bad : {P : A → Set} {_≺_ : Rel A} → WellFounded _≺_ → ((y : A) → ((z : A) → z ≺ y → P z) → P y) → (x : A) → P x
  wf-ind-bad wf ind x = ind x (λ z Rzx → wf-ind-bad wf ind z)</code></pre>
<p>Instead, the right idea is to use the fact that <span class="math inline">\(\prec\)</span> is
well-founded to generate an initial proof of accessibility for the
input <span class="math inline">\(x\)</span>, and then <em>pattern match on accessibility proofs</em> alongside
the values as we recurse. Every time we make a recursive call on some
<span class="math inline">\(y \prec x\)</span>, we can just pattern-match on the accessibility proof for
<span class="math inline">\(x\)</span> to get an accessibility proof for <span class="math inline">\(y\)</span>, so Agda will be able to see
that the whole thing is <em>structurally</em> recursive on the accessibility
proofs.</p>
<div class="sourceCode" id="cb76"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb76-1"><a href="#cb76-1" aria-hidden="true" tabindex="-1"></a>wf-ind <span class="ot">{</span>A<span class="ot">}</span> <span class="ot">{</span>P<span class="ot">}</span> <span class="ot">{_</span>≺<span class="ot">_}</span> wf ind x <span class="ot">=</span> go x <span class="ot">(</span>wf x<span class="ot">)</span></span>
<span id="cb76-2"><a href="#cb76-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb76-3"><a href="#cb76-3" aria-hidden="true" tabindex="-1"></a>  go <span class="ot">:</span> <span class="ot">(</span>x <span class="ot">:</span> A<span class="ot">)</span> <span class="ot">→</span> Acc <span class="ot">_</span>≺<span class="ot">_</span> x <span class="ot">→</span> P x</span>
<span id="cb76-4"><a href="#cb76-4" aria-hidden="true" tabindex="-1"></a>  go x <span class="ot">(</span>acc f<span class="ot">)</span> <span class="ot">=</span> ind x <span class="ot">(λ</span> z z≺x <span class="ot">→</span> go z <span class="ot">(</span>f z z≺x<span class="ot">))</span></span></code></pre></div>
</section>
<section id="less-than-is-well-founded" class="level3">
<h3>Less-than is well-founded</h3>
<p>Now that we have well-founded induction under our belts, let’s show
that the less-than relation on natural numbers is well-founded. This
corresponds to what is often called “strong induction”.<span class="sidenote-wrapper"><label for="sn-9" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-9" class="margin-toggle"/><span class="sidenote">Incidentally,
we could probably have gotten away with directly defining a principle
of strong natural number induction, without bothering with the full
generality of well-founded induction, but this way is more fun and
interesting!<br />
<br />
</span></span> To prove that <span class="math inline">\(&lt;\)</span> is well-founded, we of course must
show that every natural number is accessible under <span class="math inline">\(&lt;\)</span>. However, if
we directly try to prove <code>(m : ℕ) → (Acc _&lt;_) m</code>, we run into a
variant of the exact same problem we have been dealing with: to prove
that <span class="math inline">\(m\)</span> is accessible we need to know that <em>every</em> <span class="math inline">\(k &lt; m\)</span> is also
accessible, but again, we cannot show this directly by
recursion/induction, since <span class="math inline">\(k\)</span> may not be a structural subterm of <span class="math inline">\(m\)</span>.</p>
<p>What we need is the usual trick for proving strong induction from weak
induction: instead of proving that <span class="math inline">\(P(x)\)</span> holds for all <span class="math inline">\(x\)</span>, we prove
that <span class="math inline">\((\downarrow P)(x)\)</span> holds for all <span class="math inline">\(x\)</span>, where <span class="math inline">\(\downarrow P\)</span> is
the “downward closure” of <span class="math inline">\(P\)</span>. That is, <span class="math inline">\((\downarrow P)(x)\)</span> says that
<span class="math inline">\(P(x)\)</span> holds for <em>all</em> <span class="math inline">\(y &lt; x\)</span>.<span class="sidenote-wrapper"><label for="sn-10" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-10" class="margin-toggle"/><span class="sidenote">Note that another way to define
<span class="math inline">\((\downarrow P)(x)\)</span> is that <span class="math inline">\(P(y)\)</span> holds for all <span class="math inline">\(y \sim x\)</span>, where <span class="math inline">\(\sim\)</span>
is the <em>transitive closure</em> of the predecessor relation. As an
advanced exercise, generalize <span class="math inline">\(\downarrow_\prec P\)</span> to be defined relative to
the transitive closure of any relation <span class="math inline">\(\prec\)</span>, and then prove that <span class="math inline">\(\prec\)</span> is well-founded
if and only if its transitive closure is. For more along
these lines, see this <a href="https://boarders.github.io/posts/well_founded_induction.html">very cool (but much more abstract) post on
well-founded induction by Callan McGill</a>.<br />
<br />
</span></span></p>
<div class="sourceCode" id="cb77"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb77-1"><a href="#cb77-1" aria-hidden="true" tabindex="-1"></a>↓ <span class="ot">:</span> <span class="ot">(</span>ℕ <span class="ot">→</span> <span class="dt">Set</span><span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>ℕ <span class="ot">→</span> <span class="dt">Set</span><span class="ot">)</span></span>
<span id="cb77-2"><a href="#cb77-2" aria-hidden="true" tabindex="-1"></a>↓ P n <span class="ot">=</span> <span class="ot">(</span>k <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>k &lt; n<span class="ot">)</span> <span class="ot">→</span> P k</span></code></pre></div>
<p>Now we can prove, for all natural numbers <span class="math inline">\(m\)</span>, that every natural
number up to and including <span class="math inline">\(m\)</span> is accessible under the <span class="math inline">\(&lt;\)</span> relation. Zero is accessible
because nothing is less than it; everything up to the successor of <span class="math inline">\(m\)</span> is accessible because by induction we know everything up to <span class="math inline">\(m\)</span> is, and anything less than the successor of <span class="math inline">\(m\)</span> must in fact be <span class="math inline">\(\leq m\)</span>.</p>
<div class="sourceCode" id="cb78"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb78-1"><a href="#cb78-1" aria-hidden="true" tabindex="-1"></a>&lt;-acc <span class="ot">:</span> <span class="ot">(</span>m <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> ↓ <span class="ot">(</span>Acc <span class="ot">_</span>&lt;<span class="ot">_)</span> m</span>
<span id="cb78-2"><a href="#cb78-2" aria-hidden="true" tabindex="-1"></a>&lt;-acc zero <span class="ot">=</span> <span class="ot">λ</span> k <span class="ot">()</span></span>
<span id="cb78-3"><a href="#cb78-3" aria-hidden="true" tabindex="-1"></a>&lt;-acc <span class="ot">(</span>suc m<span class="ot">)</span> zero <span class="ot">(</span>sle le<span class="ot">)</span> <span class="ot">=</span> acc <span class="ot">(λ</span> y <span class="ot">())</span></span>
<span id="cb78-4"><a href="#cb78-4" aria-hidden="true" tabindex="-1"></a>&lt;-acc <span class="ot">(</span>suc m<span class="ot">)</span> <span class="ot">(</span>suc k<span class="ot">)</span> <span class="ot">(</span>sle le<span class="ot">)</span> <span class="ot">=</span> acc <span class="ot">(λ</span> y y&lt;sk <span class="ot">→</span> &lt;-acc m y <span class="ot">(</span>&lt;-≤-trans y&lt;sk le<span class="ot">))</span></span></code></pre></div>
<p>Finally, to show that any natural number <span class="math inline">\(n\)</span> is accessible—<em>i.e.</em> that <span class="math inline">\(&lt;\)</span>
is well-founded—we can use the fact that all numbers less than the successor of <span class="math inline">\(n\)</span>
are accessible, and just project out accessibility for <span class="math inline">\(n\)</span> itself.</p>
<div class="sourceCode" id="cb79"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb79-1"><a href="#cb79-1" aria-hidden="true" tabindex="-1"></a>&lt;-wf <span class="ot">:</span> WellFounded <span class="ot">_</span>&lt;<span class="ot">_</span></span>
<span id="cb79-2"><a href="#cb79-2" aria-hidden="true" tabindex="-1"></a>&lt;-wf n <span class="ot">=</span> &lt;-acc <span class="ot">(</span>suc n<span class="ot">)</span> n <span class="ot">(</span>n &lt;suc<span class="ot">)</span></span></code></pre></div>
</section>
</section>
<section id="the-division-algorithm" class="level2">
<h2>The division algorithm</h2>
<p>Finally, we can define the division algorithm, via well-founded
induction! The definition is very similar to our first attempt, but we use the principle of well-founded induction with <span class="math inline">\(&lt;\)</span>. Note that neither <code>divAlg</code> nor its helper function <code>go</code> is directly recursive. Instead, <code>go</code> takes an induction hypothesis as an argument, which we call instead, providing an extra proof that the subject of the induction hypothesis is in fact less than the original input. <code>wf-ind</code> takes care of the actual recursion.</p>
<div class="sourceCode" id="cb80"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb80-1"><a href="#cb80-1" aria-hidden="true" tabindex="-1"></a>divAlg <span class="ot">:</span> <span class="ot">(</span>n d <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span><span class="dv">0</span> &lt; d<span class="ot">)</span> <span class="ot">→</span> DivAlg n d</span>
<span id="cb80-2"><a href="#cb80-2" aria-hidden="true" tabindex="-1"></a>divAlg n d 0&lt;d <span class="ot">=</span> wf-ind <span class="ot">{</span>P <span class="ot">=</span> <span class="ot">λ</span> n <span class="ot">→</span> DivAlg n d<span class="ot">}</span> &lt;-wf go n</span>
<span id="cb80-3"><a href="#cb80-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb80-4"><a href="#cb80-4" aria-hidden="true" tabindex="-1"></a>  go <span class="ot">:</span> <span class="ot">(</span>n <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="ot">((</span>n′ <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> n′ &lt; n <span class="ot">→</span> DivAlg n′ d<span class="ot">)</span> <span class="ot">→</span> DivAlg n d</span>
<span id="cb80-5"><a href="#cb80-5" aria-hidden="true" tabindex="-1"></a>  go n IH <span class="kw">with</span> n decreaseBy? d</span>
<span id="cb80-6"><a href="#cb80-6" aria-hidden="true" tabindex="-1"></a>  <span class="ot">...</span> <span class="ot">|</span> LT n&lt;d <span class="ot">=</span> <span class="ot">(</span><span class="dv">0</span> , n<span class="ot">)</span> , DM <span class="ot">(</span>n +0<span class="ot">)</span> n&lt;d</span>
<span id="cb80-7"><a href="#cb80-7" aria-hidden="true" tabindex="-1"></a>  <span class="ot">...</span> <span class="ot">|</span> GE n′ n′+d≡n <span class="kw">with</span> IH n′ <span class="ot">(</span>+→&lt; 0&lt;d n′+d≡n<span class="ot">)</span></span>
<span id="cb80-8"><a href="#cb80-8" aria-hidden="true" tabindex="-1"></a>  <span class="ot">...</span> <span class="ot">|</span> <span class="ot">(</span>q , r<span class="ot">)</span> , dm <span class="ot">=</span> <span class="ot">(</span>suc q , r<span class="ot">)</span> , incDivMod n′+d≡n dm</span></code></pre></div>
<p>Using the division algorithm, we can also finally decide whether one
number divides another: zero divides zero; zero does not divide any
successor since that would imply there is some <span class="math inline">\(k\)</span> such that <span class="math inline">\(k\)</span> times
zero is nonzero, which is absurd; and if <span class="math inline">\(x\)</span> is a successor, we can
apply the division algorithm and check the remainder, applying some
previous lemmas that say what zero and nonzero remainders tells us
about divisibility.</p>
<div class="sourceCode" id="cb81"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb81-1"><a href="#cb81-1" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>∣?<span class="ot">_</span> <span class="ot">:</span> <span class="ot">(</span>x y <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> Dec <span class="ot">(</span>x ∣ y<span class="ot">)</span></span>
<span id="cb81-2"><a href="#cb81-2" aria-hidden="true" tabindex="-1"></a>zero ∣? zero <span class="ot">=</span> yes <span class="ot">(</span><span class="dv">0</span> , refl<span class="ot">)</span></span>
<span id="cb81-3"><a href="#cb81-3" aria-hidden="true" tabindex="-1"></a>zero ∣? <span class="ot">(</span>suc y<span class="ot">)</span> <span class="ot">=</span> no <span class="ot">λ</span> <span class="ot">{</span> <span class="ot">(</span>a , eq<span class="ot">)</span> <span class="ot">→</span> absurd <span class="ot">(</span>noConf <span class="ot">(</span>trans <span class="ot">(</span>sym <span class="ot">(</span>*-comm a zero<span class="ot">))</span> eq<span class="ot">))}</span></span>
<span id="cb81-4"><a href="#cb81-4" aria-hidden="true" tabindex="-1"></a><span class="ot">(</span>suc x<span class="ot">)</span> ∣? y <span class="kw">with</span> divAlg y <span class="ot">(</span>suc x<span class="ot">)</span> <span class="ot">(</span>sle zle<span class="ot">)</span></span>
<span id="cb81-5"><a href="#cb81-5" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> <span class="ot">(</span>q , zero<span class="ot">)</span> , dm <span class="ot">=</span> yes <span class="ot">(</span>mod0→divides y <span class="ot">(</span>suc x<span class="ot">)</span> dm<span class="ot">)</span></span>
<span id="cb81-6"><a href="#cb81-6" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> <span class="ot">(</span>q , suc r<span class="ot">)</span> , dm <span class="ot">=</span> no <span class="ot">(</span>modS→¬divides y <span class="ot">(</span>suc x<span class="ot">)</span> dm<span class="ot">)</span></span></code></pre></div>
</section>
<section id="primality-testing" class="level2">
<h2>Primality testing</h2>
<p>To test a number for primality, we are just going to use
straightforward, naive trial division. The straightforward way of
doing this is by starting at <span class="math inline">\(2\)</span> and counting <em>up</em>—but this is a
problem, because when pattern-matching on natural numbers we most
naturally count <em>down</em>.</p>
<p>Well, remember—build the evidence you want to pattern-match on! Let’s
develop some machinery for counting up instead of down.</p>
<section id="counting-up" class="level3">
<h3>Counting up</h3>
<p>The problem starts with <span class="math inline">\(\leq\)</span>: a proof of <span class="math inline">\(m \leq n\)</span> starts with a
base case representing evidence that <span class="math inline">\(0 \leq k\)</span>, then every
constructor application of <code>sle</code> increments both sides by one.
Pattern-matching on a proof of <span class="math inline">\(m \leq n\)</span> thus either reveals that <span class="math inline">\(m
= 0\)</span>, or that <span class="math inline">\(m&#39; \leq n&#39;\)</span> where <span class="math inline">\(m&#39;\)</span> and <span class="math inline">\(n&#39;\)</span> are the predecessors of
<span class="math inline">\(m\)</span> and <span class="math inline">\(n\)</span>: in other words, it facilitates counting <em>down</em>, just
like matching directly on <span class="math inline">\(m\)</span> would.</p>
<p>However, there is an alternative way to define the <span class="math inline">\(\leq\)</span> relation,
which we will call <span class="math inline">\(\leq&#39;\)</span>.
We can choose <em>reflexivity</em> of <span class="math inline">\(\leq&#39;\)</span> as a base case, that is, <span class="math inline">\(n \leq&#39;
n\)</span> for any <span class="math inline">\(n\)</span>. We can then <em>decrement</em> the left-hand side every time
we apply another constructor. Like so:</p>
<div class="sourceCode" id="cb82"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb82-1"><a href="#cb82-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="ot">_</span>≤′<span class="ot">_</span> <span class="ot">:</span> ℕ <span class="ot">→</span> ℕ <span class="ot">→</span> <span class="dt">Set</span> <span class="kw">where</span></span>
<span id="cb82-2"><a href="#cb82-2" aria-hidden="true" tabindex="-1"></a>  lerefl <span class="ot">:</span> <span class="ot">{</span>n <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> n ≤′ n</span>
<span id="cb82-3"><a href="#cb82-3" aria-hidden="true" tabindex="-1"></a>  lesuc <span class="ot">:</span> <span class="ot">{</span>m n <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> suc m ≤′ n <span class="ot">→</span> m ≤′ n</span></code></pre></div>
<p>Pattern-matching on a proof of <span class="math inline">\(m \leq&#39; n\)</span> thus facilitates counting
<em>up</em> from <span class="math inline">\(m\)</span> to <span class="math inline">\(n\)</span>, just like we wanted!</p>
<p>We can also prove a few lemmas about properties of <span class="math inline">\(\leq&#39;\)</span>. For
example, the two axioms that define the usual <span class="math inline">\(\leq\)</span> can be proved as
lemmas.</p>
<div class="sourceCode" id="cb83"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb83-1"><a href="#cb83-1" aria-hidden="true" tabindex="-1"></a>≤′-suc <span class="ot">:</span> <span class="ot">{</span>m n <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> m ≤′ n <span class="ot">→</span> suc m ≤′ suc n</span>
<span id="cb83-2"><a href="#cb83-2" aria-hidden="true" tabindex="-1"></a>≤′-suc lerefl <span class="ot">=</span> lerefl</span>
<span id="cb83-3"><a href="#cb83-3" aria-hidden="true" tabindex="-1"></a>≤′-suc <span class="ot">(</span>lesuc m≤′n<span class="ot">)</span> <span class="ot">=</span> lesuc <span class="ot">(</span>≤′-suc m≤′n<span class="ot">)</span></span>
<span id="cb83-4"><a href="#cb83-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb83-5"><a href="#cb83-5" aria-hidden="true" tabindex="-1"></a>0≤′ <span class="ot">:</span> <span class="ot">(</span>n <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="dv">0</span> ≤′ n</span>
<span id="cb83-6"><a href="#cb83-6" aria-hidden="true" tabindex="-1"></a>0≤′ zero <span class="ot">=</span> lerefl</span>
<span id="cb83-7"><a href="#cb83-7" aria-hidden="true" tabindex="-1"></a>0≤′ <span class="ot">(</span>suc n<span class="ot">)</span> <span class="ot">=</span> lesuc <span class="ot">(</span>≤′-suc <span class="ot">(</span>0≤′ n<span class="ot">))</span></span></code></pre></div>
<p>We can also prove that <span class="math inline">\(m \leq n\)</span> implies <span class="math inline">\(m \leq&#39; n\)</span>. (The converse
is true as well, and can be proved as an easy exercise, but we won’t need it.)</p>
<div class="sourceCode" id="cb84"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb84-1"><a href="#cb84-1" aria-hidden="true" tabindex="-1"></a>≤→≤′ <span class="ot">:</span> <span class="ot">{</span>m n <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> m ≤ n <span class="ot">→</span> m ≤′ n</span>
<span id="cb84-2"><a href="#cb84-2" aria-hidden="true" tabindex="-1"></a>≤→≤′ <span class="ot">{</span>n <span class="ot">=</span> n<span class="ot">}</span> zle <span class="ot">=</span> 0≤′ n</span>
<span id="cb84-3"><a href="#cb84-3" aria-hidden="true" tabindex="-1"></a>≤→≤′ <span class="ot">(</span>sle m≤n<span class="ot">)</span> <span class="ot">=</span> ≤′-suc <span class="ot">(</span>≤→≤′ m≤n<span class="ot">)</span></span></code></pre></div>
<p>So, we can pattern-match on a proof of <span class="math inline">\(m \leq&#39; n\)</span> to count up from <span class="math inline">\(m\)</span> to
<span class="math inline">\(n\)</span>, but this isn’t quite good enough: while counting, we won’t remember the relationship of the
intermediate values to the original <span class="math inline">\(m\)</span>. We would like to be able to
count up through some interval, from some starting <span class="math inline">\(a\)</span> to ending <span class="math inline">\(b\)</span>,
knowing all along the way that the values we count are contained in
the interval.</p>
<p>To this end, we can create a data
type <code>i ∈[ a ⋯ b ]</code> which represents a stage in counting from <span class="math inline">\(a\)</span> to
<span class="math inline">\(b\)</span>. The base case is when <span class="math inline">\(i = b\)</span>; otherwise <code>i ∈[ a ⋯ b ]</code> when <span class="math inline">\(a
\leq i\)</span> and also <code>suc i ∈[ a ⋯ b ]</code>.</p>
<div class="sourceCode" id="cb85"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb85-1"><a href="#cb85-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="ot">_</span>∈[<span class="ot">_</span>⋯<span class="ot">_</span>] <span class="ot">:</span> ℕ <span class="ot">→</span> ℕ <span class="ot">→</span> ℕ <span class="ot">→</span> <span class="dt">Set</span> <span class="kw">where</span></span>
<span id="cb85-2"><a href="#cb85-2" aria-hidden="true" tabindex="-1"></a>  stop <span class="ot">:</span> <span class="ot">{</span>a b <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> a ≤ b <span class="ot">→</span> b ∈[ a ⋯ b ]</span>
<span id="cb85-3"><a href="#cb85-3" aria-hidden="true" tabindex="-1"></a>  step <span class="ot">:</span> <span class="ot">{</span>a i b <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> a ≤ i <span class="ot">→</span> suc i ∈[ a ⋯ b ] <span class="ot">→</span> i ∈[ a ⋯ b ]</span></code></pre></div>
<p>We can then write a function which “constructs a loop”—that is,
starting from a proof of <span class="math inline">\(a \leq&#39; b\)</span>, it builds
a value of type <code>a ∈[ a ⋯ b ]</code> which represents a reified loop from
<span class="math inline">\(a\)</span> to <span class="math inline">\(b\)</span>. By pattern-matching on this value we can successively
increment from <span class="math inline">\(a\)</span> up to <span class="math inline">\(b\)</span>, with the appropriate guarantees along
the way.</p>
<div class="sourceCode" id="cb86"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb86-1"><a href="#cb86-1" aria-hidden="true" tabindex="-1"></a>loop <span class="ot">:</span> <span class="ot">(</span>a b <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>a ≤′ b<span class="ot">)</span> <span class="ot">→</span> a ∈[ a ⋯ b ]</span>
<span id="cb86-2"><a href="#cb86-2" aria-hidden="true" tabindex="-1"></a>loop a b a≤′b <span class="ot">=</span> mid a a b ≤-refl a≤′b</span>
<span id="cb86-3"><a href="#cb86-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb86-4"><a href="#cb86-4" aria-hidden="true" tabindex="-1"></a>  mid <span class="ot">:</span> <span class="ot">(</span>a i b <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>a ≤ i<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>i ≤′ b<span class="ot">)</span> <span class="ot">→</span> i ∈[ a ⋯ b ]</span>
<span id="cb86-5"><a href="#cb86-5" aria-hidden="true" tabindex="-1"></a>  mid a i b a≤i lerefl <span class="ot">=</span> stop a≤i</span>
<span id="cb86-6"><a href="#cb86-6" aria-hidden="true" tabindex="-1"></a>  mid a i b a≤i <span class="ot">(</span>lesuc i≤′b<span class="ot">)</span> <span class="ot">=</span> step a≤i <span class="ot">(</span>mid a <span class="ot">(</span>suc i<span class="ot">)</span> b <span class="ot">(</span>≤-sucr a≤i<span class="ot">)</span> i≤′b<span class="ot">)</span></span></code></pre></div>
<p>Finally, we need as a simple lemma the fact that if <code>i ∈[ a ⋯ b ]</code>
then in fact <span class="math inline">\(i \leq b\)</span>.</p>
<div class="sourceCode" id="cb87"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb87-1"><a href="#cb87-1" aria-hidden="true" tabindex="-1"></a>top <span class="ot">:</span> <span class="ot">{</span>i a b <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> i ∈[ a ⋯ b ] <span class="ot">→</span> i ≤ b</span>
<span id="cb87-2"><a href="#cb87-2" aria-hidden="true" tabindex="-1"></a>top <span class="ot">(</span>stop <span class="ot">_)</span> <span class="ot">=</span> ≤-refl</span>
<span id="cb87-3"><a href="#cb87-3" aria-hidden="true" tabindex="-1"></a>top <span class="ot">(</span>step <span class="ot">_</span> s<span class="ot">)</span> <span class="ot">=</span> ≤-sucl <span class="ot">(</span>top s<span class="ot">)</span></span></code></pre></div>
</section>
<section id="primality-testing-by-trial-division" class="level3">
<h3>Primality testing by trial division</h3>
<p>First, a lemma about downward closure: if we know <span class="math inline">\((\downarrow P)(m)\)</span>,
and we know <span class="math inline">\(P(m)\)</span>, then we know <span class="math inline">\((\downarrow P)(1 + m)\)</span>. In other
words, if <span class="math inline">\(P\)</span> holds for everything less than <span class="math inline">\(m\)</span>, we can extend it by
one by providing a proof that <span class="math inline">\(P\)</span> also holds for <span class="math inline">\(m\)</span>.</p>
<div class="sourceCode" id="cb88"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb88-1"><a href="#cb88-1" aria-hidden="true" tabindex="-1"></a>extend <span class="ot">:</span> <span class="ot">{</span>P <span class="ot">:</span> ℕ <span class="ot">→</span> <span class="dt">Set</span><span class="ot">}</span> <span class="ot">{</span>m <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> <span class="ot">(</span>↓ P<span class="ot">)</span> m <span class="ot">→</span> P m <span class="ot">→</span> <span class="ot">(</span>↓ P<span class="ot">)</span> <span class="ot">(</span>suc m<span class="ot">)</span></span>
<span id="cb88-2"><a href="#cb88-2" aria-hidden="true" tabindex="-1"></a>extend <span class="ot">{</span>m <span class="ot">=</span> m<span class="ot">}</span> soFar Pm j <span class="kw">with</span> <span class="ot">(</span>j ≟ m<span class="ot">)</span></span>
<span id="cb88-3"><a href="#cb88-3" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> yes refl <span class="ot">=</span> <span class="ot">λ</span> <span class="ot">_</span> <span class="ot">→</span> Pm</span>
<span id="cb88-4"><a href="#cb88-4" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> no j≢m <span class="ot">=</span> <span class="ot">λ</span> <span class="ot">{</span> <span class="ot">(</span>sle j≤m<span class="ot">)</span> <span class="ot">→</span> soFar j <span class="ot">(</span>≤≢→&lt; j≤m j≢m<span class="ot">)</span> <span class="ot">}</span></span></code></pre></div>
<p>Now we can define primality testing itself, via trial division. We
<code>loop</code> from <span class="math inline">\(2\)</span> up to <span class="math inline">\(n\)</span>, testing each number to see if it divides
<span class="math inline">\(n\)</span>, keeping track along the way of the fact that all the numbers less
than our current trial divisor do not divide <span class="math inline">\(n\)</span>. If the next divisor
does divide <span class="math inline">\(n\)</span>, we return it as proof that <span class="math inline">\(n\)</span> is composite. If it
does not, we <code>extend</code> our accumulating proof of all the numbers that do
not divide <span class="math inline">\(n\)</span>, and proceed to the next. If we reach <span class="math inline">\(n\)</span>, our
accumulated proof tells us that none of the numbers less than <span class="math inline">\(n\)</span>
divide it, which is proof that <span class="math inline">\(n\)</span> is prime.</p>
<div class="sourceCode" id="cb89"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb89-1"><a href="#cb89-1" aria-hidden="true" tabindex="-1"></a>prime? <span class="ot">:</span> <span class="ot">(</span>n <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span><span class="dv">2</span> ≤ n<span class="ot">)</span> <span class="ot">→</span> Prime n ⊎ Composite n</span>
<span id="cb89-2"><a href="#cb89-2" aria-hidden="true" tabindex="-1"></a>prime? n 2≤n <span class="ot">=</span> trialDiv <span class="ot">(</span>loop <span class="dv">2</span> n <span class="ot">(</span>≤→≤′ 2≤n<span class="ot">))</span> noDivisorsUpTo2</span>
<span id="cb89-3"><a href="#cb89-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb89-4"><a href="#cb89-4" aria-hidden="true" tabindex="-1"></a>  NoDivisorsUpTo <span class="ot">:</span> ℕ <span class="ot">→</span> <span class="dt">Set</span></span>
<span id="cb89-5"><a href="#cb89-5" aria-hidden="true" tabindex="-1"></a>  NoDivisorsUpTo <span class="ot">=</span> ↓ <span class="ot">(λ</span> # <span class="ot">→</span> <span class="ot">(</span><span class="dv">2</span> ≤ #<span class="ot">)</span> <span class="ot">→</span> ¬ <span class="ot">(</span># ∣ n<span class="ot">))</span></span>
<span id="cb89-6"><a href="#cb89-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb89-7"><a href="#cb89-7" aria-hidden="true" tabindex="-1"></a>  noDivisorsUpTo2 <span class="ot">:</span> NoDivisorsUpTo <span class="dv">2</span></span>
<span id="cb89-8"><a href="#cb89-8" aria-hidden="true" tabindex="-1"></a>  noDivisorsUpTo2 <span class="ot">(</span>suc zero<span class="ot">)</span> <span class="ot">_</span> <span class="ot">(</span>sle <span class="ot">())</span> <span class="ot">_</span></span>
<span id="cb89-9"><a href="#cb89-9" aria-hidden="true" tabindex="-1"></a>  noDivisorsUpTo2 <span class="ot">(</span>suc <span class="ot">(</span>suc j<span class="ot">))</span> <span class="ot">(</span>sle <span class="ot">(</span>sle <span class="ot">()))</span> <span class="ot">_</span> <span class="ot">_</span></span>
<span id="cb89-10"><a href="#cb89-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb89-11"><a href="#cb89-11" aria-hidden="true" tabindex="-1"></a>  trialDiv <span class="ot">:</span> <span class="ot">{</span>m <span class="ot">:</span> ℕ<span class="ot">}</span> <span class="ot">→</span> m ∈[ <span class="dv">2</span> ⋯ n ] <span class="ot">→</span> NoDivisorsUpTo m <span class="ot">→</span> Prime n ⊎ Composite n</span>
<span id="cb89-12"><a href="#cb89-12" aria-hidden="true" tabindex="-1"></a>  trialDiv <span class="ot">(</span>stop 2≤n<span class="ot">)</span> soFar <span class="ot">=</span> inj₁ <span class="ot">(</span>2≤n , soFar<span class="ot">)</span></span>
<span id="cb89-13"><a href="#cb89-13" aria-hidden="true" tabindex="-1"></a>  trialDiv <span class="ot">{</span>m<span class="ot">}</span> <span class="ot">(</span>step 2≤m next<span class="ot">)</span> soFar <span class="kw">with</span> m ∣? n</span>
<span id="cb89-14"><a href="#cb89-14" aria-hidden="true" tabindex="-1"></a>  <span class="ot">...</span> <span class="ot">|</span> yes m∣n <span class="ot">=</span> inj₂ <span class="ot">(</span>m , 2≤m , top next , m∣n<span class="ot">)</span></span>
<span id="cb89-15"><a href="#cb89-15" aria-hidden="true" tabindex="-1"></a>  <span class="ot">...</span> <span class="ot">|</span> no pf <span class="ot">=</span> trialDiv next <span class="ot">(</span>extend soFar <span class="ot">(λ</span> <span class="ot">_</span> <span class="ot">→</span> pf<span class="ot">))</span></span></code></pre></div>
</section>
</section>
<section id="lists" class="level2">
<h2>Lists</h2>
<p>Before we are able to state the Fundamental Theorem of Arithmetic, we need to build up a data type for lists, along with some standard list manipulation functions. First, we define the type of lists and the standard <code>foldr</code> function.</p>
<div class="sourceCode" id="cb90"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb90-1"><a href="#cb90-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> List <span class="ot">(</span>A <span class="ot">:</span> <span class="dt">Set</span><span class="ot">)</span> <span class="ot">:</span> <span class="dt">Set</span> <span class="kw">where</span></span>
<span id="cb90-2"><a href="#cb90-2" aria-hidden="true" tabindex="-1"></a>  [] <span class="ot">:</span> List A</span>
<span id="cb90-3"><a href="#cb90-3" aria-hidden="true" tabindex="-1"></a>  <span class="ot">_</span>∷<span class="ot">_</span> <span class="ot">:</span> A <span class="ot">→</span> List A <span class="ot">→</span> List A</span>
<span id="cb90-4"><a href="#cb90-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb90-5"><a href="#cb90-5" aria-hidden="true" tabindex="-1"></a>foldr <span class="ot">:</span> <span class="ot">(</span>A <span class="ot">→</span> B <span class="ot">→</span> B<span class="ot">)</span> <span class="ot">→</span> B <span class="ot">→</span> List A <span class="ot">→</span> B</span>
<span id="cb90-6"><a href="#cb90-6" aria-hidden="true" tabindex="-1"></a>foldr <span class="ot">_</span>&amp;<span class="ot">_</span> z [] <span class="ot">=</span> z</span>
<span id="cb90-7"><a href="#cb90-7" aria-hidden="true" tabindex="-1"></a>foldr <span class="ot">_</span>&amp;<span class="ot">_</span> z <span class="ot">(</span>x ∷ xs<span class="ot">)</span> <span class="ot">=</span> x &amp; foldr <span class="ot">_</span>&amp;<span class="ot">_</span> z xs</span></code></pre></div>
<p>Now we can define concatenation and product via <code>foldr</code>.</p>
<div class="sourceCode" id="cb91"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb91-1"><a href="#cb91-1" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>++<span class="ot">_</span> <span class="ot">:</span> List A <span class="ot">→</span> List A <span class="ot">→</span> List A</span>
<span id="cb91-2"><a href="#cb91-2" aria-hidden="true" tabindex="-1"></a>xs ++ ys <span class="ot">=</span> foldr <span class="ot">(_</span>∷<span class="ot">_)</span> ys xs</span>
<span id="cb91-3"><a href="#cb91-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb91-4"><a href="#cb91-4" aria-hidden="true" tabindex="-1"></a>product <span class="ot">:</span> List ℕ <span class="ot">→</span> ℕ</span>
<span id="cb91-5"><a href="#cb91-5" aria-hidden="true" tabindex="-1"></a>product <span class="ot">=</span> foldr <span class="ot">_</span>*<span class="ot">_</span> <span class="dv">1</span></span></code></pre></div>
<p>We will need <code>All</code>, which expresses that some predicate holds of all
the elements of a list. In fact, <code>All</code> is manifestly an instance of
<code>foldr</code> as well, but we would need a universe-polymorphic version of <code>foldr</code> for that, so we just write it manually.</p>
<div class="sourceCode" id="cb92"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb92-1"><a href="#cb92-1" aria-hidden="true" tabindex="-1"></a>All <span class="ot">:</span> <span class="ot">(</span>P <span class="ot">:</span> A <span class="ot">→</span> <span class="dt">Set</span><span class="ot">)</span> <span class="ot">→</span> List A <span class="ot">→</span> <span class="dt">Set</span></span>
<span id="cb92-2"><a href="#cb92-2" aria-hidden="true" tabindex="-1"></a>All P [] <span class="ot">=</span> ⊤</span>
<span id="cb92-3"><a href="#cb92-3" aria-hidden="true" tabindex="-1"></a>All P <span class="ot">(</span>x ∷ xs<span class="ot">)</span> <span class="ot">=</span> P x × All P xs</span></code></pre></div>
<p>Now, we just need a couple lemmas about concatenation: first, that if <code>P</code> holds for all the elements in <code>xs</code> and all the elements in <code>ys</code>, then it holds for all the elements in <code>xs ++ ys</code>; and second, that <code>product</code> distributes over concatenation (<em>i.e.</em> it is a homomorphism from the monoid of lists under concatenation to the monoid of natural numbers under multiplication).</p>
<div class="sourceCode" id="cb93"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb93-1"><a href="#cb93-1" aria-hidden="true" tabindex="-1"></a>All-++ <span class="ot">:</span> <span class="ot">{</span>P <span class="ot">:</span> A <span class="ot">→</span> <span class="dt">Set</span><span class="ot">}</span> <span class="ot">{</span>xs ys <span class="ot">:</span> List A<span class="ot">}</span> <span class="ot">→</span> All P xs <span class="ot">→</span> All P ys <span class="ot">→</span> All P <span class="ot">(</span>xs ++ ys<span class="ot">)</span></span>
<span id="cb93-2"><a href="#cb93-2" aria-hidden="true" tabindex="-1"></a>All-++ <span class="ot">{</span>xs <span class="ot">=</span> []<span class="ot">}</span> Pxs Pys <span class="ot">=</span> Pys</span>
<span id="cb93-3"><a href="#cb93-3" aria-hidden="true" tabindex="-1"></a>All-++ <span class="ot">{</span>xs <span class="ot">=</span> <span class="ot">_</span> ∷ <span class="ot">_}</span> <span class="ot">(</span>Px , Pxs<span class="ot">)</span> Pys <span class="ot">=</span> Px , All-++ Pxs Pys</span>
<span id="cb93-4"><a href="#cb93-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb93-5"><a href="#cb93-5" aria-hidden="true" tabindex="-1"></a>product-++ <span class="ot">:</span> <span class="ot">(</span>xs ys <span class="ot">:</span> List ℕ<span class="ot">)</span> <span class="ot">→</span> product <span class="ot">(</span>xs ++ ys<span class="ot">)</span> ≡ product xs * product ys</span>
<span id="cb93-6"><a href="#cb93-6" aria-hidden="true" tabindex="-1"></a>product-++ [] ys <span class="ot">=</span> sym <span class="ot">(_</span> +0<span class="ot">)</span></span>
<span id="cb93-7"><a href="#cb93-7" aria-hidden="true" tabindex="-1"></a>product-++ <span class="ot">(</span>x ∷ xs<span class="ot">)</span> ys <span class="ot">=</span> trans <span class="ot">(</span>x *<span class="ot">_</span> $≡ product-++ xs ys<span class="ot">)</span> <span class="ot">(</span>sym <span class="ot">(</span>*-assoc x <span class="ot">(</span>product xs<span class="ot">)</span> <span class="ot">(</span>product ys<span class="ot">)))</span></span></code></pre></div>
</section>
<section id="the-fundamental-theorem-of-arithmetic" class="level2">
<h2>The Fundamental Theorem of Arithmetic</h2>
<p>Finally, we can put all the pieces together to state and prove (one
half of) the Fundamental Theorem of Arithmetic! <code>FTA n</code> says that for
some positive integer <code>n</code>, we can find a list of natural numbers which
are all prime, and whose product is <code>n</code>.</p>
<div class="sourceCode" id="cb94"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb94-1"><a href="#cb94-1" aria-hidden="true" tabindex="-1"></a>FTA <span class="ot">:</span> ℕ <span class="ot">→</span> <span class="dt">Set</span></span>
<span id="cb94-2"><a href="#cb94-2" aria-hidden="true" tabindex="-1"></a>FTA n <span class="ot">=</span> Σ <span class="ot">(</span>List ℕ<span class="ot">)</span> <span class="ot">(λ</span> ps <span class="ot">→</span> All Prime ps × product ps ≡ n<span class="ot">)</span></span></code></pre></div>
<p>To prove that this holds for all positive integers, we can again use
well-founded induction: in the base case, if <span class="math inline">\(n = 1\)</span>, the empty list
suffices. Otherwise, we can decide whether <span class="math inline">\(n\)</span> is prime. If so, the
singleton list containing <span class="math inline">\(n\)</span> fits the bill. Otherwise, <span class="math inline">\(n = ab\)</span> where
<span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span> are both nontrivial divisors of <span class="math inline">\(n\)</span>; by the induction
hypothesis, both can be factored into primes, and the list we want for
<span class="math inline">\(n\)</span> is simply the concatenation of the factorizations for <span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span>.</p>
<div class="sourceCode" id="cb95"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb95-1"><a href="#cb95-1" aria-hidden="true" tabindex="-1"></a>fta <span class="ot">:</span> <span class="ot">(</span>n <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span><span class="dv">0</span> &lt; n<span class="ot">)</span> <span class="ot">→</span> FTA n</span>
<span id="cb95-2"><a href="#cb95-2" aria-hidden="true" tabindex="-1"></a>fta n <span class="ot">=</span> wf-ind <span class="ot">{</span>P <span class="ot">=</span> <span class="ot">(λ</span> n <span class="ot">→</span> <span class="ot">(</span><span class="dv">0</span> &lt; n<span class="ot">)</span> <span class="ot">→</span> FTA n<span class="ot">)}</span> &lt;-wf go n</span>
<span id="cb95-3"><a href="#cb95-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb95-4"><a href="#cb95-4" aria-hidden="true" tabindex="-1"></a>  go <span class="ot">:</span> <span class="ot">(</span>n <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> <span class="ot">((</span>n′ <span class="ot">:</span> ℕ<span class="ot">)</span> <span class="ot">→</span> n′ &lt; n <span class="ot">→</span> <span class="dv">0</span> &lt; n′ <span class="ot">→</span> FTA n′<span class="ot">)</span> <span class="ot">→</span> <span class="dv">0</span> &lt; n <span class="ot">→</span> FTA n</span>
<span id="cb95-5"><a href="#cb95-5" aria-hidden="true" tabindex="-1"></a>  go <span class="ot">(</span>suc zero<span class="ot">)</span> IH 0&lt;n <span class="ot">=</span> [] , <span class="ot">(</span>tt , refl<span class="ot">)</span></span>
<span id="cb95-6"><a href="#cb95-6" aria-hidden="true" tabindex="-1"></a>  go <span class="ot">(</span>suc <span class="ot">(</span>suc n<span class="ot">))</span> IH 0&lt;n <span class="kw">with</span> prime? <span class="ot">(</span>suc <span class="ot">(</span>suc n<span class="ot">))</span> <span class="ot">(</span>sle <span class="ot">(</span>sle zle<span class="ot">))</span></span>
<span id="cb95-7"><a href="#cb95-7" aria-hidden="true" tabindex="-1"></a>  <span class="ot">...</span> <span class="ot">|</span> inj₁ P <span class="ot">=</span> <span class="ot">(</span>suc <span class="ot">(</span>suc n<span class="ot">)</span> ∷ []<span class="ot">)</span> , <span class="ot">((</span>P , tt<span class="ot">)</span> , <span class="ot">(</span>suc $≡ <span class="ot">(</span>suc $≡ <span class="ot">(</span>n *1<span class="ot">))))</span></span>
<span id="cb95-8"><a href="#cb95-8" aria-hidden="true" tabindex="-1"></a>  <span class="ot">...</span> <span class="ot">|</span> inj₂ C <span class="kw">with</span> factorsOf <span class="ot">_</span> C</span>
<span id="cb95-9"><a href="#cb95-9" aria-hidden="true" tabindex="-1"></a>  <span class="ot">...</span> <span class="ot">|</span> <span class="ot">((</span>a , sle <span class="ot">_</span> , a&lt;n , <span class="ot">_)</span> , <span class="ot">(</span>b , sle <span class="ot">_</span> , b&lt;n , <span class="ot">_))</span> , ab≡n</span>
<span id="cb95-10"><a href="#cb95-10" aria-hidden="true" tabindex="-1"></a>      <span class="kw">with</span> IH a a&lt;n <span class="ot">(</span>sle zle<span class="ot">)</span></span>
<span id="cb95-11"><a href="#cb95-11" aria-hidden="true" tabindex="-1"></a>         <span class="ot">|</span> IH b b&lt;n <span class="ot">(</span>sle zle<span class="ot">)</span></span>
<span id="cb95-12"><a href="#cb95-12" aria-hidden="true" tabindex="-1"></a>  <span class="ot">...</span> <span class="ot">|</span> ps₁ , Pps₁ , prod₁ <span class="ot">|</span> ps₂ , Pps₂ , prod₂ <span class="ot">=</span> <span class="ot">(</span>ps₁ ++ ps₂<span class="ot">)</span> , <span class="ot">(</span>All-++ Pps₁ Pps₂<span class="ot">)</span> ,</span>
<span id="cb95-13"><a href="#cb95-13" aria-hidden="true" tabindex="-1"></a>    begin</span>
<span id="cb95-14"><a href="#cb95-14" aria-hidden="true" tabindex="-1"></a>      product <span class="ot">(</span>ps₁ ++ ps₂<span class="ot">)</span>      ≡[ product-++ ps₁ ps₂ ⟩≡</span>
<span id="cb95-15"><a href="#cb95-15" aria-hidden="true" tabindex="-1"></a>      product ps₁ * product ps₂ ≡[ <span class="ot">_</span>*<span class="ot">_</span> $≡ prod₁ ≡$≡ prod₂ ⟩≡</span>
<span id="cb95-16"><a href="#cb95-16" aria-hidden="true" tabindex="-1"></a>      a * b                     ≡[ ab≡n ⟩≡</span>
<span id="cb95-17"><a href="#cb95-17" aria-hidden="true" tabindex="-1"></a>      suc <span class="ot">(</span>suc n<span class="ot">)</span>               ∎</span></code></pre></div>
</section>
<section id="further-directions" class="level2">
<h2>Further Directions</h2>
<p>That concludes our tour of the Fundamental Theorem of Arithmetic in Agda! If you’ve worked through the whole thing and
completed the proofs mostly on your own, congratulations! If you want
more practice, there are a lot of directions you could take this:</p>
<ul>
<li>Doing trial division all the way up to <span class="math inline">\(n\)</span> is silly; we can stop
when we get to <span class="math inline">\(\sqrt n\)</span>. I think this would make for a nice
exercise (in fact, Taneb’s version in the Agda stdlib does this).</li>
<li>Define “<span class="math inline">\(d\)</span> is a proper divisor of <span class="math inline">\(n\)</span>” to mean that that <span class="math inline">\(d \mid n\)</span>
and <span class="math inline">\(2 \leq d &lt; n\)</span>, then show that the “is a proper divisor of” relation
is well-founded, and prove <code>fta</code> via well-founded induction on that
relation instead. This might streamline some parts of the proof;
I’m not sure.</li>
<li>The other half of the FTA says that the prime factorization is
<em>unique up to permutation</em>. To prove this, one has to define
what it means for one list to be a permutation of another, and show that
if there are two different prime factorizations then one must be a
permutation of the other (if <span class="math inline">\(p\)</span> is a prime from the first
factorization, then it divides the other factorization as well,
which means it must be equal to one of the primes in the other
factorization). I may write up this proof in a follow-up post.</li>
</ul>
</section>

</section>

<script data-isso="https://comments.byorgey.com/" src="https://comments.byorgey.com/js/embed.min.js"></script>
<section id="isso-thread"  data-title="Proving the Fundamental Theorem of Arithmetic in Agda" >
  <noscript>Javascript needs to be activated to view comments.</noscript>
</section>

]]></description>
    <pubDate>Fri, 26 Jun 2026 00:00:00 UT</pubDate>
    <guid>http://byorgey.github.io/blog/posts/2026/06/26/FTA.lagda.html</guid>
    <dc:creator>Brent Yorgey</dc:creator>
</item>
<item>
    <title>Disco Live!</title>
    <link>http://byorgey.github.io/blog/posts/2026/01/09/disco-live.html</link>
    <description><![CDATA[
<h1>Disco Live!</h1>

<div class="info">
  Posted on January  9, 2026
  
  
  <br />
  Tagged <a title="All pages tagged &#39;disco&#39;." href="/tag/disco.html" rel="tag">disco</a>, <a title="All pages tagged &#39;web&#39;." href="/tag/web.html" rel="tag">web</a>, <a title="All pages tagged &#39;WASM&#39;." href="/tag/WASM.html" rel="tag">WASM</a>, <a title="All pages tagged &#39;UI&#39;." href="/tag/UI.html" rel="tag">UI</a>, <a title="All pages tagged &#39;teaching&#39;." href="/tag/teaching.html" rel="tag">teaching</a>, <a title="All pages tagged &#39;discrete&#39;." href="/tag/discrete.html" rel="tag">discrete</a>, <a title="All pages tagged &#39;math&#39;." href="/tag/math.html" rel="tag">math</a>, <a title="All pages tagged &#39;Haskell&#39;." href="/tag/Haskell.html" rel="tag">Haskell</a>
  
</div>

<a href="https://share.joinmastodon.org/#text=Disco Live! https://byorgey.github.io/blog/posts/2026/01/09/disco-live.html" target="_blank" rel="noopener">Share on <svg role="img" aria-label="Mastodon" height="1em" viewBox="0 0 74 79" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M73.7014 17.4323C72.5616 9.05152 65.1774 2.4469 56.424 1.1671C54.9472 0.950843 49.3518 0.163818 36.3901 0.163818H36.2933C23.3281 0.163818 20.5465 0.950843 19.0697 1.1671C10.56 2.41145 2.78877 8.34604 0.903306 16.826C-0.00357854 21.0022 -0.100361 25.6322 0.068112 29.8793C0.308275 35.9699 0.354874 42.0498 0.91406 48.1156C1.30064 52.1448 1.97502 56.1419 2.93215 60.0769C4.72441 67.3445 11.9795 73.3925 19.0876 75.86C26.6979 78.4332 34.8821 78.8603 42.724 77.0937C43.5866 76.8952 44.4398 76.6647 45.2833 76.4024C47.1867 75.8033 49.4199 75.1332 51.0616 73.9562C51.0841 73.9397 51.1026 73.9184 51.1156 73.8938C51.1286 73.8693 51.1359 73.8421 51.1368 73.8144V67.9366C51.1364 67.9107 51.1302 67.8852 51.1186 67.862C51.1069 67.8388 51.0902 67.8184 51.0695 67.8025C51.0489 67.7865 51.0249 67.7753 50.9994 67.7696C50.9738 67.764 50.9473 67.7641 50.9218 67.7699C45.8976 68.9569 40.7491 69.5519 35.5836 69.5425C26.694 69.5425 24.3031 65.3699 23.6184 63.6327C23.0681 62.1314 22.7186 60.5654 22.5789 58.9744C22.5775 58.9477 22.5825 58.921 22.5934 58.8965C22.6043 58.8721 22.621 58.8505 22.6419 58.8336C22.6629 58.8167 22.6876 58.8049 22.714 58.7992C22.7404 58.7934 22.7678 58.794 22.794 58.8007C27.7345 59.9796 32.799 60.5746 37.8813 60.5733C39.1036 60.5733 40.3223 60.5733 41.5447 60.5414C46.6562 60.3996 52.0437 60.1408 57.0728 59.1694C57.1983 59.1446 57.3237 59.1233 57.4313 59.0914C65.3638 57.5847 72.9128 52.8555 73.6799 40.8799C73.7086 40.4084 73.7803 35.9415 73.7803 35.4523C73.7839 33.7896 74.3216 23.6576 73.7014 17.4323ZM61.4925 47.3144H53.1514V27.107C53.1514 22.8528 51.3591 20.6832 47.7136 20.6832C43.7061 20.6832 41.6988 23.2499 41.6988 28.3194V39.3803H33.4078V28.3194C33.4078 23.2499 31.3969 20.6832 27.3894 20.6832C23.7654 20.6832 21.9552 22.8528 21.9516 27.107V47.3144H13.6176V26.4937C13.6176 22.2395 14.7157 18.8598 16.9118 16.3545C19.1772 13.8552 22.1488 12.5719 25.8373 12.5719C30.1064 12.5719 33.3325 14.1955 35.4832 17.4394L37.5587 20.8853L39.6377 17.4394C41.7884 14.1955 45.0145 12.5719 49.2765 12.5719C52.9614 12.5719 55.9329 13.8552 58.2055 16.3545C60.4017 18.8574 61.4997 22.2371 61.4997 26.4937L61.4925 47.3144Z" fill="inherit"/></svg></a>
<section>
<p>A couple months ago, <a href="https://byorgey.github.io/blog/posts/2025/11/10/disco-web-ui.html">I asked for
help</a>
creating a web interface for
<a href="https://github.com/disco-lang/disco">Disco</a>, a
student-oriented programming language for teaching functional
programming and discrete mathematics. I am very happy to report that
<a href="https://apfelmus.nfshost.com/">Heinrich Apfelmus</a> responded to the
call, and this is the result:</p>
<p><a href="https://disco-lang.github.io/disco-live/">Disco Live!</a></p>
<p>It’s fairly bare bones at the moment, but it’s a fantastic place to
start, and far more than I would have been able to accomplish in a few
weeks. Give it a try, and let me know of any bugs you find! You are
also very welcome to contribute fixes, features, etc. on GitHub:</p>
<ul>
<li><a href="https://github.com/disco-lang/disco-live">The disco-live repo</a></li>
<li><a href="https://github.com/disco-lang/disco">The repo for disco itself</a></li>
</ul>
<p>If you want to know more about Disco, you can <a href="http://ozark.hendrix.edu/~yorgey/forest/yorgey-disco-2023/index.xml">read a paper about it
here</a>,
or <a href="https://disco-lang.readthedocs.io/en/latest/">read the language documentation</a>.</p>

</section>

<script data-isso="https://comments.byorgey.com/" src="https://comments.byorgey.com/js/embed.min.js"></script>
<section id="isso-thread"  data-title="Disco Live!" >
  <noscript>Javascript needs to be activated to view comments.</noscript>
</section>

]]></description>
    <pubDate>Fri, 09 Jan 2026 00:00:00 UT</pubDate>
    <guid>http://byorgey.github.io/blog/posts/2026/01/09/disco-live.html</guid>
    <dc:creator>Brent Yorgey</dc:creator>
</item>
<item>
    <title>Call for collaboration: Disco web UI</title>
    <link>http://byorgey.github.io/blog/posts/2025/11/10/disco-web-ui.html</link>
    <description><![CDATA[
<h1>Call for collaboration: Disco web UI</h1>

<div class="info">
  Posted on November 10, 2025
  
  
  <br />
  Tagged <a title="All pages tagged &#39;disco&#39;." href="/tag/disco.html" rel="tag">disco</a>, <a title="All pages tagged &#39;web&#39;." href="/tag/web.html" rel="tag">web</a>, <a title="All pages tagged &#39;WASM&#39;." href="/tag/WASM.html" rel="tag">WASM</a>, <a title="All pages tagged &#39;UI&#39;." href="/tag/UI.html" rel="tag">UI</a>, <a title="All pages tagged &#39;teaching&#39;." href="/tag/teaching.html" rel="tag">teaching</a>, <a title="All pages tagged &#39;discrete&#39;." href="/tag/discrete.html" rel="tag">discrete</a>, <a title="All pages tagged &#39;math&#39;." href="/tag/math.html" rel="tag">math</a>, <a title="All pages tagged &#39;Haskell&#39;." href="/tag/Haskell.html" rel="tag">Haskell</a>
  
</div>

<a href="https://share.joinmastodon.org/#text=Call for collaboration: Disco web UI https://byorgey.github.io/blog/posts/2025/11/10/disco-web-ui.html" target="_blank" rel="noopener">Share on <svg role="img" aria-label="Mastodon" height="1em" viewBox="0 0 74 79" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M73.7014 17.4323C72.5616 9.05152 65.1774 2.4469 56.424 1.1671C54.9472 0.950843 49.3518 0.163818 36.3901 0.163818H36.2933C23.3281 0.163818 20.5465 0.950843 19.0697 1.1671C10.56 2.41145 2.78877 8.34604 0.903306 16.826C-0.00357854 21.0022 -0.100361 25.6322 0.068112 29.8793C0.308275 35.9699 0.354874 42.0498 0.91406 48.1156C1.30064 52.1448 1.97502 56.1419 2.93215 60.0769C4.72441 67.3445 11.9795 73.3925 19.0876 75.86C26.6979 78.4332 34.8821 78.8603 42.724 77.0937C43.5866 76.8952 44.4398 76.6647 45.2833 76.4024C47.1867 75.8033 49.4199 75.1332 51.0616 73.9562C51.0841 73.9397 51.1026 73.9184 51.1156 73.8938C51.1286 73.8693 51.1359 73.8421 51.1368 73.8144V67.9366C51.1364 67.9107 51.1302 67.8852 51.1186 67.862C51.1069 67.8388 51.0902 67.8184 51.0695 67.8025C51.0489 67.7865 51.0249 67.7753 50.9994 67.7696C50.9738 67.764 50.9473 67.7641 50.9218 67.7699C45.8976 68.9569 40.7491 69.5519 35.5836 69.5425C26.694 69.5425 24.3031 65.3699 23.6184 63.6327C23.0681 62.1314 22.7186 60.5654 22.5789 58.9744C22.5775 58.9477 22.5825 58.921 22.5934 58.8965C22.6043 58.8721 22.621 58.8505 22.6419 58.8336C22.6629 58.8167 22.6876 58.8049 22.714 58.7992C22.7404 58.7934 22.7678 58.794 22.794 58.8007C27.7345 59.9796 32.799 60.5746 37.8813 60.5733C39.1036 60.5733 40.3223 60.5733 41.5447 60.5414C46.6562 60.3996 52.0437 60.1408 57.0728 59.1694C57.1983 59.1446 57.3237 59.1233 57.4313 59.0914C65.3638 57.5847 72.9128 52.8555 73.6799 40.8799C73.7086 40.4084 73.7803 35.9415 73.7803 35.4523C73.7839 33.7896 74.3216 23.6576 73.7014 17.4323ZM61.4925 47.3144H53.1514V27.107C53.1514 22.8528 51.3591 20.6832 47.7136 20.6832C43.7061 20.6832 41.6988 23.2499 41.6988 28.3194V39.3803H33.4078V28.3194C33.4078 23.2499 31.3969 20.6832 27.3894 20.6832C23.7654 20.6832 21.9552 22.8528 21.9516 27.107V47.3144H13.6176V26.4937C13.6176 22.2395 14.7157 18.8598 16.9118 16.3545C19.1772 13.8552 22.1488 12.5719 25.8373 12.5719C30.1064 12.5719 33.3325 14.1955 35.4832 17.4394L37.5587 20.8853L39.6377 17.4394C41.7884 14.1955 45.0145 12.5719 49.2765 12.5719C52.9614 12.5719 55.9329 13.8552 58.2055 16.3545C60.4017 18.8574 61.4997 22.2371 61.4997 26.4937L61.4925 47.3144Z" fill="inherit"/></svg></a>
<section>
<p><strong>tl;dr</strong>: I would like to have a web interface for <a href="https://github.com/disco-lang/disco">Disco</a>, a
student-oriented programming language for teaching functional
programming and discrete mathematics, which is implemented in Haskell.
I’m looking for others interested to help build it. If you like
building web stuff with Haskell compiled to WASM and want to have a
positive impact on students learning mathematics and functional
programming, <a href="http://ozark.hendrix.edu/~yorgey/forest/contact/index.xml">get in touch</a>!</p>
<section id="disco" class="level2">
<h2>Disco</h2>
<p>For the past nine (!) years I have been developing
<a href="https://github.com/disco-lang/disco">Disco</a>, a functional teaching
language for use in a discrete mathematics course. It features
first-class functions, polymorphism, and recursive algebraic data
types, along with various built-in mathematical niceties and syntax
that is designed to be close to mathematical practice.</p>
<p>As a simple example, here’s a recursive function in Disco to compute the
<a href="https://oeis.org/A002487">hyperbinary numbers</a>:</p>
<pre><code>h : N -&gt; N
h(0)      = 1
h(2n)     = h(n) + h(n .- 1)
h(2n + 1) = h(n)</code></pre>
<p>Since recursive functions in Disco are automatically memoized, this
evaluates almost instantly even on very large numbers:</p>
<pre><code>Disco&gt; h(1000000)
1287</code></pre>
<p>If you want to know more about Disco, you can <a href="http://ozark.hendrix.edu/~yorgey/forest/yorgey-disco-2023/index.xml">read a paper about it
here</a>,
or <a href="https://disco-lang.readthedocs.io/en/latest/">read the language documentation</a>.</p>
</section>
<section id="the-problem" class="level2">
<h2>The problem</h2>
<p>I want students in my <a href="https://hendrix-cs.github.io/math240/">Discrete Mathematics
course</a> (or any Discrete
Mathematics course) to be able to use Disco: to play around at a REPL,
write and test their own code, and so on.</p>
<p>However, getting students to install Haskell and build Disco from
source is a total non-starter, for multiple reasons. Some students in
the course are not all that tech-savvy. Some students don’t even have
their own computer, or the computer they do have chokes when trying to
compile a large Haskell project (<em>e.g.</em> because of limited memory).
Even aside from those issues, I simply don’t want to spend time and
effort helping students install stuff at the beginning of the semester
(at least not in this class).</p>
</section>
<section id="old-solution-replit" class="level2">
<h2>Old solution: Replit</h2>
<p>For a couple years, students were able to use Disco via a site called
Replit, which provided free educational accounts, and supported
arbitrary Nix configurations. Since the <a href="https://hackage.haskell.org/package/disco">disco package on
Hackage</a> was picked up by
nixpkgs, it was possible to spin up a Disco interpreter on Replit in
just a few seconds. Replit provided a virtual file system, an editor,
and, of course, a REPL.</p>
<p>This was a great solution while it lasted, but sadly it is no longer
viable:</p>
<ul>
<li>Disco has been broken in nixpkgs for a while now, and I have no idea
how to fix it.</li>
<li>Even if I could fix it, Replit has stopped supporting free education
accounts, and started trying to shove LLMs into everything, making it no
longer a viable teaching platform.</li>
</ul>
</section>
<section id="solution-criteria" class="level2">
<h2>Solution criteria</h2>
<p>There are a few non-negotiable criteria that any solution must meet:</p>
<ul>
<li><p>It must either run on existing cloud infrastructure, or run
completely client-side. I do not want to be in the business of
running a server, or of worrying about mitigating DOS attacks (by
which I mean students accidentally running infinite loops generating
infinite amounts of memory). I also do not want to be in the
business of managing accounts and logins.</p></li>
<li><p>Students should not have to install anything. As I mentioned
before, this is a nonstarter for some students.</p></li>
<li><p>It should allow students to work at a Disco REPL, and also test
their own Disco code.</p></li>
</ul>
</section>
<section id="potential-solutions" class="level2">
<h2>Potential solutions</h2>
<ul>
<li><p>Of course, a really nice solution would be to find an existing site
which replicates some of the functionality we used to have with
Replit and supports educational uses. I kind of doubt such a thing
exists, though I would be happy to be wrong about this.</p></li>
<li><p>Another possibility is to have students use VSCode in their browsers
via GitHub; to make this work we would have to add LSP support to
Disco and package it up appropriately. I’m not really excited about
using GitHub for this, although implementing LSP for Disco is
independently a great idea.</p></li>
<li><p>The other solution I can think of is to compile Disco to WASM, and
build a web UI on top of it, so that the whole thing runs in the
student’s browser. I spent some time on this last year and
successfully got Disco to compile to WASM, but didn’t make it any
farther than that. Honestly, I simply don’t know anything about web
development, and I am not very motivated to learn.</p></li>
</ul>
</section>
<section id="ui-levels" class="level2">
<h2>UI levels</h2>
<p>Running with the last idea above (WASM + a custom web UI), what could
such a thing look like? What features would we want? Here are some
different solutions I could imagine, in increasing order of effort.</p>
<ul>
<li><p><strong>Level 0</strong> would be to have just a web-based REPL. Students can
edit Disco code on their own device, upload it to the website, then
evaluate expressions at the REPL. Having to reupload their code
every time they make changes would be annoying, but this would still
be better than nothing.</p></li>
<li><p><strong>Level 1</strong> would be to have a web-based editor and REPL. Students
can type code in the editor, then push a button to load it into the
REPL and play with it.</p></li>
<li><p><strong>Level 2</strong> would be to have a web-based filesystem + editor + REPL.
Students can see a list of multiple files, edit them individually, and
load any of them into the REPL. The filesystem must live on their own
computer, not on a remote server; but it could be their real
filesystem, or a virtual filesystem.</p></li>
</ul>
<p>I don’t know how difficult any of these are; I would assume that
at least some of them can be achieved by gluing together some existing
Javascript components (e.g. <a href="https://codemirror.net/">CodeMirror</a>?).
I’m sure it will require extending Disco itself with some new APIs,
but I can definitely work on that part once I know what would be needed.</p>
<p>If you know how to build web UIs like this and are interested in
helping, <a href="http://ozark.hendrix.edu/~yorgey/forest/contact/index.xml">get in touch</a>!</p>
</section>

</section>

<script data-isso="https://comments.byorgey.com/" src="https://comments.byorgey.com/js/embed.min.js"></script>
<section id="isso-thread"  data-title="Call for collaboration: Disco web UI" >
  <noscript>Javascript needs to be activated to view comments.</noscript>
</section>

]]></description>
    <pubDate>Mon, 10 Nov 2025 00:00:00 UT</pubDate>
    <guid>http://byorgey.github.io/blog/posts/2025/11/10/disco-web-ui.html</guid>
    <dc:creator>Brent Yorgey</dc:creator>
</item>
<item>
    <title>Decidable equality for indexed data types, take 2</title>
    <link>http://byorgey.github.io/blog/posts/2025/08/22/OneLevelTypesIndexed2.lagda.html</link>
    <description><![CDATA[
<h1>Decidable equality for indexed data types, take 2</h1>

<div class="info">
  Posted on August 22, 2025
  
  
  <br />
  Tagged <a title="All pages tagged &#39;agda&#39;." href="/tag/agda.html" rel="tag">agda</a>, <a title="All pages tagged &#39;equality&#39;." href="/tag/equality.html" rel="tag">equality</a>, <a title="All pages tagged &#39;path&#39;." href="/tag/path.html" rel="tag">path</a>, <a title="All pages tagged &#39;dependent&#39;." href="/tag/dependent.html" rel="tag">dependent</a>, <a title="All pages tagged &#39;indexed&#39;." href="/tag/indexed.html" rel="tag">indexed</a>, <a title="All pages tagged &#39;agda&#39;." href="/tag/agda.html" rel="tag">agda</a>
  
</div>

<a href="https://share.joinmastodon.org/#text=Decidable equality for indexed data types, take 2 https://byorgey.github.io/blog/posts/2025/08/22/OneLevelTypesIndexed2.lagda.html" target="_blank" rel="noopener">Share on <svg role="img" aria-label="Mastodon" height="1em" viewBox="0 0 74 79" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M73.7014 17.4323C72.5616 9.05152 65.1774 2.4469 56.424 1.1671C54.9472 0.950843 49.3518 0.163818 36.3901 0.163818H36.2933C23.3281 0.163818 20.5465 0.950843 19.0697 1.1671C10.56 2.41145 2.78877 8.34604 0.903306 16.826C-0.00357854 21.0022 -0.100361 25.6322 0.068112 29.8793C0.308275 35.9699 0.354874 42.0498 0.91406 48.1156C1.30064 52.1448 1.97502 56.1419 2.93215 60.0769C4.72441 67.3445 11.9795 73.3925 19.0876 75.86C26.6979 78.4332 34.8821 78.8603 42.724 77.0937C43.5866 76.8952 44.4398 76.6647 45.2833 76.4024C47.1867 75.8033 49.4199 75.1332 51.0616 73.9562C51.0841 73.9397 51.1026 73.9184 51.1156 73.8938C51.1286 73.8693 51.1359 73.8421 51.1368 73.8144V67.9366C51.1364 67.9107 51.1302 67.8852 51.1186 67.862C51.1069 67.8388 51.0902 67.8184 51.0695 67.8025C51.0489 67.7865 51.0249 67.7753 50.9994 67.7696C50.9738 67.764 50.9473 67.7641 50.9218 67.7699C45.8976 68.9569 40.7491 69.5519 35.5836 69.5425C26.694 69.5425 24.3031 65.3699 23.6184 63.6327C23.0681 62.1314 22.7186 60.5654 22.5789 58.9744C22.5775 58.9477 22.5825 58.921 22.5934 58.8965C22.6043 58.8721 22.621 58.8505 22.6419 58.8336C22.6629 58.8167 22.6876 58.8049 22.714 58.7992C22.7404 58.7934 22.7678 58.794 22.794 58.8007C27.7345 59.9796 32.799 60.5746 37.8813 60.5733C39.1036 60.5733 40.3223 60.5733 41.5447 60.5414C46.6562 60.3996 52.0437 60.1408 57.0728 59.1694C57.1983 59.1446 57.3237 59.1233 57.4313 59.0914C65.3638 57.5847 72.9128 52.8555 73.6799 40.8799C73.7086 40.4084 73.7803 35.9415 73.7803 35.4523C73.7839 33.7896 74.3216 23.6576 73.7014 17.4323ZM61.4925 47.3144H53.1514V27.107C53.1514 22.8528 51.3591 20.6832 47.7136 20.6832C43.7061 20.6832 41.6988 23.2499 41.6988 28.3194V39.3803H33.4078V28.3194C33.4078 23.2499 31.3969 20.6832 27.3894 20.6832C23.7654 20.6832 21.9552 22.8528 21.9516 27.107V47.3144H13.6176V26.4937C13.6176 22.2395 14.7157 18.8598 16.9118 16.3545C19.1772 13.8552 22.1488 12.5719 25.8373 12.5719C30.1064 12.5719 33.3325 14.1955 35.4832 17.4394L37.5587 20.8853L39.6377 17.4394C41.7884 14.1955 45.0145 12.5719 49.2765 12.5719C52.9614 12.5719 55.9329 13.8552 58.2055 16.3545C60.4017 18.8574 61.4997 22.2371 61.4997 26.4937L61.4925 47.3144Z" fill="inherit"/></svg></a>
<section>
<p>In a <a href="https://byorgey.github.io/blog/posts/2024/09/09/OneLevelTypesIndexed.lagda.html">post from a year
ago</a>,
I explored how to prove decidable equality in Agda of a particular
indexed data type. Recently, I discovered a different way to
accomplish the same thing, without resorting to embedded sigma types.</p>
<p>This post is literate Agda; you can <a href="https://github.com/byorgey/blog/blob/main/posts/2025/08/22/OneLevelTypesIndexed2.lagda.md">download it
here</a>
if you want to play along. I tested everything here with Agda version
2.6.4.3 and version 2.0 of the standard library. (I assume it would
also work with more recent versions, but haven’t tested it.)</p>
<section id="background" class="level2">
<h2>Background</h2>
<p><em>This section is repeated from my <a href="https://byorgey.github.io/blog/posts/2024/09/09/OneLevelTypesIndexed.lagda.html">previous
post</a>,
which I assume no one remembers.</em></p>
<p>First, some imports and a module declaration. Note that the entire
development is parameterized by some abstract set <code>B</code> of base types,
which must have decidable equality.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">open</span> <span class="kw">import</span> Data<span class="ot">.</span>Product <span class="kw">using</span> <span class="ot">(</span>Σ <span class="ot">;</span> <span class="ot">_</span>×<span class="ot">_</span> <span class="ot">;</span> <span class="ot">_</span>,<span class="ot">_</span> <span class="ot">;</span> -,<span class="ot">_</span> <span class="ot">;</span> proj₁ <span class="ot">;</span> proj₂<span class="ot">)</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">open</span> <span class="kw">import</span> Data<span class="ot">.</span>Product<span class="ot">.</span>Properties <span class="kw">using</span> <span class="ot">(</span>≡-dec<span class="ot">)</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">open</span> <span class="kw">import</span> Function <span class="kw">using</span> <span class="ot">(_</span>∘<span class="ot">_)</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">open</span> <span class="kw">import</span> Relation<span class="ot">.</span>Binary <span class="kw">using</span> <span class="ot">(</span>DecidableEquality<span class="ot">)</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">open</span> <span class="kw">import</span> Relation<span class="ot">.</span>Binary<span class="ot">.</span>PropositionalEquality <span class="kw">using</span> <span class="ot">(_</span>≡<span class="ot">_</span> <span class="ot">;</span> refl<span class="ot">)</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="kw">open</span> <span class="kw">import</span> Relation<span class="ot">.</span>Nullary<span class="ot">.</span>Decidable <span class="kw">using</span> <span class="ot">(</span>yes<span class="ot">;</span> no<span class="ot">;</span> Dec<span class="ot">)</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">module</span> OneLevelTypesIndexed2 <span class="ot">(</span>B <span class="ot">:</span> <span class="dt">Set</span><span class="ot">)</span> <span class="ot">(</span>≟B <span class="ot">:</span> DecidableEquality B<span class="ot">)</span> <span class="kw">where</span></span></code></pre></div>
<p>We’ll work with a simple type system containing base types, function
types, and some distinguished type constructor □. So far, this is
just to give some context; it is not the final version of the code we
will end up with, so we stick it in a local module so it won’t end up
in the top-level namespace.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> Unindexed <span class="kw">where</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">data</span> Ty <span class="ot">:</span> <span class="dt">Set</span> <span class="kw">where</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    base <span class="ot">:</span> B <span class="ot">→</span> Ty</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="ot">_</span>⇒<span class="ot">_</span> <span class="ot">:</span> Ty <span class="ot">→</span> Ty <span class="ot">→</span> Ty</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    □<span class="ot">_</span> <span class="ot">:</span> Ty <span class="ot">→</span> Ty</span></code></pre></div>
<p>For example, if <span class="math inline">\(X\)</span> and <span class="math inline">\(Y\)</span> are base types, then we could write down a
type like <span class="math inline">\(\square ((\square \square X \to Y) \to \square Y)\)</span>:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>  <span class="kw">infixr</span> <span class="dv">2</span> <span class="ot">_</span>⇒<span class="ot">_</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">infix</span> <span class="dv">30</span> □<span class="ot">_</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="kw">postulate</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    BX BY <span class="ot">:</span> B</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>  X <span class="ot">:</span> Ty</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>  X <span class="ot">=</span> base BX</span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>  Y <span class="ot">:</span> Ty</span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>  Y <span class="ot">=</span> base BY</span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>  example <span class="ot">:</span> Ty</span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>  example <span class="ot">=</span> □ <span class="ot">((</span>□ □ X ⇒ Y<span class="ot">)</span> ⇒ □ Y<span class="ot">)</span></span></code></pre></div>
<p>However, for reasons that would take us too far afield in this blog
post, I <em>don’t</em> want to allow immediately nested boxes, like <span class="math inline">\(\square
\square X\)</span>. We can still have multiple boxes in a type, and even
boxes nested inside of other boxes, as long as there is at least one
arrow in between. In other words, I only want to rule out boxes
immediately applied to another type with an outermost box. So we
don’t want to allow the example type given above (since it contains
<span class="math inline">\(\square \square X\)</span>), but, for example, <span class="math inline">\(\square ((\square X \to Y)
\to \square Y)\)</span> would be OK.</p>
</section>
<section id="two-encodings" class="level2">
<h2>Two encodings</h2>
<p>In my <a href="https://byorgey.github.io/blog/posts/2024/09/09/OneLevelTypesIndexed.lagda.html">previous blog
post</a>,
I ended up with the following encoding of types indexed by a <code>Boxity</code>,
which records the number of top-level boxes. Since the boxity of the
arguments to an arrow type do not matter, we make them sigma types
that package up a boxity with a type having that boxity. I was then
able to define decidable equality for <code>ΣTy</code> and <code>Ty</code> by mutual
recursion.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> Boxity <span class="ot">:</span> <span class="dt">Set</span> <span class="kw">where</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>  ₀ <span class="ot">:</span> Boxity</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  ₁ <span class="ot">:</span> Boxity</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="kw">variable</span> b b₁ b₂ b₃ b₄ <span class="ot">:</span> Boxity</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> WithSigma <span class="kw">where</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>  ΣTy <span class="ot">:</span> <span class="dt">Set</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">data</span> Ty <span class="ot">:</span> Boxity <span class="ot">→</span> <span class="dt">Set</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>  ΣTy <span class="ot">=</span> Σ Boxity Ty</span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">data</span> Ty <span class="kw">where</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>    □<span class="ot">_</span> <span class="ot">:</span> Ty ₀ <span class="ot">→</span> Ty ₁</span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>    base <span class="ot">:</span> B <span class="ot">→</span> Ty ₀</span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>    <span class="ot">_</span>⇒<span class="ot">_</span> <span class="ot">:</span> ΣTy <span class="ot">→</span> ΣTy <span class="ot">→</span> Ty ₀</span></code></pre></div>
<p>The problem is that working with this definition of <code>Ty</code> is really
annoying! Every time we construct or pattern-match on an arrow type,
we have to package up each argument type into a dependent pair with
its <code>Boxity</code>; this introduces syntactic clutter, and in many cases we
know exactly what the <code>Boxity</code> has to be, so it’s not even
informative. The version we really want looks more like this:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> Ty <span class="ot">:</span> Boxity <span class="ot">→</span> <span class="dt">Set</span> <span class="kw">where</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>  base <span class="ot">:</span> B <span class="ot">→</span> Ty ₀</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>  <span class="ot">_</span>⇒<span class="ot">_</span> <span class="ot">:</span> <span class="ot">{</span>b₁ b₂ <span class="ot">:</span> Boxity<span class="ot">}</span> <span class="ot">→</span> Ty b₁ <span class="ot">→</span> Ty b₂ <span class="ot">→</span> Ty ₀</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>  □<span class="ot">_</span> <span class="ot">:</span> Ty ₀ <span class="ot">→</span> Ty ₁</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="kw">infixr</span> <span class="dv">2</span> <span class="ot">_</span>⇒<span class="ot">_</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="kw">infix</span> <span class="dv">30</span> □<span class="ot">_</span></span></code></pre></div>
<p>In this version, the boxities of the arguments to the arrow
constructor are just implicit parameters of the arrow constructor
itself. Previously, I was unable to get decidable equality to go
through for this version… but just the other day, I finally realized
how to make it work!</p>
</section>
<section id="path-dependent-equality" class="level2">
<h2>Path-dependent equality</h2>
<p>The key trick that makes everything work is to define a
<em>path-dependent equality</em> type. I <a href="https://martinescardo.github.io/dependent-equality-lecture/DependentEquality.html">learned this from Martín
Escardó</a>.
The idea is that we can express equality between two indexed things
with different indices, as long as we also have an equality between
the indices.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ot">_</span>≡⟦<span class="ot">_</span>⟧<span class="ot">_</span> <span class="ot">:</span> <span class="ot">{</span>A <span class="ot">:</span> <span class="dt">Set</span><span class="ot">}</span> <span class="ot">{</span>B <span class="ot">:</span> A <span class="ot">→</span> <span class="dt">Set</span><span class="ot">}</span> <span class="ot">{</span>a₀ a₁ <span class="ot">:</span> A<span class="ot">}</span> <span class="ot">→</span> B a₀ <span class="ot">→</span> a₀ ≡ a₁ <span class="ot">→</span> B a₁ <span class="ot">→</span> <span class="dt">Set</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>b₀ ≡⟦ refl ⟧ b₁   <span class="ot">=</span>   b₀ ≡ b₁</span></code></pre></div>
<p>That’s exactly what we need here: the ability to express
equality between <code>Ty</code> values, which may be indexed by different
boxities—as long as we know that the boxities are equal.</p>
</section>
<section id="decidable-equality-for-ty" class="level2">
<h2>Decidable equality for <code>Ty</code></h2>
<p>We can now use this to directly encode decidable equality for <code>Ty</code>.
First, we can easily define decidable equality for <code>Boxity</code>.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>Boxity-≟ <span class="ot">:</span> DecidableEquality Boxity</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>Boxity-≟ ₀ ₀ <span class="ot">=</span> yes refl</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>Boxity-≟ ₀ ₁ <span class="ot">=</span> no <span class="ot">λ</span> <span class="ot">()</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>Boxity-≟ ₁ ₀ <span class="ot">=</span> no <span class="ot">λ</span> <span class="ot">()</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>Boxity-≟ ₁ ₁ <span class="ot">=</span> yes refl</span></code></pre></div>
<p>Here is the type of the decision procedure: given two <code>Ty</code> values
which may have <em>different</em> boxities, we decide whether or not we can
produce a witness to their equality. Such a witness consists of a
<em>pair</em> of (1) a proof that the boxities are equal, and (2) a proof
that the types are equal, depending on (1).<span class="sidenote-wrapper"><label for="sn-0" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0" class="margin-toggle"/><span class="sidenote">We would really like to
write this as <code>Σ (b₁ ≡ b₂) λ p → σ ≡⟦ p ⟧ τ</code>, but for some reason Agda
requires us to fill in some extra implicit arguments before it is
happy that everything is unambiguous, <a href="https://github.com/agda/agda/issues/2264">requiring some ugly syntax</a>.<br />
<br />
</span></span></p>
<div class="sourceCode" id="cb8"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>Ty-≟′ <span class="ot">:</span> <span class="ot">(</span>σ <span class="ot">:</span> Ty b₁<span class="ot">)</span> <span class="ot">→</span> <span class="ot">(</span>τ <span class="ot">:</span> Ty b₂<span class="ot">)</span> <span class="ot">→</span> Dec <span class="ot">(</span>Σ <span class="ot">(</span>b₁ ≡ b₂<span class="ot">)</span> <span class="ot">λ</span> p <span class="ot">→</span> <span class="ot">_</span>≡⟦<span class="ot">_</span>⟧<span class="ot">_</span> <span class="ot">{_}</span> <span class="ot">{</span>Ty<span class="ot">}</span> σ p τ<span class="ot">)</span></span></code></pre></div>
<p>Before showing the definition of <code>Ty-≟′</code>, let’s see that we can use it
to easily define both a boxity-homogeneous version of decidable
equality for <code>Ty</code>, as well as decidable equality for <code>Σ Boxity Ty</code>:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>Ty-≟ <span class="ot">:</span> DecidableEquality <span class="ot">(</span>Ty b<span class="ot">)</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>Ty-≟ <span class="ot">{</span>b<span class="ot">}</span> σ τ <span class="kw">with</span> Ty-≟′ σ τ</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> no σ≢τ <span class="ot">=</span> no <span class="ot">(λ</span> σ≡τ <span class="ot">→</span> σ≢τ <span class="ot">(</span> refl , σ≡τ<span class="ot">))</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> yes <span class="ot">(</span>refl , σ≡τ<span class="ot">)</span> <span class="ot">=</span> yes σ≡τ</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>ΣTy-≟ <span class="ot">:</span> DecidableEquality <span class="ot">(</span>Σ Boxity Ty<span class="ot">)</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>ΣTy-≟ <span class="ot">(_</span> , σ<span class="ot">)</span> <span class="ot">(_</span> , τ<span class="ot">)</span> <span class="kw">with</span> Ty-≟′ σ τ</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> no σ≢τ <span class="ot">=</span> no <span class="ot">λ</span> <span class="ot">{</span> refl <span class="ot">→</span> σ≢τ <span class="ot">(</span>refl , refl<span class="ot">)</span> <span class="ot">}</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> yes <span class="ot">(</span>refl , refl<span class="ot">)</span> <span class="ot">=</span> yes refl</span></code></pre></div>
<p>A lot of pattern matching on <code>refl</code> and everything falls out quite easily.</p>
<p>And now the definition of <code>Ty-≟′</code>. It looks complicated, but it is
actually not very difficult. The most interesting case is when
comparing two arrow types for equality: we must first compare the
boxities of the arguments, then consider the arguments themselves once
we know the boxities are equal.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode agda"><code class="sourceCode agda"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>Ty-≟′ <span class="ot">(</span>□ σ<span class="ot">)</span> <span class="ot">(</span>□ τ<span class="ot">)</span> <span class="kw">with</span> Ty-≟′ σ τ</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> yes <span class="ot">(</span>refl , refl<span class="ot">)</span> <span class="ot">=</span> yes <span class="ot">(</span>refl , refl<span class="ot">)</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> no σ≢τ <span class="ot">=</span> no <span class="ot">λ</span> <span class="ot">{</span> <span class="ot">(</span>refl , refl<span class="ot">)</span> <span class="ot">→</span> σ≢τ <span class="ot">(</span>refl , refl<span class="ot">)</span> <span class="ot">}</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>Ty-≟′ <span class="ot">(</span>base S<span class="ot">)</span> <span class="ot">(</span>base T<span class="ot">)</span> <span class="kw">with</span> ≟B S T</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> yes refl <span class="ot">=</span> yes <span class="ot">(</span>refl , refl<span class="ot">)</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> no S≢T <span class="ot">=</span> no <span class="ot">λ</span> <span class="ot">{</span> <span class="ot">(</span>refl , refl<span class="ot">)</span> <span class="ot">→</span> S≢T refl <span class="ot">}</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>Ty-≟′ <span class="ot">(_</span>⇒<span class="ot">_</span> <span class="ot">{</span>b₁<span class="ot">}</span> <span class="ot">{</span>b₂<span class="ot">}</span> σ₁ σ₂<span class="ot">)</span> <span class="ot">(_</span>⇒<span class="ot">_</span> <span class="ot">{</span>b₃<span class="ot">}</span> <span class="ot">{</span>b₄<span class="ot">}</span> τ₁ τ₂<span class="ot">)</span> <span class="kw">with</span> Boxity-≟ b₁ b₃ <span class="ot">|</span> Boxity-≟ b₂ b₄ <span class="ot">|</span> Ty-≟′ σ₁ τ₁ <span class="ot">|</span> Ty-≟′ σ₂ τ₂</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> no b₁≢b₃ <span class="ot">|</span> <span class="ot">_</span> <span class="ot">|</span> <span class="ot">_</span> <span class="ot">|</span> <span class="ot">_</span> <span class="ot">=</span> no <span class="ot">λ</span> <span class="ot">{</span> <span class="ot">(</span>refl , refl<span class="ot">)</span> <span class="ot">→</span> b₁≢b₃ refl <span class="ot">}</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> yes <span class="ot">_</span> <span class="ot">|</span> no b₂≢b₄ <span class="ot">|</span> <span class="ot">_</span> <span class="ot">|</span> <span class="ot">_</span> <span class="ot">=</span> no <span class="ot">λ</span> <span class="ot">{</span> <span class="ot">(</span>refl , refl<span class="ot">)</span> <span class="ot">→</span> b₂≢b₄ refl <span class="ot">}</span></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> yes <span class="ot">_</span> <span class="ot">|</span> yes <span class="ot">_</span> <span class="ot">|</span> no σ₁≢τ₁ <span class="ot">|</span> <span class="ot">_</span> <span class="ot">=</span> no <span class="ot">λ</span> <span class="ot">{</span> <span class="ot">(</span>refl , refl<span class="ot">)</span> <span class="ot">→</span> σ₁≢τ₁ <span class="ot">(</span>refl , refl<span class="ot">)</span> <span class="ot">}</span></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> yes <span class="ot">_</span> <span class="ot">|</span> yes <span class="ot">_</span> <span class="ot">|</span> yes <span class="ot">_</span> <span class="ot">|</span> no σ₂≢τ₂ <span class="ot">=</span> no <span class="ot">λ</span> <span class="ot">{</span> <span class="ot">(</span>refl , refl<span class="ot">)</span> <span class="ot">→</span> σ₂≢τ₂ <span class="ot">(</span>refl , refl<span class="ot">)</span> <span class="ot">}</span></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a><span class="ot">...</span> <span class="ot">|</span> yes <span class="ot">_</span> <span class="ot">|</span> yes <span class="ot">_</span> <span class="ot">|</span> yes <span class="ot">(</span>refl , refl<span class="ot">)</span> <span class="ot">|</span> yes <span class="ot">(</span>refl , refl<span class="ot">)</span> <span class="ot">=</span> yes <span class="ot">(</span>refl , refl<span class="ot">)</span></span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a>Ty-≟′ <span class="ot">(</span>□ <span class="ot">_)</span> <span class="ot">(</span>base <span class="ot">_)</span> <span class="ot">=</span> no <span class="ot">λ</span> <span class="ot">()</span></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a>Ty-≟′ <span class="ot">(</span>□ <span class="ot">_)</span> <span class="ot">(_</span> ⇒ <span class="ot">_)</span> <span class="ot">=</span> no <span class="ot">λ</span> <span class="ot">()</span></span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a>Ty-≟′ <span class="ot">(</span>base <span class="ot">_)</span> <span class="ot">(</span>□ <span class="ot">_)</span> <span class="ot">=</span> no <span class="ot">λ</span> <span class="ot">()</span></span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a>Ty-≟′ <span class="ot">(</span>base <span class="ot">_)</span> <span class="ot">(_</span> ⇒ <span class="ot">_)</span> <span class="ot">=</span> no <span class="ot">λ</span> <span class="ot">{</span> <span class="ot">(</span>refl , <span class="ot">())</span> <span class="ot">}</span></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a>Ty-≟′ <span class="ot">(_</span> ⇒ <span class="ot">_)</span> <span class="ot">(</span>□ <span class="ot">_)</span> <span class="ot">=</span> no <span class="ot">λ</span> <span class="ot">()</span></span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a>Ty-≟′ <span class="ot">(_</span> ⇒ <span class="ot">_)</span> <span class="ot">(</span>base <span class="ot">_)</span> <span class="ot">=</span> no <span class="ot">λ</span> <span class="ot">{</span> <span class="ot">(</span>refl , <span class="ot">())</span> <span class="ot">}</span></span></code></pre></div>
</section>

</section>

<script data-isso="https://comments.byorgey.com/" src="https://comments.byorgey.com/js/embed.min.js"></script>
<section id="isso-thread"  data-title="Decidable equality for indexed data types, take 2" >
  <noscript>Javascript needs to be activated to view comments.</noscript>
</section>

]]></description>
    <pubDate>Fri, 22 Aug 2025 00:00:00 UT</pubDate>
    <guid>http://byorgey.github.io/blog/posts/2025/08/22/OneLevelTypesIndexed2.lagda.html</guid>
    <dc:creator>Brent Yorgey</dc:creator>
</item>
<item>
    <title>Competitive programming in Haskell: sparse tables</title>
    <link>http://byorgey.github.io/blog/posts/2025/07/18/sparse-table.html</link>
    <description><![CDATA[
<h1>Competitive programming in Haskell: sparse tables</h1>

<div class="info">
  Posted on July 18, 2025
  
  
  <br />
  Tagged <a title="All pages tagged &#39;monoid&#39;." href="/tag/monoid.html" rel="tag">monoid</a>, <a title="All pages tagged &#39;semigroup&#39;." href="/tag/semigroup.html" rel="tag">semigroup</a>, <a title="All pages tagged &#39;idempotent&#39;." href="/tag/idempotent.html" rel="tag">idempotent</a>, <a title="All pages tagged &#39;range&#39;." href="/tag/range.html" rel="tag">range</a>, <a title="All pages tagged &#39;query&#39;." href="/tag/query.html" rel="tag">query</a>, <a title="All pages tagged &#39;sum&#39;." href="/tag/sum.html" rel="tag">sum</a>, <a title="All pages tagged &#39;sparse&#39;." href="/tag/sparse.html" rel="tag">sparse</a>, <a title="All pages tagged &#39;table&#39;." href="/tag/table.html" rel="tag">table</a>, <a title="All pages tagged &#39;Haskell&#39;." href="/tag/Haskell.html" rel="tag">Haskell</a>, <a title="All pages tagged &#39;competitive programming&#39;." href="/tag/competitive%20programming.html" rel="tag">competitive programming</a>
  
</div>

<a href="https://share.joinmastodon.org/#text=Competitive programming in Haskell: sparse tables https://byorgey.github.io/blog/posts/2025/07/18/sparse-table.html" target="_blank" rel="noopener">Share on <svg role="img" aria-label="Mastodon" height="1em" viewBox="0 0 74 79" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M73.7014 17.4323C72.5616 9.05152 65.1774 2.4469 56.424 1.1671C54.9472 0.950843 49.3518 0.163818 36.3901 0.163818H36.2933C23.3281 0.163818 20.5465 0.950843 19.0697 1.1671C10.56 2.41145 2.78877 8.34604 0.903306 16.826C-0.00357854 21.0022 -0.100361 25.6322 0.068112 29.8793C0.308275 35.9699 0.354874 42.0498 0.91406 48.1156C1.30064 52.1448 1.97502 56.1419 2.93215 60.0769C4.72441 67.3445 11.9795 73.3925 19.0876 75.86C26.6979 78.4332 34.8821 78.8603 42.724 77.0937C43.5866 76.8952 44.4398 76.6647 45.2833 76.4024C47.1867 75.8033 49.4199 75.1332 51.0616 73.9562C51.0841 73.9397 51.1026 73.9184 51.1156 73.8938C51.1286 73.8693 51.1359 73.8421 51.1368 73.8144V67.9366C51.1364 67.9107 51.1302 67.8852 51.1186 67.862C51.1069 67.8388 51.0902 67.8184 51.0695 67.8025C51.0489 67.7865 51.0249 67.7753 50.9994 67.7696C50.9738 67.764 50.9473 67.7641 50.9218 67.7699C45.8976 68.9569 40.7491 69.5519 35.5836 69.5425C26.694 69.5425 24.3031 65.3699 23.6184 63.6327C23.0681 62.1314 22.7186 60.5654 22.5789 58.9744C22.5775 58.9477 22.5825 58.921 22.5934 58.8965C22.6043 58.8721 22.621 58.8505 22.6419 58.8336C22.6629 58.8167 22.6876 58.8049 22.714 58.7992C22.7404 58.7934 22.7678 58.794 22.794 58.8007C27.7345 59.9796 32.799 60.5746 37.8813 60.5733C39.1036 60.5733 40.3223 60.5733 41.5447 60.5414C46.6562 60.3996 52.0437 60.1408 57.0728 59.1694C57.1983 59.1446 57.3237 59.1233 57.4313 59.0914C65.3638 57.5847 72.9128 52.8555 73.6799 40.8799C73.7086 40.4084 73.7803 35.9415 73.7803 35.4523C73.7839 33.7896 74.3216 23.6576 73.7014 17.4323ZM61.4925 47.3144H53.1514V27.107C53.1514 22.8528 51.3591 20.6832 47.7136 20.6832C43.7061 20.6832 41.6988 23.2499 41.6988 28.3194V39.3803H33.4078V28.3194C33.4078 23.2499 31.3969 20.6832 27.3894 20.6832C23.7654 20.6832 21.9552 22.8528 21.9516 27.107V47.3144H13.6176V26.4937C13.6176 22.2395 14.7157 18.8598 16.9118 16.3545C19.1772 13.8552 22.1488 12.5719 25.8373 12.5719C30.1064 12.5719 33.3325 14.1955 35.4832 17.4394L37.5587 20.8853L39.6377 17.4394C41.7884 14.1955 45.0145 12.5719 49.2765 12.5719C52.9614 12.5719 55.9329 13.8552 58.2055 16.3545C60.4017 18.8574 61.4997 22.2371 61.4997 26.4937L61.4925 47.3144Z" fill="inherit"/></svg></a>
<section>
<p>Continuing a <a href="https://byorgey.github.io/blog/posts/2025/06/23/range-queries-classified.html">series of
posts</a>
on techniques for calculating <em>range queries</em>, today I will present
the <a href="https://cp-algorithms.com/data_structures/sparse-table.html"><em>sparse table</em> data structure</a>, for doing fast range queries on a
static sequence with an <em>idempotent</em> combining operation.</p>
<section id="motivation" class="level2">
<h2>Motivation</h2>
<p>In my <a href="https://byorgey.github.io/blog/posts/2025/06/27/prefix-sums.html">previous
post</a>,
we saw that if we have a static sequence and a binary operation with a
<em>group</em> structure (<em>i.e.</em> every element has an inverse), we can
precompute a prefix sum table in <span class="math inline">\(O(n)\)</span> time, and then use it to answer
arbitrary range queries in <span class="math inline">\(O(1)\)</span> time.</p>
<p>What if we don’t have inverses? We can’t use prefix sums, but can we
do something else that still allows us to answer range queries in
<span class="math inline">\(O(1)\)</span>? One thing we could always do would be to construct an <span class="math inline">\(n
\times n\)</span> table storing the answer to <em>every possible</em> range
query—that is, <span class="math inline">\(Q[i,j]\)</span> would store the value of the range <span class="math inline">\(a_i
\diamond \dots \diamond a_j\)</span>. Then we could just look up the answer to
any range query in <span class="math inline">\(O(1)\)</span>. Naively computing the value of each
<span class="math inline">\(Q[i,j]\)</span> would take <span class="math inline">\(O(n)\)</span> time, for a total of <span class="math inline">\(O(n^3)\)</span> time to fill
in each of the entries in the table<span class="sidenote-wrapper"><label for="sn-0" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0" class="margin-toggle"/><span class="sidenote">We only have to fill in <span class="math inline">\(Q[i,j]\)</span>
where <span class="math inline">\(i &lt; j\)</span>, but this is still about <span class="math inline">\(n^2/2\)</span> entries.<br />
<br />
</span></span>, though it’s not
too hard to fill in the table in <span class="math inline">\(O(n^2)\)</span> total time, spending only
<span class="math inline">\(O(1)\)</span> to fill in each entry—I’ll leave this to you as an exercise.</p>
<p>However, <span class="math inline">\(O(n^2)\)</span> is often too big. Can we do better? More
generally, we are looking for a particular <em>subset</em> of range queries
to precompute, such that the total number is asymptotically less than
<span class="math inline">\(n^2\)</span>, but we can still compute the value of any arbitrary range query
by combining some (constant number of) precomputed ranges. In the case
of a group structure, we were able to compute the values for only
prefix ranges of the form <span class="math inline">\(1 \dots k\)</span>, then compute the value of an arbitrary
range using two prefixes, via subtraction.</p>
<p>A sparse table is exactly such a scheme for precomputing a subset of
ranges.<span class="sidenote-wrapper"><label for="sn-1" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-1" class="margin-toggle"/><span class="sidenote">In fact, I believe, but do not know for sure, that this is
where the name “sparse table” comes from—it is “sparse” in the sense
that it only stores a sparse subset of range values.<br />
<br />
</span></span> Rather than only
a linear number of ranges, as with prefix sums, we have to compute
<span class="math inline">\(O(n \lg n)\)</span> of them, but that’s still way better than <span class="math inline">\(O(n^2)\)</span>. Note,
however, that a sparse table only works when the combining operation
is <em>idempotent</em>, that is, when <span class="math inline">\(x \diamond x = x\)</span> for all <span class="math inline">\(x\)</span>. For
example, we can use a sparse table with combining operations such as
<span class="math inline">\(\max\)</span> or <span class="math inline">\(\gcd\)</span>, but not with <span class="math inline">\(+\)</span> or <span class="math inline">\(\times\)</span>. Let’s see how it works.</p>
</section>
<section id="sparse-tables" class="level2">
<h2>Sparse tables</h2>
<p>The basic idea behind a sparse table is that we precompute a series of
“levels”, where level <span class="math inline">\(i\)</span> stores values for ranges of length <span class="math inline">\(2^i\)</span>. So level
<span class="math inline">\(0\)</span> stores “ranges of length <span class="math inline">\(1\)</span>”—that is, the elements of the
original sequence; level <span class="math inline">\(1\)</span> stores ranges of length <span class="math inline">\(2\)</span>; level
<span class="math inline">\(2\)</span> stores ranges of length <span class="math inline">\(4\)</span>; and so on. Formally, <span class="math inline">\(T[i,j]\)</span>
stores the value of the range of length <span class="math inline">\(2^i\)</span> starting at index <span class="math inline">\(j\)</span>.
That is,</p>
<p><span class="math display">\[T[i,j] = a_j \diamond \dots \diamond a_{j+2^i-1}.\]</span></p>
<p>We can see that <span class="math inline">\(i\)</span> only needs to go from <span class="math inline">\(0\)</span> up to <span class="math inline">\(\lfloor \lg n
\rfloor\)</span>; above that and the stored ranges would be larger than
the entire sequence. So this table has size <span class="math inline">\(O(n \lg n)\)</span>.</p>
<p>Two important questions remain: how do we compute this table in the
first place? And once we have it, how do we use it to answer arbitrary
range queries in <span class="math inline">\(O(1)\)</span>?</p>
<p>Computing the table is easy: each range on level <span class="math inline">\(i\)</span>, of length <span class="math inline">\(2^i\)</span>, is the
combination of two length-<span class="math inline">\(2^{i-1}\)</span> ranges from the previous level. That is,</p>
<p><span class="math display">\[T[i,j] = T[i-1, j] \diamond T[i-1, j+2^{i-1}]\]</span></p>
<p>The zeroth level just consists of the elements of the original
sequence, and we can compute each subsequent level using values from
the previous level, so we can fill in the entire table in <span class="math inline">\(O(n \lg n)\)</span>
time, doing just a single combining operation for each value in the table.</p>
<p>Once we have the table, we can compute the value of an arbitrary
range <span class="math inline">\([l,r]\)</span> as follows:</p>
<ul>
<li><p>Compute the biggest power of two that fits within the range, that
is, the largest <span class="math inline">\(k\)</span> such that <span class="math inline">\(2^k \leq r - l + 1\)</span>. We can compute
this simply as <span class="math inline">\(\lfloor \lg (r - l + 1) \rfloor\)</span>.</p></li>
<li><p>Look up two range values of length <span class="math inline">\(2^k\)</span>, one for the range which begins at <span class="math inline">\(l\)</span>
(that is, <span class="math inline">\(T[k, l]\)</span>) and one for the range which ends at <span class="math inline">\(r\)</span> (that is, <span class="math inline">\(T[k, r -
2^k + 1]\)</span>). These two ranges overlap; but because the combining
operation is idempotent, combining the values of the ranges yields
the value for our desired range <span class="math inline">\([l,r]\)</span>.</p>
<p>This is why we require the combining operation to be idempotent:
otherwise the values in the overlap would be overrepresented in the
final, combined value.</p></li>
</ul>
</section>
<section id="haskell-code" class="level2">
<h2>Haskell code</h2>
<p>Let’s write some Haskell code! First, a little module for idempotent
semigroups. Note that we couch everything in terms of <em>semigroups</em>,
not monoids, because we have no particular need of an identity
element; indeed, some of the most important examples like <span class="math inline">\(\min\)</span> and
<span class="math inline">\(\max\)</span> don’t have an identity element. The <code>IdempotentSemigroup</code>
class has no methods, since as compared to <code>Semigroup</code> it only adds a
law. However, it’s still helpful to signal the requirement. You
might like to convince yourself that all the instances listed below
really are idempotent.</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">module</span> <span class="dt">IdempotentSemigroup</span> <span class="kw">where</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Bits</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Semigroup</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="co">-- | An idempotent semigroup is one where the binary operation</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="co">--   satisfies the law @x &lt;&gt; x = x@ for all @x@.</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="dt">Semigroup</span> m <span class="ot">=&gt;</span> <span class="dt">IdempotentSemigroup</span> m</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Ord</span> a <span class="ot">=&gt;</span> <span class="dt">IdempotentSemigroup</span> (<span class="dt">Min</span> a)</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Ord</span> a <span class="ot">=&gt;</span> <span class="dt">IdempotentSemigroup</span> (<span class="dt">Max</span> a)</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">IdempotentSemigroup</span> <span class="dt">All</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">IdempotentSemigroup</span> <span class="dt">Any</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">IdempotentSemigroup</span> <span class="dt">Ordering</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">IdempotentSemigroup</span> ()</span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">IdempotentSemigroup</span> (<span class="dt">First</span> a)</span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">IdempotentSemigroup</span> (<span class="dt">Last</span> a)</span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Bits</span> a <span class="ot">=&gt;</span> <span class="dt">IdempotentSemigroup</span> (<span class="dt">And</span> a)</span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Bits</span> a <span class="ot">=&gt;</span> <span class="dt">IdempotentSemigroup</span> (<span class="dt">Ior</span> a)</span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> (<span class="dt">IdempotentSemigroup</span> a, <span class="dt">IdempotentSemigroup</span> b) <span class="ot">=&gt;</span> <span class="dt">IdempotentSemigroup</span> (a,b)</span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">IdempotentSemigroup</span> b <span class="ot">=&gt;</span> <span class="dt">IdempotentSemigroup</span> (a <span class="ot">-&gt;</span> b)</span></code></pre></div>
<p>Now, some code for sparse tables. First, a few imports.</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="ot">{-# LANGUAGE TupleSections #-}</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">module</span> <span class="dt">SparseTable</span> <span class="kw">where</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Array</span> (<span class="dt">Array</span>, array, (!))</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Bits</span> (countLeadingZeros, finiteBitSize, (!&lt;&lt;.))</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">IdempotentSemigroup</span></span></code></pre></div>
<p>The sparse table data structure itself is just a 2D array over some
idempotent semigroup <code>m</code>. Note that <code>UArray</code> would be more efficient,
but (1) that would make the code for building the sparse table more
annoying (more on this later), and (2) it would require a bunch of
tedious additional constraints on <code>m</code>.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">SparseTable</span> m <span class="ot">=</span> <span class="dt">SparseTable</span> (<span class="dt">Array</span> (<span class="dt">Int</span>, <span class="dt">Int</span>) m)</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> (<span class="dt">Show</span>)</span></code></pre></div>
<p>We will frequently need to compute rounded-down base-two logarithms,
so we define a function for it. A straightforward implementation
would be to repeatedly shift right by one bit and count the number of
shifts needed to reach zero; however, there is a better way, using
<code>Data.Bits.countLeadingZeros</code>. It has a naive default implementation
which counts right bit shifts, but in most cases it compiles down to
much more efficient machine instructions.</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">-- | Logarithm base 2, rounded down to the nearest integer.  Computed</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="co">--   efficiently using primitive bitwise instructions, when available.</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="ot">lg ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>lg n <span class="ot">=</span> finiteBitSize n <span class="op">-</span> <span class="dv">1</span> <span class="op">-</span> countLeadingZeros n</span></code></pre></div>
<p>Now let’s write a function to construct a sparse table, given a
sequence of values. Notice how the sparse table array <code>st</code> is <a href="https://byorgey.github.io/blog/posts/2023/06/02/dynamic-programming-in-haskell-lazy-immutable-arrays.html">defined
recursively</a>.
This works because the <code>Array</code> type is lazy in the stored values, with
the added benefit that only the array values we end up actually
needing will be computed. However, this comes with a decent amount of
overhead. If we wanted to use an unboxed array instead, we wouldn’t
be able to use
the recursive definition trick; instead, we would have to <a href="https://byorgey.github.io/blog/posts/2021/11/17/competitive-programming-in-haskell-bfs-part-4-implementation-via-stuarray.html">use an
<code>STUArray</code></a>
and fill in the values in a specific order. The code for this would
be longer and much more tedious, but could be faster if we end up
needing all the values in the array anyway.</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="co">-- | Construct a sparse table which can answer range queries over the</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="co">--   given list in $O(1)$ time.  Constructing the sparse table takes</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="co">--   $O(n \lg n)$ time and space, where $n$ is the length of the list.</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="ot">fromList ::</span> <span class="dt">IdempotentSemigroup</span> m <span class="ot">=&gt;</span> [m] <span class="ot">-&gt;</span> <span class="dt">SparseTable</span> m</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>fromList ms <span class="ot">=</span> <span class="dt">SparseTable</span> st</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>  n <span class="ot">=</span> <span class="fu">length</span> ms</span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>  lgn <span class="ot">=</span> lg n</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>  st <span class="ot">=</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>    array ((<span class="dv">0</span>, <span class="dv">0</span>), (lgn, n <span class="op">-</span> <span class="dv">1</span>)) <span class="op">$</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>      <span class="fu">zip</span> ((<span class="dv">0</span>,) <span class="op">&lt;$&gt;</span> [<span class="dv">0</span> <span class="op">..</span>]) ms</span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">++</span> [ ((i, j), st <span class="op">!</span> (i <span class="op">-</span> <span class="dv">1</span>, j) <span class="op">&lt;&gt;</span> st <span class="op">!</span> (i <span class="op">-</span> <span class="dv">1</span>, j <span class="op">+</span> <span class="dv">1</span> <span class="op">!&lt;&lt;.</span> (i <span class="op">-</span> <span class="dv">1</span>)))</span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a>           <span class="op">|</span> i <span class="ot">&lt;-</span> [<span class="dv">1</span> <span class="op">..</span> lgn]</span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>           , j <span class="ot">&lt;-</span> [<span class="dv">0</span> <span class="op">..</span> n <span class="op">-</span> <span class="dv">1</span> <span class="op">!&lt;&lt;.</span> i]</span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a>           ]</span></code></pre></div>
<p>Finally, we can write a function to answer range queries.</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="co">-- | \$O(1)$. @range st l r@ computes the range query which is the</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="co">--   @sconcat@ of all the elements from index @l@ to @r@ (inclusive).</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="fu">range</span><span class="ot"> ::</span> <span class="dt">IdempotentSemigroup</span> m <span class="ot">=&gt;</span> <span class="dt">SparseTable</span> m <span class="ot">-&gt;</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> m</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="fu">range</span> (<span class="dt">SparseTable</span> st) l r <span class="ot">=</span> st <span class="op">!</span> (k, l) <span class="op">&lt;&gt;</span> st <span class="op">!</span> (k, r <span class="op">-</span> (<span class="dv">1</span> <span class="op">!&lt;&lt;.</span> k) <span class="op">+</span> <span class="dv">1</span>)</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>  k <span class="ot">=</span> lg (r <span class="op">-</span> l <span class="op">+</span> <span class="dv">1</span>)</span></code></pre></div>
</section>
<section id="applications" class="level2">
<h2>Applications</h2>
<p>Most commonly, we can use a sparse table to find the minimum or
maximum values on a range, <span class="math inline">\(\min\)</span> and <span class="math inline">\(\max\)</span> being the quintessential
idempotent operations. For example, this plays a key role in a
solution to the (quite tricky) problem
<a href="https://open.kattis.com/problems/ograda">Ograda</a>.<span class="sidenote-wrapper"><label for="sn-2" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-2" class="margin-toggle"/><span class="sidenote">At first it
seemed like that problem should be solvable with some kind of <a href="https://byorgey.github.io/blog/posts/2024/11/27/stacks-queues.html">sliding
window</a> approach, but I couldn’t figure out how to make it work!<br />
<br />
</span></span></p>
<p>What if we want to find the <em>index of</em> the minimum or maximum value in
a given range (see, for example, <a href="https://open.kattis.com/problems/worstweather">Worst Weather</a>)? We can easily accomplish this using the semigroup <code>Min (Arg m i)</code> (or <code>Max (Arg m i)</code>), where <code>m</code> is the type of the values and <code>i</code> is
the index type. <code>Arg</code>, from <code>Data.Semigroup</code>, is just a pair which uses only the first value
for its <code>Eq</code> and <code>Ord</code> instances, and carries along the second value
(which is also exposed via <code>Functor</code>, <code>Foldable</code>, and <code>Traversable</code>
instances). In the example below, we can see that the call to <code>range st 0 3</code> returns both the max value on the range (<code>4</code>) and its index
(<code>2</code>) which got carried along for the ride:</p>
<pre><code>λ&gt; :m +Data.Semigroup
λ&gt; st = fromList (map Max (zipWith Arg [2, 3, 4, 2, 7, 4, 9] [0..]))
λ&gt; range st 0 3
Max {getMax = Arg 4 2}</code></pre>
<p>Finally, I will mention that being able to compute range minimum
queries is one way to compute lowest common ancestors for a (static,
rooted) tree. First, walk the tree via a depth-first search and
record the depth of each node encountered in sequence, a so-called
<a href="https://en.wikipedia.org/wiki/Euler_tour_technique">Euler tour</a> (note
that you must record <em>every</em> visit to a node—before visiting any of
its children, in between each child, and after visiting all the
children). Now the minimum depth recorded between visits to any two
nodes will correspond to their lowest common ancestor.</p>
<p>Here are a few problems that involve computing least common ancestors
in a tree, though note there are also other techniques for computing
LCAs (such as binary jumping) which I plan to write about eventually.</p>
<ul>
<li><a href="https://open.kattis.com/problems/tourists">Tourists</a></li>
<li><a href="https://open.kattis.com/problems/stogovi">Stogovi</a></li>
<li><a href="https://open.kattis.com/problems/windiesel">Win Diesel</a></li>
</ul>
</section>

</section>

<script data-isso="https://comments.byorgey.com/" src="https://comments.byorgey.com/js/embed.min.js"></script>
<section id="isso-thread"  data-title="Competitive programming in Haskell: sparse tables" >
  <noscript>Javascript needs to be activated to view comments.</noscript>
</section>

]]></description>
    <pubDate>Fri, 18 Jul 2025 00:00:00 UT</pubDate>
    <guid>http://byorgey.github.io/blog/posts/2025/07/18/sparse-table.html</guid>
    <dc:creator>Brent Yorgey</dc:creator>
</item>
<item>
    <title>Competitive programming in Haskell: prefix sums</title>
    <link>http://byorgey.github.io/blog/posts/2025/06/27/prefix-sums.html</link>
    <description><![CDATA[
<h1>Competitive programming in Haskell: prefix sums</h1>

<div class="info">
  Posted on June 27, 2025
  
  
  <br />
  Tagged <a title="All pages tagged &#39;monoid&#39;." href="/tag/monoid.html" rel="tag">monoid</a>, <a title="All pages tagged &#39;range&#39;." href="/tag/range.html" rel="tag">range</a>, <a title="All pages tagged &#39;query&#39;." href="/tag/query.html" rel="tag">query</a>, <a title="All pages tagged &#39;prefix&#39;." href="/tag/prefix.html" rel="tag">prefix</a>, <a title="All pages tagged &#39;sum&#39;." href="/tag/sum.html" rel="tag">sum</a>, <a title="All pages tagged &#39;Haskell&#39;." href="/tag/Haskell.html" rel="tag">Haskell</a>, <a title="All pages tagged &#39;competitive programming&#39;." href="/tag/competitive%20programming.html" rel="tag">competitive programming</a>
  
</div>

<a href="https://share.joinmastodon.org/#text=Competitive programming in Haskell: prefix sums https://byorgey.github.io/blog/posts/2025/06/27/prefix-sums.html" target="_blank" rel="noopener">Share on <svg role="img" aria-label="Mastodon" height="1em" viewBox="0 0 74 79" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M73.7014 17.4323C72.5616 9.05152 65.1774 2.4469 56.424 1.1671C54.9472 0.950843 49.3518 0.163818 36.3901 0.163818H36.2933C23.3281 0.163818 20.5465 0.950843 19.0697 1.1671C10.56 2.41145 2.78877 8.34604 0.903306 16.826C-0.00357854 21.0022 -0.100361 25.6322 0.068112 29.8793C0.308275 35.9699 0.354874 42.0498 0.91406 48.1156C1.30064 52.1448 1.97502 56.1419 2.93215 60.0769C4.72441 67.3445 11.9795 73.3925 19.0876 75.86C26.6979 78.4332 34.8821 78.8603 42.724 77.0937C43.5866 76.8952 44.4398 76.6647 45.2833 76.4024C47.1867 75.8033 49.4199 75.1332 51.0616 73.9562C51.0841 73.9397 51.1026 73.9184 51.1156 73.8938C51.1286 73.8693 51.1359 73.8421 51.1368 73.8144V67.9366C51.1364 67.9107 51.1302 67.8852 51.1186 67.862C51.1069 67.8388 51.0902 67.8184 51.0695 67.8025C51.0489 67.7865 51.0249 67.7753 50.9994 67.7696C50.9738 67.764 50.9473 67.7641 50.9218 67.7699C45.8976 68.9569 40.7491 69.5519 35.5836 69.5425C26.694 69.5425 24.3031 65.3699 23.6184 63.6327C23.0681 62.1314 22.7186 60.5654 22.5789 58.9744C22.5775 58.9477 22.5825 58.921 22.5934 58.8965C22.6043 58.8721 22.621 58.8505 22.6419 58.8336C22.6629 58.8167 22.6876 58.8049 22.714 58.7992C22.7404 58.7934 22.7678 58.794 22.794 58.8007C27.7345 59.9796 32.799 60.5746 37.8813 60.5733C39.1036 60.5733 40.3223 60.5733 41.5447 60.5414C46.6562 60.3996 52.0437 60.1408 57.0728 59.1694C57.1983 59.1446 57.3237 59.1233 57.4313 59.0914C65.3638 57.5847 72.9128 52.8555 73.6799 40.8799C73.7086 40.4084 73.7803 35.9415 73.7803 35.4523C73.7839 33.7896 74.3216 23.6576 73.7014 17.4323ZM61.4925 47.3144H53.1514V27.107C53.1514 22.8528 51.3591 20.6832 47.7136 20.6832C43.7061 20.6832 41.6988 23.2499 41.6988 28.3194V39.3803H33.4078V28.3194C33.4078 23.2499 31.3969 20.6832 27.3894 20.6832C23.7654 20.6832 21.9552 22.8528 21.9516 27.107V47.3144H13.6176V26.4937C13.6176 22.2395 14.7157 18.8598 16.9118 16.3545C19.1772 13.8552 22.1488 12.5719 25.8373 12.5719C30.1064 12.5719 33.3325 14.1955 35.4832 17.4394L37.5587 20.8853L39.6377 17.4394C41.7884 14.1955 45.0145 12.5719 49.2765 12.5719C52.9614 12.5719 55.9329 13.8552 58.2055 16.3545C60.4017 18.8574 61.4997 22.2371 61.4997 26.4937L61.4925 47.3144Z" fill="inherit"/></svg></a>
<section>
<p>In a <a href="https://byorgey.github.io/blog/posts/2025/06/23/range-queries-classified.html">previous blog
post</a>
I categorized a number of different techniques for calculating <em>range queries</em>.
Today, I will discuss one of those techniques which is simple but frequently
useful.</p>
<section id="precomputing-prefix-sums" class="level2">
<h2>Precomputing prefix sums</h2>
<p>Suppose we have a static sequence of values <span class="math inline">\(a_1, a_2, a_3, \dots,
a_n\)</span> drawn from some
<a href="https://en.wikipedia.org/wiki/Group_(mathematics)">group</a><span class="sidenote-wrapper"><label for="sn-0" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0" class="margin-toggle"/><span class="sidenote">That is,
there is an associative binary operation with an identity element, and
every element has an inverse.<br />
<br />
</span></span>, and want
to be able to compute the total value (according to the group
operation) of any contiguous subrange. That is, given a range
<span class="math inline">\([i,j]\)</span>, we want to compute <span class="math inline">\(a_i \diamond a_{i+1} \diamond \dots
\diamond a_j\)</span> (where <span class="math inline">\(\diamond\)</span> is the group operation). For example,
we might have a sequence of integers and want to compute the sum, or
perhaps the bitwise xor (but not the maximum) of all the values in any particular
subrange.</p>
<p>Of course, we could simply compute <span class="math inline">\(a_i \diamond \dots \diamond a_j\)</span>
directly, but that takes <span class="math inline">\(O(n)\)</span> time. With some simple preprocessing,
it’s possible to compute the value of any range in constant time.</p>
<p>The key idea is to precompute an array <span class="math inline">\(P\)</span> of <em>prefix sums</em>, so <span class="math inline">\(P_i =
a_1 \diamond \dots \diamond a_i\)</span>. This can be computed in linear time
via a <em>scan</em>; for example:</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">import</span> <span class="dt">Data.Array</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.List</span> (scanl&#39;)</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="ot">prefix ::</span> <span class="dt">Monoid</span> a <span class="ot">=&gt;</span> [a] <span class="ot">-&gt;</span> <span class="dt">Array</span> <span class="dt">Int</span> a</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>prefix a <span class="ot">=</span> listArray (<span class="dv">0</span>, <span class="fu">length</span> a) <span class="op">$</span> scanl&#39; (<span class="op">&lt;&gt;</span>) <span class="fu">mempty</span> a</span></code></pre></div>
<p><span class="sidenote-wrapper"><label for="sn-1" class="margin-toggle">&#8853;</label><input type="checkbox" id="sn-1" class="margin-toggle"/><span class="marginnote">Actually, I would typically use an <em>unboxed</em> array, which is
faster but slightly more limited in its uses: import
<code>Data.Array.Unboxed</code>, use <code>UArray</code> instead of <code>Array</code>, and add an
<code>IArray UArray a</code> constraint.<br />
<br />
</span></span></p>
<p>Note that we set <span class="math inline">\(P_0 = 0\)</span> (or whatever the identity element is for
the group); this is why I had the sequence of values indexed starting
from <span class="math inline">\(1\)</span>, so <span class="math inline">\(P_0\)</span> corresponds to the empty sum, <span class="math inline">\(P_1 = a_1\)</span>, <span class="math inline">\(P_2 =
a_1 \diamond a_2\)</span>, and so on.</p>
<p>Now, for the value of the range <span class="math inline">\([i,j]\)</span>, just compute <span class="math inline">\(P_j \diamond
P_{i-1}^{-1}\)</span>—that is, we start with a prefix that ends at the right place, then
cancel or “subtract” the prefix that ends right before the range we
want. For example, to find the sum of the integers <span class="math inline">\(a_5 + \dots +
a_{10}\)</span>, we can compute <span class="math inline">\(P_{10} - P_4\)</span>.</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="fu">range</span><span class="ot"> ::</span> <span class="dt">Group</span> a <span class="ot">=&gt;</span> <span class="dt">Array</span> <span class="dt">Int</span> a <span class="ot">-&gt;</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> a</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="fu">range</span> p i j <span class="ot">=</span> p<span class="op">!</span>j <span class="op">&lt;&gt;</span> inv (p<span class="op">!</span>(i<span class="op">-</span><span class="dv">1</span>))</span></code></pre></div>
<p>That’s why this only works for groups but not for general monoids:
only in a group can we <em>cancel</em> unwanted values. So, for example,
this works for finding the sum of any range, but not the maximum.</p>
</section>
<section id="practice-problems" class="level2">
<h2>Practice problems</h2>
<p>Want to practice? Here are a few problems that can be solved using
techniques discussed in this post:</p>
<ul>
<li><a href="https://open.kattis.com/problems/nucleotides">Determining Nucleotide Assortments</a></li>
<li><a href="https://open.kattis.com/problems/einvigi">Einvígi</a></li>
<li><a href="https://open.kattis.com/problems/srednji">Srednji</a></li>
<li><a href="https://open.kattis.com/problems/veggjakalli">Veggja Kalli</a></li>
</ul>
<p>It is possible to generalize this scheme to 2D—that is, to compute
the value of any <em>subrectangle</em> of a <em>2D grid</em> of values from some
group in only <span class="math inline">\(O(1)\)</span> time. I will leave you the fun of figuring out
the details.</p>
<ul>
<li><a href="https://open.kattis.com/problems/prozor">Prozor</a></li>
<li><a href="https://open.kattis.com/problems/rust">Rust</a></li>
</ul>
<p>If you’re looking for an extra challenge, here are a few harder
problems which use techniques from this post as an important
component, but require some additional nontrivial ingredients:</p>
<ul>
<li><a href="https://open.kattis.com/problems/killingchaos">Killing Chaos</a></li>
<li><a href="https://open.kattis.com/problems/ozljeda">Ozljeda</a></li>
<li><a href="https://open.kattis.com/problems/vudu">Vudu</a></li>
</ul>
</section>

</section>

<script data-isso="https://comments.byorgey.com/" src="https://comments.byorgey.com/js/embed.min.js"></script>
<section id="isso-thread"  data-title="Competitive programming in Haskell: prefix sums" >
  <noscript>Javascript needs to be activated to view comments.</noscript>
</section>

]]></description>
    <pubDate>Fri, 27 Jun 2025 00:00:00 UT</pubDate>
    <guid>http://byorgey.github.io/blog/posts/2025/06/27/prefix-sums.html</guid>
    <dc:creator>Brent Yorgey</dc:creator>
</item>
<item>
    <title>Competitive programming in Haskell: range queries, classified</title>
    <link>http://byorgey.github.io/blog/posts/2025/06/23/range-queries-classified.html</link>
    <description><![CDATA[
<h1>Competitive programming in Haskell: range queries, classified</h1>

<div class="info">
  Posted on June 23, 2025
  
  
  <br />
  Tagged <a title="All pages tagged &#39;semigroup&#39;." href="/tag/semigroup.html" rel="tag">semigroup</a>, <a title="All pages tagged &#39;monoid&#39;." href="/tag/monoid.html" rel="tag">monoid</a>, <a title="All pages tagged &#39;range&#39;." href="/tag/range.html" rel="tag">range</a>, <a title="All pages tagged &#39;query&#39;." href="/tag/query.html" rel="tag">query</a>, <a title="All pages tagged &#39;Haskell&#39;." href="/tag/Haskell.html" rel="tag">Haskell</a>, <a title="All pages tagged &#39;competitive programming&#39;." href="/tag/competitive%20programming.html" rel="tag">competitive programming</a>
  
</div>

<a href="https://share.joinmastodon.org/#text=Competitive programming in Haskell: range queries, classified https://byorgey.github.io/blog/posts/2025/06/23/range-queries-classified.html" target="_blank" rel="noopener">Share on <svg role="img" aria-label="Mastodon" height="1em" viewBox="0 0 74 79" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M73.7014 17.4323C72.5616 9.05152 65.1774 2.4469 56.424 1.1671C54.9472 0.950843 49.3518 0.163818 36.3901 0.163818H36.2933C23.3281 0.163818 20.5465 0.950843 19.0697 1.1671C10.56 2.41145 2.78877 8.34604 0.903306 16.826C-0.00357854 21.0022 -0.100361 25.6322 0.068112 29.8793C0.308275 35.9699 0.354874 42.0498 0.91406 48.1156C1.30064 52.1448 1.97502 56.1419 2.93215 60.0769C4.72441 67.3445 11.9795 73.3925 19.0876 75.86C26.6979 78.4332 34.8821 78.8603 42.724 77.0937C43.5866 76.8952 44.4398 76.6647 45.2833 76.4024C47.1867 75.8033 49.4199 75.1332 51.0616 73.9562C51.0841 73.9397 51.1026 73.9184 51.1156 73.8938C51.1286 73.8693 51.1359 73.8421 51.1368 73.8144V67.9366C51.1364 67.9107 51.1302 67.8852 51.1186 67.862C51.1069 67.8388 51.0902 67.8184 51.0695 67.8025C51.0489 67.7865 51.0249 67.7753 50.9994 67.7696C50.9738 67.764 50.9473 67.7641 50.9218 67.7699C45.8976 68.9569 40.7491 69.5519 35.5836 69.5425C26.694 69.5425 24.3031 65.3699 23.6184 63.6327C23.0681 62.1314 22.7186 60.5654 22.5789 58.9744C22.5775 58.9477 22.5825 58.921 22.5934 58.8965C22.6043 58.8721 22.621 58.8505 22.6419 58.8336C22.6629 58.8167 22.6876 58.8049 22.714 58.7992C22.7404 58.7934 22.7678 58.794 22.794 58.8007C27.7345 59.9796 32.799 60.5746 37.8813 60.5733C39.1036 60.5733 40.3223 60.5733 41.5447 60.5414C46.6562 60.3996 52.0437 60.1408 57.0728 59.1694C57.1983 59.1446 57.3237 59.1233 57.4313 59.0914C65.3638 57.5847 72.9128 52.8555 73.6799 40.8799C73.7086 40.4084 73.7803 35.9415 73.7803 35.4523C73.7839 33.7896 74.3216 23.6576 73.7014 17.4323ZM61.4925 47.3144H53.1514V27.107C53.1514 22.8528 51.3591 20.6832 47.7136 20.6832C43.7061 20.6832 41.6988 23.2499 41.6988 28.3194V39.3803H33.4078V28.3194C33.4078 23.2499 31.3969 20.6832 27.3894 20.6832C23.7654 20.6832 21.9552 22.8528 21.9516 27.107V47.3144H13.6176V26.4937C13.6176 22.2395 14.7157 18.8598 16.9118 16.3545C19.1772 13.8552 22.1488 12.5719 25.8373 12.5719C30.1064 12.5719 33.3325 14.1955 35.4832 17.4394L37.5587 20.8853L39.6377 17.4394C41.7884 14.1955 45.0145 12.5719 49.2765 12.5719C52.9614 12.5719 55.9329 13.8552 58.2055 16.3545C60.4017 18.8574 61.4997 22.2371 61.4997 26.4937L61.4925 47.3144Z" fill="inherit"/></svg></a>
<section>
<section id="static-range-queries" class="level2">
<h2>Static range queries</h2>
<p>Suppose we have a sequence of values, which is <em>static</em> in the sense
that the values in the sequence will never change, and we want to
perform <em>range queries</em>, that is, for various ranges we want to
compute the total of all consecutive values in the range, according to
some binary combining operation. For example, we might want to
compute the maximum, sum, or product of all the consecutive values in
a certain subrange. We have various options depending on the kind of
ranges we want and the algebraic properties of the operation.</p>
<ul>
<li><p>If we want ranges corresponding to a <em>sliding window</em>, we can use
<a href="https://byorgey.github.io/blog/posts/2024/11/27/stacks-queues.html">an amortized queue
structure</a>
to find the total of each range in <span class="math inline">\(O(1)\)</span>, for an arbitrary
monoid.
<!-- ^[If we have a group, then no special data structure is -->
<!-- needed: just keep track of the value of the current window, and add -->
<!-- and subtract values as they enter and leave the window, -->
<!-- respectively.] --></p></li>
<li><p>If we want arbitrary ranges but the operation is a <em>group</em>, the
solution is relatively straightforward: we can precompute all
<em><a href="https://byorgey.github.io/blog/posts/2025/06/27/prefix-sums.html">prefix sums</a></em>, and subtract to find the result for an arbitrary
range in <span class="math inline">\(O(1)\)</span>.</p></li>
<li><p>If the operation is an <em>idempotent semigroup</em> (that is, it has the
property that <span class="math inline">\(x \diamond x = x\)</span> for all <span class="math inline">\(x\)</span>), we can use a <em><a href="https://byorgey.github.io/blog/posts/2025/07/18/sparse-table.html">sparse
table</a></em>, which takes <span class="math inline">\(O(n \lg n)\)</span> time and space for precomputation,
and then allows us to answer arbitrary range queries in <span class="math inline">\(O(1)\)</span>.</p></li>
<li><p>If the operation is an arbitrary monoid, we can use a <em><a href="https://cp-algorithms.com/data_structures/sqrt-tree.html">sqrt tree</a></em>,
which uses <span class="math inline">\(O(n \lg \lg n)\)</span> precomputed time and space, and allows
answering arbitrary range queries in <span class="math inline">\(O(\lg \lg n)\)</span>. I will write
about this in a future post.</p></li>
</ul>
</section>
<section id="dynamic-range-queries" class="level2">
<h2>Dynamic range queries</h2>
<p>What if we want <em>dynamic</em> range queries, that is, we want to be able
to interleave range queries with arbitrary updates to the values of
the sequence?</p>
<ul>
<li>If the operation is an arbitrary monoid, we can use a segment
tree.</li>
<li>If the operation is a group, we can use a <a href="https://cp-algorithms.com/data_structures/fenwick.html">Fenwick tree</a>.</li>
</ul>
<p>I published <a href="https://byorgey.github.io/blog/posts/2025/01/23/Fenwick.html">a paper about Fenwick
trees</a>,
which also discusses segment trees, but I should write more about
them here!</p>
</section>
<section id="table" class="level2">
<h2>Table</h2>
<p>Here’s a table summarizing the above classification scheme. I plan to
fill in links as I write blog posts about each row.</p>
<figure class="fullwidth">
<table>
<colgroup>
<col style="width: 9%" />
<col style="width: 14%" />
<col style="width: 20%" />
<col style="width: 23%" />
<col style="width: 16%" />
<col style="width: 14%" />
</colgroup>
<thead>
<tr>
<th style="text-align: left;">Sequence</th>
<th style="text-align: left;">Ranges</th>
<th style="text-align: left;">Operation</th>
<th style="text-align: left;">Solution</th>
<th style="text-align: left;">Precomputation</th>
<th style="text-align: left;">Queries</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">Static</td>
<td style="text-align: left;">Sliding window</td>
<td style="text-align: left;">Monoid</td>
<td style="text-align: left;"><a href="https://byorgey.github.io/blog/posts/2024/11/27/stacks-queues.html">Amortized queue</a></td>
<td style="text-align: left;"><span class="math inline">\(O(1)\)</span></td>
<td style="text-align: left;"><span class="math inline">\(O(1)\)</span></td>
</tr>
<tr>
<td style="text-align: left;">Static</td>
<td style="text-align: left;">Arbitrary</td>
<td style="text-align: left;">Group</td>
<td style="text-align: left;"><a href="https://byorgey.github.io/blog/posts/2025/06/27/prefix-sums.html">Prefix sum table</a></td>
<td style="text-align: left;"><span class="math inline">\(O(n)\)</span></td>
<td style="text-align: left;"><span class="math inline">\(O(1)\)</span></td>
</tr>
<tr>
<td style="text-align: left;">Static</td>
<td style="text-align: left;">Arbitrary</td>
<td style="text-align: left;">Idempotent semigroup</td>
<td style="text-align: left;"><a href="https://byorgey.github.io/blog/posts/2025/07/18/sparse-table.html">Sparse table</a></td>
<td style="text-align: left;"><span class="math inline">\(O(n \lg n)\)</span></td>
<td style="text-align: left;"><span class="math inline">\(O(1)\)</span></td>
</tr>
<tr>
<td style="text-align: left;">Static</td>
<td style="text-align: left;">Arbitrary</td>
<td style="text-align: left;">Monoid</td>
<td style="text-align: left;">Sqrt tree</td>
<td style="text-align: left;"><span class="math inline">\(O(n \lg \lg n)\)</span></td>
<td style="text-align: left;"><span class="math inline">\(O(\lg \lg n)\)</span></td>
</tr>
<tr>
<td style="text-align: left;">Dynamic</td>
<td style="text-align: left;">Arbitrary</td>
<td style="text-align: left;">Group</td>
<td style="text-align: left;">Fenwick tree</td>
<td style="text-align: left;"><span class="math inline">\(O(n)\)</span></td>
<td style="text-align: left;"><span class="math inline">\(O(\lg n)\)</span></td>
</tr>
<tr>
<td style="text-align: left;">Dynamic</td>
<td style="text-align: left;">Arbitrary</td>
<td style="text-align: left;">Monoid</td>
<td style="text-align: left;">Segment tree</td>
<td style="text-align: left;"><span class="math inline">\(O(n)\)</span></td>
<td style="text-align: left;"><span class="math inline">\(O(\lg n)\)</span></td>
</tr>
</tbody>
</table>
</figure>
</section>

</section>

<script data-isso="https://comments.byorgey.com/" src="https://comments.byorgey.com/js/embed.min.js"></script>
<section id="isso-thread"  data-title="Competitive programming in Haskell: range queries, classified" >
  <noscript>Javascript needs to be activated to view comments.</noscript>
</section>

]]></description>
    <pubDate>Mon, 23 Jun 2025 00:00:00 UT</pubDate>
    <guid>http://byorgey.github.io/blog/posts/2025/06/23/range-queries-classified.html</guid>
    <dc:creator>Brent Yorgey</dc:creator>
</item>
<item>
    <title>Monads are not like burritos</title>
    <link>http://byorgey.github.io/blog/posts/2025/06/16/monads-are-not-burritos.html</link>
    <description><![CDATA[
<h1>Monads are not like burritos</h1>

<div class="info">
  Posted on June 16, 2025
  
  
  <br />
  Tagged <a title="All pages tagged &#39;monad&#39;." href="/tag/monad.html" rel="tag">monad</a>, <a title="All pages tagged &#39;pedagogy&#39;." href="/tag/pedagogy.html" rel="tag">pedagogy</a>, <a title="All pages tagged &#39;meme&#39;." href="/tag/meme.html" rel="tag">meme</a>, <a title="All pages tagged &#39;burrito&#39;." href="/tag/burrito.html" rel="tag">burrito</a>, <a title="All pages tagged &#39;analogy&#39;." href="/tag/analogy.html" rel="tag">analogy</a>, <a title="All pages tagged &#39;Haskell&#39;." href="/tag/Haskell.html" rel="tag">Haskell</a>
  
</div>

<a href="https://share.joinmastodon.org/#text=Monads are not like burritos https://byorgey.github.io/blog/posts/2025/06/16/monads-are-not-burritos.html" target="_blank" rel="noopener">Share on <svg role="img" aria-label="Mastodon" height="1em" viewBox="0 0 74 79" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M73.7014 17.4323C72.5616 9.05152 65.1774 2.4469 56.424 1.1671C54.9472 0.950843 49.3518 0.163818 36.3901 0.163818H36.2933C23.3281 0.163818 20.5465 0.950843 19.0697 1.1671C10.56 2.41145 2.78877 8.34604 0.903306 16.826C-0.00357854 21.0022 -0.100361 25.6322 0.068112 29.8793C0.308275 35.9699 0.354874 42.0498 0.91406 48.1156C1.30064 52.1448 1.97502 56.1419 2.93215 60.0769C4.72441 67.3445 11.9795 73.3925 19.0876 75.86C26.6979 78.4332 34.8821 78.8603 42.724 77.0937C43.5866 76.8952 44.4398 76.6647 45.2833 76.4024C47.1867 75.8033 49.4199 75.1332 51.0616 73.9562C51.0841 73.9397 51.1026 73.9184 51.1156 73.8938C51.1286 73.8693 51.1359 73.8421 51.1368 73.8144V67.9366C51.1364 67.9107 51.1302 67.8852 51.1186 67.862C51.1069 67.8388 51.0902 67.8184 51.0695 67.8025C51.0489 67.7865 51.0249 67.7753 50.9994 67.7696C50.9738 67.764 50.9473 67.7641 50.9218 67.7699C45.8976 68.9569 40.7491 69.5519 35.5836 69.5425C26.694 69.5425 24.3031 65.3699 23.6184 63.6327C23.0681 62.1314 22.7186 60.5654 22.5789 58.9744C22.5775 58.9477 22.5825 58.921 22.5934 58.8965C22.6043 58.8721 22.621 58.8505 22.6419 58.8336C22.6629 58.8167 22.6876 58.8049 22.714 58.7992C22.7404 58.7934 22.7678 58.794 22.794 58.8007C27.7345 59.9796 32.799 60.5746 37.8813 60.5733C39.1036 60.5733 40.3223 60.5733 41.5447 60.5414C46.6562 60.3996 52.0437 60.1408 57.0728 59.1694C57.1983 59.1446 57.3237 59.1233 57.4313 59.0914C65.3638 57.5847 72.9128 52.8555 73.6799 40.8799C73.7086 40.4084 73.7803 35.9415 73.7803 35.4523C73.7839 33.7896 74.3216 23.6576 73.7014 17.4323ZM61.4925 47.3144H53.1514V27.107C53.1514 22.8528 51.3591 20.6832 47.7136 20.6832C43.7061 20.6832 41.6988 23.2499 41.6988 28.3194V39.3803H33.4078V28.3194C33.4078 23.2499 31.3969 20.6832 27.3894 20.6832C23.7654 20.6832 21.9552 22.8528 21.9516 27.107V47.3144H13.6176V26.4937C13.6176 22.2395 14.7157 18.8598 16.9118 16.3545C19.1772 13.8552 22.1488 12.5719 25.8373 12.5719C30.1064 12.5719 33.3325 14.1955 35.4832 17.4394L37.5587 20.8853L39.6377 17.4394C41.7884 14.1955 45.0145 12.5719 49.2765 12.5719C52.9614 12.5719 55.9329 13.8552 58.2055 16.3545C60.4017 18.8574 61.4997 22.2371 61.4997 26.4937L61.4925 47.3144Z" fill="inherit"/></svg></a>
<section>
<p>In January 2009, while just a baby first-year PhD student, I wrote a
blog post titled <a href="https://byorgey.github.io/blog/posts/2009/01/12/abstraction-intuition-and-the-monad-tutorial-fallacy.html">Abstraction, intuition, and the “monad tutorial
fallacy”</a>.
In it, I made the argument that humans tend to learn best by first
grappling with concrete examples, and only later proceeding to
higher-level intuition and analogies; hence, it’s a mistake to
think that clearly presenting your intuition for a topic will help
other people understand it. Analogies and intuition can help, but
only when accompanied by concrete examples and active engagement. To
illustrate the point, I made up a fictitious programmer with a
fictitious analogy.</p>
<blockquote>
<p>But now Joe goes and writes a monad tutorial called “Monads are
Burritos,” under the well-intentioned but mistaken assumption that
if other people read his magical insight, learning about monads will
be a snap for them. “Monads are easy,” Joe writes. “Think of them as
burritos.” Joe hides all the actual details about types and such
because those are scary, and people will learn better if they can
avoid all that difficult and confusing stuff. Of course, exactly
the opposite is true, and all Joe has done is make it <em>harder</em> for
people to learn about monads…</p>
</blockquote>
<p>My intention was to choose a fictitious analogy which was obviously
ridiculous and silly, as a parody of many of the monad tutorials which
existed at the time (and still do). <a href="https://blog.plover.com/meta/about-me.html">Mark Jason Dominus</a>
then wrote a blog post, <a href="https://blog.plover.com/prog/burritos.html">Monads are like
burritos</a>, pointing out
that actually, monads <em>are</em> kinda like burritos. It’s really funny,
though I don’t think it’s actually a very good analogy, and my guess
is that Mark would agree: it was clearly written as a silly joke and
not as a real way to explain monads.</p>
<p>In any case, from that point the “monads are burritos” meme took on a
life of its own. For example:</p>
<ul>
<li><a href="https://chrisdone.com/posts/monads-are-burritos/">Chris Done made a webcomic about
it</a></li>
<li><a href="https://edwardmorehouse.github.io/silliness/burrito_monads.pdf">Ed Morehouse wrote a ridiculous paper exploring the categorical
foundations of burritos</a></li>
<li><a href="https://github.com/withoutboats/burrito">Someone made a <code>burrito</code> library in Rust</a></li>
<li><a href="https://x.com/DrEugeniaCheng/status/1316817271961116679">Dr Eugenia Cheng tweeted about it</a></li>
</ul>
<p>I even joined in the fun and made this meme image about bad monad
tutorials:</p>
<p><img src="images/monad_tutorial.jpg" /></p>
<p>Of course there are <a href="https://www.reddit.com/r/haskell/comments/6bxk1v/why_monads_always_get_compared_to_burritos/">lots of people who still understand that it was all just a silly joke</a>.
Recently, however, I’ve seen several instances where people apparently
believe “monads are burritos” is a real, helpful thing and not just a
joke meme. For example, see <a href="https://lobste.rs/s/xmpj1p/you_probably_wrote_half_monad_by_accident">this thread on
lobste.rs</a>,
or <a href="https://mathstodon.xyz/@CubeRootOfTrue/114404282908533701">this Mastodon post</a>.</p>
<p>So, to set the record straight: “monads are burritos” is <em>not</em> a helpful
analogy!<span class="sidenote-wrapper"><label for="sn-0" class="margin-toggle sidenote-number"></label><input type="checkbox" id="sn-0" class="margin-toggle"/><span class="sidenote">Yes, I am writing a blog post because <a href="https://xkcd.com/386/">People Are Wrong On
The Internet</a>, and I know it probably won’t
make any difference, but here we are.<br />
<br />
</span></span> Why not, you ask?
To expand on my reasons from a <a href="https://www.reddit.com/r/haskell/comments/3bdrlj/comment/ct24jmc/">10-year-old Reddit
comment</a>:</p>
<ul>
<li>The burrito analogy strongly implies that a value of type <code>m a</code>
somehow “contains” a value (or values) of type <code>a</code>. But that is not
true for all monads (e.g. there is no sense in which a value of type
<code>IO String</code> contains a <code>String</code>).</li>
<li>Relatedly, the analogy also implies that a value of type <code>m a</code> can
be “unwrapped” to get an <code>a</code>, but this is impossible for many monads.</li>
<li>It is not actually very easy to take a burrito containing a burrito
and merge it into a single-level burrito. At least this is not in
any sense a natural operation on burritos. Perhaps you could argue
that it is always easy to remove outer tortilla layers (but not the
innermost one since the food will all fall out), but this is a bad
analogy, since in general <code>join</code> does not just “remove” an outer
layer, but somehow merges the effects of two layers into one.</li>
</ul>
<p>Actually, burritos are a great analogy for the <code>Identity</code> monad!
…but not much beyond that.</p>
<p>On a more positive note, my sense is that the average
pedagogical quality of Haskell materials, and monad tutorials in
particular, has indeed gone up significantly since 2009. I’d love to
think this can be at least partially attributed to my original blog
post, though of course it’s impossible to know that for sure.</p>

</section>

<script data-isso="https://comments.byorgey.com/" src="https://comments.byorgey.com/js/embed.min.js"></script>
<section id="isso-thread"  data-title="Monads are not like burritos" >
  <noscript>Javascript needs to be activated to view comments.</noscript>
</section>

]]></description>
    <pubDate>Mon, 16 Jun 2025 00:00:00 UT</pubDate>
    <guid>http://byorgey.github.io/blog/posts/2025/06/16/monads-are-not-burritos.html</guid>
    <dc:creator>Brent Yorgey</dc:creator>
</item>
<item>
    <title>Introduction to competitive programming in Haskell</title>
    <link>http://byorgey.github.io/blog/posts/2025/06/10/comprog-hs-intro.html</link>
    <description><![CDATA[
<h1>Introduction to competitive programming in Haskell</h1>

<div class="info">
  Posted on June 10, 2025
  
  
  <br />
  Tagged <a title="All pages tagged &#39;Kattis&#39;." href="/tag/Kattis.html" rel="tag">Kattis</a>, <a title="All pages tagged &#39;competitive programming&#39;." href="/tag/competitive%20programming.html" rel="tag">competitive programming</a>, <a title="All pages tagged &#39;haskell&#39;." href="/tag/haskell.html" rel="tag">haskell</a>
  
</div>

<a href="https://share.joinmastodon.org/#text=Introduction to competitive programming in Haskell https://byorgey.github.io/blog/posts/2025/06/10/comprog-hs-intro.html" target="_blank" rel="noopener">Share on <svg role="img" aria-label="Mastodon" height="1em" viewBox="0 0 74 79" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M73.7014 17.4323C72.5616 9.05152 65.1774 2.4469 56.424 1.1671C54.9472 0.950843 49.3518 0.163818 36.3901 0.163818H36.2933C23.3281 0.163818 20.5465 0.950843 19.0697 1.1671C10.56 2.41145 2.78877 8.34604 0.903306 16.826C-0.00357854 21.0022 -0.100361 25.6322 0.068112 29.8793C0.308275 35.9699 0.354874 42.0498 0.91406 48.1156C1.30064 52.1448 1.97502 56.1419 2.93215 60.0769C4.72441 67.3445 11.9795 73.3925 19.0876 75.86C26.6979 78.4332 34.8821 78.8603 42.724 77.0937C43.5866 76.8952 44.4398 76.6647 45.2833 76.4024C47.1867 75.8033 49.4199 75.1332 51.0616 73.9562C51.0841 73.9397 51.1026 73.9184 51.1156 73.8938C51.1286 73.8693 51.1359 73.8421 51.1368 73.8144V67.9366C51.1364 67.9107 51.1302 67.8852 51.1186 67.862C51.1069 67.8388 51.0902 67.8184 51.0695 67.8025C51.0489 67.7865 51.0249 67.7753 50.9994 67.7696C50.9738 67.764 50.9473 67.7641 50.9218 67.7699C45.8976 68.9569 40.7491 69.5519 35.5836 69.5425C26.694 69.5425 24.3031 65.3699 23.6184 63.6327C23.0681 62.1314 22.7186 60.5654 22.5789 58.9744C22.5775 58.9477 22.5825 58.921 22.5934 58.8965C22.6043 58.8721 22.621 58.8505 22.6419 58.8336C22.6629 58.8167 22.6876 58.8049 22.714 58.7992C22.7404 58.7934 22.7678 58.794 22.794 58.8007C27.7345 59.9796 32.799 60.5746 37.8813 60.5733C39.1036 60.5733 40.3223 60.5733 41.5447 60.5414C46.6562 60.3996 52.0437 60.1408 57.0728 59.1694C57.1983 59.1446 57.3237 59.1233 57.4313 59.0914C65.3638 57.5847 72.9128 52.8555 73.6799 40.8799C73.7086 40.4084 73.7803 35.9415 73.7803 35.4523C73.7839 33.7896 74.3216 23.6576 73.7014 17.4323ZM61.4925 47.3144H53.1514V27.107C53.1514 22.8528 51.3591 20.6832 47.7136 20.6832C43.7061 20.6832 41.6988 23.2499 41.6988 28.3194V39.3803H33.4078V28.3194C33.4078 23.2499 31.3969 20.6832 27.3894 20.6832C23.7654 20.6832 21.9552 22.8528 21.9516 27.107V47.3144H13.6176V26.4937C13.6176 22.2395 14.7157 18.8598 16.9118 16.3545C19.1772 13.8552 22.1488 12.5719 25.8373 12.5719C30.1064 12.5719 33.3325 14.1955 35.4832 17.4394L37.5587 20.8853L39.6377 17.4394C41.7884 14.1955 45.0145 12.5719 49.2765 12.5719C52.9614 12.5719 55.9329 13.8552 58.2055 16.3545C60.4017 18.8574 61.4997 22.2371 61.4997 26.4937L61.4925 47.3144Z" fill="inherit"/></svg></a>
<section>
<p>A few days ago I gave a talk at <a href="https://zfoh.ch/zurihac2025/">ZuriHac
2025</a> entitled <em>Haskell for Competitive
Programming</em>, a basic introduction to competitive programming in
general, and the joy of using Haskell for competitive programming in
particular. This is an expanded version of my talk in blog post form.
(For an even gentler introduction to competitive programming in
Haskell, see <a href="https://byorgey.github.io/blog/posts/2019/04/24/competitive-programming-in-haskell-basic-setup.html">this old blog post from
2019</a>.)</p>
<section id="competitive-programming" class="level2">
<h2>Competitive Programming</h2>
<p>First of all, what is <em>competitive programming</em>? It’s a broad term,
but when I talk about competitive programming I have something in mind
along the following lines:</p>
<ul>
<li>There are well-specified input and output formats, usually with a
few examples, and a precise specification of what the output should
be for a given input.</li>
<li>Your job is to write a program which transforms input meeting the
specification into a correct output.</li>
<li>You submit your program, which is tested on a number of inputs and
declared correct if and only if it yields the correct output for all
the tested inputs.</li>
<li>There is often time pressure involved—that is, you have a limited
amount of time in which to write your program. However, it is also
possible to participate “recreationally”, simply for the joy of
problem-solving, without time pressure (in fact, the vast majority
of the competitive programming I do is of this form, though I have
occasionally participated in timed contests).</li>
</ul>
<p>There are many variations: whether you are allowed to use code
libraries prepared ahead of time, or must type everything from
scratch; outputs can be scored according to some criteria rather
than simply being judged right or wrong; and so on.</p>
<p>There are many sites which allow you to participate in contests and/or
solve competitive programming problems recreationally. My favorite is
<a href="https://open.kattis.com">Open Kattis</a>; I mention some others at the
end of this post.</p>
</section>
<section id="pot-a-first-example" class="level2">
<h2>Pot: a first example</h2>
<p>As an introductory example, let’s look at
<a href="https://open.kattis.com/problems/pot">Pot</a>. As usual, there’s a silly
story, but what it boils down to is that we will be given a sequence
of numbers, and we should interpret the last digit of each number as an
exponent, then sum the results. For example, if given <code>125</code>, we
should interpret it as <span class="math inline">\(12^5\)</span>, and so on.</p>
<section id="dealing-with-io-via-interact" class="level3">
<h3>Dealing with I/O via <code>interact</code></h3>
<p>An imperative approach to such a problem would involve doing a
sequence of input commands, some computation, and a sequence of output
commands—possibly interleaved with one another—and we might
immediately think to start using functions like <code>getLine</code> and
<code>putStrLn</code> to do the required I/O in Haskell. However, there is a
much more fruitful functional perspective: we are simply being asked
to implement a particular (partial) function of type <code>String -&gt; String</code>. The fact that the function’s input and output should be
hooked up to the program’s standard input and output is just an
implementation detail. Competitive programming is functional at
heart!</p>
<p>It turns out that Haskell’s standard library already has the perfect
built-in function for this scenario:</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="fu">interact</span><span class="ot"> ::</span> (<span class="dt">String</span> <span class="ot">-&gt;</span> <span class="dt">String</span>) <span class="ot">-&gt;</span> <span class="dt">IO</span> ()</span></code></pre></div>
<p><code>interact</code> takes a pure <code>String -&gt; String</code> function and turns it into
an <code>IO</code> action which reads from standard input, passes the input to
the given <code>String -&gt; String</code> function, and prints the result to standard output. It even
does this using <em>lazy</em> I/O—that is, the input is
read lazily, as demanded by the function, so that the output and input
can be automatically interleaved depending on which parts of the
output depend on which parts of the input. In particular, this means
that that the entire input need not be stored in memory at once. If
the inputs can be processed into outputs in a streaming fashion—as
is the case in the example problem we are currently
considering—then the input and output will be interleaved. In
general, this kind of lazy I/O is
<a href="https://stackoverflow.com/questions/5892653/whats-so-bad-about-lazy-i-o">problematic</a>
and even unsafe, but it’s perfect for this scenario.</p>
</section>
<section id="solving-the-problem-with-a-pipeline" class="level3">
<h3>Solving the problem with a pipeline</h3>
<p>So <code>interact</code> does all the <code>IO</code> for us, and all we have to do is write
a pure <code>String -&gt; String</code> function which transforms the input to the
output. In this case, we can split the input into <code>lines</code>, <code>drop</code> the
first line (we don’t need to know how many lines of input there
are—we just get a list of all of them, since <code>interact</code> will read
until EOF), <code>read</code> each number and turn it into the first digits
raised to the power of the last digit, then <code>sum</code> them and <code>show</code> the
result. The full solution is below. Notice how I use the “backwards
composition” operator <code>(&gt;&gt;&gt;)</code>, since I find it more convenient to type
from left to right as I’m thinking about transforming from input to
output.</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">import</span> <span class="dt">Control.Category</span> ((&gt;&gt;&gt;))</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> <span class="fu">interact</span> <span class="op">$</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>  <span class="fu">lines</span> <span class="op">&gt;&gt;&gt;</span> <span class="fu">drop</span> <span class="dv">1</span> <span class="op">&gt;&gt;&gt;</span> <span class="fu">map</span> (<span class="fu">read</span> <span class="op">&gt;&gt;&gt;</span> process) <span class="op">&gt;&gt;&gt;</span> <span class="fu">sum</span> <span class="op">&gt;&gt;&gt;</span> <span class="fu">show</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="ot">process ::</span> <span class="dt">Integer</span> <span class="ot">-&gt;</span> <span class="dt">Integer</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>process n <span class="ot">=</span> (n <span class="ot">`div`</span> <span class="dv">10</span>) <span class="op">^</span> (n <span class="ot">`mod`</span> <span class="dv">10</span>)</span></code></pre></div>
<p>I use <code>Integer</code> here since raw performance doesn’t matter much for
this easy problem, and <code>Integer</code> avoids any potential problems with
overflow. However, using <code>Int</code> instead of <code>Integer</code> can make a big
difference for some compute-intensive problems. On Kattis, <code>Int</code> will
always be 64 bits, but last time I checked <code>Int</code> can be 32 bits on
Codeforces.</p>
</section>
</section>
<section id="shopping-list-wholemeal-programming-and-bytestring" class="level2">
<h2>Shopping List: wholemeal programming and ByteString</h2>
<p>Let’s consider <a href="https://open.kattis.com/problems/shoppinglist">Shopping List</a> as a second example. In this
problem, we are given a list of shopping lists, where each shopping
list consists of a list of space-separated items on a single line. We
are asked to find the items which are common to all the shopping
lists, and print them in alphabetical order.</p>
<section id="wholemeal-programming-with-standard-data-structures" class="level3">
<h3>Wholemeal programming with standard data structures</h3>
<p>This problem is very amenable to a <a href="https://www.cs.ox.ac.uk/ralf.hinze/publications/ICFP09.pdf">“wholemeal programming”
approach</a>,
where we work entirely at the level of whole data structure
transformations rather than looping over individual elements. We can
turn each shopping list into a set, then find the intersection of all
the sets. Moreover, if we use <code>Data.Set</code>, which uses an ordering on
the elements, we will get the result in alphabetical order “for free”
(“free” as in the amount of code we have to write, not necessarily
runtime cost). Haskell has a decent collection of data structures in
the <code>containers</code> library (<code>(Int)Set</code>, <code>(Int)Map</code>, <code>Seq</code>, <code>Tree</code>, and
even <code>Graph</code>) with a large collection of standard methods to construct
and manipulate them, which are bread and butter for many competitive
programming problems.</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="ot">{-# LANGUAGE ImportQualifiedPost #-}</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Category</span> ((&gt;&gt;&gt;))</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Set</span> (<span class="dt">Set</span>)</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Set</span> <span class="kw">qualified</span> <span class="kw">as</span> <span class="dt">S</span></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>main <span class="ot">=</span> <span class="fu">interact</span> <span class="op">$</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>  <span class="fu">lines</span> <span class="op">&gt;&gt;&gt;</span> <span class="fu">drop</span> <span class="dv">1</span> <span class="op">&gt;&gt;&gt;</span> <span class="fu">map</span> (<span class="fu">words</span> <span class="op">&gt;&gt;&gt;</span> S.fromList) <span class="op">&gt;&gt;&gt;</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>  <span class="fu">foldr1</span> S.intersection <span class="op">&gt;&gt;&gt;</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>  (\s <span class="ot">-&gt;</span> <span class="fu">show</span> (S.size s) <span class="op">:</span> S.toList s) <span class="op">&gt;&gt;&gt;</span> <span class="fu">unlines</span></span></code></pre></div>
</section>
<section id="bytestring-vs-string" class="level3">
<h3><code>ByteString</code> vs <code>String</code></h3>
<p>Unfortunately, when we try submitting this code, we get a Time Limit
Exceeded error! What’s wrong?</p>
<p>The issue is our use of <code>String</code>, which is an actual linked list of
characters and is very slow, especially when we have many short
strings, as in this problem. In the worst case, we could have 100
shopping lists, each with 5000 items of length 10, for a total of up
to 5 MB of input; with that much input data to read, any overhead
associated with reading and parsing the input can make a significant
difference.</p>
<p>Switching to <code>ByteString</code> is much faster. Why not <code>Text</code>, you ask?
Well, <code>Text</code> has to do a bunch of extra work to deal properly with
Unicode encodings, but in 99.99% of all competitive programming problems
I’ve ever seen, the input is guaranteed to be ASCII. So not
only do we not need <code>Text</code>, we can get away with a version of
<code>ByteString</code> that simply assumes every character is a single 8-bit
byte!</p>
<p>Once we import it, all we need to do is replace a bunch of
<code>String</code> operations with corresponding <code>ByteString</code> ones.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE ImportQualifiedPost #-}</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Control.Category</span> ((&gt;&gt;&gt;))</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Set</span> (<span class="dt">Set</span>)</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.Set</span> <span class="kw">qualified</span> <span class="kw">as</span> <span class="dt">S</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="kw">import</span> <span class="dt">Data.ByteString.Lazy.Char8</span> <span class="kw">qualified</span> <span class="kw">as</span> <span class="dt">BS</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> BS.interact <span class="op">$</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>  BS.lines <span class="op">&gt;&gt;&gt;</span> <span class="fu">drop</span> <span class="dv">1</span> <span class="op">&gt;&gt;&gt;</span> <span class="fu">map</span> (BS.words <span class="op">&gt;&gt;&gt;</span> S.fromList) <span class="op">&gt;&gt;&gt;</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>  <span class="fu">foldr1</span> S.intersection <span class="op">&gt;&gt;&gt;</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>  (\s <span class="ot">-&gt;</span> BS.pack (<span class="fu">show</span> (S.size s)) <span class="op">:</span> S.toList s) <span class="op">&gt;&gt;&gt;</span> BS.unlines</span></code></pre></div>
</section>
</section>
<section id="a-favourable-ending-input-parsing-and-lazy-recursive-structures" class="level2">
<h2>A Favourable Ending: input parsing and lazy recursive structures</h2>
<p>As a last example, let’s look at <a href="https://open.kattis.com/problems/favourable">A Favourable
Ending</a>. This problem
consists of a number of test cases; each test case describes a
choose-your-own-adventure book with a number of sections, where each
section is either an ending (either good or bad), or allows the reader
to choose among three sections to proceed to next. For each test case,
we are asked how many distinct stories there are with good endings.</p>
<p>More abstractly, since we are guaranteed that there are no loops, the
sections of the book form a
<a href="https://en.wikipedia.org/wiki/Directed_acyclic_graph">DAG</a>, and we
are asked to count the number of distinct paths in a DAG from a
distinguished start node to any of a distinguished set of “good”
leaves.</p>
<section id="parsing-with-scanner" class="level3">
<h3>Parsing with Scanner</h3>
<p>Parsing the input for this problem is trickier than the other
examples so far. In theory, we could still ignore the first number
specifying the number of test cases, and just continue reading test
cases until EOF. However, each test case begins with a number
specifying the number of sections in the book, and we cannot ignore
this number: we need to know how many lines to read before the start
of the next test case. Doing this manually involves pattern-matching
on a list of lines, using <code>splitAt</code> to split off the lines for each
test case, and manually passing around the list of the remaining
lines: tedious.</p>
<p>Fortunately, Haskell is great at building abstractions to insulate us
from such tedium. I’ve developed a <a href="https://byorgey.github.io/blog/posts/2019/05/22/competitive-programming-in-haskell-scanner.html">simple <code>Scanner</code>
abstraction</a>
which works well in this context.</p>
<p>We begin by creating some data types to represent the input in
structured form:</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">type</span> <span class="dt">Book</span> <span class="ot">=</span> <span class="dt">Map</span> <span class="dt">Int</span> <span class="dt">Section</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Section</span> <span class="ot">=</span> <span class="dt">End</span> <span class="dt">Disposition</span> <span class="op">|</span> <span class="dt">Choice</span> [<span class="dt">Int</span>]</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> (<span class="dt">Eq</span>, <span class="dt">Show</span>)</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Disposition</span> <span class="ot">=</span> <span class="dt">Favourably</span> <span class="op">|</span> <span class="dt">Catastrophically</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">deriving</span> (<span class="dt">Eq</span>, <span class="dt">Show</span>, <span class="dt">Read</span>)</span></code></pre></div>
<p>Now we can write a <code>Scanner</code> to read a <code>Book</code>:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ot">book ::</span> <span class="dt">Scanner</span> <span class="dt">Book</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>book <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  s <span class="ot">&lt;-</span> int</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>  M.fromList <span class="op">&lt;$&gt;</span> s <span class="op">&gt;&lt;</span> ((,) <span class="op">&lt;$&gt;</span> int <span class="op">&lt;*&gt;</span> section)</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="ot">section ::</span> <span class="dt">Scanner</span> <span class="dt">Section</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>section <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>  t <span class="ot">&lt;-</span> peek</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">if</span> <span class="fu">isDigit</span> (BS.head t)</span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">then</span> <span class="dt">Choice</span> <span class="op">&lt;$&gt;</span> (<span class="dv">3</span> <span class="op">&gt;&lt;</span> int)</span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">else</span> <span class="dt">End</span> <span class="op">.</span> readLower <span class="op">.</span> BS.unpack <span class="op">&lt;$&gt;</span> str</span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a><span class="ot">readLower ::</span> <span class="dt">Read</span> a <span class="ot">=&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> a</span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a>readLower <span class="ot">=</span> <span class="fu">read</span> <span class="op">.</span> onHead <span class="fu">toUpper</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a><span class="ot">onHead ::</span> (a <span class="ot">-&gt;</span> a) <span class="ot">-&gt;</span> [a] <span class="ot">-&gt;</span> [a]</span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a>onHead _ [] <span class="ot">=</span> []</span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a>onHead f (x <span class="op">:</span> xs) <span class="ot">=</span> f x <span class="op">:</span> xs</span></code></pre></div>
<p>(<code>readLower</code> and <code>onHead</code> are functions in my personal competitive
programming template, included here for completeness).</p>
<p>One more piece of boilerplate we can write at this point is the <code>main</code>
function, which simply consists of running the <code>Scanner</code> to read all the
test cases, solving each test case, and formatting the output.</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>main <span class="ot">=</span> BS.interact <span class="op">$</span> runScanner (numberOf book) <span class="op">&gt;&gt;&gt;</span> <span class="fu">map</span> (solve <span class="op">&gt;&gt;&gt;</span> showB) <span class="op">&gt;&gt;&gt;</span> BS.unlines</span></code></pre></div>
</section>
<section id="dp-topsort-with-a-lazy-recursive-map" class="level3">
<h3>DP + topsort with a lazy recursive map</h3>
<p>With all that framework out of the way, we can turn to actually
solving the problem. And here is where something really fun happens.
In a typical imperative language, we would have to first topologically
sort the book sections, then use dynamic programming to compute the
number of good stories beginning at each section, starting with the
leaves and proceeding backwards through the topological sort to the
start—dozens of lines of code. However, in Haskell we can get all
of this for free, just by defining a lazy, recursive map!</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ot">solve ::</span> <span class="dt">Book</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>solve book <span class="ot">=</span> endings <span class="op">!</span> <span class="dv">1</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">where</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>    endings <span class="ot">=</span> M.fromList [(p, endingsFrom (book<span class="op">!</span>p)) <span class="op">|</span> p <span class="ot">&lt;-</span> M.keys book]</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>    endingsFrom (<span class="dt">End</span> d) <span class="ot">=</span> <span class="kw">if</span> d <span class="op">==</span> <span class="dt">Favourably</span> <span class="kw">then</span> <span class="dv">1</span> <span class="kw">else</span> <span class="dv">0</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>    endingsFrom (<span class="dt">Choice</span> ps) <span class="ot">=</span> <span class="fu">sum</span> <span class="op">$</span> <span class="fu">map</span> (endings <span class="op">!</span>) ps</span></code></pre></div>
<p><code>endings</code> is a <code>Map</code> from each book section to the number of favorable
stories starting with that section. Notice how its values are defined
via the <code>endingsFrom</code> function, which is in turn defined, in the
<code>Choice</code> case, by looking up the values of the choices in the
<code>endings</code> map and summing them. <code>endings</code> is thus defined
recursively, which works because it is lazy in the values. When we
demand the value of <code>endings ! 1</code>, the runtime system starts evaluating
thunks in the map as needed, implicitly doing a topological sort for us.</p>
<p>Here’s another way to think about this: what we really want is the
function <code>endingsFrom : Section -&gt; Int</code>, which tells us how many good
endings there are starting at a given section. It can be defined via a
recurrence; however, if we were to literally implement it as a
recursive function, our program would spend a ridiculous amount of
time recomputing the same values over and over again. So, we insert a
lazy map in the middle to memoize it (there are <a href="https://byorgey.github.io/blog/posts/2023/06/06/dynamic-programming-in-haskell-automatic-memoization.html">other data
structures</a>
that can be used for this purpose as well).</p>
</section>
</section>
<section id="resources" class="level2">
<h2>Resources</h2>
<p>Here are some resources in case you’re interested in exploring more.</p>
<ul>
<li><a href="https://open.kattis.com">Open Kattis</a> has a collection of thousands
of high-quality problems which can be solved in Haskell (or many
other languages). If you just want to try solving some problems for
fun, it’s a great place to start.</li>
<li>There are also other sites which accept Haskell, such as
<a href="https://codeforces.com/">Codeforces</a>. Check these out if you want
to actually participate in timed contests.</li>
<li>My public <a href="http://ozark.hendrix.edu/~yorgey/kattis.html">listing of Kattis problems I have solved</a>, with my own personal
rating system.</li>
<li>I’ve written a series of <a href="https://byorgey.github.io/blog/tag/competitive%20programming.html">blog posts</a> about competitive
programming in Haskell, on a variety of topics.</li>
<li>I also have a <a href="https://github.com/byorgey/comprog-hs/">repository of modules</a> I’ve developed
specifically for competitive programming. Many of the modules are
documented in one or more blog posts.</li>
<li>Soumik Sarkar has an even <a href="https://github.com/meooow25/haccepted">larger collection of Haskell libraries for
competitive programming</a>.</li>
</ul>
</section>

</section>

<script data-isso="https://comments.byorgey.com/" src="https://comments.byorgey.com/js/embed.min.js"></script>
<section id="isso-thread"  data-title="Introduction to competitive programming in Haskell" >
  <noscript>Javascript needs to be activated to view comments.</noscript>
</section>

]]></description>
    <pubDate>Tue, 10 Jun 2025 00:00:00 UT</pubDate>
    <guid>http://byorgey.github.io/blog/posts/2025/06/10/comprog-hs-intro.html</guid>
    <dc:creator>Brent Yorgey</dc:creator>
</item>
<item>
    <title>Hendrix College Programming Contest 2025</title>
    <link>http://byorgey.github.io/blog/posts/2025/03/13/HCPC25.html</link>
    <description><![CDATA[
<h1>Hendrix College Programming Contest 2025</h1>

<div class="info">
  Posted on March 13, 2025
  
  
  <br />
  Tagged <a title="All pages tagged &#39;competitive programming&#39;." href="/tag/competitive%20programming.html" rel="tag">competitive programming</a>, <a title="All pages tagged &#39;Hendrix&#39;." href="/tag/Hendrix.html" rel="tag">Hendrix</a>, <a title="All pages tagged &#39;programming&#39;." href="/tag/programming.html" rel="tag">programming</a>, <a title="All pages tagged &#39;contest&#39;." href="/tag/contest.html" rel="tag">contest</a>, <a title="All pages tagged &#39;HCPC&#39;." href="/tag/HCPC.html" rel="tag">HCPC</a>, <a title="All pages tagged &#39;Kattis&#39;." href="/tag/Kattis.html" rel="tag">Kattis</a>
  
</div>

<a href="https://share.joinmastodon.org/#text=Hendrix College Programming Contest 2025 https://byorgey.github.io/blog/posts/2025/03/13/HCPC25.html" target="_blank" rel="noopener">Share on <svg role="img" aria-label="Mastodon" height="1em" viewBox="0 0 74 79" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M73.7014 17.4323C72.5616 9.05152 65.1774 2.4469 56.424 1.1671C54.9472 0.950843 49.3518 0.163818 36.3901 0.163818H36.2933C23.3281 0.163818 20.5465 0.950843 19.0697 1.1671C10.56 2.41145 2.78877 8.34604 0.903306 16.826C-0.00357854 21.0022 -0.100361 25.6322 0.068112 29.8793C0.308275 35.9699 0.354874 42.0498 0.91406 48.1156C1.30064 52.1448 1.97502 56.1419 2.93215 60.0769C4.72441 67.3445 11.9795 73.3925 19.0876 75.86C26.6979 78.4332 34.8821 78.8603 42.724 77.0937C43.5866 76.8952 44.4398 76.6647 45.2833 76.4024C47.1867 75.8033 49.4199 75.1332 51.0616 73.9562C51.0841 73.9397 51.1026 73.9184 51.1156 73.8938C51.1286 73.8693 51.1359 73.8421 51.1368 73.8144V67.9366C51.1364 67.9107 51.1302 67.8852 51.1186 67.862C51.1069 67.8388 51.0902 67.8184 51.0695 67.8025C51.0489 67.7865 51.0249 67.7753 50.9994 67.7696C50.9738 67.764 50.9473 67.7641 50.9218 67.7699C45.8976 68.9569 40.7491 69.5519 35.5836 69.5425C26.694 69.5425 24.3031 65.3699 23.6184 63.6327C23.0681 62.1314 22.7186 60.5654 22.5789 58.9744C22.5775 58.9477 22.5825 58.921 22.5934 58.8965C22.6043 58.8721 22.621 58.8505 22.6419 58.8336C22.6629 58.8167 22.6876 58.8049 22.714 58.7992C22.7404 58.7934 22.7678 58.794 22.794 58.8007C27.7345 59.9796 32.799 60.5746 37.8813 60.5733C39.1036 60.5733 40.3223 60.5733 41.5447 60.5414C46.6562 60.3996 52.0437 60.1408 57.0728 59.1694C57.1983 59.1446 57.3237 59.1233 57.4313 59.0914C65.3638 57.5847 72.9128 52.8555 73.6799 40.8799C73.7086 40.4084 73.7803 35.9415 73.7803 35.4523C73.7839 33.7896 74.3216 23.6576 73.7014 17.4323ZM61.4925 47.3144H53.1514V27.107C53.1514 22.8528 51.3591 20.6832 47.7136 20.6832C43.7061 20.6832 41.6988 23.2499 41.6988 28.3194V39.3803H33.4078V28.3194C33.4078 23.2499 31.3969 20.6832 27.3894 20.6832C23.7654 20.6832 21.9552 22.8528 21.9516 27.107V47.3144H13.6176V26.4937C13.6176 22.2395 14.7157 18.8598 16.9118 16.3545C19.1772 13.8552 22.1488 12.5719 25.8373 12.5719C30.1064 12.5719 33.3325 14.1955 35.4832 17.4394L37.5587 20.8853L39.6377 17.4394C41.7884 14.1955 45.0145 12.5719 49.2765 12.5719C52.9614 12.5719 55.9329 13.8552 58.2055 16.3545C60.4017 18.8574 61.4997 22.2371 61.4997 26.4937L61.4925 47.3144Z" fill="inherit"/></svg></a>
<section>
<p>I haven’t written on here in a while, mostly because a lot of my time
has gone into preparing for the second annual <a href="https://hendrix-cs.github.io/hcpc/">Hendrix College
Programming Contest</a>, which will
take place this <a href="https://www.timeanddate.com/worldclock/fixedtime.html?msg=Hendrix+College+Programming+Contest+2025&amp;iso=20250315T1230&amp;p1=134&amp;ah=5">Saturday, March 15, from 12:30-5:30pm CDT (17:30-22:30 UTC)</a>.</p>
<p>I’ve created an <a href="https://hcpc25.kattis.com/contests/vxtved">open mirror
contest</a> which will run in
parallel to the official contest, so if you want to grab some friends
and try solving some of the problems together using your favorite
language, be my guest!</p>

</section>

<script data-isso="https://comments.byorgey.com/" src="https://comments.byorgey.com/js/embed.min.js"></script>
<section id="isso-thread"  data-title="Hendrix College Programming Contest 2025" >
  <noscript>Javascript needs to be activated to view comments.</noscript>
</section>

]]></description>
    <pubDate>Thu, 13 Mar 2025 00:00:00 UT</pubDate>
    <guid>http://byorgey.github.io/blog/posts/2025/03/13/HCPC25.html</guid>
    <dc:creator>Brent Yorgey</dc:creator>
</item>

    </channel>
</rss>
