<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Blueberry Wren Thoughts</title>
    <subtitle>The bloggings of Wren</subtitle>
    <link rel="self" type="application/atom+xml" href="https://blueberrywren.dev/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://blueberrywren.dev"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-10-10T00:00:00+00:00</updated>
    <id>https://blueberrywren.dev/atom.xml</id>
    <entry xml:lang="en">
        <title>A tale of four theorem provers, or: A (reasonably) opinionated comparison of Isabelle&#x2F;HOL, Lean, HOL4, and Agda</title>
        <published>2026-10-10T00:00:00+00:00</published>
        <updated>2026-10-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/primes/"/>
        <id>https://blueberrywren.dev/blog/primes/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/primes/">&lt;h1 id=&quot;the-above-wow-long-title&quot;&gt;The above (wow, long title)&lt;&#x2F;h1&gt;
&lt;p&gt;In which I compare Lean, Isabelle&#x2F;HOL, Agda, and HOL4 with only mild regard for &quot;fairness&quot;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;what-are-we-comparing-anyway&quot;&gt;What are we comparing, anyway?&lt;&#x2F;h1&gt;
&lt;p&gt;All four of the above are theorem proving applications; that is, their purpose is to computer-formalize mathematics.
Broadly speaking, both Lean and Agda are dependent-types based systems, utilizing the Curry-Howard correspondence to prove theorems via a complex type system, whereas Isabelle&#x2F;HOL and HOL4 are LCF-style systems, with a small &quot;proof kernel&quot; containing base rules (e.g. &lt;code&gt;forall x, x = x&lt;&#x2F;code&gt;) that all proofs must be constructed via.
Both foundations have advantages and disadvantages, and some will be discussed.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;and-on-what&quot;&gt;And on what?&lt;&#x2F;h1&gt;
&lt;p&gt;I have formalized in all four a proof of the infinitude of primes; that is, the statement &quot;For any number n, there is a prime larger than n&quot;. The exact proof formalized is the &quot;usual&quot; construction by Euclid, which you can find on Wikipedia if you want; &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Euclid%27s_theorem&quot;&gt;see here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;All of the proofs structurally look similar (mostly, we&#x27;ll get to that), and hence it was the user experience that made the difference. For transparency, before this experiment, I was most familiar with Isabelle&#x2F;HOL and Agda, and to some extent learnt HOL4 and Lean as part of this review.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;comparison-time&quot;&gt;Comparison time!&lt;&#x2F;h1&gt;
&lt;p&gt;What follows is a bunch of opinions and somewhat arbitrary categories. Don&#x27;t expect an unbiased review, please. If you only want proof comparisons, skip to Proof Comparisons, and if you only want more opinions, read the below and then skip to Arbitrary Rankings. The opinions go first.&lt;&#x2F;p&gt;
&lt;p&gt;I do not claim any of the following proofs are perfect! They&#x27;re probably quite mediocre, really.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;overarching-similarities-differences&quot;&gt;Overarching similarities&#x2F;differences&lt;&#x2F;h2&gt;
&lt;p&gt;There are a few categories by which we can group these theorem provers. We have the above mentioned:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;LCF-style: Isabelle&#x2F;HOL, HOL4&lt;&#x2F;li&gt;
&lt;li&gt;Dependent-style: Lean, Agda&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;But there&#x27;s also:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;interactivity&quot;&gt;Interactivity&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;High-interactivity: Isabelle&#x2F;HOL, Lean&lt;&#x2F;li&gt;
&lt;li&gt;Low-interactivity: HOL4, Agda&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Reasoning: Both Isabelle&#x2F;HOL and Lean provide &quot;live updates&quot; as you type, and their structured proofs can be &quot;down-arrow&quot;&#x27;d through, to see intermediate steps. In contrast, both completed HOL4 and Agda proofs exist as fully-put-together terms that must be manually taken apart if you wish to inspect their internals. Both HOL4 and Agda can show you your current state and related information at any time, of course.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;automation&quot;&gt;Automation&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;High-automation: Isabelle&#x2F;HOL, HOL4&lt;&#x2F;li&gt;
&lt;li&gt;Medium-automation: Lean&lt;&#x2F;li&gt;
&lt;li&gt;Low-automation: Agda&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Isabelle&#x2F;HOL has &lt;code&gt;sledgehammer&lt;&#x2F;code&gt;, which calls out to a number of external proof generation methods (SAT&#x2F;SMT solvers, various FOL solvers, etc). For any goal that looks doable-but-annoying, there&#x27;s a solid chance &lt;code&gt;sledgehammer&lt;&#x2F;code&gt; can solve it - this is nice because it saves you work, but the proofs it generates are also indecipherable, which is perhaps less than ideal. There also exists an equivalent for HOL4 called HolyHammer, but I didn&#x27;t realize it existed until after I was writing this. Oh well. Isabelle&#x2F;HOL and HOL4 both have very good support for many automated simplification and proof methods, which come in quite handy when trying to work with complex assumptions, for example. It may not be obvious how to proceed without simplification kicking in to chunk everything down.&lt;&#x2F;p&gt;
&lt;p&gt;Lean has decent automation, but not to the same level as Isabelle&#x2F;HOL or HOL4. Its &lt;code&gt;simp&lt;&#x2F;code&gt; is not nearly as productive, and while &lt;code&gt;grind&lt;&#x2F;code&gt; is a very neat approach that can sometimes rival &lt;code&gt;sledgehammer&lt;&#x2F;code&gt;, a lot of the time it&#x27;s quite useless for reasons beyond me. Both &lt;code&gt;sledgehammer&lt;&#x2F;code&gt; and &lt;code&gt;grind&lt;&#x2F;code&gt; are all-or-nothing; if they don&#x27;t solve the goal, they make no progress. This is in contrast to &lt;code&gt;simp&lt;&#x2F;code&gt; (in all three), or more specialized tools like &lt;code&gt;auto&lt;&#x2F;code&gt; (Isabelle&#x2F;HOL) or &lt;code&gt;gvs&lt;&#x2F;code&gt; (HOL4), which can make some progress and then leave the context in (ideally) a better place. The fact Lean doesn&#x27;t have nearly as good partial-automation is a bit of a shame, because in my experience that&#x27;s what actually matters more. Notably, both Lean and Isabelle&#x2F;HOL have a &lt;code&gt;try&lt;&#x2F;code&gt; (In Isabelle&#x2F;HOL, &lt;code&gt;try&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;try0&lt;&#x2F;code&gt; for with&#x2F;without &lt;code&gt;sledgehammer&lt;&#x2F;code&gt;; in Lean, &lt;code&gt;try?&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;exact?&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;rw?&lt;&#x2F;code&gt;) that &quot;have a go&quot; at your goal with various automated methods and direct solve attempts. HOL4 doesn&#x27;t have an equivalent, as far as I can tell, which is unfortunate, as it&#x27;s quite handy.&lt;&#x2F;p&gt;
&lt;p&gt;Agda has essentially no automation. The only simplification you get is what can be computed based on inputs to functions. This, to be a bit frank, sort of sucks. It&#x27;s quite hard to get things done because there&#x27;s so much manual fiddling that must be taken into account. I am personally not a fan.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;foundations&quot;&gt;Foundations&lt;&#x2F;h3&gt;
&lt;p&gt;Isabelle&#x2F;HOL and HOL4 are both extremely classical in their foundations, which means that they accept the Law of Excluded Middle (∀ P. ¬P ∨ P), and both also axiomatize Hilbert&#x27;s epsilon, which leads also to the Axiom of Choice. This seems to have a very positive effect on automated solvers, which quite often rely on laws such as double-negation elimination (¬¬P --&amp;gt; P), which is equivalent to the LEM. Lean is theoretically constructive (and hence does not have the LEM by default), but some of the &quot;good&quot; proof automation requires the LEM, and it seems the norm to use Lean classically, so that&#x27;s what I did. &lt;code&gt;grind&lt;&#x2F;code&gt; for example just assumes you&#x27;re using it. This does have the disadvantage that Lean isn&#x27;t as good at dealing with e.g. existentials, for example.&lt;&#x2F;p&gt;
&lt;p&gt;Agda is constructive by default, and it seems the norm in the Agda world to keep your proofs that way, so I did. The big advantage of this is that after proving there are infinitely many primes, I can actually generate them! I can give my proof a number, and it&#x27;ll spit out a prime bigger than that number. The disadvantage is that it is &lt;em&gt;horribly&lt;&#x2F;em&gt; slow to do so:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;0: 2 (instant)&lt;&#x2F;li&gt;
&lt;li&gt;1: 3 (instant)&lt;&#x2F;li&gt;
&lt;li&gt;2: 7 (instant)&lt;&#x2F;li&gt;
&lt;li&gt;3: 5 (instant)&lt;&#x2F;li&gt;
&lt;li&gt;4: 11 (quarter second)&lt;&#x2F;li&gt;
&lt;li&gt;5: 7 (quarter second)&lt;&#x2F;li&gt;
&lt;li&gt;6: 71 (3s)&lt;&#x2F;li&gt;
&lt;li&gt;7: 61 (10s)&lt;&#x2F;li&gt;
&lt;li&gt;8: 19 (40s)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This may make sense if you looked at the proof structure above; we consider &lt;code&gt;(n + 1)! + 1&lt;&#x2F;code&gt;, so inside that proof, it&#x27;s checking primality at numbers around ~360,000; that&#x27;s going to be a bit slow. This construction, it should be noted, isn&#x27;t meant to be fast, but it&#x27;s also the most natural one. Is it worth giving up the LEM and good proof automation? You decide.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;dependent-types-as-a-foundation-vs-lcf&quot;&gt;Dependent types as a foundation vs LCF&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;m more a fan of LCF because it seems more amenable to automation, and I don&#x27;t see the point of carrying around proof terms (classical logic is too useful!). If you vehemently disagree, email me at contact AT blueberrywren.dev, and if I like your argument enough I&#x27;ll post it here.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;interaction-mode&quot;&gt;Interaction mode&lt;&#x2F;h3&gt;
&lt;p&gt;Both Lean and Isabelle&#x2F;HOL are interacted with interactively. Lean has modes for other editors, but high recommends the use of VSCode, and Isabelle&#x2F;HOL has its own editor (jEdit) that it also practically forces the use of. This is &lt;em&gt;fine&lt;&#x2F;em&gt;; I understand why they do this, as interactive development is reasonably hard to make generic. Both of them make it work.&lt;&#x2F;p&gt;
&lt;p&gt;HOL4 is interacted with via either an Emacs mode or a Vim mode, and keybinds that allow one to copy text in&#x2F;out of a running HOL4 REPL. This sounds weird because it is, but it works surprisingly well. I was already an Emacs user, so nothing really changed for me.&lt;&#x2F;p&gt;
&lt;p&gt;Agda is also interacted with via an Emacs mode, but everything happens in your file; you can use keybinds to refresh the state, add proof goals, etc. It also works fine.&lt;&#x2F;p&gt;
&lt;p&gt;As mentioned above, the advantage of the Lean&#x2F;Isabelle&#x2F;HOL approach is that one can see proofs in-progress, which you can&#x27;t with Agda.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;documentation&quot;&gt;Documentation&lt;&#x2F;h3&gt;
&lt;p&gt;Both Isabelle&#x2F;HOL and HOL4 have extremely good mechanisms for searching for theorems; an editor panel + &lt;code&gt;find_theorems&lt;&#x2F;code&gt; for the former, and &lt;code&gt;DB.find&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;DB.match&lt;&#x2F;code&gt; for the latter. These allow for the searching of theorems by both name and by patterns, so I could for example search for lemmas of form &lt;code&gt;_ &amp;lt; SUC _&lt;&#x2F;code&gt;. This is &lt;em&gt;so&lt;&#x2F;em&gt; handy! Very often you know the &lt;em&gt;shape&lt;&#x2F;em&gt; of something you want, but maybe not the lemma itself.&lt;&#x2F;p&gt;
&lt;p&gt;Lean has leansearch and loogle, which are interesting, but they:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Aren&#x27;t built in.&lt;&#x2F;li&gt;
&lt;li&gt;Aren&#x27;t as good.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Which kind of sucks. &lt;code&gt;exact?&lt;&#x2F;code&gt; and &lt;code&gt;rw?&lt;&#x2F;code&gt; exist as &quot;here&#x27;s stuff you might be able to do&quot;, but they&#x27;re nowhere near as flexible.&lt;&#x2F;p&gt;
&lt;p&gt;Agda, as expected perhaps, does not have an equivalent. One must become a master of &lt;del&gt;zen&lt;&#x2F;del&gt; looking through the right parts of the Agda standard library.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;proof-comparisons&quot;&gt;Proof Comparisons&lt;&#x2F;h1&gt;
&lt;p&gt;Note: This isn&#x27;t really meant to be a tutorial for any of these, though I will do a little explaining at the start. It&#x27;s mostly for the reader to compare them, and see what ~equivalent statement proofs look like in different languages.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s get into the proofs! We&#x27;ll go segment by segment, exploring sections of the proof and explaining as we go. Before that, some vaguely interesting stats:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Isabelle&#x2F;HOL: 117 LOC, with 19 proofs.&lt;&#x2F;li&gt;
&lt;li&gt;Lean: 155 LOC, with 12 proofs.&lt;&#x2F;li&gt;
&lt;li&gt;HOL4: 190 LOC, with 16 proofs.&lt;&#x2F;li&gt;
&lt;li&gt;Agda: 264 LOC, with 45 proofs (29, not counting &lt;code&gt;where&lt;&#x2F;code&gt; blocks)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These are nowhere near apples-to-apples, but they&#x27;re still fun.&lt;&#x2F;p&gt;
&lt;p&gt;We start with defining divisibility. In Agda we cheat and use the standard library version, so we can get proofs around computing divisors, which I didn&#x27;t feel like redoing.&lt;&#x2F;p&gt;
&lt;p&gt;Isabelle&#x2F;HOL:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;definition divides :: &amp;quot;nat ⇒ nat ⇒ bool&amp;quot; where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;quot;divides n k = (∃j. j * n = k)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Lean:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@[grind]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;def divides (n k : Nat) : Prop :=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ∃q, k = n * q&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;HOL4:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Definition divides_def:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  divides n k = ∃q. q * n = k&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;End&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Agda (looks like, in the standard library):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;record _∣_ (m n : ℕ) : Set where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  constructor divides&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  field quotient : ℕ&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        equality : n ≡ quotient * m&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So, basically the same. Then there&#x27;s a few lemmas around divisibility proved (&lt;code&gt;divides k 0&lt;&#x2F;code&gt;, &lt;code&gt;divides k k&lt;&#x2F;code&gt;, etc). One we&#x27;ll show off is &lt;code&gt;divides n k ==&amp;gt; divides n j ==&amp;gt; divides n (k - j)&lt;&#x2F;code&gt;, as it&#x27;s mildly interesting in some of the theorem provers. In all of the following, the mult&#x2F;sub lemma essentially states &lt;code&gt;a * (b - c) = a * b - a * c&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Isabelle&#x2F;HOL:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma divides_diff: &amp;quot;divides x k ⟹ divides x n ⟹ divides x (k - n)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  using divides_def by (metis diff_mult_distrib)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The proof search procedure &lt;code&gt;metis&lt;&#x2F;code&gt; does most of the work.&lt;&#x2F;p&gt;
&lt;p&gt;Lean:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theorem divides_sub (n j k : Nat) (h1 : divides n k) (h2 : divides n j)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  : divides n (k - j) := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  obtain ⟨q1, h1⟩ := h1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  obtain ⟨q2, h2⟩ := h2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  unfold divides&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  exists (q1 - q2)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  grind [Nat.mul_sub]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We do some unpacking, then identify &lt;code&gt;q1 - q2&lt;&#x2F;code&gt; as the other term (such that &lt;code&gt;n * (q1 - q2) = k - j&lt;&#x2F;code&gt;). Then grind with the appropriate lemma gets us there.&lt;&#x2F;p&gt;
&lt;p&gt;HOL4:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Theorem divides_sub:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  divides n k ⇒ divides n j ⇒ divides n (k - j)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Proof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  rpt strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; metis_tac[RIGHT_SUB_DISTRIB, divides_def]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Like Isabelle&#x2F;HOL, when supplied with the appropriate lemmas, &lt;code&gt;metis_tac&lt;&#x2F;code&gt; takes it out.&lt;&#x2F;p&gt;
&lt;p&gt;Agda:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;divides-sub : ∀ {i j k} → i ∣ j → i ∣ k → i ∣ (j ∸ k)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;divides-sub {i} (divides-refl q₁) (divides-refl q₂) = divides (q₁ ∸ q₂) (sym (*-distribʳ-∸ i q₁ q₂))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Very similar. &lt;code&gt;divides-refl&lt;&#x2F;code&gt; is an abbreviation for &lt;code&gt;divides _ refl&lt;&#x2F;code&gt;, and like in Lean, we must manually point out &lt;code&gt;q₁ ∸ q₂&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;It was interesting to me that the Lean proof was, to some extent, such a pain. I had to put more effort into that one than any of the others, despite Lean having reasonably decent automation! Finding the appropriate lemmas was mildly more painful, and this was while I was still puzzling over syntax, to be fair.&lt;&#x2F;p&gt;
&lt;p&gt;We next need to define the product of a list of numbers, which looks like the following:&lt;&#x2F;p&gt;
&lt;p&gt;Isabelle&#x2F;HOL:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;fun prod_list :: &amp;quot;nat list ⇒ nat&amp;quot; where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;prod_list [] = 1&amp;quot; | &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;prod_list (x # xs) = x * prod_list xs&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Lean:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@[simp, grind]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;def prod_list (xs : List Nat) : Nat :=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  match xs with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | [] =&amp;gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | x :: xs =&amp;gt; x * prod_list xs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;simp&lt;&#x2F;code&gt; and &lt;code&gt;grind&lt;&#x2F;code&gt; markers were meant to help the automated proof methods out, and they did!&lt;&#x2F;p&gt;
&lt;p&gt;HOL4:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Definition prod_list_def:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (prod_list [] = 1) ∧&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (prod_list (x :: xs) = x * prod_list xs)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;End&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Agda:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list : List Nat → Nat&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list [] = 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list (x ∷ xs) = x * prod-list xs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Defining things in HOL4 is a little interesting, because you&#x27;re just defining the body as a proof! That definition spits out a theorem &lt;code&gt;prod_list_def&lt;&#x2F;code&gt; that is literally&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;val it = ⊢ prod_list [] = 1 ∧ ∀x xs. prod_list (x::xs) = x * prod_list xs: thm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;Here in the Agda proof we also do a bunch of work to set up what will become a decision procedure for primality. This is because later we wish to ask &quot;Is this prime?&quot;, and without the LEM to say &quot;It must either be prime or not prime&quot;, we need to write an algorithm to decide this for us.&lt;&#x2F;p&gt;
&lt;p&gt;Back on track, we need to show a few lemmas around with prod list function. One of the interesting ones is as follows, where we prove that a number in said list will divide the product of the list.&lt;&#x2F;p&gt;
&lt;p&gt;Isabelle&#x2F;HOL:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma divides_prod_list: &amp;quot;x ∈ set xs ⟹ divides x (prod_list xs)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (induct xs)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply simp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply auto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply (case_tac xs; simp add: divides_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (case_tac xs; simp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (rule mult_divide_l)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by assumption&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Very implicit; it&#x27;s hard to tell what&#x27;s going on, but the basic structure is there. Induct on the list, do some casing, apply a lemma about &lt;code&gt;divides _ (_ * _)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Lean:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theorem divides_prod_list : ∀ xs x, x ∈ xs -&amp;gt; divides x (prod_list xs) := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  intros xs x mem&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  induction xs with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | nil =&amp;gt; grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | cons y ys ih =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    by_cases h : (x = y)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    · rw [h]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      simp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      exists (prod_list ys)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    · cases mem with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      | head =&amp;gt; grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      | tail =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        rename_i a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        have ⟨h, hq⟩ := ih a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        simp at *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        rw [hq]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        exists (y * h)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Reasonably large. We have to destructure the membership quite manually, which gets a little troublesome. It&#x27;s a fairly straightforward proof, though.&lt;&#x2F;p&gt;
&lt;p&gt;HOL4:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Theorem divides_prod_list:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  x ∈ set xs ⇒ divides x (prod_list xs)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Proof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Induct_on ‘xs’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;- fs[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;- (fs[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; rpt strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;- (fs[prod_list_def, divides_def]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;gt;&amp;gt; qexists_tac ‘prod_list xs’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;gt;&amp;gt; simp[])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;- (fs[divides_def, prod_list_def]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;gt;&amp;gt; qexists_tac ‘h * q’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;gt;&amp;gt; rev_drule EQ_SYM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;gt;&amp;gt; strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;gt;&amp;gt; fs[]))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Also not crazy, although it&#x27;s hard to see the exact structure without comments (which I didn&#x27;t write :P). This is a good time to point out HOL4 proofs are literally just SML terms! There&#x27;s nothing more to it! The combinators &lt;code&gt;&amp;gt;&amp;gt;&lt;&#x2F;code&gt; and &lt;code&gt;&amp;gt;-&lt;&#x2F;code&gt; (for apply latter to all subgoals of former, and to one subgoal of former resp.) are just infix functions composing other functions! It&#x27;s all just SML! You interact with HOL4 through a REPL, so you construct stuff dynamically, but then you have to puzzle piece your function together afterwards. Once you know that, it&#x27;s more obvious what&#x27;s going on; we induct, handle the first case, then simplification on &lt;code&gt;MEM x (h ∷ xs)&lt;&#x2F;code&gt; give us two goals (&lt;code&gt;x = h&lt;&#x2F;code&gt; and &lt;code&gt;x ≠ h, MEM x xs&lt;&#x2F;code&gt; resp.)&lt;&#x2F;p&gt;
&lt;p&gt;Agda:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list-divides : ∀ xs x → x ∈ xs → x ∣ prod-list xs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list-divides [] x ()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list-divides (y ∷ xs) x (here refl) = divides (prod-list xs) (*-comm y (prod-list xs))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list-divides (y ∷ xs) x (there p) with prod-list-divides xs x p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | divides q eq rewrite eq = divides (y * q) (sym (*-assoc y q x))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Very explicit, but also quite concise. Matching on the list membership is quite intuitive, because the Agda mode in Emacs includes a command &lt;code&gt;C-c C-c&lt;&#x2F;code&gt; to automatically case split on basically everything.&lt;&#x2F;p&gt;
&lt;p&gt;While it&#x27;s much more implicit in Isabelle&#x2F;HOL and HOL4 (a common theme), all four of these proofs take the form of asking whether the value we care about is at the head of the list, or somewhere later on, and that decides what we fill in divisibility with.&lt;&#x2F;p&gt;
&lt;p&gt;Then, Primality!&lt;&#x2F;p&gt;
&lt;p&gt;Isabelle&#x2F;HOL:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;definition prime :: &amp;quot;nat ⇒ bool&amp;quot; where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;quot;prime p = ((p &amp;gt; 1) ∧ (∀x. divides x p ⟶ x = p ∨ x = 1))&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Lean:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@[simp, grind]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;def prime (n : Nat) : Prop :=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (n &amp;gt; 1) ∧ (∀k, divides k n -&amp;gt; k = 1 ∨ k = n)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;HOL4:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Definition prime_def:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  prime n = ((1 &amp;lt; n) ∧ (∀k. divides k n ⇒ k = 1 ∨ k = n))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;End&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Agda:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;record Prime (n : Nat) : Set where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  constructor isprime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  field&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    gt1 : n &amp;gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    div : ∀ k → k ∣ n → k ≡ 1 ⊎ k ≡ n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In Agda we also define what it means to be composite as a &quot;positive&quot; definition, instead of just &quot;not prime&quot;; this makes working with it quite a bit easier.&lt;&#x2F;p&gt;
&lt;p&gt;The next &quot;interesting&quot; proof is proving that every not-prime number greater than one has a prime factor. In Agda this is part of the definition of being composite, so we don&#x27;t bother including it. We&#x27;re going to move slightly faster from now on, so I won&#x27;t explain each snippet. Just compare yourselves.&lt;&#x2F;p&gt;
&lt;p&gt;Isabelle&#x2F;HOL:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma prime_factor: &amp;quot;¬(prime k) ⟹ k &amp;gt; 1 ⟹ ∃p. prime p ∧ divides p k&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (induct k rule: measure_induct[of &amp;quot;id&amp;quot;]; simp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (rotate_tac 1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (subst (asm) prime_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply clarsimp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (case_tac &amp;quot;prime xa&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply blast&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (erule_tac x=xa in allE)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (* found with sledgehammer *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (metis divides_gt divides_trans less_Suc0 not_less_iff_gr_or_eq zero_not_divides)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Lean:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theorem prime_factor : ∀k, ¬(prime k) -&amp;gt; 1 &amp;lt; k -&amp;gt; ∃p, prime p ∧ divides p k := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  intros k nprime kgt1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  induction k using Nat.strongRecOn with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | ind k&amp;#39; ih =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    simp at nprime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    obtain ⟨x,⟨xd,dvds⟩,xn1,xnk⟩ := nprime kgt1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    clear nprime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    by_cases h : prime x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    · exists x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    · have lt : x &amp;lt; k&amp;#39; := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        apply Nat.lt_of_le_of_ne&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        · apply divides_less &amp;lt;;&amp;gt; grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        · assumption&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      have gt : 1 &amp;lt; x := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        cases x &amp;lt;;&amp;gt; grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      obtain ⟨p,⟨prm,dvds⟩⟩ := ih x lt h gt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      exists p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      refine ⟨prm, ?_⟩&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      apply divides_trans&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      · assumption&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      · grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;HOL4:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Theorem prime_factor:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ∀k. ¬(prime k) ⇒ 1 &amp;lt; k ⇒ ∃p. prime p ∧ divides p k&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Proof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  completeInduct_on ‘k’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; rpt strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; qpat_x_assum ‘¬_’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  (fn h =&amp;gt; assume_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                          (REWRITE_RULE [prime_def] h))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; gvs[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; Cases_on ‘prime k&amp;#39;’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;- (qexists ‘k&amp;#39;’ &amp;gt;&amp;gt; simp[])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;- (first_x_assum $ qspecl_then [‘k&amp;#39;’] mp_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; ‘0 &amp;lt; k&amp;#39;’ by metis_tac[divides_gt1_gt0]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; ‘1 &amp;lt; k&amp;#39;’ by decide_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; ‘k&amp;#39; &amp;lt;= k’ by gvs[divides_less]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; ‘k&amp;#39; &amp;lt; k’ by decide_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; first_x_assum drule&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; gvs[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; qexists ‘p’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; metis_tac[divides_trans])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The steps of &lt;code&gt;0 &amp;lt; k&#x27;&lt;&#x2F;code&gt; ~&amp;gt; &lt;code&gt;1 &amp;lt; k&#x27;&lt;&#x2F;code&gt; and &lt;code&gt;k&#x27; &amp;lt;= k&lt;&#x2F;code&gt; ~&amp;gt; &lt;code&gt;k&#x27; &amp;lt; k&lt;&#x2F;code&gt; in the HOL4 one annoyed me a lot, but I couldn&#x27;t figure out how to golf them down. Similarly, this line:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    obtain ⟨x,⟨xd,dvds⟩,xn1,xnk⟩ := nprime kgt1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;of the Lean proof causes me pain.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;re almost there now! Two more steps to go: Prove there&#x27;s always a prime outside a given set (list) of numbers, and use that to show the final statement. First, the former:&lt;&#x2F;p&gt;
&lt;p&gt;Isabelle&#x2F;HOL:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma another_prime: &amp;quot;(∀x∈set xs. x &amp;gt; 1) ⟹ ∃p. prime p ∧ p ∉ set xs&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (case_tac &amp;quot;prime (Suc (prod_list xs))&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  using prod_list_lt apply fastforce&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (frule prime_factor)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply clarsimp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (case_tac &amp;quot;length xs = 0&amp;quot;; clarsimp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply (rule prod_list_gt_zero; clarsimp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  using prime_gt_one apply fastforce&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  using divides_prod_list divides_diff prime_gt_one one_divides&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (metis One_nat_def Suc_diff_Suc cancel_comm_monoid_add_class.diff_cancel lessI nat_less_le)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Lean:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theorem another_prime (xs : List Nat) (xsgt : ∀x, x ∈ xs -&amp;gt; 1 &amp;lt; x)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  : ∃p, prime p ∧ p ∉ xs := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by_cases h : prime (Nat.succ (prod_list xs))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  · exists (Nat.succ (prod_list xs))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    refine ⟨h, ?a⟩&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    by_contra&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    have lt : Nat.succ (prod_list xs) ≤ prod_list xs := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      apply prod_list_lt &amp;lt;;&amp;gt; grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  · have ⟨pf, isprm, dvds⟩ : ∃p, prime p ∧ divides p (Nat.succ (prod_list xs)) := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      apply prime_factor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      · exact h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      · grind [prod_list_nz]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    by_cases g : pf ∈ xs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    · have pfdvds : divides pf (prod_list xs) := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        apply divides_prod_list &amp;lt;;&amp;gt; grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      have divone : divides pf ((Nat.succ (prod_list xs)) - prod_list xs) := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        apply divides_sub &amp;lt;;&amp;gt; grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      have also : divides pf 1 := by grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      grind [divides_not_one]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    · grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;HOL4:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Theorem another_prime:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ∀(xs : num list). (∀x. x ∈ set xs ⇒ 1 &amp;lt; x)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    ⇒ ∃p. prime p ∧ p ∉ set xs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Proof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  rpt strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; Cases_on ‘prime (SUC (prod_list xs))’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;- (qexists ‘SUC (prod_list xs)’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; metis_tac[LESS_REFL, OR_LESS, prod_list_lt, gt1_gt0_weaken])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;- (drule prime_factor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; impl_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;- metis_tac[ONE, LESS_MONO, prod_list_nz,gt1_gt0_weaken]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;- (strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;gt;&amp;gt; Cases_on ‘MEM p xs’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;gt;- (‘divides p (prod_list xs)’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                by metis_tac[divides_prod_list]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              &amp;gt;&amp;gt; ‘divides p ((SUC (prod_list xs)) - prod_list xs)’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                by metis_tac [divides_sub]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              &amp;gt;&amp;gt; gvs[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              &amp;gt;&amp;gt; metis_tac[prime_one, prime_zero, divides_not_one])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;gt;- (qexists ‘p’ &amp;gt;&amp;gt; metis_tac[])))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Agda:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prime-not-in : ∀ xs → (∀ x → x ∈ xs → x &amp;gt; 0) → Σ _ λ k → k ∉ xs × Prime k&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prime-not-in xs gt with 2 ≤? prod-list xs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | no ¬a = 2 , lemma , two-prime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lemma : 2 ∈ xs → ⊥&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lemma pf with prod-list-lt xs gt 2 pf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ... | also = ¬a also&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | yes a with prime-or-composite (suc (prod-list xs)) (s≤s (≤-trans (s≤s z≤n) a))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | inj₁ x = suc (prod-list xs) , lemma , x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lemma : (suc (prod-list xs)) ∈ xs → ⊥&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lemma pf with prod-list-lt xs gt (suc (prod-list xs)) pf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ... | also = 1+n≰n also&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | inj₂ (composite p Pp p&amp;lt;n p∣) with p ∈? xs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | no ¬b = p , ¬b , Pp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | yes b with prod-list-divides xs p b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | divs with divides-sub p∣ divs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | sothen = ⊥-elim (lemma {p} {prod-list xs} sothen λ{ refl → one-prime Pp })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    suc-sub : ∀ i → suc i ∸ i ≡ 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    suc-sub zero = refl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    suc-sub (suc i) = suc-sub i&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lemma : ∀ {i j} → i ∣ (suc j ∸ j) → i ≢ 1 → ⊥&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lemma {_} {j} div neq rewrite suc-sub j = divides-not-one div neq&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The Agda proof differs slightly to accommodate the lack of ranges later.&lt;&#x2F;p&gt;
&lt;p&gt;The Isabelle&#x2F;HOL proof clearly wins in terms of length here, but it&#x27;s also really unclear what&#x27;s going on. Everyone else gets progressively more verbose, and the HOL4 proof in particular here is a bit nastily nested. &lt;code&gt;metis_tac[]&lt;&#x2F;code&gt; (a first-order solver) does a lot of heavy lifting, as does &lt;code&gt;grind&lt;&#x2F;code&gt;. If you&#x27;re wondering why both Isabelle&#x2F;HOL and HOL4 have something named &lt;code&gt;metis&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;metis_tac&lt;&#x2F;code&gt;, it&#x27;s because it was ported to Isabelle&#x2F;HOL from HOL4.&lt;&#x2F;p&gt;
&lt;p&gt;We arrive at our final statement! Agda requires some more fiddling as it doesn&#x27;t have ranges built in like the other two do, but we use our lemma above to construct the list &lt;code&gt;[2..n]&lt;&#x2F;code&gt;, and then show there&#x27;s a prime outside that (and that it hence must be above &lt;code&gt;n&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;Isabelle&#x2F;HOL:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma infinite_primes: &amp;quot;∃p. prime p ∧ p &amp;gt; n&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (insert another_prime[where xs=&amp;quot;[2 ..&amp;lt; Suc n]&amp;quot;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (case_tac &amp;quot;n ≤ 1&amp;quot;; clarsimp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply (rule_tac x=2 in exI)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply simp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (rule_tac x=p in exI)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply simp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  using prime_gt_one by force&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Lean:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theorem infinite_primes : ∀ n, ∃p, prime p ∧ p &amp;gt; n := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  intros n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by_cases h : ¬(1 &amp;lt; n)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  · exists 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    grind [prime_two]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  · simp at h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    obtain ⟨p, prm, notin⟩ := another_prime (List.range&amp;#39; 2 n) (by grind)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    refine ⟨p, prm, ?notin⟩&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;HOL4:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Theorem infinite_primes:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ∀n. ∃p. prime p ∧ p &amp;gt; n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Proof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; Cases_on ‘n &amp;lt; 1’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;- (qexists ‘2’ &amp;gt;&amp;gt; simp[prime_two])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;- (qspec_then ‘listRangeINC 2 n’ assume_tac another_prime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; ‘∀x. MEM x [2 .. n] ⇒ 1 &amp;lt; x’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        by (rpt strip_tac &amp;gt;&amp;gt; gvs[MEM_listRangeINC])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; first_x_assum rev_drule&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; rpt strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; qexists ‘p’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; gvs[MEM_listRangeINC, prime_gt_one]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; ‘p ≠ 0’ by metis_tac[prime_zero]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; ‘p ≠ 1’ by metis_tac[prime_one]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; decide_tac)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It annoys me I couldn&#x27;t get this smaller, but oh well.&lt;&#x2F;p&gt;
&lt;p&gt;Agda:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;infinite-primes : ∀ i → Σ _ λ p → p &amp;gt; i × Prime p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;infinite-primes zero = 2 , s≤s z≤n , two-prime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;infinite-primes (suc i) with prime-not-in (list-up-to (2+ i)) (list-up-to-nz (2+ i))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | p , notin , Pp = p , DNE (2+ i ≤? p) lemma , Pp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    notzero : p ≢ 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    notzero = prime-not-zero p Pp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    implies : ∀ {a b} → (suc a ≤ b → ⊥) → (a ≡ b) ⊎ (a &amp;gt; b)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    implies {a} {b} x with compare a b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ... | less .a k = ⊥-elim (x (s≤s (m≤m+n a k)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ... | equal .a = inj₁ refl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ... | greater .b k = inj₂ (s≤s (m≤m+n b k))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lemma : ((2+ i ≤ p) → ⊥) → ⊥&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lemma x with implies x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ... | inj₁ refl = notin (there (here refl))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ... | inj₂ (s≤s a) = notin (list-up-to-contains (2+ i) p (≤-trans a (≤-trans (n≤1+n i) (n≤1+n (suc i)))) (prime-not-zero p Pp))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We&#x27;ve done it! Euclid would be proud. (probably)&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s now time for more opinions!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;arbitrary-rankings&quot;&gt;Arbitrary Rankings&lt;&#x2F;h1&gt;
&lt;p&gt;I have five criteria I&#x27;ll be ranking on:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Ease of proof &lt;em&gt;discovery&lt;&#x2F;em&gt; (how easy is it to figure out what I want to do)&lt;&#x2F;li&gt;
&lt;li&gt;Ease of proof &lt;em&gt;manipulation&lt;&#x2F;em&gt; (how easy is it to do what I want)&lt;&#x2F;li&gt;
&lt;li&gt;Enjoyment (how much fun did I have)&lt;&#x2F;li&gt;
&lt;li&gt;Annoyance factor (how often was I going &quot;ugh!&quot;)&lt;&#x2F;li&gt;
&lt;li&gt;Puzzled factor (how often did I go &quot;why can&#x27;t you solve this??&quot;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;ease-of-proof-discovery-higher-better&quot;&gt;Ease of proof discovery (higher better)&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Isabelle&#x2F;HOL&lt;&#x2F;li&gt;
&lt;li&gt;HOL4&lt;&#x2F;li&gt;
&lt;li&gt;Lean&lt;&#x2F;li&gt;
&lt;li&gt;Agda&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Not much to comment on here, really. &lt;code&gt;sledgehammer&lt;&#x2F;code&gt; is a great boon, and both Isabelle&#x2F;HOL and HOL4&#x27;s theorem discovery tools are great. Lean was reasonably close behind, with &lt;code&gt;try?&lt;&#x2F;code&gt; often giving good related lemmas as a solve, and Agda was clearly last. Paging through &lt;code&gt;.agda&lt;&#x2F;code&gt; files online to find lemmas is annoying.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ease-of-proof-manipulation-higher-better&quot;&gt;Ease of proof manipulation (higher better)&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Agda&lt;&#x2F;li&gt;
&lt;li&gt;Lean&lt;&#x2F;li&gt;
&lt;li&gt;HOL4&lt;&#x2F;li&gt;
&lt;li&gt;Isabelle&#x2F;HOL&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Love it or hate it, Agda being entirely raw proof terms means things are essentially exactly what you tell them to be. There&#x27;s never a moment where you&#x27;re going &quot;Damn, why won&#x27;t the simplifier just expand this but not that!&quot;. Lean is pretty good here, as it&#x27;s quite conservative around what it chooses to manipulate and everything is explicitly named. HOL4 has a pretty reasonable learning curve as one learns to use things like &lt;code&gt;qpat_assum&lt;&#x2F;code&gt; that can target based on patterns (e.g. &lt;code&gt;¬_&lt;&#x2F;code&gt;), but once you figure it out it&#x27;s not bad. Isabelle&#x2F;HOL really isn&#x27;t stunning here; it&#x27;s often hard to get it to do &lt;em&gt;exactly&lt;&#x2F;em&gt; what you want.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;enjoyment-higher-better&quot;&gt;Enjoyment (higher better)&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;HOL4&lt;&#x2F;li&gt;
&lt;li&gt;Lean&lt;&#x2F;li&gt;
&lt;li&gt;Isabelle&#x2F;HOL&lt;&#x2F;li&gt;
&lt;li&gt;Agda&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;I had a great time learning both HOL4 and Lean, but HOL4 edges out because it&#x27;s such a unique interaction mode and it&#x27;s still very powerful. Lean was fun, although annoying at some times, and Isabelle&#x2F;HOL wasn&#x27;t particularly interesting, but some of that is because i&#x27;m familiar with it. Agda sort of sucked at times; writing a whole primality decision procedure and fiddling with type nonsense got quite annoying after a while.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;annoyance-factor-lower-better&quot;&gt;Annoyance factor (lower better)&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Agda&lt;&#x2F;li&gt;
&lt;li&gt;HOL4 &#x2F; Lean (tied second)&lt;&#x2F;li&gt;
&lt;li&gt;Isabelle&#x2F;HOL&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Agda &quot;wins&quot; for the same reasons as above. Having to do really manual proof search and fiddling constantly wasn&#x27;t super pleasant. HOL4 and Lean both had their own annoyances and I think it&#x27;s unfair to rank one over the other; the learning curve on assumption manipulation &#x2F; sim was quite significant in HOL4 and Lean&#x27;s automated tools were finicky enough it quite sucked at times. Isabelle&#x2F;HOL i&#x27;m just used to, so there&#x27;s some bias there.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;puzzled-factor-lower-better&quot;&gt;Puzzled factor (lower better)&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;HOL4&lt;&#x2F;li&gt;
&lt;li&gt;Lean&lt;&#x2F;li&gt;
&lt;li&gt;Isabelle&#x2F;HOL&lt;&#x2F;li&gt;
&lt;li&gt;Agda&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Same reasons as above; there were a lot of times where HOL4 just had me going &quot;huh????&quot; because some theorem-tactic wasn&#x27;t doing what I expected it to, or was transforming the goal in an unpredictable way. Lean had similar, where it would just randomly decide &quot;erm actually i&#x27;m not going to solve this really simple goal for you with &lt;code&gt;grind&lt;&#x2F;code&gt; do it yourself please&quot; in ways that left me baffled. Seriously, sometimes &lt;code&gt;grind&lt;&#x2F;code&gt; is smarter than &lt;code&gt;sledgehammer&lt;&#x2F;code&gt; and sometimes it&#x27;s stupider than &lt;code&gt;simp&lt;&#x2F;code&gt;. Weird. Isabelle&#x2F;HOL had some of the same but was generally fine, and Agda was utterly predictable.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;overall-best-in-class&quot;&gt;Overall best in class&lt;&#x2F;h1&gt;
&lt;p&gt;HOL4! I had a great time learning it, it&#x27;s a seriously interesting system. I didn&#x27;t &lt;em&gt;not&lt;&#x2F;em&gt; enjoy Lean, but there&#x27;s enough odd stuff going on to make me slightly wary of it, I suppose. Isabelle&#x2F;HOL remains the one I&#x27;m best at (I am somewhat paid to write it, so that helps), and Agda is Agda.&lt;&#x2F;p&gt;
&lt;p&gt;What should you try? Well, all of them, but I would at least try out something new. If you&#x27;ve only used dependent theorem provers before, try Isabelle&#x2F;HOL or HOL4, and vice versa. If you&#x27;ve only used theorem provers that work fully interactively like Lean, try HOL4 or Agda! New experiences are the joys of life.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;all-the-code&quot;&gt;All the code&lt;&#x2F;h1&gt;
&lt;p&gt;Enjoy.&lt;&#x2F;p&gt;
&lt;details&gt;
&lt;summary&gt;Unfold for everything.&lt;&#x2F;summary&gt;
&lt;p&gt;Isabelle&#x2F;HOL:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theory primes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  imports Main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;begin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;definition divides :: &amp;quot;nat ⇒ nat ⇒ bool&amp;quot; where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;quot;divides n k = (∃j. j * n = k)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma zero_not_divides: &amp;quot;k ≠ 0 ⟹ ¬(divides 0 k)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (simp add: divides_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma one_divides: &amp;quot;divides k 1 ⟹ k = 1&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (simp add: divides_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma divide_mult_l: &amp;quot;divides x k ⟹ divides x (n * k)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  using divides_def by auto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma divides_diff: &amp;quot;divides x k ⟹ divides x n ⟹ divides x (k - n)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  using divides_def by (metis diff_mult_distrib)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma divides_gt: &amp;quot;k ≠ 0 ⟹ n &amp;gt; k ⟹ ¬(divides n k)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (clarsimp simp add: divides_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma divides_less: &amp;quot;k ≠ 0 ⟹ divides n k ⟹ n ≤ k&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (clarsimp simp add: divides_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma divides_trans: &amp;quot;divides n k ⟹ divides k j ⟹ divides n j&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  using divides_def by force&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;fun prod_list :: &amp;quot;nat list ⇒ nat&amp;quot; where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;prod_list [] = 1&amp;quot; | &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;prod_list (x # xs) = x * prod_list xs&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma prod_list_gt_zero: &amp;quot;(∀x∈set xs. x ≠ 0) ⟹ length xs &amp;gt; 0 ⟹ prod_list xs &amp;gt; 0&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (induct xs)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply simp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (case_tac xs; clarsimp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma prod_list_lt: &amp;quot;(∀x∈set xs. x &amp;gt; 0) ⟹ ∀x∈set xs. x ≤ prod_list xs&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (induct xs)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply simp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply auto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  using prod_list_gt_zero apply fastforce&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (erule_tac x=x in ballE)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  using mult_eq_if apply auto[1]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by blast&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma divides_prod_list: &amp;quot;x ∈ set xs ⟹ divides x (prod_list xs)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (induct xs)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply simp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply auto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply (case_tac xs; simp add: divides_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (case_tac xs; simp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (rule divide_mult_l)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by assumption&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;definition prime :: &amp;quot;nat ⇒ bool&amp;quot; where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;quot;prime p = ((p &amp;gt; 1) ∧ (∀x. divides x p ⟶ x = p ∨ x = 1))&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma prime_zero[simp]: &amp;quot;¬(prime 0)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (clarsimp simp add: prime_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma prime_one[simp]: &amp;quot;¬(prime 1)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (clarsimp simp add: prime_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma prime_two[simp]: &amp;quot;prime 2&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (clarsimp simp add: prime_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (case_tac x; clarsimp simp add: divides_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (case_tac nat; clarsimp simp add: divides_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (case_tac j; simp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma prime_gt_one: &amp;quot;prime p ⟹ p &amp;gt; 1&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  using prime_def by simp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma notprime_split: &amp;quot;¬(prime k) ⟹ k &amp;gt; 1 ⟹ ∃n j. n &amp;lt; k ∧ j &amp;lt; k ∧ k = n * j&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (clarsimp simp add: prime_def divides_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (rule_tac x=x in exI)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (rule conjI)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply (metis less_Suc0 linorder_neqE_nat mult_is_0 n_less_m_mult_n)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (rule_tac x=j in exI)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply auto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (metis bot_nat_0.not_eq_extremum mult_zero_left not_less_zero)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma prime_not_divides_one: &amp;quot;prime p ⟹ ¬(divides p 1)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (clarsimp simp add: prime_def divides_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma prime_factor: &amp;quot;¬(prime k) ⟹ k &amp;gt; 1 ⟹ ∃p. prime p ∧ divides p k&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (induct k rule: measure_induct[of &amp;quot;id&amp;quot;]; simp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (rotate_tac 1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (subst (asm) prime_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply clarsimp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (case_tac &amp;quot;prime xa&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply blast&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (erule_tac x=xa in allE)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (metis divides_gt divides_trans less_Suc0 not_less_iff_gr_or_eq zero_not_divides)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma another_prime: &amp;quot;(∀x∈set xs. x &amp;gt; 1) ⟹ ∃p. prime p ∧ p ∉ set xs&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (case_tac &amp;quot;prime (Suc (prod_list xs))&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  using prod_list_lt apply fastforce&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (frule prime_factor)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply clarsimp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (case_tac &amp;quot;length xs = 0&amp;quot;; clarsimp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply (rule prod_list_gt_zero; clarsimp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  using prime_gt_one apply fastforce&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  using divides_prod_list divides_diff prime_gt_one one_divides&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (metis One_nat_def Suc_diff_Suc cancel_comm_monoid_add_class.diff_cancel lessI nat_less_le)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma infinite_primes: &amp;quot;∃p. prime p ∧ p &amp;gt; n&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (insert another_prime[where xs=&amp;quot;[2 ..&amp;lt; Suc n]&amp;quot;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (case_tac &amp;quot;n ≤ 1&amp;quot;; clarsimp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply (rule_tac x=2 in exI)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply simp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (rule_tac x=p in exI)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply simp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  using prime_gt_one by force&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Lean:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import Primes.Basic&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import Mathlib.Tactic.ByContra&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set_option linter.style.setOption false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set_option linter.flexible false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set_option linter.style.whitespace false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@[grind]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;def divides (n k : Nat) : Prop :=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ∃q, k = n * q&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theorem divides_one (n : Nat) : divides n 1 -&amp;gt; n = 1 := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  intro ⟨q, hq⟩&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  cases n &amp;lt;;&amp;gt; cases q &amp;lt;;&amp;gt; grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theorem divides_not_one (n : Nat) (d : divides n 1) (neq : n ≠ 1) : False := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  grind [divides_one]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theorem divides_sub (n j k : Nat) (h1 : divides n k) (h2 : divides n j)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  : divides n (k - j) := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  obtain ⟨q1, h1⟩ := h1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  obtain ⟨q2, h2⟩ := h2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  unfold divides&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  exists (q1 - q2)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  grind [Nat.mul_sub]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theorem divides_less (n k : Nat) : k ≠ 0 -&amp;gt; divides n k -&amp;gt; n ≤ k := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  intro knz div&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  simp at *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  obtain ⟨q,hq⟩ := div&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  cases q &amp;lt;;&amp;gt; grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theorem divides_trans (n k j) : divides n k -&amp;gt; divides k j -&amp;gt; divides n j := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  intro ⟨a,b⟩ ⟨c,d⟩&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  simp [divides] at *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  exists (a * c)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@[simp, grind]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;def prod_list (xs : List Nat) : Nat :=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  match xs with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | [] =&amp;gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | x :: xs =&amp;gt; x * prod_list xs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theorem divides_prod_list : ∀ xs x, x ∈ xs -&amp;gt; divides x (prod_list xs) := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  intros xs x mem&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  induction xs with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | nil =&amp;gt; grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | cons y ys ih =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    by_cases h : (x = y)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    · rw [h]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      simp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      exists (prod_list ys)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    · cases mem with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      | head =&amp;gt; grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      | tail =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        rename_i a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        have ⟨h, hq⟩ := ih a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        simp at *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        rw [hq]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        exists (y * h)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theorem prod_list_nz : ∀ xs, (∀ x ∈ xs, x &amp;gt; 0) -&amp;gt; prod_list xs &amp;gt; 0 := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  intros xs f&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  induction xs with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | nil =&amp;gt; grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | cons x xs ih =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    obtain b : prod_list xs &amp;gt; 0 := ih (by grind)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    simp [*]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theorem prod_list_lt : ∀ xs, (∀ x ∈ xs, x &amp;gt; 0) -&amp;gt; ∀ y ∈ xs, y &amp;lt;= prod_list xs := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  intro xs f y yin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  induction xs with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | nil =&amp;gt; grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | cons yp ys ih =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cases yin with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    | head =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      obtain a : prod_list ys &amp;gt; 0 := by grind [prod_list_nz]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      exact Nat.le_mul_of_pos_right y a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    | tail _ a =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      obtain a : y &amp;lt;= prod_list ys := ih (by grind) a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      obtain b : yp &amp;gt; 0 := f yp (by grind)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      apply Nat.le_trans&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      · exact a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      · exact Nat.le_mul_of_pos_left (prod_list ys) b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@[simp, grind]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;def prime (n : Nat) : Prop :=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (n &amp;gt; 1) ∧ (∀k, divides k n -&amp;gt; k = 1 ∨ k = n)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theorem prime_two : prime 2 := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  simp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  intros k x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  simp [divides] at x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  have ⟨q,hq⟩ := x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (cases q &amp;lt;;&amp;gt; cases k &amp;lt;;&amp;gt; grind)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theorem prime_factor : ∀k, ¬(prime k) -&amp;gt; 1 &amp;lt; k -&amp;gt; ∃p, prime p ∧ divides p k := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  intros k nprime kgt1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  induction k using Nat.strongRecOn with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | ind k&amp;#39; ih =&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    simp at nprime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    obtain ⟨x,⟨xd,dvds⟩,xn1,xnk⟩ := nprime kgt1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    clear nprime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    by_cases h : prime x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    · exists x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    · have lt : x &amp;lt; k&amp;#39; := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        apply Nat.lt_of_le_of_ne&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        · apply divides_less &amp;lt;;&amp;gt; grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        · assumption&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      have gt : 1 &amp;lt; x := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        cases x &amp;lt;;&amp;gt; grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      obtain ⟨p,⟨prm,dvds⟩⟩ := ih x lt h gt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      exists p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      refine ⟨prm, ?_⟩&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      apply divides_trans&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      · assumption&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      · grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theorem another_prime (xs : List Nat) (xsgt : ∀x, x ∈ xs -&amp;gt; 1 &amp;lt; x)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  : ∃p, prime p ∧ p ∉ xs := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by_cases h : prime (Nat.succ (prod_list xs))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  · exists (Nat.succ (prod_list xs))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    refine ⟨h, ?a⟩&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    by_contra&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    have lt : Nat.succ (prod_list xs) ≤ prod_list xs := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      apply prod_list_lt &amp;lt;;&amp;gt; grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  · have ⟨pf, isprm, dvds⟩ : ∃p, prime p ∧ divides p (Nat.succ (prod_list xs)) := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      apply prime_factor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      · exact h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      · grind [prod_list_nz]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    by_cases g : pf ∈ xs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    · have pfdvds : divides pf (prod_list xs) := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        apply divides_prod_list &amp;lt;;&amp;gt; grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      have divone : divides pf ((Nat.succ (prod_list xs)) - prod_list xs) := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        apply divides_sub &amp;lt;;&amp;gt; grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      have also : divides pf 1 := by grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      grind [divides_not_one]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    · grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theorem infinite_primes : ∀ n, ∃p, prime p ∧ p &amp;gt; n := by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  intros n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by_cases h : ¬(1 &amp;lt; n)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  · exists 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    grind [prime_two]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  · simp at h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    obtain ⟨p, prm, notin⟩ := another_prime (List.range&amp;#39; 2 n) (by grind)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    refine ⟨p, prm, ?notin⟩&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    grind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;HOL4:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open arithmeticTheory listTheory prim_recTheory listRangeTheory;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Definition divides_def:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  divides n k = ∃q. q * n = k&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;End&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Theorem divides_not_one:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ∀n. divides n 1 ⇒ n ≠ 1 ⇒ F&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Proof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  simp[divides_def]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Theorem divides_less:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  k ≠ 0 ⇒ divides n k ⇒ n ≤ k&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Proof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  rpt strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; gvs[divides_def]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Theorem divides_trans:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  divides a b ⇒ divides b c ⇒ divides a c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Proof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  rpt strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; gvs[divides_def]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; qexists ‘q * q&amp;#39;’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; gvs[MULT_ASSOC_COMM]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Theorem divides_sub:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  divides n k ⇒ divides n j ⇒ divides n (k - j)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Proof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  rpt strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; metis_tac[RIGHT_SUB_DISTRIB, divides_def]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Definition prod_list_def:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (prod_list [] = 1) ∧&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (prod_list (x :: xs) = x * prod_list xs)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;End&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Theorem divides_prod_list:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  x ∈ set xs ⇒ divides x (prod_list xs)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Proof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Induct_on ‘xs’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;- fs[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;- (fs[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; rpt strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;- (fs[prod_list_def, divides_def]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;gt;&amp;gt; qexists_tac ‘prod_list xs’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;gt;&amp;gt; simp[])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;- (fs[divides_def, prod_list_def]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;gt;&amp;gt; qexists_tac ‘h * q’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;gt;&amp;gt; rev_drule EQ_SYM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;gt;&amp;gt; strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;gt;&amp;gt; fs[]))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QED      &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Theorem prod_list_nz:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ∀xs. (∀x. x ∈ set xs ⇒ 0 &amp;lt; x) ⇒ 0 &amp;lt; prod_list xs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Proof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  rpt strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; Induct_on ‘xs’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; fs[prod_list_def]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Theorem prod_list_lt:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ∀xs. (∀x. x ∈ set xs ⇒ 0 &amp;lt; x) ⇒ ∀y. y ∈ set xs ⇒ y ≤ prod_list xs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Proof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  rpt strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; Induct_on ‘xs’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; gvs[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; rpt strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; gvs[prod_list_def]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; metis_tac[prod_list_nz, LE_MULT_CANCEL_LBARE, LE_TRANS]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Definition prime_def:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  prime n = ((1 &amp;lt; n) ∧ (∀k. divides k n ⇒ k = 1 ∨ k = n))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;End&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Theorem prime_zero:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ¬(prime 0)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Proof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  fs[prime_def]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QED        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Theorem prime_one:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ¬(prime 1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Proof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  fs[prime_def]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Theorem prime_gt_one[simp]:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  prime n ⇒ 1 &amp;lt; n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Proof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  fs[prime_def]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Theorem prime_two:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  prime 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Proof        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  fs[prime_def]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; rpt strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; fs[divides_def]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; (Cases_on ‘k’ &amp;gt;&amp;gt; Cases_on ‘q’ &amp;gt;&amp;gt; fs[MULT_SUC])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Theorem divides_gt1_gt0:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ∀n k. divides n k ⇒ 1 &amp;lt; k ⇒ 0 &amp;lt; n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Proof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  rpt strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; gvs[divides_def]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; (Cases_on ‘q’ &amp;gt;&amp;gt; gvs[MULT_SUC])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; (Cases_on ‘n’ &amp;gt;&amp;gt; gvs[])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Theorem prime_factor:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ∀k. ¬(prime k) ⇒ 1 &amp;lt; k ⇒ ∃p. prime p ∧ divides p k&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Proof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  completeInduct_on ‘k’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; rpt strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; qpat_x_assum ‘¬_’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  (fn h =&amp;gt; assume_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                          (REWRITE_RULE [prime_def] h))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; gvs[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; Cases_on ‘prime k&amp;#39;’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;- (qexists ‘k&amp;#39;’ &amp;gt;&amp;gt; simp[])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;- (first_x_assum $ qspecl_then [‘k&amp;#39;’] mp_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; ‘0 &amp;lt; k&amp;#39;’ by metis_tac[divides_gt1_gt0]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; ‘1 &amp;lt; k&amp;#39;’ by decide_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; ‘k&amp;#39; &amp;lt;= k’ by gvs[divides_less]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; ‘k&amp;#39; &amp;lt; k’ by decide_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; first_x_assum drule&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; gvs[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; qexists ‘p’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; metis_tac[divides_trans])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Theorem gt1_gt0_weaken:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ∀x. 1 &amp;lt; x ⇒ 0 &amp;lt; x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Proof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  strip_tac &amp;gt;&amp;gt; decide_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Theorem another_prime:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ∀(xs : num list). (∀x. x ∈ set xs ⇒ 1 &amp;lt; x)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    ⇒ ∃p. prime p ∧ p ∉ set xs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Proof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  rpt strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; Cases_on ‘prime (SUC (prod_list xs))’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;- (qexists ‘SUC (prod_list xs)’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; metis_tac[LESS_REFL, OR_LESS,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                   prod_list_lt, gt1_gt0_weaken])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;- (drule prime_factor   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; impl_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;- metis_tac[ONE, LESS_MONO, prod_list_nz,gt1_gt0_weaken]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;- (strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;gt;&amp;gt; Cases_on ‘MEM p xs’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;gt;- (‘divides p (prod_list xs)’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                by metis_tac[divides_prod_list]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              &amp;gt;&amp;gt; ‘divides p ((SUC (prod_list xs)) - prod_list xs)’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                by metis_tac [divides_sub]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              &amp;gt;&amp;gt; gvs[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              &amp;gt;&amp;gt; metis_tac[prime_one, prime_zero, divides_not_one])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;gt;- (qexists ‘p’ &amp;gt;&amp;gt; metis_tac[])))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Theorem infinite_primes:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ∀n. ∃p. prime p ∧ p &amp;gt; n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Proof&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;&amp;gt; Cases_on ‘n &amp;lt; 1’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;- (qexists ‘2’ &amp;gt;&amp;gt; simp[prime_two])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;gt;- (qspec_then ‘listRangeINC 2 n’ assume_tac another_prime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; ‘∀x. MEM x [2 .. n] ⇒ 1 &amp;lt; x’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        by (rpt strip_tac &amp;gt;&amp;gt; gvs[MEM_listRangeINC])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; first_x_assum rev_drule&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; rpt strip_tac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; qexists ‘p’&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; gvs[MEM_listRangeINC, prime_gt_one]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; ‘p ≠ 0’ by metis_tac[prime_zero]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; ‘p ≠ 1’ by metis_tac[prime_one]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;gt;&amp;gt; decide_tac)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Agda:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open import Data.Nat renaming (ℕ to Nat)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open import Data.Nat.Properties&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open import Relation.Binary.PropositionalEquality&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open import Data.Product&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open import Data.Empty&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open import Relation.Nullary.Negation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open import Data.List&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open import Data.Sum&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open import Relation.Nullary.Decidable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open import Relation.Binary&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open import Relation.Nullary.Reflects&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open import Data.Nat.Divisibility&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open import Data.Bool using (Bool; true; false)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open import Data.Fin using (zero; suc; Fin; toℕ; fromℕ; fromℕ&amp;lt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open import Data.Fin.Properties using (toℕ-fromℕ; toℕ-fromℕ&amp;lt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open import Induction.WellFounded&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open import Data.Nat.Induction using (&amp;lt;-wellFounded; &amp;lt;-rec)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import Data.List.Membership.DecPropositional as DecPropMembership&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open DecPropMembership Data.Nat._≟_&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open import Data.List.Relation.Unary.Any using (here; there)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-- The prime decision procedure was with assistance from https:&#x2F;&#x2F;gist.github.com&#x2F;copumpkin&#x2F;1286093&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;div-goes-into : ∀ i k → k ≢ 0 → i ∣ k → i ≤ k&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;div-goes-into i k neq (divides zero eq) = ⊥-elim (neq eq)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;div-goes-into zero k neq (divides (suc q) eq) = z≤n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;div-goes-into (suc i) k neq (divides-refl (suc q)) = s≤s (m≤m+n i (q * suc i))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;divides-zero : ∀ i → 0 ∣ i → i ≡ 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;divides-zero zero (divides q eq) = refl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;divides-zero (suc i) (divides q eq) rewrite *-comm q 0 = eq&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;divides-trans : ∀ {i j k} → i ∣ j → j ∣ k → i ∣ k&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;divides-trans {i} (divides-refl q₁) (divides q₂ eq₂) = divides (q₂ * q₁) (trans eq₂ (sym (*-assoc q₂ q₁ i)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;divides-sub : ∀ {i j k} → i ∣ j → i ∣ k → i ∣ (j ∸ k)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;divides-sub {i} (divides-refl q₁) (divides-refl q₂) = divides (q₁ ∸ q₂) (sym (*-distribʳ-∸ i q₁ q₂))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;divides-one : ∀ i → i ∣ 1 → i ≡ 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;divides-one zero (divides (suc q) eq) rewrite *-comm q 0 = ⊥-elim (1+n≢0 eq)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;divides-one (suc zero) (divides (suc q) eq) = refl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;divides-not-one : ∀ {i} → i ∣ 1 → i ≢ 1 → ⊥&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;divides-not-one {zero} (divides q eq) neq rewrite *-comm q 0 = 1+n≢0 eq&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;divides-not-one {suc zero} (divides q eq) neq = neq refl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;divides-not-one {2+ i} (divides zero eq) neq = 1+n≢0 eq&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;divides-not-one {2+ i} (divides (suc q) eq) neq = 1+n≢0 (sym (suc-injective eq))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lt-left-suc : ∀ i j → i ≤ j → i ≢ j → suc i ≤ j&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lt-left-suc zero zero z≤n p = ⊥-elim (p refl)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lt-left-suc zero (suc j) z≤n p = s≤s z≤n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lt-left-suc (suc i) zero () p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lt-left-suc (suc i) (suc j) (s≤s x) p = s≤s (lt-left-suc i j x λ q → p (cong suc q))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;not : {A : Set} → Dec A → Dec (¬ A)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;not (yes p) = no (λ z → z p)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;not (no ¬p) = yes ¬p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;DNE : {A : Set} → Dec A → ¬ ¬ A → A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;DNE (yes p) f = p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;DNE (no ¬p) f = ⊥-elim (f ¬p)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Decide : {A : Set} (P : A → Set) → Set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Decide P = ∀ i → Dec (P i)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lt-lower : ∀ {i j} → suc i ≤ suc j → i ≢ j → suc i ≤ j&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lt-lower {zero} {zero} (s≤s p) q = ⊥-elim (q refl)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lt-lower {zero} {suc j} (s≤s p) q = s≤s z≤n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lt-lower {suc i} {suc j} (s≤s p) q = s≤s (lt-lower p λ x → q (cong suc x))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lt-decide : ∀ i → (P : Nat → Set) (p? : ∀ n → n &amp;lt; i → Dec (P n)) → (∀ n → n &amp;lt; i → P n) ⊎ (Σ _ λ j → j &amp;lt; i × ¬ (P j))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lt-decide zero P p? = inj₁ λ _ ()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lt-decide (suc i) P p? with lt-decide i P h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    h : (n : Nat) → n &amp;lt; i → Dec (P n)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    h n lt = p? n (s≤s (&amp;lt;⇒≤ lt))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | inj₂ (a , b , c) = inj₂ (a , s≤s (≤-trans (n≤1+n a) b) , c)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | inj₁ x with p? i ≤-refl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | no ¬a = inj₂ (i , ≤-refl , ¬a)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | yes a = inj₁ h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    h : (n : Nat) → suc n ≤ suc i → P n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    h n lt with n ≟ i&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ... | yes refl = a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ... | no ¬a = x n (lt-lower lt ¬a)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;¬lt-decide : ∀ i → (P : Nat → Set) (p? : ∀ n → n &amp;lt; i → Dec (P n)) → (∀ n → n &amp;lt; i → ¬ P n) ⊎ (Σ _ λ j → j &amp;lt; i × (P j))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;¬lt-decide i P p? with lt-decide i (λ x → ¬ (P x)) (λ n x → not (p? n x))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | inj₁ x = inj₁ x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | inj₂ (a , b , c) = inj₂ (a , b , DNE (p? a b) c)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;record Prime (n : Nat) : Set where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  constructor isprime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  field&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    gt1 : n &amp;gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    div : ∀ k → k ∣ n → k ≡ 1 ⊎ k ≡ n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;open Prime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;zero-prime : ¬ (Prime 0)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;zero-prime ()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prime-not-zero : ∀ p → Prime p → p ≢ 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prime-not-zero p x refl = zero-prime x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;one-prime : ¬ (Prime 1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;one-prime (isprime (s≤s ()) div)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;two-prime : Prime 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;two-prime .gt1 = s≤s (s≤s z≤n)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;two-prime .div zero (divides (suc q) eq) rewrite *-comm q 0 = ⊥-elim (1+n≢0 eq)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;two-prime .div (suc zero) (divides (suc q) eq) = inj₁ refl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;two-prime .div (2+ zero) (divides (suc q) eq) = inj₂ refl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;record Composite (n : Nat) : Set where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  constructor composite&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  field&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    p : Nat&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Pp : Prime p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    p&amp;lt;n : p &amp;lt; n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    p∣ : p ∣ n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;not-prime-and-composite : ∀ p → Prime p → Composite p → ⊥&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;not-prime-and-composite _ (isprime gt2 div₁) (composite p (isprime gt3 div₂) p&amp;lt;n p∣) with div₁ p p∣&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | inj₁ refl = one-prime (isprime gt3 div₂)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | inj₂ refl = 1+n≰n p&amp;lt;n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prime-or-composite : ∀ p → p &amp;gt; 1 → Prime p ⊎ Composite p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prime-or-composite (suc zero) (s≤s ())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prime-or-composite (2+ p) lt = &amp;lt;-rec _ h p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    h : (x : Nat) →&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         ({y : Nat} → suc y ≤ x → Prime (2+ y) ⊎ Composite (2+ y)) →&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         Prime (2+ x) ⊎ Composite (2+ x)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    h x f with ¬lt-decide x (λ k → (2+ k) ∣ (2+ x)) (λ n nlt → 2+ n ∣? 2+ x)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ... | inj₂ (ev₁ , ev₂ , ev₃) with f ev₂&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    h x f | inj₂ (ev₁ , ev₂ , ev₃) | inj₁ prm = inj₂ (composite (2+ ev₁) prm (s≤s (s≤s ev₂)) ev₃)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    h x f | inj₂ (ev₁ , ev₂ , ev₃) | inj₂ (composite p Pp (s≤s p&amp;lt;n) p∣) =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        inj₂ (composite p Pp (s≤s (≤-trans p&amp;lt;n (≤-trans ev₂ (n≤1+n x)))) (divides-trans p∣ ev₃))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    h x f | inj₁ eq = inj₁ (isprime (s≤s (s≤s z≤n)) lemma)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        lemma : (k : Nat) → k ∣ 2+ x → k ≡ 1 ⊎ k ≡ 2+ x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        lemma k dv with k ≟ 1 | k ≟ (2+ x)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ... | no ¬a | yes refl = inj₂ refl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ... | yes refl | no ¬b = inj₁ refl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ... | yes refl | yes ()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        lemma zero dv | no ¬a | no ¬b rewrite divides-zero (2+ x) dv = inj₂ refl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        lemma (suc zero) dv | no ¬a | no ¬b = inj₁ refl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        lemma (2+ k) dv | no ¬a | no ¬b with suc k ≤? x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ... | yes k≤x = ⊥-elim (eq k k≤x dv)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        ... | no ¬k≤x = ⊥-elim (¬k≤x sothen)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            one : 2+ k ≤ 2+ x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            one = div-goes-into (2+ k) (2+ x) 1+n≢0 dv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            two : k ≤ x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            two with one&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            ... | s≤s (s≤s a) = a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            also : k ≢ x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            also x = ¬b (cong suc (cong suc x))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            sothen : suc k ≤ x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            sothen = lt-left-suc k x two also&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list : List Nat → Nat&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list [] = 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list (x ∷ xs) = x * prod-list xs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list-nz : ∀ xs → (∀ x → x ∈ xs → x &amp;gt; 0) → prod-list xs &amp;gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list-nz [] f = s≤s z≤n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list-nz (x ∷ []) f rewrite *-comm x 1 rewrite +-comm x 0 = f x (here refl)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list-nz (x ∷ x₁ ∷ xs) f = h {x} (f x (here refl)) (prod-list-nz (x₁ ∷ xs) (λ x₂ z → f x₂ (there z)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    h : ∀ {i j} → 1 ≤ i → 1 ≤ j → 1 ≤ i * j&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    h {suc i} {suc j} (s≤s a) (s≤s b) = s≤s z≤n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list-NZ : ∀ xs → (∀ x → x ∈ xs → x &amp;gt; 0) → NonZero (prod-list xs)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list-NZ xs f = &amp;gt;-nonZero (prod-list-nz xs f)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list-lt : ∀ xs → (∀ x → x ∈ xs → x &amp;gt; 0) → ∀ y → y ∈ xs → y ≤ prod-list xs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list-lt [] f y ()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list-lt (x ∷ xs) f y (here refl) = m≤m*n x (prod-list xs) ⦃ prod-list-NZ xs λ x₂ z → f x₂ (there z) ⦄&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list-lt (x ∷ xs) f y (there py) = also (prod-list-lt xs (λ x₂ z → f x₂ (there z)) y py) (f x (here refl))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lt+ : ∀ {i j k} → i ≤ j → i ≤ j + k&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lt+ z≤n = z≤n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lt+ (s≤s x) = s≤s (lt+ x)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    also : ∀ {i j k} → i ≤ k → 1 ≤ j → i ≤ j * k&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    also a (s≤s z≤n) = lt+ a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list-divides : ∀ xs x → x ∈ xs → x ∣ prod-list xs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list-divides [] x ()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list-divides (y ∷ xs) x (here refl) = divides (prod-list xs) (*-comm y (prod-list xs))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prod-list-divides (y ∷ xs) x (there p) with prod-list-divides xs x p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | divides q eq rewrite eq = divides (y * q) (sym (*-assoc y q x))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prime-not-in : ∀ xs → (∀ x → x ∈ xs → x &amp;gt; 0) → Σ _ λ k → k ∉ xs × Prime k&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prime-not-in xs gt with 2 ≤? prod-list xs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | no ¬a = 2 , lemma , two-prime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lemma : 2 ∈ xs → ⊥&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lemma pf with prod-list-lt xs gt 2 pf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ... | also = ¬a also&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | yes a with prime-or-composite (suc (prod-list xs)) (s≤s (≤-trans (s≤s z≤n) a))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | inj₁ x = suc (prod-list xs) , lemma , x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lemma : (suc (prod-list xs)) ∈ xs → ⊥&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lemma pf with prod-list-lt xs gt (suc (prod-list xs)) pf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ... | also = 1+n≰n also&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | inj₂ (composite p Pp p&amp;lt;n p∣) with p ∈? xs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | no ¬b = p , ¬b , Pp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | yes b with prod-list-divides xs p b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | divs with divides-sub p∣ divs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | sothen = ⊥-elim (lemma {p} {prod-list xs} sothen λ{ refl → one-prime Pp })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    suc-sub : ∀ i → suc i ∸ i ≡ 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    suc-sub zero = refl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    suc-sub (suc i) = suc-sub i&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lemma : ∀ {i j} → i ∣ (suc j ∸ j) → i ≢ 1 → ⊥&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lemma {_} {j} div neq rewrite suc-sub j = divides-not-one div neq&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;list-up-to : Nat → List Nat&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;list-up-to 0 = 1 ∷ []&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;list-up-to (suc n) = suc n ∷ list-up-to n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;list-up-to-nz : ∀ k x → x ∈ list-up-to k → x &amp;gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;list-up-to-nz zero x (here refl) = s≤s z≤n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;list-up-to-nz (suc k) x (here refl) = s≤s z≤n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;list-up-to-nz (suc k) x (there p) = list-up-to-nz k x p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;list-up-to-contains : ∀ i j → j ≤ i → j ≢ 0 → j ∈ list-up-to i&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;list-up-to-contains zero zero z≤n b = ⊥-elim (b refl)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;list-up-to-contains zero (suc j) () b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;list-up-to-contains (suc i) zero z≤n b = ⊥-elim (b refl)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;list-up-to-contains (suc i) (suc j) (s≤s a) b with suc i ≟ suc j&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | no ¬c = there (list-up-to-contains i (suc j) (lt-left-suc j i a λ x → ¬c (cong suc (sym x))) b)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | yes refl = here refl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;infinite-primes : ∀ i → Σ _ λ p → p &amp;gt; i × Prime p&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;infinite-primes zero = 2 , s≤s z≤n , two-prime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;infinite-primes (suc i) with prime-not-in (list-up-to (2+ i)) (list-up-to-nz (2+ i))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... | p , notin , Pp = p , DNE (2+ i ≤? p) lemma , Pp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    notzero : p ≢ 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    notzero = prime-not-zero p Pp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    implies : ∀ {a b} → (suc a ≤ b → ⊥) → (a ≡ b) ⊎ (a &amp;gt; b)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    implies {a} {b} x with compare a b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ... | less .a k = ⊥-elim (x (s≤s (m≤m+n a k)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ... | equal .a = inj₁ refl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ... | greater .b k = inj₂ (s≤s (m≤m+n b k))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lemma : ((2+ i ≤ p) → ⊥) → ⊥&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lemma x with implies x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ... | inj₁ refl = notin (there (here refl))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ... | inj₂ (s≤s a) = notin (list-up-to-contains (2+ i) p (≤-trans a (≤-trans (n≤1+n i) (n≤1+n (suc i)))) (prime-not-zero p Pp))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;details&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Verifying (simple) C in Isabelle&#x2F;HOL with AutoCorres</title>
        <published>2026-08-28T00:00:00+00:00</published>
        <updated>2026-08-28T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/isabelle-autocorres-tut/"/>
        <id>https://blueberrywren.dev/blog/isabelle-autocorres-tut/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/isabelle-autocorres-tut/">&lt;h1 id=&quot;verifying-simple-c-in-isabelle-hol-with-autocorres&quot;&gt;Verifying (simple) C in Isabelle&#x2F;HOL with AutoCorres&lt;&#x2F;h1&gt;
&lt;p&gt;This post details the first steps of verifying a C function in Isabelle&#x2F;HOL using AutoCorres. It&#x27;ll go over the basic setup for Isabelle and AutoCorres, what AutoCorres gives you, and how we can verify some basic properties of a function (here, the sum of a list.) I use the latest versions of Isabelle and AutoCorres available at time of writing (24&#x2F;08&#x2F;26).&lt;&#x2F;p&gt;
&lt;h1 id=&quot;caveats&quot;&gt;Caveats&lt;&#x2F;h1&gt;
&lt;p&gt;This is &lt;em&gt;not&lt;&#x2F;em&gt; official documentation for AutoCorres, nor may it be 100% correct in all places. All the proofs go through, but I do not work on AutoCorres, nor have I used it professionally; most of my experience is hobby verification. However, I have found resources on it are woefully lacking, so I wished to introduce some more. Much of this information has been gleaned from the official documentation (which can be found &lt;a href=&quot;https:&#x2F;&#x2F;trustworthy.systems&#x2F;projects&#x2F;OLD&#x2F;autocorres&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;,) and &lt;a href=&quot;https:&#x2F;&#x2F;cgi.cse.unsw.edu.au&#x2F;~cs4161&#x2F;&quot;&gt;this UNSW course&lt;&#x2F;a&gt;. When it runs, the slides&#x2F;similar may be removed for some time - they exist on the internet archive also.&lt;&#x2F;p&gt;
&lt;p&gt;Any errors in the prose or code of the following are my own.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;assumed-knowledge&quot;&gt;Assumed knowledge&lt;&#x2F;h1&gt;
&lt;p&gt;This article assumes a little either Isabelle&#x2F;HOL or general verification knowledge, but I try to explain wherever feasible. A bit of C knowledge is required as well, and so is a little knowledge about program verification - a little Hoare logic, and the like. I&#x27;ll try to explain as much as I can without being excessively verbose, and much of it is very searchable. Let&#x27;s get into it!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;installing-isabelle&quot;&gt;Installing Isabelle&lt;&#x2F;h1&gt;
&lt;p&gt;You can find Isabelle &lt;a href=&quot;https:&#x2F;&#x2F;isabelle.in.tum.de&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;. Install as is appropriate for your platform. You can decide whether to put &lt;code&gt;isabelle&lt;&#x2F;code&gt; in your path or not.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;installing-autocorres&quot;&gt;Installing AutoCorres&lt;&#x2F;h1&gt;
&lt;p&gt;First, pick a directory for your project. It may be feasible to use AutoCorres globally, but I wouldn&#x27;t recommend it for versioning reasons. Then, AutoCorres can be found by scrolling down &lt;a href=&quot;https:&#x2F;&#x2F;trustworthy.systems&#x2F;projects&#x2F;OLD&#x2F;autocorres&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;. (It will probably take you &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;seL4&#x2F;l4v&#x2F;releases&quot;&gt;here&lt;&#x2F;a&gt;, whereupon you should scroll down to the latest AutoCorres release). You only need the AutoCorres download, as it bundles the C parser. Take that file, and extract it in your directory of choice.&lt;&#x2F;p&gt;
&lt;p&gt;Then we need to build AutoCorres. From the directory where you unpacked it, run&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; L4V_ARCH=X64&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;path-to-isabell&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; build&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; -v -b -o&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; document=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;false -d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; autocorres-1.12 AutoCorres&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This&#x27;ll take a second.&lt;&#x2F;p&gt;
&lt;p&gt;Replace paths as appropriate. Note that &lt;code&gt;L4V_ARCH&lt;&#x2F;code&gt; is &lt;em&gt;not&lt;&#x2F;em&gt; the architecture you are on - it determines how the tool translates various C sizes into Isabelle. This will need to be the same architecture you launch with later. There are some others, and on a related note:&lt;&#x2F;p&gt;
&lt;h1 id=&quot;look-at-the-autocorres-readme&quot;&gt;Look at the AutoCorres README!&lt;&#x2F;h1&gt;
&lt;p&gt;It may not all make sense yet, but it may answer some questions.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;launching-isabelle-with-autocorres&quot;&gt;Launching Isabelle with AutoCorres&lt;&#x2F;h1&gt;
&lt;p&gt;I recommend making a little shell script for this step (&lt;code&gt;launch.sh&lt;&#x2F;code&gt; perhaps.) You&#x27;ll need to invoke Isabelle in a manner similar to the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;#!&#x2F;bin&#x2F;sh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;L4V_ARCH&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;X64&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; &#x2F;Applications&#x2F;Isabelle2025.app&#x2F;bin&#x2F;isabelle&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; jedit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; -d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; autocorres-1.12&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; -l&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; AutoCorres my_theory.thy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Remember that &lt;code&gt;L4V_ARCH&lt;&#x2F;code&gt; needs to be the same as earlier.&lt;&#x2F;p&gt;
&lt;p&gt;Now that we have Isabelle running, we can use AutoCorres to generate Isabelle versions of C files. The manner in which this is performed is long, complex, and interesting - I recommend a rabbit hole evening - but in short, the C parser first translates it to a deep embedding in a language called Simpl, and then AutoCorres takes this Simpl representation and turns it into a monadic shallow embedding best it can.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;some-c-to-verify&quot;&gt;Some C to verify&lt;&#x2F;h1&gt;
&lt;p&gt;Here&#x27;s what we&#x27;ll be verifying today:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;unsigned int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; list_sum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;unsigned int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;list&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; unsigned int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; length&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    unsigned int&lt;&#x2F;span&gt;&lt;span&gt; sum &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;unsigned int&lt;&#x2F;span&gt;&lt;span&gt; i &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;; i &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; length; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        sum &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;+=&lt;&#x2F;span&gt;&lt;span&gt; list[i];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; sum;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The following will be expanded on shortly:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The use of unsigned&lt;&#x2F;li&gt;
&lt;li&gt;What it means to verify code&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We&#x27;ll put it in a C file named &lt;code&gt;list_sum.c&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;verifying-it&quot;&gt;Verifying it&lt;&#x2F;h1&gt;
&lt;p&gt;At this point, your directory should look something like&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;autocorres-1.12&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;my_theory.thy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;list_sum.c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;launch.sh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;or similar.&lt;&#x2F;p&gt;
&lt;p&gt;Begin a regular Isabelle theory, importing AutoCorres (and whatever else you want):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theory my_theory&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  imports Main &amp;quot;AutoCorres.AutoCorres&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;begin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We then need to let AutoCorres perform its magic. First, we &quot;install&quot; the C file with the C parser:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;external_file &amp;quot;list_sum.c&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;install_C_file &amp;quot;list_sum.c&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can use &lt;code&gt;print_theorems&lt;&#x2F;code&gt; to see what this defines. Of particular interest is &lt;code&gt;list_sum_body_def&lt;&#x2F;code&gt;. Then, AutoCorres:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;autocorres [skip_word_abs] &amp;quot;list_sum.c&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;tangent-what-s-going-on&quot;&gt;Tangent: What&#x27;s going on?&lt;&#x2F;h2&gt;
&lt;p&gt;The idea the C parser and AutoCorres use for verifying C is that it is reasonable to do a very direct translation of C to Simpl, and then a &lt;em&gt;refinement&lt;&#x2F;em&gt; to the monadic representation. The C parser is correct through inspection, and extensive testing. However, the translation of Simpl to the monadic form is verified - there exist Isabelle-checkable proofs that show that the monadic representation, however different it may be, behaves identically to the Simpl equivalent. This makes the monadic form a refinement of Simpl, and is why the things we prove about the monadic forms translate back down to C.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;back-to-autocorres&quot;&gt;Back to AutoCorres&lt;&#x2F;h2&gt;
&lt;p&gt;This might also take a second.&lt;&#x2F;p&gt;
&lt;p&gt;We choose to use &lt;code&gt;skip_word_abs&lt;&#x2F;code&gt;, skipping the &quot;word abstraction&quot; that can turn integers into Isabelle &lt;code&gt;nat&lt;&#x2F;code&gt;s. This makes unsigned integers perform modular arithmetic instead of using overflow checks; this has positives and negatives. Read the README for more, but perhaps you can guess why this is advantageous in our case? (Hint: is &lt;code&gt;sum&lt;&#x2F;code&gt; overflowing allowed?)&lt;&#x2F;p&gt;
&lt;p&gt;Again, you can use &lt;code&gt;print_theorems&lt;&#x2F;code&gt; to see what this gives you. Of particular interest is &lt;code&gt;list_sum&#x27;_def&lt;&#x2F;code&gt;. This is the monadic embedding of our function.&lt;&#x2F;p&gt;
&lt;p&gt;We then need to enter the locale (think of it as an environment) defined by the C parser and AutoCorres, so your file should look something like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theory my_theory&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  imports Main &amp;quot;AutoCorres.AutoCorres&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;begin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;external_file &amp;quot;list_sum.c&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;install_C_file &amp;quot;list_sum.c&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;autocorres [skip_word_abs] &amp;quot;list_sum.c&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;context list_sum begin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;(* See below. *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;thm list_sum_body_def&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;thm list_sum&amp;#39;_def&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;term heap_w32&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;term heap_w32_update&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We do our work in this locale. If you haven&#x27;t already, &lt;code&gt;term list_sum_body&lt;&#x2F;code&gt; and &lt;code&gt;term list_sum&#x27;&lt;&#x2F;code&gt;. The former is the deep embedding produced by the C parser, and the latter is the result of AutoCorres&#x27;s shallow embedding. These can be unfolded with &lt;code&gt;list_sum_body_def&lt;&#x2F;code&gt; and &lt;code&gt;list_sum&#x27;_def&lt;&#x2F;code&gt; respectively. You can examine the types of things with ctrl-hover (cmd-hover on Macs.)&lt;&#x2F;p&gt;
&lt;p&gt;Also examine &lt;code&gt;term heap_w32&lt;&#x2F;code&gt;. The type for the monadic state used by AutoCorres is called &lt;code&gt;lifted_globals&lt;&#x2F;code&gt; (You may see it displayed as &lt;code&gt;&#x27;a lifted_globals_scheme&lt;&#x2F;code&gt; in some places.) It&#x27;s a record containing fields for each type of pointer used; ours only uses &lt;code&gt;unsigned int *&lt;&#x2F;code&gt;, so it only contains information for 32 bit words. We can examine the extract and update functions used in &lt;code&gt;list_sum&#x27;_def&lt;&#x2F;code&gt; with &lt;code&gt;term heap_w32&lt;&#x2F;code&gt; and &lt;code&gt;term heap_w32_update&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Which monad AutoCorres chooses to embed a function into depends on the function, and can also be configured. This function is simple enough that it can be encoded with purely &lt;code&gt;option&lt;&#x2F;code&gt;, but others include &lt;code&gt;pure&lt;&#x2F;code&gt;, &lt;code&gt;gets&lt;&#x2F;code&gt; (option with state,) and &lt;code&gt;nondet&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;tangent-what-does-it-mean-to-verify-something&quot;&gt;Tangent: What does it mean to verify something?&lt;&#x2F;h1&gt;
&lt;p&gt;Yes, this is a reasonable question to ask. What does it actually mean to verify this function? Generally, there are a few reasons to verify something:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;To prove it never &quot;fails&quot; (what failing means is another question)&lt;&#x2F;li&gt;
&lt;li&gt;To prove it produces some desired output&lt;&#x2F;li&gt;
&lt;li&gt;To prove it holds some desired property&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;We&#x27;ll look at all three.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;on-level-of-depth&quot;&gt;On level-of-depth&lt;&#x2F;h2&gt;
&lt;p&gt;The not failing example will go into quite a lot of depth, whereas the correctness example will go into much less, only covering broad strokes. This is because the proofs are quite similar, and if you find the former excessively verbose, you might want to skip to the latter.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;not-failing-good&quot;&gt;Not failing (good)&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s consider what we need for this function to not fail in C. The obvious constraint is that &lt;code&gt;list[i]&lt;&#x2F;code&gt; must be defined for all &lt;code&gt;0 &amp;lt;= i &amp;lt; length&lt;&#x2F;code&gt;. Using &lt;code&gt;term is_valid_w32 :: &quot;lifted_globals ⇒ 32 word ptr ⇒ bool&quot; &lt;&#x2F;code&gt;, we can state this as a definition:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;definition list_defined_to :: &amp;quot;lifted_globals ⇒ 32 word ptr ⇒ 32 word ⇒ bool&amp;quot; where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;quot;list_defined_to s list len ≡ ∀i. 0 ≤ i ∧ i &amp;lt; len ⟶ is_valid_w32 s (list +⇩p uint i)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Notes:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;list&lt;&#x2F;code&gt; is a &lt;code&gt;32 word ptr&lt;&#x2F;code&gt;, as perhaps expected. &lt;code&gt;len&lt;&#x2F;code&gt; has been converted into a &lt;code&gt;32 word&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;s&lt;&#x2F;code&gt; is our state for the function, and carries information as mentioned about the heap.&lt;&#x2F;li&gt;
&lt;li&gt;We use the perhaps confusing &lt;code&gt;+⇩p&lt;&#x2F;code&gt; for pointer addition. You can write this in jedit with &lt;code&gt;+ \&amp;lt;^sub&amp;gt; &amp;lt;enter&amp;gt; p&lt;&#x2F;code&gt;. We also need an explicit type conversion &lt;code&gt;uint i&lt;&#x2F;code&gt;, as you can add negatives to a pointer, so the argument is an &lt;code&gt;uint&lt;&#x2F;code&gt; (this is &lt;em&gt;not&lt;&#x2F;em&gt; unsigned int; that&#x27;s &lt;code&gt;unat&lt;&#x2F;code&gt;. &lt;code&gt;int&lt;&#x2F;code&gt; here corresponds to Isabelle &lt;code&gt;int&lt;&#x2F;code&gt;, which is signed.)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Now we have our suitable precondition, let&#x27;s set up our &quot;doesn&#x27;t fail&quot; lemma. We expect that:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;If:
&lt;ul&gt;
&lt;li&gt;The list is defined properly&lt;&#x2F;li&gt;
&lt;li&gt;Some other property Q is true&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Then:
&lt;ul&gt;
&lt;li&gt;Our function does return successfully, and&lt;&#x2F;li&gt;
&lt;li&gt;Our function does not modify any state, so&lt;&#x2F;li&gt;
&lt;li&gt;That property is still true.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We can state this using the combinator &lt;code&gt;ovalidNF&lt;&#x2F;code&gt;. The NF stands for &lt;code&gt;no fail&lt;&#x2F;code&gt;, and it adds the additional condition that our program does not fail in some way during execution. Precisely what we want! It takes three arguments:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;term ovalidNF&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;(*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;&amp;quot;ovalidNF&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;  :: &amp;quot;(&amp;#39;a ⇒ bool) ⇒ (&amp;#39;a ⇒ &amp;#39;b option) ⇒ (&amp;#39;b ⇒ &amp;#39;a ⇒ bool) ⇒ bool&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;*)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The arguments are:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;A precondition function.&lt;&#x2F;li&gt;
&lt;li&gt;A computation function.&lt;&#x2F;li&gt;
&lt;li&gt;A postcondition function.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Note that use the &lt;code&gt;option&lt;&#x2F;code&gt; combinators as AutoCorres has translated our function into the &lt;code&gt;option&lt;&#x2F;code&gt; monad. Also note that our postcondition takes both the state &lt;code&gt;&#x27;a&lt;&#x2F;code&gt; and the return value &lt;code&gt;&#x27;b&lt;&#x2F;code&gt;. When we use &lt;code&gt;ovalidNF&lt;&#x2F;code&gt; with &lt;code&gt;list_sum&#x27;&lt;&#x2F;code&gt;, &lt;code&gt;&#x27;a&lt;&#x2F;code&gt; will be our state &lt;code&gt;lifted_globals&lt;&#x2F;code&gt;. So, our lemma then becomes:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma list_sum_no_fail: &amp;quot;ovalidNF (λs. list_defined_to s list len ∧ Q s)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                  (list_sum&amp;#39; list len)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                  (λret s. Q s)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we have our list defined properly and some property Q, and we run our program, then it does not fail and Q is still true (as our program did not modify any state).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;proof-time-detailed&quot;&gt;Proof time! (detailed)&lt;&#x2F;h2&gt;
&lt;p&gt;If you&#x27;re familiar with Hoare logic, you&#x27;ll know we probably want to use some sort of weakest precondition reasoning. A weakest precondition is roughly &quot;what is the smallest amount of information we need to know for this to be true&quot;, which allows us to simplify our proof obligations. Indeed, AutoCorres provides us with a family of tactics such as &lt;code&gt;wp&lt;&#x2F;code&gt; and &lt;code&gt;wpsimp&lt;&#x2F;code&gt;. However, I&#x27;ve found it useful to start these proofs by unfolding the function at hand, and applying &lt;code&gt;auto&lt;&#x2F;code&gt; or similar to get some simplification going. Then we can apply &lt;code&gt;wp&lt;&#x2F;code&gt; to apply relevant weakest precondition rules automatically.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (unfold list_sum&amp;#39;_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply auto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply wp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This should leave you with a state something like the following. We can see how our function has been simplified down to combinators like &lt;code&gt;owhile&lt;&#x2F;code&gt; and &lt;code&gt;oreturn&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;proof (prove)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;goal (1 subgoal):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 1. ovalidNF (λs. list_defined_to s list len ∧ Q s) (owhile (λ(i, sum) s. i &amp;lt; len) (λ(i, sum). do {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       y ← oguard (λs. is_valid_w32 s (list +⇩p uint i));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       sum ← ogets (λs. sum + heap_w32 s (list +⇩p uint i));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       oreturn (i + 1, sum)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                                       (0, 0))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     (λr. case r of (x, y) ⇒ Q)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you&#x27;re unfamiliar with Isabelle, this is our proof goal or obligation - it&#x27;s what we&#x27;re required to prove to finish the proof as a whole.&lt;&#x2F;p&gt;
&lt;p&gt;I &lt;em&gt;highly&lt;&#x2F;em&gt; recommend using the Query tab of jedit throughout (or equivalents like &lt;code&gt;find_theorems&lt;&#x2F;code&gt;.) &lt;code&gt;name: foo&lt;&#x2F;code&gt; will come in handy, and it&#x27;s a nice fuzzy search. &lt;code&gt;find_theorems solves&lt;&#x2F;code&gt; will do what&#x27;s on the tin, and &lt;code&gt;find_theorem intro&lt;&#x2F;code&gt; will find theorems that could apply.&lt;&#x2F;p&gt;
&lt;p&gt;As we have a while-loop, a reasonable step is to add an invariant. An invariant is something that is &lt;em&gt;invariant&lt;&#x2F;em&gt; over the loop - it is always true, at the top of every loop cycle, and right after the loop finishes. This is how we conclude things about what a loop does. Indeed, we can see a theorem of use:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Reader_Option_VCG.owhile_add_inv: owhile ?C ?B ?x = owhile_inv ?C ?B ?x ?I ?M&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Most of the time, the prefixes can be omitted.&lt;&#x2F;p&gt;
&lt;p&gt;So first, we add an invariant, and then we can use &lt;code&gt;wp&lt;&#x2F;code&gt; to transform our &lt;code&gt;owhile_inv&lt;&#x2F;code&gt; into theorems we can work with.&lt;&#x2F;p&gt;
&lt;p&gt;The invariants we care about right now are:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt; i ≤ len&lt;&#x2F;code&gt; (for termination)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;list_defined_to s list len&lt;&#x2F;code&gt; (for no-failure)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Q s&lt;&#x2F;code&gt; (for simplified correctness)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;We also care that this loop terminates, so let&#x27;s add a suitable measure.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (subst owhile_add_inv[where I=&amp;quot;λ(i, sum) s. i ≤ len ∧ list_defined_to s list len ∧ Q s&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                and M=&amp;quot;λ(i, sum) s. unat (len - i)&amp;quot;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;I&lt;&#x2F;code&gt; is our invariant, and &lt;code&gt;M&lt;&#x2F;code&gt; is the termination measure for the loop. Note the type conversion in &lt;code&gt;M&lt;&#x2F;code&gt;. Then, &lt;code&gt;wp&lt;&#x2F;code&gt; for weakest precondition reasoning again:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply wp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply auto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(unconstrained &lt;code&gt;auto&lt;&#x2F;code&gt; here technically isn&#x27;t the best practice, as it&#x27;s affecting multiple goals, but in this instance it works alright.) This leaves me with the following three goals. Again if you&#x27;re unfamiliar with Isabelle, the left-hand-side represents our &quot;known facts&quot;, and the right-hand-side is our goal, like earlier.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;proof (prove)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;goal (3 subgoals):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 1. ⋀a s. ⟦a &amp;lt; len; a ≤ len; list_defined_to s list len; Q s⟧ ⟹ is_valid_w32 s (list +⇩p uint a)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 2. ⋀a s. ⟦a &amp;lt; len; a ≤ len; list_defined_to s list len; Q s⟧ ⟹ a + 1 ≤ len&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 3. ⋀a b m.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       ⦉λs. a ≤ len ∧ list_defined_to s list len ∧ Q s ∧ a &amp;lt; len ∧ unat (len - a) = m⦊ do {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         y ← oguard (λs. is_valid_w32 s (list +⇩p uint a));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         sum ← λc. Some (b + heap_w32 c (list +⇩p uint a));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         λb. Some (a + 1, sum)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       } ⦉λr s. (case r of (i, sum) ⇒ λs. unat (len - i)) s &amp;lt; m⦊&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The first we talked about earlier - the access &lt;code&gt;list[i]&lt;&#x2F;code&gt; must be valid. We can solve this subgoal by unfolding &lt;code&gt;list_defined_to&lt;&#x2F;code&gt; via &lt;code&gt;list_defined_to_def&lt;&#x2F;code&gt;, and basic reasoning.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply (simp add: list_defined_to_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For the second, it seems obvious - why hasn&#x27;t &lt;code&gt;auto&lt;&#x2F;code&gt; solved it? (If it were on &lt;code&gt;nat&lt;&#x2F;code&gt;s, it certainly would have.) Alas, it&#x27;s on &lt;code&gt;32 word&lt;&#x2F;code&gt;s, which as we have chosen to use modular arithmetic, are slightly less nice. I found it slightly hard to search for theorems involving &lt;code&gt;+&lt;&#x2F;code&gt; as it&#x27;s so overloaded, but luckily here &lt;code&gt;find_theorems solves&lt;&#x2F;code&gt; finds &lt;code&gt;Word.inc_le: ?i &amp;lt; ?m ⟹ ?i + 1 ≤ ?m&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply (simp add: inc_le)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The final goal is more interesting. The initial intuition might be to use &lt;code&gt;wp&lt;&#x2F;code&gt; again, but this leaves us with nasty metavariables because of the chaining nature of the binds, and the fact that AutoCorres here is slightly too general. With a little searching we have the following, which it seems like &lt;code&gt;wp&lt;&#x2F;code&gt; is applying:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Reader_Option_VCG.obind_wp: ⟦⋀r. ⦉?R r⦊ ?g r ⦉?Q⦊; ⦉?P⦊ ?f ⦉?R⦊⟧ ⟹ ⦉?P⦊ ?f &amp;gt;&amp;gt;= ?g ⦉?Q⦊&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But we only really need &lt;code&gt;?R&lt;&#x2F;code&gt; to be identical to &lt;code&gt;?P&lt;&#x2F;code&gt;. We could instantiate &lt;code&gt;?R&lt;&#x2F;code&gt; manually each time, or we can make a little helper lemma. Above this lemma, we add&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma obind_wp_weak: &amp;quot; ⟦⋀r. ⦉P⦊ g r ⦉Q⦊; ⦉P⦊ f ⦉λs. P⦊⟧ ⟹ ⦉P⦊ obind f g ⦉Q⦊&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (erule obind_wp, assumption)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then we can apply &lt;code&gt;obind_wp_weak&lt;&#x2F;code&gt; as many times as needed (There are two binds.)&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (rule obind_wp_weak)+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We hence have:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;proof (prove)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;goal (3 subgoals):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 1. ⋀a b m r ra.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       ⦉λs. a ≤ len ∧ list_defined_to s list len ∧ Q s ∧ a &amp;lt; len ∧ unat (len - a) = m⦊ &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       λb. Some (a + 1, ra) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       ⦉λr s. (case r of (i, sum) ⇒ λs. unat (len - i)) s &amp;lt; m⦊&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 2. ⋀a b m r.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       ⦉λs. a ≤ len ∧ list_defined_to s list len ∧ Q s ∧ a &amp;lt; len ∧ unat (len - a) = m⦊ &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       λc. Some (b + heap_w32 c (list +⇩p uint a)) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       ⦉λs sa. a ≤ len ∧ list_defined_to sa list len ∧ Q sa ∧ a &amp;lt; len ∧ unat (len - a) = m⦊&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 3. ⋀a b m.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       ⦉λs. a ≤ len ∧ list_defined_to s list len ∧ Q s ∧ a &amp;lt; len ∧ unat (len - a) = m⦊ &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       oguard (λs. is_valid_w32 s (list +⇩p uint a)) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       ⦉λs sa. a ≤ len ∧ list_defined_to sa list len ∧ Q sa ∧ a &amp;lt; len ∧ unat (len - a) = m⦊&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s finally time to start unfolding the definition of &lt;code&gt;ovalid&lt;&#x2F;code&gt; so we can crunch down these last few goals. If we hit the first goal with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    apply (simp add: ovalid_def, clarsimp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;we&#x27;re left with&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 1. ⋀a s. ⟦a ≤ len; list_defined_to s list len; Q s; a &amp;lt; len⟧&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          ⟹ unat (len - (a + 1)) &amp;lt; unat (len - a)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is part of the proof that our measure is correct and our loop terminates. &lt;code&gt;sledgehammer&lt;&#x2F;code&gt; takes it out nicely.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;    (* Found with sledgehammer *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    apply (metis diff_diff_eq gt0_iff_gem1 less_diff_gt0 unat_mono)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Tip: I fiddled with this for a bit manually, but if it looks fiddly and obvious, there&#x27;s a good chance sledgehammer can do it.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, the last two are easy:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (simp add: ovalid_def)+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We have a proof of non-failure! This is very exciting.&lt;&#x2F;p&gt;
&lt;p&gt;The final proof is as follows:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma obind_wp_weak: &amp;quot; ⟦⋀r. ⦉P⦊ g r ⦉Q⦊; ⦉P⦊ f ⦉λs. P⦊⟧ ⟹ ⦉P⦊ obind f g ⦉Q⦊&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (erule obind_wp, assumption)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma list_sum_no_fail: &amp;quot;ovalidNF (λs. list_defined_to s list len ∧ Q s)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                  (list_sum&amp;#39; list len)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                  (λret s. Q s)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (unfold list_sum&amp;#39;_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply auto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply wp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (subst owhile_add_inv[where I=&amp;quot;λ(i, sum) s. i ≤ len ∧ list_defined_to s list len ∧ Q s&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                and M=&amp;quot;λ(i, sum) s. unat (len - i)&amp;quot;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply wp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     apply auto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     apply (simp add: list_defined_to_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply (simp add: inc_le)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (rule obind_wp_weak)+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    apply (simp add: ovalid_def, clarsimp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    apply (metis diff_diff_eq gt0_iff_gem1 less_diff_gt0 unat_mono)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (simp add: ovalid_def)+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h1 id=&quot;correctness-also-good&quot;&gt;Correctness (also good)&lt;&#x2F;h1&gt;
&lt;p&gt;Then, what does it mean for our function to be correct? Well, a reasonable definition is that it produces the output we expect. We then need to figure out what &quot;output we expect&quot; means.&lt;&#x2F;p&gt;
&lt;p&gt;We could have also defined the sum of a list as similar to the following recursive function:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;function list_sum_spec :: &amp;quot;lifted_globals ⇒ 32 word ptr ⇒ 32 word ⇒ 32 word ⇒ 32 word&amp;quot; where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;list_sum_spec s list len i = (if i = 0 then 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                               else heap_w32 s (list +⇩p uint (i - 1))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                    + list_sum_spec s list len (i - 1))&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;  (* The pattern matching is trivially complete. *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by pat_completeness auto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that we explicitly check for 0 to ensure the recursion terminates (We can&#x27;t pattern match on 0&#x2F;Suc, as we&#x27;re working with &lt;code&gt;32 word&lt;&#x2F;code&gt;s.). Unfortunately, this function&#x27;s termination can&#x27;t be proven automatically due to the use of a &lt;code&gt;32 word&lt;&#x2F;code&gt;, which Isabelle isn&#x27;t as good with as its own &lt;code&gt;nat&lt;&#x2F;code&gt;s. This is why we use a &lt;code&gt;function&lt;&#x2F;code&gt; instead of &lt;code&gt;fun&lt;&#x2F;code&gt;, and we must do the termination proof ourselves:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;termination&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;  (* Note that the measure is just i, as it&amp;#39;s decreasing. *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (rule local.termination[where R=&amp;quot;measure (λ(_,_,len,i). unat i)&amp;quot;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply blast&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (unfold measure_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (simp add: measure_unat)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We also delete &lt;code&gt;list_sum_spec.simps&lt;&#x2F;code&gt; from the default simp set because it seems to cause some solvers to loop.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;declare list_sum_spec.simps [simp del]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can set up our lemma like before, but this time, we use the &lt;code&gt;ret&lt;&#x2F;code&gt; parameter:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma list_sum_correct: &amp;quot;ovalid (λs. list_defined_to s list len)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                (list_sum&amp;#39; list len)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                (λret s. list_sum_spec s list len len = ret)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We want the result to be equivalent to summing the entire list with our recursive &lt;code&gt;spec&lt;&#x2F;code&gt; function. We also don&#x27;t bother to prove that it doesn&#x27;t fail here.&lt;&#x2F;p&gt;
&lt;p&gt;We can begin as before, omitting the &lt;code&gt;auto&lt;&#x2F;code&gt; step. We then need to annotate with a suitable invariant. A hint: We want the sum &lt;em&gt;at the end&lt;&#x2F;em&gt; to be correct, so a good invariant should capture correctness &lt;em&gt;at every step&lt;&#x2F;em&gt;, which gives us full correctness when the loop finishes.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (subst owhile_add_inv[where I=&amp;quot;λ(i, sum) s. i ≤ len ∧ list_defined_to s list len&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                                            ∧ list_sum_spec s list len i = sum&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                and M=&amp;quot;λ(i, sum) s. unat (len - i)&amp;quot;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We have to manually &lt;code&gt;subst list_sum_spec.simps&lt;&#x2F;code&gt; a few times as we deleted it from the simp set, but otherwise the proof is very straightforward. Mine came out to be:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;function list_sum_spec :: &amp;quot;lifted_globals ⇒ 32 word ptr ⇒ 32 word ⇒ 32 word ⇒ 32 word&amp;quot; where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;list_sum_spec s list len i = (if i = 0 then 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                               else heap_w32 s (list +⇩p uint (i - 1))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                    + list_sum_spec s list len (i - 1))&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by pat_completeness auto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;termination&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (rule local.termination[where R=&amp;quot;measure (λ(_,_,len,i). unat i)&amp;quot;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply blast&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (unfold measure_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (simp add: measure_unat)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;declare list_sum_spec.simps [simp del]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma list_sum_correct: &amp;quot;ovalid (λs. list_defined_to s list len)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                (list_sum&amp;#39; list len)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                (λret s. list_sum_spec s list len len = ret)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (unfold list_sum&amp;#39;_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply wp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (subst owhile_add_inv[where I=&amp;quot;λ(i, sum) s. i ≤ len ∧ list_defined_to s list len&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                                            ∧ list_sum_spec s list len i = sum&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                and M=&amp;quot;λ(i, sum) s. unat (len - i)&amp;quot;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply wp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    apply auto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     apply (simp add: inc_le)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply (subst list_sum_spec.simps)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply (simp add: less_is_non_zero_p1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply (subst list_sum_spec.simps)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by simp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We could take this one step further if we wanted, and define a bijection between &lt;code&gt;32 word list&lt;&#x2F;code&gt; and &lt;code&gt;32 word ptr&lt;&#x2F;code&gt; assuming our precondition, and then also show that our own spec is equivalent to the sum of that list. That&#x27;d give us even more confidence our function is correct. I&#x27;m personally pretty convinced, but you&#x27;re welcome to try this yourself!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;properties-also-good&quot;&gt;Properties (also good!)&lt;&#x2F;h1&gt;
&lt;p&gt;We could then finally prove that if some property is true for the sum of a list, it&#x27;s true for the result of our program. I won&#x27;t detail this one; it should follow reasonably easily from the former two.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h1&gt;
&lt;p&gt;So, what have we (hopefully) learnt?&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;How to install and setup Isabelle and AutoCorres&lt;&#x2F;li&gt;
&lt;li&gt;What it means to prove things about programs&lt;&#x2F;li&gt;
&lt;li&gt;How to set up appropriate proofs&lt;&#x2F;li&gt;
&lt;li&gt;How to prove them&lt;&#x2F;li&gt;
&lt;li&gt;What tools we have available and how we can search for more&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;I hope this has been informative!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-whole-file&quot;&gt;The whole file&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;code&gt;list_sum.c&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;unsigned int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; list_sum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;unsigned int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;list&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; unsigned int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; length&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    unsigned int&lt;&#x2F;span&gt;&lt;span&gt; sum &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;unsigned int&lt;&#x2F;span&gt;&lt;span&gt; i &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;; i &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; length; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        sum &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;+=&lt;&#x2F;span&gt;&lt;span&gt; list[i];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; sum;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;my_theory.thy&lt;&#x2F;code&gt; (With less fixing of indentation for the web, sorry):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;theory my_theory&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  imports Main &amp;quot;AutoCorres.AutoCorres&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;begin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;external_file &amp;quot;list_sum.c&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;install_C_file &amp;quot;list_sum.c&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;autocorres [skip_word_abs] &amp;quot;list_sum.c&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;context list_sum begin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;definition list_defined_to :: &amp;quot;lifted_globals ⇒ 32 word ptr ⇒ 32 word ⇒ bool&amp;quot; where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;quot;list_defined_to s list len ≡ ∀i. 0 ≤ i ∧ i &amp;lt; len ⟶ is_valid_w32 s (list +⇩p uint i)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma obind_wp_weak: &amp;quot; ⟦⋀r. ⦉P⦊ g r ⦉Q⦊; ⦉P⦊ f ⦉λs. P⦊⟧ ⟹ ⦉P⦊ obind f g ⦉Q⦊&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (erule obind_wp, assumption)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma list_sum_no_fail: &amp;quot;ovalidNF (λs. list_defined_to s list len ∧ Q s) (list_sum&amp;#39; list len) (λret s. Q s)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (unfold list_sum&amp;#39;_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply auto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply wp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (subst owhile_add_inv[where I=&amp;quot;λ(i, sum) s. i ≤ len ∧ list_defined_to s list len ∧ Q s&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                and M=&amp;quot;λ(i, sum) s. unat (len - i)&amp;quot;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply wp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     apply auto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     apply (simp add: list_defined_to_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply (simp add: inc_le)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (rule obind_wp_weak)+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    apply (simp add: ovalid_def, clarsimp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    apply (metis diff_diff_eq gt0_iff_gem1 less_diff_gt0 unat_mono)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (simp add: ovalid_def)+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;function list_sum_spec :: &amp;quot;lifted_globals ⇒ 32 word ptr ⇒ 32 word ⇒ 32 word ⇒ 32 word&amp;quot; where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;list_sum_spec s list len i = (if i = 0 then 0 else heap_w32 s (list +⇩p uint (i - 1)) + list_sum_spec s list len (i - 1))&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by pat_completeness auto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;termination&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (rule local.termination[where R=&amp;quot;measure (λ(_,_,len,i). unat i)&amp;quot;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply blast&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (unfold measure_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by (simp add: measure_unat)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;declare list_sum_spec.simps [simp del]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma list_sum_correct: &amp;quot;ovalid (λs. list_defined_to s list len) (list_sum&amp;#39; list len) (λret s. list_sum_spec s list len len = ret)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (unfold list_sum&amp;#39;_def)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply wp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (subst owhile_add_inv[where I=&amp;quot;λ(i, sum) s. i ≤ len ∧ list_defined_to s list len ∧ list_sum_spec s list len i = sum&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                and M=&amp;quot;λ(i, sum) s. unat (len - i)&amp;quot;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply wp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    apply auto&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     apply (simp add: inc_le)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply (subst list_sum_spec.simps)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply (simp add: less_is_non_zero_p1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   apply (subst list_sum_spec.simps)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  by simp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A bit underwhelming for how long it took to explain, perhaps!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Flat&#x2F;Non-higher-order construction of ANF via mutable holes</title>
        <published>2026-05-14T00:00:00+00:00</published>
        <updated>2026-05-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/anf-mutable/"/>
        <id>https://blueberrywren.dev/blog/anf-mutable/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/anf-mutable/">&lt;h1 id=&quot;flat-non-higher-order-construction-of-anf-via-mutable-holes&quot;&gt;Flat&#x2F;Non-higher-order  construction of ANF via mutable holes&lt;&#x2F;h1&gt;
&lt;p&gt;This post will describe an algorithm for constructing an ANF&#x2F;similar IR from a functional-like base language with no closure usage,
and with no related excess space requirements. This algorithm is as far as I know not new, and has apparently been known in
imperative compilation for a while. However, I admittedly have no source for this, nor
have I seen it described for functional-like languages.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to Ryan Brewer and rpjohnst for their inspiration on this.&lt;&#x2F;p&gt;
&lt;p&gt;If you are only interested in code, please skip to Implementation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;&#x2F;h2&gt;
&lt;p&gt;First, let us describe our input and output languages. Our input language will look like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; ml&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Let&lt;&#x2F;span&gt;&lt;span&gt; of string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; ml&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; ml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt; of string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Int&lt;&#x2F;span&gt;&lt;span&gt; of int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt; of ml&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; ml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Print&lt;&#x2F;span&gt;&lt;span&gt; of ml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is meant to echo some simple functional programming language, and contains all the elements needed to demonstrate the algorithm.&lt;&#x2F;p&gt;
&lt;p&gt;Our output language will look like a lexically-scoped flat ANF-style construction, with all lets at the toplevel.
The goal is to convert from our input &lt;code&gt;ml&lt;&#x2F;code&gt; to this language.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; base&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt; of string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt; of string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Int&lt;&#x2F;span&gt;&lt;span&gt; of int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Print&lt;&#x2F;span&gt;&lt;span&gt; of string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Let&lt;&#x2F;span&gt;&lt;span&gt; of string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; base&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; anf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Done&lt;&#x2F;span&gt;&lt;span&gt; of string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Hole&lt;&#x2F;span&gt;&lt;span&gt; of anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; option&lt;&#x2F;span&gt;&lt;span&gt; ref&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The notable addition is the &lt;code&gt;Hole&lt;&#x2F;code&gt; constructor in &lt;code&gt;anf&lt;&#x2F;code&gt;, the purpose of which will be described now.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-premise&quot;&gt;The premise&lt;&#x2F;h2&gt;
&lt;p&gt;Imagine we are trying to convert the term&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;x + 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When we arrive at the body of &lt;code&gt;x&lt;&#x2F;code&gt;, we have a conundrum. We need to put the conversion of &lt;code&gt;y&lt;&#x2F;code&gt; before &lt;code&gt;x&lt;&#x2F;code&gt;,
so that using &lt;code&gt;y&lt;&#x2F;code&gt; is well-scoped. Hence, we must convert &lt;code&gt;y&lt;&#x2F;code&gt; before we can continue. How do we use this conversion, though?
&lt;code&gt;x&lt;&#x2F;code&gt;&#x27;s content needs to be put in the &lt;code&gt;anf&lt;&#x2F;code&gt; field of &lt;code&gt;y&lt;&#x2F;code&gt;&#x27;s &lt;code&gt;Let&lt;&#x2F;code&gt;, so it&#x27;s not clear how to both convert &lt;code&gt;y&lt;&#x2F;code&gt; before &lt;code&gt;x&lt;&#x2F;code&gt; and
to use &lt;code&gt;x&lt;&#x2F;code&gt;&#x27;s finished conversion in &lt;code&gt;y&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;One &quot;traditional&quot; method of solving this is via continuations, where &lt;code&gt;y&lt;&#x2F;code&gt; is passed a closure representing &quot;what to do next&quot;, after it
converts its body. We can then put &lt;code&gt;x&lt;&#x2F;code&gt;&#x27;s content in that closure, which will be invoked later. This has two main flaws:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It uses excess space. A conversion of a term will allocate ~2x the memory &quot;needed&quot;; it must allocate for the ANF construction itself, and for the closures needed during the construction.&lt;&#x2F;li&gt;
&lt;li&gt;It is slower, due to the aforementioned closure allocation and application.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This method resolves these.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-algorithm&quot;&gt;The algorithm&lt;&#x2F;h2&gt;
&lt;p&gt;Recall that we left a &lt;code&gt;Hole of anf option ref&lt;&#x2F;code&gt; field in our &lt;code&gt;anf&lt;&#x2F;code&gt; type. I will denote a hole like this: &lt;code&gt;[·]&lt;&#x2F;code&gt;.
The central idea is that our conversion of any given &lt;code&gt;ml&lt;&#x2F;code&gt; fragment will return:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The fragment itself.&lt;&#x2F;li&gt;
&lt;li&gt;A name we can use to refer to what was bound in the fragment (In the conversion of addition&#x2F;similar with nested content, names must be conjured.)&lt;&#x2F;li&gt;
&lt;li&gt;The reference created by the hole, so that it may be filled.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; convert&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; ml&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; option&lt;&#x2F;span&gt;&lt;span&gt; ref)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Consider this simplified example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;in x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When we convert &lt;code&gt;x&lt;&#x2F;code&gt;, this signals for the conversion of &lt;code&gt;y&lt;&#x2F;code&gt;. There are two steps to converting a &lt;code&gt;let&lt;&#x2F;code&gt; - we
must first convert the &quot;head&quot; (&lt;code&gt;2&lt;&#x2F;code&gt;), and then the &quot;body&quot; (&lt;code&gt;y&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;Converting the &lt;code&gt;head&lt;&#x2F;code&gt; will result in something of form&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt; in &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[·]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that the hole is left to be filled later. This way, the conversion of &lt;code&gt;y&lt;&#x2F;code&gt;&#x27;s head need know nothing about its environment.
We represent this in code via the &lt;code&gt;Hole&lt;&#x2F;code&gt; constructor, which contains a reference to a fragment that either may be empty (&lt;code&gt;None&lt;&#x2F;code&gt;)
or filled (&lt;code&gt;Some ...&lt;&#x2F;code&gt;).
The conversion of the body can then proceed by first generating the expected addition, binding it to &lt;code&gt;nm&lt;&#x2F;code&gt; so it may be referenced later:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; nm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[·]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We now need to get this fragment into the proper lexical scope. We can do this by plugging it into the hole left by the conversion of the head:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; nm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  [·]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, returning this fragment, the name bound (&lt;code&gt;y&lt;&#x2F;code&gt;), and the reference to the inner hole, we can continue converting &lt;code&gt;x&lt;&#x2F;code&gt;;
First, convert the head, using the name returned by the conversion of &lt;code&gt;y&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; nm in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[·]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, the body:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; nm2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; x in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[·]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Plug:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; nm in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; nm2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; x in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  [·]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And finally plug it into the hole returned by &lt;code&gt;y&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; nm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; nm in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;      let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; nm2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; x in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      [·]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We are left with a final hole we can plug with &lt;code&gt;Done&lt;&#x2F;code&gt; to be explicit about the end of a control flow path.
One disadvantage of this strategy is that it does generate many unneeded names. Most of these can be avoided by carefully special
casing certain &lt;code&gt;lets&lt;&#x2F;code&gt;, and the rest can be eliminated via a simple folding pass.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;implementation&quot;&gt;Implementation&lt;&#x2F;h2&gt;
&lt;p&gt;Below is a sample implementation of this algorithm, in OCaml.&lt;&#x2F;p&gt;
&lt;details&gt;
&lt;summary&gt;
  The implementation can be unfolded here.
&lt;&#x2F;summary&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; ml&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Let&lt;&#x2F;span&gt;&lt;span&gt; of string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; ml&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; ml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt; of string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Int&lt;&#x2F;span&gt;&lt;span&gt; of int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt; of ml&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; ml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Print&lt;&#x2F;span&gt;&lt;span&gt; of ml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;(* Suffix with &amp;#39; to dodge OCaml annoyances. *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; base&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39; of string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39; of string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Int&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39; of int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Print&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39; of string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Let&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39; of string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; base&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; anf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Done&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39; of string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Hole&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39; of anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; option&lt;&#x2F;span&gt;&lt;span&gt; ref&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; fresh_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; counter&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ref&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  fun&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; ()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    incr counter&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;    &amp;quot;nm&amp;quot; ^&lt;&#x2F;span&gt;&lt;span&gt; string_of_int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; !&lt;&#x2F;span&gt;&lt;span&gt;counter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;(* A helper to make an anf fragment of form&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;   let new_name = base in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;   [·]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt; *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; make_let_hole&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;base&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; base)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; (anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; option&lt;&#x2F;span&gt;&lt;span&gt; ref)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; fresh_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; ()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; r&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ref&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; None&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;Let&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; (name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; base&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Hole&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; r)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; r)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; rec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; convert&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;ml&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; ml)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; (anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; option&lt;&#x2F;span&gt;&lt;span&gt; ref)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;  match&lt;&#x2F;span&gt;&lt;span&gt; ml&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; nm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;                (* Bind to a new name, and return.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;                   A case that can be eliminated in most cases.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;                   *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    make_let_hole (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;Name&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; nm)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    make_let_hole (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;Int&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; i)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;    (* First, we convert `a` and `b` *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;a_anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; a_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; a_hole&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; convert a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;b_anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; b_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; b_hole&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; convert b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;    (* We chose a left-to-right evaluation order, so we&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;       want to put `a` before `b`. Hence, plug `b`&amp;#39;s fragment&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;       into the hole provided by `a`.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;       *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    a_hole&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt; b_anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;    (* Then, we need a fragment for the addition itself. *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;add_anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; add_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; add_hole&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      make_let_hole (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;Add&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; (a_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; b_name))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;    (* We put this in `b`&amp;#39;s hole. *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    b_hole&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt; add_anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;    (* Finally, we return the whole expression.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;       Everything is contained within `a_anf`.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;       If the user wishes to refer to the result of this conversion,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;       they should use add_name.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;       If they wish to plug something into it,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;       they should use add_hole.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;       *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (a_anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; add_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; add_hole)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Print&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; body&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;    (* Print is similar. *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;body_anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; body_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; body_hole&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; convert body&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;print_anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; print_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; print_hole&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      make_let_hole (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;Print&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; body_name)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    body_hole&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt; print_anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (body_anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; print_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; print_hole)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; head&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; body&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;head_anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; head_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; head_hole&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; convert head&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;body_anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; body_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; body_hole&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; convert body&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;    (* We need to bind this let before body to ensure it is&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;       properly lexically scoped.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;       *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; let_anf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Let&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; (name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Name&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; head_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; body_anf)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;    (* Then fill it as expected. *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    head_hole&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; let&lt;&#x2F;span&gt;&lt;span&gt;_anf;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (head_anf, body_name, body_hole)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;details&gt;
&lt;p&gt;I recommend toying with the conversion yourself, using &lt;code&gt;utop&lt;&#x2F;code&gt; or similar.
In the following, I will &quot;clean up&quot; the output slightly, as to not make it unreadable.&lt;&#x2F;p&gt;
&lt;p&gt;If we use our first example term:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;utop #&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; term&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Let&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;&amp;quot;x&amp;quot;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Let&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;&amp;quot;y&amp;quot;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;Name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; &amp;quot;y&amp;quot;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;Name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; &amp;quot;x&amp;quot;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;));;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; term&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; ml&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;  Let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;&amp;quot;x&amp;quot;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;&amp;quot;y&amp;quot;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;Name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; &amp;quot;y&amp;quot;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;Name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; &amp;quot;x&amp;quot;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;utop&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; convert&lt;&#x2F;span&gt;&lt;span&gt; term;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;(* Cleaned up: *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; nm1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; nm1 in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; nm2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; y in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; nm3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; nm4&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; nm2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; nm3 in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; nm4 in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; nm5&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; x in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; nm6&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; nm7&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; nm5&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; nm6 in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Hole [·]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;, &amp;quot;nm7&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;, &amp;lt;empty reference&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can then plug the returned hole, as described.
Via some inspection, we can verify this is indeed correct, and conforms to our ANF-like form, as expected.&lt;&#x2F;p&gt;
&lt;p&gt;As mentioned earlier, the large amount of duplicate names can be mitigated through strategies such as
special casing &lt;code&gt;let _ = &amp;lt;direct base&amp;gt;&lt;&#x2F;code&gt; and folding passes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;properties&quot;&gt;Properties&lt;&#x2F;h2&gt;
&lt;p&gt;Clearly, the algorithm does not use closures, or any indirect jumps. It does not allocate any more than needed for the representation of
the output program; there is no excessive closure allocation. I do not currently have a good way to test performance on real-world large inputs,
but I have no reason to believe it would not perform better than an equivalent higher-order version.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;future-work&quot;&gt;Future work&lt;&#x2F;h2&gt;
&lt;p&gt;I believe this method should be extendable to CPS as well, although I have not tried as of the moment. The &quot;usual&quot; higher-order CPS
conversion described in e.g. &quot;Compiling with continuations, continued&quot; looks quite similar to the higher-order presentation
of ANF conversion, so I would be interested in whether it can be similarly massaged into a mutable form.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Type safe interpreters</title>
        <published>2026-01-17T00:00:00+00:00</published>
        <updated>2026-01-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/type-safe-interpreters/"/>
        <id>https://blueberrywren.dev/blog/type-safe-interpreters/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/type-safe-interpreters/">&lt;p&gt;It is well known that most software has bugs&lt;sup&gt;&lt;i&gt;[Citation needed]&lt;&#x2F;i&gt;&lt;&#x2F;sup&gt;.
It is also well known that interpreters are mostly software&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. One issue that one might
run into in an interpreter is &lt;em&gt;type safety&lt;&#x2F;em&gt;: It may very well be possible for your
typed language&#x27;s interpreter to nevertheless end up in a state where it is asked
to evaluate &lt;code&gt;1 + &quot;hi!&quot;&lt;&#x2F;code&gt;. What can we do about that?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gadts-generalized-adts&quot;&gt;GADTs: Generalized ADTs&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;GADTs are a technique for increasing type safety in a program, by &quot;indexing&quot; a constructor by a type.
One of the canonical examples for this is an &lt;code&gt;Option&lt;&#x2F;code&gt;-like. Imagine we wanted a type-safe way to ensure
that in some cases, we could always extract the value inside. One way of doing this is to add an extra
type parameter, and use that to mark whether something is inside. We will use OCaml for this demonstration.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;(* Dummy constructors; we are only using these for their types *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; yes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Yes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; no&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; No&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #88846F;&quot;&gt; _&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; maybe&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;      |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;  ^&lt;&#x2F;span&gt;&lt;span&gt; regular &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;information&lt;&#x2F;span&gt;&lt;span&gt; inside&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;      ^&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; marker&lt;&#x2F;span&gt;&lt;span&gt; of &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;whether the information exists&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span&gt; Nothing &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (no&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; maybe&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span&gt; Just &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (yes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; maybe&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that we have used a different syntax than usual. Normally, we put a type parameter in the constructor,
like &lt;code&gt;type &#x27;a list&lt;&#x2F;code&gt;, and then use that throughout (&lt;code&gt;&#x27;a * &#x27;a list&lt;&#x2F;code&gt;). However, as we are changing that type
in the &quot;return&quot; of the constructor, we need a syntax that allows us to change that. &lt;code&gt;_&lt;&#x2F;code&gt; marks a type parameter
we &quot;don&#x27;t need to name&quot; (as we always specify it), and in this case, we always specify both. Then, we
add our elements before a &lt;code&gt;-&amp;gt;&lt;&#x2F;code&gt;, mimicking a function. The general form of this in OCaml is &lt;code&gt;t1 * t2 * ... * tn -&amp;gt; t&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now, if we have something of type &lt;code&gt;(yes, &#x27;a) maybe&lt;&#x2F;code&gt;, we know it contains a value! The only other way a &lt;code&gt;maybe&lt;&#x2F;code&gt; can be
formed is via &lt;code&gt;Nothing&lt;&#x2F;code&gt;, but that gives it type &lt;code&gt;(no, &#x27;a) maybe&lt;&#x2F;code&gt;, so it&#x27;d be type-incorrect. This means we
can write a function like&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; get&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; (yes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; maybe&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;a = &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  match x with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | Just a -&amp;gt; a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and have it be total; there is no missing case, because the missing case is a type error. Note that when writing a
function like &lt;code&gt;or_else : (_, &#x27;a) maybe -&amp;gt; &#x27;a -&amp;gt; &#x27;a&lt;&#x2F;code&gt;, we need to use this interesting piece of syntax:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; or_else&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; m&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; (m&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; maybe&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; = fun&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; x def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;  match&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Just&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Nothing&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; def&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is as otherwise OCaml&#x27;s normal type inference can get in our way and infer the wrong type, leading to a type error.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-4-1&quot;&gt;&lt;a href=&quot;#fn-4&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;type-safe-interpreters&quot;&gt;Type safe interpreters&lt;&#x2F;h2&gt;
&lt;p&gt;How does this allow us to get a more type-safe interpreter, though? Well, let&#x27;s start by introducing our expression
type:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; _ expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We&#x27;ve added space for a type parameter. What should integers and booleans look like? Maybe we should paramaterize our expressions
by the type they &quot;evaluate to&quot; - that way, when we have a &lt;code&gt;&#x27;a expr&lt;&#x2F;code&gt;, we know that it&#x27;ll evaluate to something
of type &lt;code&gt;&#x27;a&lt;&#x2F;code&gt;. Hence:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | Lit : int -&amp;gt; int expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | Bool : bool -&amp;gt; bool expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, we want to add a case for &lt;code&gt;Add&lt;&#x2F;code&gt; and &lt;code&gt;Negate&lt;&#x2F;code&gt;. Naturally, we shouldn&#x27;t be able to add two booleans, so let&#x27;s restrict it
to only taking in &lt;code&gt;int expr&lt;&#x2F;code&gt;s, and similar for negate. We also know that these should return integers, too.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | Add : int expr * int expr -&amp;gt; int expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | Negate : int expr -&amp;gt; int expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We&#x27;ve already added type safety! It&#x27;s impossible to write &lt;code&gt;Add (Bool true, Lit 5)&lt;&#x2F;code&gt;, because &lt;code&gt;Add&lt;&#x2F;code&gt; expects a &lt;code&gt;int expr&lt;&#x2F;code&gt;,
but &lt;code&gt;Bool true&lt;&#x2F;code&gt; is a &lt;code&gt;bool expr&lt;&#x2F;code&gt;. Let&#x27;s keep going: &lt;code&gt;&amp;lt;=&lt;&#x2F;code&gt; (or &lt;code&gt;Leq&lt;&#x2F;code&gt;) should take two integers and return a boolean,
and &lt;code&gt;If&lt;&#x2F;code&gt; should take a boolean as its first argument, but anything for its second and third.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | Leq : int expr * int expr -&amp;gt; bool expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | If : bool expr * &amp;#39;a expr * &amp;#39;a expr -&amp;gt; &amp;#39;a expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that we can still use generic parameters, like &lt;code&gt;&#x27;a&lt;&#x2F;code&gt; here - we just need to think about when it makes sense to do so,
to get the type safety we want.&lt;&#x2F;p&gt;
&lt;p&gt;Now for functions. What should a function look like here? One way of implementing them is with a &quot;Higher-order abstract syntax&quot;(HOAS)&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; approach,
where we use the functions of the host language to make functions in the interpreted language. In that case, we should
take a function as the argument to our constructor, but when what is our result type? That function type! We&#x27;ll
need to know it later to safely write &lt;code&gt;Apply&lt;&#x2F;code&gt;, so we &quot;store&quot; it in the type now. We also want the function
to take and return an &lt;code&gt;_ expr&lt;&#x2F;code&gt;, so we can do constructions like &lt;code&gt;Lam (fun x -&amp;gt; Add(x,x))&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | Lam : (&amp;#39;a expr -&amp;gt; &amp;#39;b expr) -&amp;gt; (&amp;#39;a expr -&amp;gt; &amp;#39;b expr) expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that the function is not an &lt;code&gt;expr&lt;&#x2F;code&gt; at first, as otherwise we would have no way to construct it in the first
place. (Remember, this is how we make functions.)&lt;&#x2F;p&gt;
&lt;p&gt;Then &lt;code&gt;Apply&lt;&#x2F;code&gt;. It should take in a function, and a value, and then return the function applied to the value.
This hence translates as:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | Apply : (&amp;#39;a expr -&amp;gt; &amp;#39;b expr) expr * &amp;#39;a expr-&amp;gt; &amp;#39;b expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As a finale, we&#x27;ll add pairs and projections. I won&#x27;t elaborate on these, hoping that it&#x27;s becoming obvious how
they work.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | Pair : &amp;#39;a expr * &amp;#39;b expr -&amp;gt; (&amp;#39;a * &amp;#39;b) expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | Fst : (&amp;#39;a * &amp;#39;b) expr -&amp;gt; &amp;#39;a expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  | Snd : (&amp;#39;a * &amp;#39;b) expr -&amp;gt; &amp;#39;b expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;details&gt;&lt;summary&gt;All of the above in one code block&lt;&#x2F;summary&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; _ expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Lit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Bool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; bool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; bool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Negate&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Leq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; bool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; If&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; bool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Lam&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Apply&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Pair&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Fst&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Snd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;details&gt;
&lt;h2 id=&quot;examples&quot;&gt;Examples&lt;&#x2F;h2&gt;
&lt;p&gt;Now let&#x27;s look at some examples and their types.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;utop # Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- : int expr = Lit 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;utop # Bool true;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- : bool expr = Bool true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;utop # Add (Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;, Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;);;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- : int expr = Add (Lit 4, Lit 5)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;utop # Lam (fun f -&amp;gt; f);;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- : (&amp;#39;a expr -&amp;gt; &amp;#39;a expr) expr = Lam &amp;lt;fun&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;utop # Apply (Lam (fun x -&amp;gt; Add(x,x)), Lit 5);;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- : int expr = Apply (Lam &amp;lt;fun&amp;gt;, Lit 5)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;utop # Lam (fun b -&amp;gt; If (b, Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;, Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;));;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- : (bool expr -&amp;gt; int expr) expr = Lam &amp;lt;fun&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We have that a construction like &lt;code&gt;Lam (fun b -&amp;gt; If (b, b, Lit 6))&lt;&#x2F;code&gt; is not just an error, but a &lt;em&gt;type error&lt;&#x2F;em&gt;!
This means it&#x27;s caught at compile time!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;utop # Lam (fun b -&amp;gt; If (b, b, Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;));;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                               ^^^^^&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Error: This constructor has &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; int expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;       but an expression was expected&lt;&#x2F;span&gt;&lt;span&gt; of &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; bool expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       Type &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;int is not compatible&lt;&#x2F;span&gt;&lt;span&gt; with &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; bool&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;the-actual-evaluator&quot;&gt;The actual evaluator&lt;&#x2F;h2&gt;
&lt;p&gt;From here, the evaluator itself is very simple. We just write the interpretation of our language, as usual:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; rec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; eval&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; = fun&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;  match&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Lit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Bool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; eval a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; eval b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Negate&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; (eval a)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Leq&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (eval a)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span&gt; (eval b)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; If&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;cond&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; (eval cond)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; then&lt;&#x2F;span&gt;&lt;span&gt; (eval l)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; (eval r))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Lam&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;fun&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; f x)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Apply&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; eval ((eval f) x)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Pair&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (eval a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; eval b)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Fst&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; fst (eval a)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Snd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; snd (eval a);;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;Lam&lt;&#x2F;code&gt; and &lt;code&gt;Apply&lt;&#x2F;code&gt; cases are interesting. In the former, we need to return a &lt;em&gt;function&lt;&#x2F;em&gt; of type &lt;code&gt;&#x27;a expr -&amp;gt; &#x27;b expr&lt;&#x2F;code&gt;.
We can start by introducing a function &lt;code&gt;fun x -&amp;gt;&lt;&#x2F;code&gt;, but we have &lt;code&gt;f : &#x27;a expr -&amp;gt; &#x27;b expr&lt;&#x2F;code&gt;, so we just apply it.
In the latter, we need to &lt;code&gt;eval f&lt;&#x2F;code&gt; to get a function &lt;code&gt;&#x27;a expr -&amp;gt; &#x27;b expr&lt;&#x2F;code&gt; from &lt;code&gt;f&lt;&#x2F;code&gt;, which is of type
&lt;code&gt;(&#x27;a expr -&amp;gt; &#x27;b expr) expr&lt;&#x2F;code&gt;. We can then pass it &lt;code&gt;x&lt;&#x2F;code&gt;, which is of type &lt;code&gt;&#x27;a expr&lt;&#x2F;code&gt; to get a &lt;code&gt;&#x27;b expr&lt;&#x2F;code&gt;, which
we must then evaluate again to get a &lt;code&gt;&#x27;b&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now we can run the above examples.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;utop # eval (Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;);;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- : int = 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;utop # eval (Bool true);;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- : bool = true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;utop # eval (Add (Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;, Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;));;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- : int = 9&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;utop # eval (Lam (fun f -&amp;gt; f));;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- : &amp;#39;_weak1 expr -&amp;gt; &amp;#39;_weak1 expr = &amp;lt;fun&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;(* The `_weak1` is due to an internal OCaml limitation, called the &amp;quot;value restriction&amp;quot;. *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;utop # eval (Apply (Lam (fun x -&amp;gt; Add(x,x)), Lit 5));;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- : int = 10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;utop # eval (Lam (fun b -&amp;gt; If (b, Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;, Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;)), Bool true);;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- : bool expr -&amp;gt; int expr = &amp;lt;fun&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;(* Note that this gives us a function returning `int expr`. We&amp;#39;d need to either use `Apply`, like below,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;   or `eval` to get an `int` out of it.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;*)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;utop # eval (Apply (Lam (fun b -&amp;gt; If (b, Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;, Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;)), Bool true));;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- : int = 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Remember, all of the above is completely type safe! We have succesfully constructed an interpreter that can never
type error.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-do-you-apply-this&quot;&gt;How do you apply this?&lt;&#x2F;h2&gt;
&lt;p&gt;In short, it can be hard. One way is to have a &quot;base&quot; language that&#x27;s parsed, and then have your typechecker produce
a representation like the above that you then know is type correct. However, this does prevent typechecker bugs
from sneaking through, which was our entire goal!&lt;&#x2F;p&gt;
&lt;p&gt;To some extent, this is kicking the bucket down the road - you are now relying that your &quot;host language&quot;&#x27;s typechecker
is correct. However, this is a numbers game; if you&#x27;re writing in OCaml or Haskell or similar, the chances of that
are very very high unless you&#x27;re using extremely weird features.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;aside-denotional-semantics&quot;&gt;Aside: Denotional semantics&lt;&#x2F;h2&gt;
&lt;p&gt;The astute may have noted that this is essentially a version of denotional semantics. We&#x27;re interpreting into the
type-safe domain of the host language to ensure that the types always line up (as they must, for the interpretation
to succeed, and the typechecker of the host language ensures that).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;all-code&quot;&gt;All code&lt;&#x2F;h2&gt;
&lt;details&gt;&lt;summary&gt;All the code in one block, for pasting.&lt;&#x2F;summary&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; _ expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Lit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Bool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; bool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; bool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Negate&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Leq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; bool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; If&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; bool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Lam&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Apply&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Pair&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Fst&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Snd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span&gt;;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; rec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; eval&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; = fun&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;  match&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Lit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Bool&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; eval a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; eval b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Negate&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; (eval a)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Leq&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (eval a)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span&gt; (eval b)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; If&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;cond&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; (eval cond)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; then&lt;&#x2F;span&gt;&lt;span&gt; (eval l)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; (eval r))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Lam&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;fun&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; f x)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Apply&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; eval ((eval f) x)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Pair&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (eval a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; eval b)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Fst&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; fst (eval a)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Snd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; snd (eval a);;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;details&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;No, I won&#x27;t do the same joke twice. Most of the time. &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;I am not going into what &quot;ADT&quot; stands for, as it&#x27;s a whole nother debate. &lt;a href=&quot;#fr-2-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-4&quot;&gt;
&lt;p&gt;It may for example eagerly infer &lt;code&gt;(yes, &#x27;a) maybe -&amp;gt; (yes, &#x27;a) maybe&lt;&#x2F;code&gt;, which is a type error, as we also want to handle the &lt;code&gt;(no, &#x27;a) maybe&lt;&#x2F;code&gt; &lt;code&gt;Nothing&lt;&#x2F;code&gt; case. &lt;a href=&quot;#fr-4-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;Higher-order abstract syntax. A bit too in-depth to explore in full right now, but worth exploring. &lt;a href=&quot;#fr-3-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Axiom J in Homotopy Type Theory (HoTT)</title>
        <published>2026-01-01T00:00:00+00:00</published>
        <updated>2026-01-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/cubical-j/"/>
        <id>https://blueberrywren.dev/blog/cubical-j/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/cubical-j/">&lt;h2 id=&quot;preface&quot;&gt;Preface&lt;&#x2F;h2&gt;
&lt;p&gt;Happy new years!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;notation&quot;&gt;Notation&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;∀&lt;&#x2F;code&gt; may be used in place of a Pi-type in some cases. A nested &lt;code&gt;Π (a b : A). ...&lt;&#x2F;code&gt; (or sim. for &lt;code&gt;Σ&lt;&#x2F;code&gt;) represents &lt;code&gt;Π (a : A). Π (b : A). ...&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;j&quot;&gt;J&lt;&#x2F;h3&gt;
&lt;p&gt;Axiom J is the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Given:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;A : Type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;x y : A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;P : Π (a b : A). a = b -&amp;gt; Type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;P x x refl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;and&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;eq : x = y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;we can conclude&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;P x y eq&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;where &lt;code&gt;refl : ∀x. x = x&lt;&#x2F;code&gt;. In short, for any property &lt;code&gt;P&lt;&#x2F;code&gt;, if &lt;code&gt;P&lt;&#x2F;code&gt; is true for &lt;code&gt;x x refl&lt;&#x2F;code&gt;,
and we know that &lt;code&gt;eq : x = y&lt;&#x2F;code&gt;, then &lt;code&gt;P&lt;&#x2F;code&gt; is true for &lt;code&gt;x y eq&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In a non-cubical context, this is obvious - the only proof of &lt;code&gt;x = y&lt;&#x2F;code&gt; for any &lt;code&gt;x&lt;&#x2F;code&gt; and &lt;code&gt;y&lt;&#x2F;code&gt; is &lt;code&gt;refl&lt;&#x2F;code&gt;, so it&#x27;s close to a no-op. However, in HoTT, where there may
be many proofs of &lt;code&gt;x = y&lt;&#x2F;code&gt;, Axiom J is slightly less obvious. Why can we conclude that &lt;code&gt;P&lt;&#x2F;code&gt; is true for any path if we are only given that
it is true at &lt;code&gt;refl&lt;&#x2F;code&gt;?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why&quot;&gt;Why?&lt;&#x2F;h2&gt;
&lt;p&gt;First, let&#x27;s curry &lt;code&gt;P&lt;&#x2F;code&gt;, turning the initial arguments from a Pi-type to a Sigma-type:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;P : Π (a b : A). a = b -&amp;gt; Type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;==&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;P : (Σ(a : A). Σ(b : A). a = b) -&amp;gt; Type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And rewrite the above accordingly.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Given:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;A : Type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;x y : A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;P : (Σ(a : A). Σ(b : A). a = b) -&amp;gt; Type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;P (x, x, refl)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;and&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;eq : x = y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;we can conclude&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;P (x, y, eq)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We will first apply the principle that if &lt;code&gt;a = b&lt;&#x2F;code&gt;, then &lt;code&gt;P a -&amp;gt; P b&lt;&#x2F;code&gt;, generally called something like &lt;code&gt;subst&lt;&#x2F;code&gt;itution. We can use &lt;code&gt;P (x, x, refl)&lt;&#x2F;code&gt; as our &quot;&lt;code&gt;P a&lt;&#x2F;code&gt;&quot;. We then aim to show that:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Given:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;eq : x = y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(x, x, refl) = (x, y, eq)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The first element is obvious - clearly &lt;code&gt;x = x&lt;&#x2F;code&gt;. Now we have to show that &lt;code&gt;(x, refl) = (y, eq)&lt;&#x2F;code&gt;.
This seems impossible! We do &lt;em&gt;not&lt;&#x2F;em&gt; have that &lt;code&gt;refl = eq&lt;&#x2F;code&gt;, due to the nature of HoTT.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s approach this by analysing the type of &lt;code&gt;(x, refl)&lt;&#x2F;code&gt; and &lt;code&gt;(y, eq)&lt;&#x2F;code&gt; (it&#x27;s the same for both; otherwise the equality above wouldn&#x27;t make sense).&lt;&#x2F;p&gt;
&lt;p&gt;Looking at the type of &lt;code&gt;P&lt;&#x2F;code&gt; above, we can conclude that&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(x, refl) : Σ(b : A). x = b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      ^ note the `x` here we got from &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                        the first element of the tuple&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;and then necessarily&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(y, eq)   : Σ(b : A). x = b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now for the trick. While we do &lt;em&gt;not&lt;&#x2F;em&gt; have that &lt;code&gt;refl = eq&lt;&#x2F;code&gt;, we don&#x27;t actually need it!
It turns out that we can prove that any element of &lt;code&gt;Σ(b : A). x = b&lt;&#x2F;code&gt; is equal to any other element of &lt;code&gt;Σ(b : A). x = b&lt;&#x2F;code&gt;, irregardless of
the proof of equality used - in other words, &lt;code&gt;Σ(b : A). x = b&lt;&#x2F;code&gt; only has one inhabitant. This property (only having one inhabitant) is called &quot;contractibility&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;A &quot;proper&quot; proof of this requires some careful thinking
(One can be found &lt;a href=&quot;https:&#x2F;&#x2F;1lab.dev&#x2F;1Lab.Path.html#34069&quot;&gt;here as &lt;code&gt;Singleton-contract&lt;&#x2F;code&gt;, in Cubical Agda, courtesy of the 1lab&lt;&#x2F;a&gt;,
and it&#x27;s Lemma 3.11.8 in the HoTT book, at time of writing.), but I&#x27;ll give an informal one here.&lt;&#x2F;p&gt;
&lt;p&gt;Consider what &lt;code&gt;Σ(b : A). x = b&lt;&#x2F;code&gt; &lt;em&gt;means&lt;&#x2F;em&gt;. One way of interpreting it is like it&#x27;s a subset - that
&quot;&lt;code&gt;Σ(b : A). x = b&lt;&#x2F;code&gt; is the type of things that are elements of &lt;code&gt;A&lt;&#x2F;code&gt; equal to &lt;code&gt;x&lt;&#x2F;code&gt;&quot;.
However, there&#x27;s only one of those! Namely, &lt;code&gt;x&lt;&#x2F;code&gt; itself. If we chose anything else, we wouldn&#x27;t have &lt;code&gt;x = b&lt;&#x2F;code&gt; in the first place.
This means that our choice of equality doesn&#x27;t matter at all - when we consider the tuple as a whole, there can only be one inhabitant.
Hence, as we already have that &lt;code&gt;x = y&lt;&#x2F;code&gt;, we have &lt;code&gt;(x, refl) = (x, eq) = (y, eq)&lt;&#x2F;code&gt;, completing our proof.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tldr&quot;&gt;TLDR&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;J : Π (A : Type) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      (x y : A)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      (eq : x = y)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      (P : Π(a b : A). x = y -&amp;gt; Type).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         P x x refl &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&amp;gt; P x y eq&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Goal : P x y eq&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Consider the equivalent &quot;curried&quot; version, so curry &lt;code&gt;P&lt;&#x2F;code&gt;:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;J : Π (A : Type) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      (x y : A)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      (eq : x = y)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      (P : (Σ(a : A). Σ(b : A). a = b) -&amp;gt; Type).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         P (x, x, refl)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&amp;gt; P (x, y, eq)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Goal : P (x, y, eq)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Use &lt;code&gt;subst : a = b -&amp;gt; P a -&amp;gt; P b&lt;&#x2F;code&gt;:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Goal : (x, x, refl) = (x, y, eq)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;Use that &lt;code&gt;Π x a b. a = b -&amp;gt; (x, a) = (x, b)&lt;&#x2F;code&gt; (with &lt;code&gt;a = (x, refl)&lt;&#x2F;code&gt; and &lt;code&gt;b = (y, eq)&lt;&#x2F;code&gt;:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Goal : (x, refl) = (y, eq)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;Use that &lt;code&gt;Σ(b : A). x = b&lt;&#x2F;code&gt; is contractible (&lt;code&gt;Π (one two : Σ(b : A). x = b)). one = two&lt;&#x2F;code&gt;):&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Done!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A handwavy &quot;proof term&quot; may look like (ommitting some &quot;obvious&quot; arguments, as one may do with implicit arguments in Agda):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Given:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;subst : Π P a b. a = b -&amp;gt; P a -&amp;gt; P b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;subst-fst : Π x y p q. (x , p) = (x , q) -&amp;gt; x = y -&amp;gt; (x , p) = (y , q)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pair-snd-eq : Π x a b. a = b -&amp;gt; (x , a) = (x , b)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;singleton-contractible : Π x (one two : Σ(b : A). x = b)). one = two&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;We have:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;J : Π (A : Type) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      (x y : A)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      (eq : x = y)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      (P : (Σ(a : A). Σ(b : A). a = b) -&amp;gt; Type).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         P x x refl &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&amp;gt; P x y eq&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;J A x y eq P Pxxrefl = &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  subst  (pair-snd-eq singleton-contractible) Pxxrefl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Written in Pure Sea</title>
        <published>2025-12-19T00:00:00+00:00</published>
        <updated>2025-12-19T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/pure-sea/"/>
        <id>https://blueberrywren.dev/blog/pure-sea/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/pure-sea/">&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣴⣶⠾⠿⠿⠯⣷⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⣾⠛⠁⠀⠀⠀⠀⠀⠀⠈⢻⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⠿⠁⠀⠀⠀⢀⣤⣾⣟⣛⣛⣶⣬⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⠟⠃⠀⠀⠀⠀⠀⣾⣿⠟⠉⠉⠉⠉⠛⠿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⡟⠋⠀⠀⠀⠀⠀⠀⠀⣿⡏⣤⠀⠀__&#x2F;\웃_⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;⠀⠀⠀⠀⠀⠀⠀⣠⡿⠛⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⣷⡍⠀⠀\____&#x2F;⠀⠀⠀⢀⣀⣀⣤⣤⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀ &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;⠀⠀⠀⠀⠀⣠⣼⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠷⣤⣤⣠⣤⣤⡤⡶⣶⢿⠟⠹⠿⠄⣿⣿⠏⠀⣀⣤⡦⠀⠀⠀⠀⣀⡄&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;⢀⣄⣠⣶⣿⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠓⠚⠋⠉⠀⠀⠀⠀⠀⠀⠈⠛⡛⡻⠿⠿⠙⠓⢒⣺⡿⠋⠁&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;⠉⠉⠉⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠁⠀&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I don&#x27;t have great C legs.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Horrible answers to &quot;What is a type?&quot;</title>
        <published>2025-11-17T00:00:00+00:00</published>
        <updated>2025-11-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/horrible-types/"/>
        <id>https://blueberrywren.dev/blog/horrible-types/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/horrible-types/">&lt;ul&gt;
&lt;li&gt;A set.&lt;&#x2F;li&gt;
&lt;li&gt;Absolutely not a set.&lt;&#x2F;li&gt;
&lt;li&gt;An element of a category.&lt;&#x2F;li&gt;
&lt;li&gt;A proposition.&lt;&#x2F;li&gt;
&lt;li&gt;A chosen fixed point of a generating function.&lt;&#x2F;li&gt;
&lt;li&gt;The initial algebra&#x2F;final coalgebra of a generating endofunctor over a reasonable base category (say, &lt;code&gt;Set&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;A metaphorical representation of bytes.&lt;&#x2F;li&gt;
&lt;li&gt;A membership function &lt;code&gt;UNIV → bool&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;That thing you put after the &lt;code&gt;:&lt;&#x2F;code&gt; to make the computer stop yelling at you :(&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;as any&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Propaganda made up by Big Typechecker to make us complacent.&lt;&#x2F;li&gt;
&lt;li&gt;Nerd shit.&lt;&#x2F;li&gt;
&lt;li&gt;The archetype of person that you tend to feel attracted to romantically.&lt;&#x2F;li&gt;
&lt;li&gt;A metal plate with a glyph, used for printing ink onto paper.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Opinion piece: On Zig (and the design choices within)</title>
        <published>2025-10-14T00:00:00+00:00</published>
        <updated>2025-10-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/on-zig/"/>
        <id>https://blueberrywren.dev/blog/on-zig/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/on-zig/">&lt;p&gt;(From someone who has spent far too much time thinking about the designs of programming languages)&lt;&#x2F;p&gt;
&lt;p&gt;This post is split up into a few sections. I would also like to preface this post with:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;This is a little bit of a rant. I believe it presents some very reasonable points about Zig as a language, but it&#x27;s not going to be
perfect or completely objective. It is an opinion piece, and you&#x27;re free to ignore it if you want.&lt;&#x2F;li&gt;
&lt;li&gt;Existing memory safe languages are not perfect. Rust will be used as an example quite a bit, as from what is currently available, it embodies closer to what I think is reasonable in a programming language. However, there is still much room for improvement in this space.&lt;&#x2F;li&gt;
&lt;li&gt;All of the following is ultimately my opinion. If you disagree, you are welcome to find me somewhere on the internet and ask me more.&lt;&#x2F;li&gt;
&lt;li&gt;I bear no grudge or ill will against anyone who contributes to, works on, or is otherwise involved in the Zig community. The following are things I have noted about the language, not the people behind it. If you enjoy Zig, go and write it, and make cool stuff - I am not the programming language police.&lt;&#x2F;li&gt;
&lt;li&gt;Exception to the above: I have one gripe about the Zig community. This gripe &quot;targets&quot; no one person in particular; rather, larger trends.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;ideological-differences&quot;&gt;Ideological differences&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;memory&quot;&gt;Memory&lt;&#x2F;h3&gt;
&lt;p&gt;First, and very much foremost, Zig is not memory safe. This is, in my opinion, the most
egregious thing in this post, by a very large margin. Moreso, Zig does not make any attempt to
be memory safe -
it can catch some things at runtime, with specific allocators, but so can C these days. Indeed, there
are some cases, like use-after-realloc, that &lt;code&gt;asan&lt;&#x2F;code&gt; can catch and Zig cannot.&lt;&#x2F;p&gt;
&lt;p&gt;A language in the modern day that does not make an attempt at memory safety is, in my opinion, not reasonable. It has been shown that in some areas, up to 70% of security bugs are due to memory safety issues (&lt;a href=&quot;https:&#x2F;&#x2F;www.chromium.org&#x2F;Home&#x2F;chromium-security&#x2F;memory-safety&#x2F;&quot;&gt;Source&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;I subscribe to the idea that the user must be constrained. It is perhaps harsh to say, but for large and complex programs, I believe that there are very few programmers who will write memory-correct code nine times out of ten. When writing code with others, that goes down. I personally do not believe I fit into that category.&lt;&#x2F;p&gt;
&lt;p&gt;The fact that Zig allows the user to write faulty software is supported by various somewhat informal, but still useful, statistics. Notably, the following statistic disregard duplicates, and unreported errors. However, general trends are still of note.&lt;&#x2F;p&gt;
&lt;p&gt;UPDATE: Someone has done a much more thorough analysis of crashes in JS runtimes! Thank you to the authors of the &lt;a href=&quot;https:&#x2F;&#x2F;js-segfault-compare.sigmasd.workers.dev&#x2F;&quot;&gt;Javascript Runtime Segfault Tracker&lt;&#x2F;a&gt;, which demonstrates my point very effectively. To quote the person who sent me this: &quot;it&#x27;s a log scale. i&#x27;ll let you guess which runtime is responsible for that.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;For posterity, I leave my own analysis below:&lt;&#x2F;p&gt;
&lt;details&gt;&lt;summary&gt;Here are some:&lt;&#x2F;summary&gt;
&lt;ol&gt;
&lt;li&gt;The Rust compiler has had a lifetime 59,780 issues reported. Of these, 4,158 contain one of &quot;crash&quot;, &quot;segmentation fault&quot;, or &quot;segfault&quot;.&lt;&#x2F;li&gt;
&lt;li&gt;The Zig compiler has had a lifetime 13,269 issues reported. Of these, 2,260 contain one of &quot;crash&quot;, &quot;segmentation fault&quot;, or &quot;segfault&quot;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This means that, roughly:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;7% of lifetime issues reported in the Rust compiler are crashes.&lt;&#x2F;li&gt;
&lt;li&gt;17% of lifetime issues reported in the Zig compiler are crashes.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Not ideal.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The Node&#x2F;v8 JS runtime, written partially itself in JS and partially in C++, has had a lifetime 19,631 issues reported, 1,710 of which contain one of the above keywords.&lt;&#x2F;li&gt;
&lt;li&gt;The Deno JS runtime, written primarily in Rust, has had a lifetime 13,422 issues reported, 552 of which contain one of the above keywords.&lt;&#x2F;li&gt;
&lt;li&gt;The Bun JS runtime, written in Zig, has had a lifetime 13,828 issues reported, 3676 of which contain one of the above keywords.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Again, this roughly means:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;8.7% of lifetime issues reported in Node are crashes.&lt;&#x2F;li&gt;
&lt;li&gt;4.1% of lifetime issues reported in Deno are crashes.&lt;&#x2F;li&gt;
&lt;li&gt;26.5% (!!!) of lifetime issues reported in Bun are crashes.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Also not great. Again, these statistics are slightly off at best simply due to the nature of their collection, but the trends do not lie.&lt;&#x2F;p&gt;
&lt;&#x2F;details&gt;
&lt;p&gt;If you&#x27;re not reading the above: It can be summarized as &quot;Pretty bad.&quot;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;philosophy&quot;&gt;Philosophy&lt;&#x2F;h3&gt;
&lt;p&gt;At one point, this part of the article contained a runthrough of the &lt;code&gt;zig zen&lt;&#x2F;code&gt;, and my opinions on each bullet point. I have decided that that is not a constructive discussion of Zig. It suffices for me to say that I do not believe Zig particularly embodies its own zen.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;practical&quot;&gt;Practical&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;comptime&quot;&gt;Comptime&lt;&#x2F;h3&gt;
&lt;p&gt;Zig does generics in an odd way. I believe this is the best way of putting it.
This post is not meant to be, nor will it contain, a proper explanation of Zig&#x27;s &lt;code&gt;comptime&lt;&#x2F;code&gt;
capabilities, so I refer the reader to the wider internet there. However, doing generics
with &quot;normal&quot; code means that there are multiple ways to write the same generic function.
There is no standardization between different libraries, different styles of writing code, and
different users of Zig. Every person can do generics in their own special way.&lt;&#x2F;p&gt;
&lt;p&gt;This obviously has slightly dire effects on readability. In practice, most Zig users are reasonable enough
to stick to some &quot;common patterns&quot; of doing generics and similar, but it is widely known that if the user is giving the ability to do something, it will be done. I believe that generics are important enough they should be first class.&lt;&#x2F;p&gt;
&lt;p&gt;Arguments can be made that Zig&#x27;s comptime is also useful for other things, not just generics. Some examples I have been given are conditional compilation, and variadic functions. Beyond these, I am yet to see a convincing motivating example that &lt;em&gt;requires&lt;&#x2F;em&gt; the machinery that Zig provides. Every such example can, in my experience, be solved with less powerful (and hence, for the most part, less confusing) machinery.&lt;&#x2F;p&gt;
&lt;p&gt;As a result, I am inclined to believe that Zig&#x27;s comptime is a very large and all-encompassing feature that ultimately brings very little to the table that smaller features cannot.&lt;&#x2F;p&gt;
&lt;p&gt;I am personally a proponent of a good macro system, but I will readily admit people can also go overboard with one of those.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;casting&quot;&gt;Casting&lt;&#x2F;h3&gt;
&lt;p&gt;Zig&#x27;s casting is a bit cumbersome. To cast a float to a specific int width, for example, must be done with &lt;code&gt;@as(i32, @intFromFloat(flt))&lt;&#x2F;code&gt;. Bit of a mouthful. Inference can help here (For example if a variable is already known to be a &lt;code&gt;i32&lt;&#x2F;code&gt;, the outer cast is not needed), but I would think that with Zig&#x27;s comptime abilities, this could be made a bit nicer. Luckily, it is common Zig practice to annotate everything if possible, so this does come up slightly less in practice. It is still a bit bulky however.&lt;&#x2F;p&gt;
&lt;p&gt;Float to int casting additionally can invoke undefined behavior if the float is outside the integer&#x27;s range. I personally prefer truncating semantics, with perhaps a specialized method (&lt;code&gt;intFromFloatUnsafe&lt;&#x2F;code&gt;?) for UB semantics. That&#x27;s more of a personal preference though.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;semantics&quot;&gt;Semantics&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;result-location-semantics-rls&quot;&gt;Result location semantics (RLS)&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;ziglang.org&#x2F;documentation&#x2F;0.15.1&#x2F;#Result-Location-Semantics&quot;&gt;See here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Result location semantics are in theory a quite nice idea. Knowing predictably where things are going to be placed in memory is, of course, good for any systems-adjacent language! In practice, there are several choices within RLS that I find counterintuitive. Take the following example, where we attempt to swap two struct members in place:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; = @&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;&amp;quot;std&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; What&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #000000;background-color: #FFFFFF;&quot;&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;text-decoration: underline;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #000000;background-color: #FFFFFF;&quot;&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;text-decoration: underline;&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() void {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    var x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #000000;background-color: #FFFFFF;&quot;&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;text-decoration: underline;&quot;&gt;What&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; = .&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; .&lt;&#x2F;span&gt;&lt;span&gt;a &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; .&lt;&#x2F;span&gt;&lt;span&gt;b &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt; };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #000000;background-color: #FFFFFF;&quot;&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;text-decoration: underline;&quot;&gt;What&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; .&lt;&#x2F;span&gt;&lt;span&gt;a &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;b,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; .&lt;&#x2F;span&gt;&lt;span&gt;b &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;a };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;log&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;info&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;&amp;quot;x: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; .&lt;&#x2F;span&gt;&lt;span&gt;{x});&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    var y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #000000;background-color: #FFFFFF;&quot;&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;text-decoration: underline;&quot;&gt;What&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; = .&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; .&lt;&#x2F;span&gt;&lt;span&gt;a &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; .&lt;&#x2F;span&gt;&lt;span&gt;b &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt; };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; = .&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; .&lt;&#x2F;span&gt;&lt;span&gt;a &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;b,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; .&lt;&#x2F;span&gt;&lt;span&gt;b &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;a };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;log&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;info&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;&amp;quot;y: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; .&lt;&#x2F;span&gt;&lt;span&gt;{y});&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This outputs the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;info&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;: .&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; .&lt;&#x2F;span&gt;&lt;span&gt;a &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; .&lt;&#x2F;span&gt;&lt;span&gt;b &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;info&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;: .&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; .&lt;&#x2F;span&gt;&lt;span&gt;a &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; .&lt;&#x2F;span&gt;&lt;span&gt;b &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I will note that the equivalent C can only be written in the former style, and it prints the former.&lt;&#x2F;p&gt;
&lt;p&gt;The only difference between the latter and the former is whether the type name is present. This is intended behavior! Indeed, this very example is given in the Zig reference, a fact that I find odd. Why give a warning against something when you could just fix it? Zig does not have move or copy constructors; I do not think there is very much reason for the latter to ever behave the way it does. One extra register is all you ever need, even for an arbitrary parallel move! (&lt;a href=&quot;https:&#x2F;&#x2F;compiler.club&#x2F;parallel-moves&#x2F;&quot;&gt;Source&lt;&#x2F;a&gt;.)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;pointer-reference-optimization&quot;&gt;Pointer reference optimization&lt;&#x2F;h3&gt;
&lt;p&gt;In its previous form, PRO has been removed from Zig. There was a long period where this would print &lt;code&gt;5&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; = @&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;&amp;quot;std&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; AAAA&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    foo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;text-decoration: underline;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; kindabad&lt;&#x2F;span&gt;&lt;span&gt;(a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; AAAA&lt;&#x2F;span&gt;&lt;span&gt;, b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;: *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;AAAA&lt;&#x2F;span&gt;&lt;span&gt;) void {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.*.&lt;&#x2F;span&gt;&lt;span&gt;foo[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;debug&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;&amp;quot;unideal: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; .&lt;&#x2F;span&gt;&lt;span&gt;{ a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;foo[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; !&lt;&#x2F;span&gt;&lt;span&gt;void {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    var f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; AAAA&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; undefined;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;foo[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;    kindabad&lt;&#x2F;span&gt;&lt;span&gt;(f,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;f);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As Zig would correctly, per PRO at the time, but incorrectly per common sense, pass &lt;code&gt;a&lt;&#x2F;code&gt; as a reference.&lt;&#x2F;p&gt;
&lt;p&gt;This is actually mildly unfortunate. It&#x27;s a very interesting optimization, and being able to guarantee behavior around optimization of parameter passing would also be quite beneficial. Unfortunately, Zig simply does not have the level of control needed to do it. Aliasing is freely allowed, and in order to make PRO work, it cannot be. Rust can, and in many cases does, do this! It&#x27;s a shame Zig has to miss out.&lt;&#x2F;p&gt;
&lt;p&gt;There is current work to make PRO work in the case of pure functions (&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ziglang&#x2F;zig&#x2F;issues&#x2F;5973#issuecomment-2380332493&quot;&gt;Source&lt;&#x2F;a&gt;), so I remain hopeful that it will return in some form eventually.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;misc-improvable-things&quot;&gt;Misc. Improvable things&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;speed&quot;&gt;Speed&lt;&#x2F;h3&gt;
&lt;p&gt;The Zig compiler is not particularly fast. The LLVM backend even more so; compared to Clang, (which has the home field advantage, but can still be quite slow), and by my measurements, Clang is consistently between 3-10x faster. A new Zig backend has been written to help fix this; by similar measurements, it is consistently faster than Clang by 1.5-2x, and much faster than the Zig LLVM backend. While these numbers are nothing to scoff at, I believe there is more room for improvement, and I would like to see where it goes. Zig is a simpler language than C when comptime is not involved, and I would be excited to see that reflected in the benchmarks. It is also possible that Zig could use LLVM more efficiently, but I cannot comment on this without digging into the internals of the compiler.&lt;&#x2F;p&gt;
&lt;p&gt;Of course, all of this is quite reasonable. The Zig compiler has had far, far fewer man-hours put into it, and this of course reflects in aspects of the compiler that simply take a lot of time, such as these. I look forward to seeing what can be done in the future.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tooling&quot;&gt;Tooling&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;build-system&quot;&gt;Build system&lt;&#x2F;h4&gt;
&lt;p&gt;The Zig build system is a little confusing. It is very neat to be able to write build system code in the language itself, and this is a feature I believe more languages should have. Unfortunately, it is as of current not well documented enough to justify its own complexity. This of course can be improved, and I hope it is.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;language-server&quot;&gt;Language server&lt;&#x2F;h4&gt;
&lt;p&gt;Zig currently does not have a &quot;first class&quot; language server. The &quot;Zig Language Server&quot;, or ZLS, is unofficial; It does not have real compiler integration, so it is unfortunately limited in some ways. The creator of Zig apparently does not use a language server while programming, so I do slightly understand why it is not a priority, but I personally believe tools like a good language server are quite essential to wider&#x2F;popular usage. Here are some quotes I have heard from people who have used it far more than I:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&quot;Deeply horrid&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&quot;It is one of the worst LSPs I have ever used&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&quot;Don&#x27;t get me started&quot;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Apparently it is very limited when &lt;code&gt;comptime&lt;&#x2F;code&gt; comes into play, and cannot handle compound types like 2D arrays.&lt;&#x2F;p&gt;
&lt;p&gt;I cannot offer much firsthand experience however.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;debug-mode&quot;&gt;Debug mode&lt;&#x2F;h3&gt;
&lt;p&gt;There are always more errors to be caught. I particularly recently noticed that Zig cannot currently catch use-after-realloc errors, like the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; = @&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;&amp;quot;std&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; !&lt;&#x2F;span&gt;&lt;span&gt;void {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span&gt; allocator&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;heap&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;page_allocator;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    var buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; = try&lt;&#x2F;span&gt;&lt;span&gt; allocator&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;alloc&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;text-decoration: underline;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    buffer[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span&gt; new_buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; = try&lt;&#x2F;span&gt;&lt;span&gt; allocator&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;realloc&lt;&#x2F;span&gt;&lt;span&gt;(buffer,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;    &#x2F;&#x2F; Should be caught!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    buffer[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 99&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    allocator&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;free&lt;&#x2F;span&gt;&lt;span&gt;(new_buffer);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Address sanitizer with Clang can catch this, so theoretically Zig should be able to catch it (perhaps with a similar system) too.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;misc-improvable-things-that-won-t-be-improved-for-reasons-beyond-me&quot;&gt;Misc. Improvable things that won&#x27;t be improved for reasons beyond me&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;behavior-around-undefined&quot;&gt;Behavior around &lt;code&gt;undefined&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;debug-mode-1&quot;&gt;Debug mode&lt;&#x2F;h4&gt;
&lt;p&gt;Apparently, it is desired that comparisons with &lt;code&gt;undefined&lt;&#x2F;code&gt; panic. This seems reasonable to me. However, the issue for this has been open &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ziglang&#x2F;zig&#x2F;issues&#x2F;63&quot;&gt;for almost ten years&lt;&#x2F;a&gt;, which makes me worry that it might be a while still until it is finished.&lt;&#x2F;p&gt;
&lt;p&gt;This panics in &lt;code&gt;Debug&lt;&#x2F;code&gt; and &lt;code&gt;ReleaseSafe&lt;&#x2F;code&gt; modes, however, so it does at least work in some cases.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() void {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #000000;background-color: #FFFFFF;&quot;&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;text-decoration: underline;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; undefined;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; (x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;safety&quot;&gt;Safety&lt;&#x2F;h4&gt;
&lt;p&gt;According to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ziglang&#x2F;zig&#x2F;issues&#x2F;21915&quot;&gt;this issue&lt;&#x2F;a&gt;, it is &quot;not a goal of the Zig compiler&quot; to catch issues like the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;() void {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    var buf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; []&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;text-decoration: underline;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; undefined;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;    &#x2F;&#x2F; Very not allowed!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    buf[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This just seems silly to me. Catching something like this, in the simple case, should be just one pass over the AST; why not do it?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tabs-and-syntax&quot;&gt;Tabs and syntax&lt;&#x2F;h3&gt;
&lt;p&gt;Zig simply doesn&#x27;t allow tabs in comments and strings? &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ziglang&#x2F;zig-spec&#x2F;issues&#x2F;38&quot;&gt;This issue&lt;&#x2F;a&gt; explains more, but the justification of &quot;it (a tab) is ambiguous (in) how it should be rendered&quot;, I do not quite agree with.&lt;&#x2F;p&gt;
&lt;p&gt;Strings make some sense; you can still write &lt;code&gt;\t&lt;&#x2F;code&gt; for a tab, and they do indeed make output ambiguous. However, they&#x27;re still allowed in indentation! This means that in commenting out code, you can take a program from valid to invalid. &lt;code&gt;zig fmt&lt;&#x2F;code&gt; does reify tabs into spaces, but if your editor is misconfigured and you&#x27;re not running &lt;code&gt;zig fmt&lt;&#x2F;code&gt; constantly?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tabs.zig:5:36: error: comment contains invalid byte: &amp;#39;\t&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;&#x2F;        const str: *const [1:0]u8 = &amp;quot;w&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ^~~~~~~~~~~&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Very odd.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly, the following will not compile:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; (a &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;&amp;gt;=&lt;&#x2F;span&gt;&lt;span&gt;b) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;because the whitespace isn&#x27;t correct. Zig doesn&#x27;t have warnings, so this is always a compile error.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;iteration&quot;&gt;Iteration&lt;&#x2F;h3&gt;
&lt;p&gt;Zig does not have a way to iterate through a slice or similar in any way except one-at-a-time forwards. Anything else? You&#x27;re using a &lt;code&gt;while&lt;&#x2F;code&gt; loop, and you&#x27;ll enjoy it. Zig blanket bans proposals to change the language, so despite issues like &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ziglang&#x2F;zig&#x2F;issues&#x2F;21814&quot;&gt;this one&lt;&#x2F;a&gt;, I doubt this will happen any time soon.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;warnings&quot;&gt;Warnings&lt;&#x2F;h3&gt;
&lt;p&gt;Zig doesn&#x27;t have &#x27;em. Everything is an error. In practice, this mostly manifests through reasonably harmless things like &quot;unused variable&quot; notices becoming errors, which is reasonably annoying when just trying to spitball.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;my-only-note-on-the-community&quot;&gt;My only note on the community&lt;&#x2F;h2&gt;
&lt;p&gt;For the most part, the community is about par for the course for programming language communities; that is to say, quite nice. However, I have had some reasonably negative interactions that I feel are somewhat of a general trend. They usually proceed like the following:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;I ask a question about solving something in Zig. Often, given my background, it is about adapting my more functional-esque thinking to Zig.&lt;&#x2F;li&gt;
&lt;li&gt;Someone chimes in with a half-solution that does not actually address my problem.&lt;&#x2F;li&gt;
&lt;li&gt;I attempt to communicate this to them, which often involves explaining the features I would use in &amp;lt;insert other language&amp;gt;.&lt;&#x2F;li&gt;
&lt;li&gt;They insist that these features are not needed, but do not elaborate on how one would solve the problem without them.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This is unpleasant, and while it&#x27;s not a particularly uncommon thing to see in programming language communities, Zig seems to have a bit of a bad case of it. I suspect it is due to Zig&#x27;s fairly minimalistic nature; it lacks a lot of features that one would otherwise use to solve problems. Of course, this is the appeal for many, but still. It is made worse when said topic is something one is particularly knowledgeable about, and the people you are conversing with believe they can solve the issue without that knowledge.&lt;&#x2F;p&gt;
&lt;p&gt;I do not believe that a few bad apples necessarily spoil the whole barrel here, but they definitely sour it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;&#x2F;h2&gt;
&lt;p&gt;I find Zig interesting, with an unfortunately negative connotation. I believe the goal of a C-like memory unsafe language &quot;for the modern day&quot;, while interesting at first glance, ignores many of the issues that make C a problem in said modern day. Much of Zig seems to me like &quot;wishful thinking&quot;; if every programmer was 150% smarter and more capable, perhaps it would work. Alas, they are not; myself included.&lt;&#x2F;p&gt;
&lt;p&gt;I believe that modern concerns of memory safety and correctness require modern solutions; not performing patchwork fixes over the core issue.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Isabelle&#x2F;HOL: The various rule methods</title>
        <published>2025-09-19T00:00:00+00:00</published>
        <updated>2025-09-19T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/isabelle-rule-musings/"/>
        <id>https://blueberrywren.dev/blog/isabelle-rule-musings/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/isabelle-rule-musings/">&lt;p&gt;The following is adapted from the &lt;a href=&quot;https:&#x2F;&#x2F;isabelle.in.tum.de&#x2F;documentation.html&quot;&gt;Isabelle&#x2F;HOL 2025 tutorial&lt;&#x2F;a&gt;, particularly 5.2 and onwards. It will explain much more thoroughly than I can, so please use it as a source of truth.&lt;&#x2F;p&gt;
&lt;p&gt;I also make no promise that the following is entirely 100% correct. It is ultimately my understanding, but I have run it past several others, and to the best of our knowledge it is correct.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;notes&quot;&gt;Notes&lt;&#x2F;h1&gt;
&lt;p&gt;These rule methods can be used in many different ways. While some general principles are mentioned below, if the prerequisits are met,
every rule can theoretically be used with every rule method. Many of these various combinations will not be beneficial to proving a given
goal, and hence it is useful to know how the rule methods interact with rules and proof states in order to select the correct pairing.&lt;&#x2F;p&gt;
&lt;p&gt;In that vein, the same rule will be interpreted differently by these different rule methods. Read more for how they work, and hence why.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;rule-erule-drule-and-frule-informally&quot;&gt;&lt;code&gt;rule&lt;&#x2F;code&gt;, &lt;code&gt;erule&lt;&#x2F;code&gt;, &lt;code&gt;drule&lt;&#x2F;code&gt;, and &lt;code&gt;frule&lt;&#x2F;code&gt;, informally&lt;&#x2F;h1&gt;
&lt;p&gt;We use &lt;code&gt;P&lt;&#x2F;code&gt;, &lt;code&gt;Q&lt;&#x2F;code&gt;, and &lt;code&gt;R&lt;&#x2F;code&gt; as arbitrary assumptions and goals throughout.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rule&quot;&gt;&lt;code&gt;rule&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Consider the introduction rule &lt;code&gt;conjI&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P   Q&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;----- conjI&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ∧&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; Q&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we have a goal of form &lt;code&gt;R ==&amp;gt; P ∧ Q&lt;&#x2F;code&gt;, from &lt;code&gt;conjI&lt;&#x2F;code&gt; we can infer that it is sufficent to seperately prove &lt;code&gt;P&lt;&#x2F;code&gt; and &lt;code&gt;Q&lt;&#x2F;code&gt;. Indeed, performing &lt;code&gt;apply (rule conjI)&lt;&#x2F;code&gt; on a goal of this shape will result in two goals:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; R&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; P&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; R&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; Q&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;which can be then proven seperately. &lt;code&gt;rule&lt;&#x2F;code&gt; is for backwards-reasoning; here we can see that as moving &quot;backwards up&quot; the introduction rule (Starting with the bottom, and ending with the top.) It is therefore useful for introduction rules, as demonstrated.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;erule&quot;&gt;&lt;code&gt;erule&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;erule&lt;&#x2F;code&gt; is designed to function with elimination rules. The &lt;code&gt;e&lt;&#x2F;code&gt; hence stands for &lt;code&gt;elimination&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;eliminator&lt;&#x2F;code&gt;. Take for example the elimination rule for disjunction:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ∨&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; Q&lt;&#x2F;span&gt;&lt;span&gt;     (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; R&lt;&#x2F;span&gt;&lt;span&gt;)    (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; R&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;-------------------------------- disjE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;              R&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(Informally, to prove something about a disjunction, we must handle both possible cases.)&lt;&#x2F;p&gt;
&lt;p&gt;If we have a goal of the form:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ∨&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; R&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;we can perform &lt;code&gt;apply (erule disjE)&lt;&#x2F;code&gt; to transform this into two goals:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; R&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; R&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;where we must handle each possible case of the disjunction. &lt;code&gt;erule&lt;&#x2F;code&gt; is a bit of both backwards and forwards reasoning. In the above elimination rule, we can see that we need three assumptions to prove &lt;code&gt;R&lt;&#x2F;code&gt; --- we already have &lt;code&gt;P ∨ Q&lt;&#x2F;code&gt;, so it is sufficient to then only additionally prove &lt;code&gt;P ==&amp;gt; R&lt;&#x2F;code&gt; and &lt;code&gt;Q ==&amp;gt; R&lt;&#x2F;code&gt;, which are exactly the goals &lt;code&gt;erule&lt;&#x2F;code&gt; gives us.&lt;&#x2F;p&gt;
&lt;p&gt;Notable: &lt;code&gt;erule&lt;&#x2F;code&gt; deletes the already-held assumption, as it is &quot;rarely useful&quot; (quoting the Isabelle&#x2F;HOL tutorial). See below&#x27;s note for more.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;note-on-rule-vs-erule&quot;&gt;Note on &lt;code&gt;rule&lt;&#x2F;code&gt; vs &lt;code&gt;erule&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;As mentioned, &lt;code&gt;erule&lt;&#x2F;code&gt; deliberately deletes the already-held assumptions when using an elimination rule. Above, we could see that &lt;code&gt;P ∨ Q&lt;&#x2F;code&gt; was not present in the generated goals, as it was already assumed. By instead using &lt;code&gt;rule&lt;&#x2F;code&gt;, we can keep the original goal in our assumptions as follows. If we apply the principles from the &lt;code&gt;rule&lt;&#x2F;code&gt; section to &lt;code&gt;disjE&lt;&#x2F;code&gt;, we would get:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ∨&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; R&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apply (rule disjE)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;⟦&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ∨&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ⟧ ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ∨&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; Q&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;⟦&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ∨&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; Q&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ⟧ ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; R&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;⟦&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ∨&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; Q&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ⟧ ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; R&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;i.e., &lt;code&gt;rule&lt;&#x2F;code&gt;, as expected, replaces the goal R with the goals sufficent to prove it. In this case, however, the first goal is trivial, and in the latter two, &lt;code&gt;P ∨ Q&lt;&#x2F;code&gt; holds little worth, as we know either &lt;code&gt;P&lt;&#x2F;code&gt; or &lt;code&gt;Q&lt;&#x2F;code&gt;. This is why &lt;code&gt;erule&lt;&#x2F;code&gt; automatically discharges the first goal and deletes the already-held assumption.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;drule&quot;&gt;&lt;code&gt;drule&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;For the sake of example, recall (one of) the conjunction elimination rules:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ∧&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; Q&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;----- conjunct1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;  P&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This rule is more specifically called a &quot;destruction&quot; rule, as it takes apart (destroys) the original term (here the conjunction) and concludes with one of its subterms. The &lt;code&gt;d&lt;&#x2F;code&gt; in &lt;code&gt;drule&lt;&#x2F;code&gt; therefore stands for &lt;code&gt;destruction&lt;&#x2F;code&gt; or &lt;code&gt;destroy&lt;&#x2F;code&gt;. Destruction rules are used for forwards-reasoning, as you move &quot;forwards down&quot; the rule.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;apply (drule conjunct1)&lt;&#x2F;code&gt; hence replaces an assumption of form &lt;code&gt;P ∧ Q&lt;&#x2F;code&gt; with one of &lt;code&gt;P&lt;&#x2F;code&gt;, deleting the original &lt;code&gt;P ∧ Q&lt;&#x2F;code&gt; assumption.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ∧&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; R&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apply (drule conjunct1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; R&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;frule&quot;&gt;&lt;code&gt;frule&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;frule&lt;&#x2F;code&gt; functions the same as &lt;code&gt;drule&lt;&#x2F;code&gt;, but does not delete the original premise. The &lt;code&gt;f&lt;&#x2F;code&gt; stands for &lt;code&gt;forwards&lt;&#x2F;code&gt;, as it is used for forwards-reasoning.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ∧&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; R&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apply (frule conjunct1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;⟦&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ∧&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; Q&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ⟧ ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; R&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;useful-related-tools&quot;&gt;Useful related tools&lt;&#x2F;h2&gt;
&lt;p&gt;For all the above rule methods, &lt;code&gt;[of P₁ P₂ ... Pₙ]&lt;&#x2F;code&gt; can be used to explicitly instantiate them instead of using the &lt;code&gt;rule_tac&lt;&#x2F;code&gt; family (which is explained below). This instantiates left-to-right by occurence, so with&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;thm conjI (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;* ⟦?&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;⟧ ==&amp;gt; ?&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ∧ ?&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;conjI [of A B]&lt;&#x2F;code&gt; will result in the instantiation &lt;code&gt;⟦A; B⟧ ==&amp;gt; A ∧ B&lt;&#x2F;code&gt;, from where the rule will proceed.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;R&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ∧&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;Isabelle&lt;&#x2F;span&gt;&lt;span&gt; can solve this on its own, but for the sake &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;of&lt;&#x2F;span&gt;&lt;span&gt; example&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apply (rule conjI [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;of&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; A B&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; R&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; R&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Notably, &lt;code&gt;[of ...]&lt;&#x2F;code&gt; does still work with the &lt;code&gt;_tac&lt;&#x2F;code&gt; family, but there is (as far as I know) no reason to use it over &lt;code&gt;_tac&lt;&#x2F;code&gt;&#x27;s explicit instantiation. Speaking of:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-tac-suffixes&quot;&gt;The &lt;code&gt;_tac&lt;&#x2F;code&gt; suffixes&lt;&#x2F;h2&gt;
&lt;p&gt;For each of the above,  there is a corresponding &lt;code&gt;_tac&lt;&#x2F;code&gt; (standing for tactic): &lt;code&gt;rule_tac&lt;&#x2F;code&gt;, &lt;code&gt;drule_tac&lt;&#x2F;code&gt;, etc. These &lt;code&gt;_tac&lt;&#x2F;code&gt;s are slightly more powerful than their &lt;code&gt;_tac&lt;&#x2F;code&gt;less equivalents. Firstly, each allows for the various premises to be explicitly instantiated by name. For example, with the &lt;code&gt;conjI&lt;&#x2F;code&gt; rule, one could explicitly write&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;thm conjI (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;* ⟦?&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;⟧ ==&amp;gt; ?&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ∧ ?&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;R&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ⋀&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;apply (rule_tac &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt; and &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; conjI)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; R&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; R&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This allows the rule to refer to meta-forall-bound variables, which most commonly arise when performing induction or similar. For a goal of form:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;with some &lt;code&gt;n :: nat&lt;&#x2F;code&gt; mentioned in &lt;code&gt;P&lt;&#x2F;code&gt;, performing &lt;code&gt;apply (induction n)&lt;&#x2F;code&gt; will generate the goals&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P 0&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;⋀&lt;&#x2F;span&gt;&lt;span&gt; nat&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; P&lt;&#x2F;span&gt;&lt;span&gt; nat &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; P&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;Suc&lt;&#x2F;span&gt;&lt;span&gt; nat) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; Variable&lt;&#x2F;span&gt;&lt;span&gt; naming may differ&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;. *&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;nat&lt;&#x2F;code&gt; is a meta-forall bound variable. This functions as expected; during the induction step of an inductive proof, we must prove that for any &lt;code&gt;nat&lt;&#x2F;code&gt;, &lt;code&gt;P nat ==&amp;gt; P (Suc nat)&lt;&#x2F;code&gt;. Because it is meta-forall bound, &lt;code&gt;rule&lt;&#x2F;code&gt; and friends cannot refer to &lt;code&gt;nat&lt;&#x2F;code&gt; directly using &lt;code&gt;[of ...]&lt;&#x2F;code&gt; (Although, automatic unification can work). Instead, we must use &lt;code&gt;rule_tac&lt;&#x2F;code&gt; and friends to refer to it. I am not quite sure why this is, but I presume it is due to internal complexities around the meta-forall.&lt;&#x2F;p&gt;
&lt;details&gt;&lt;summary&gt;A small artificial example of this difference, if the above is not clear.&lt;&#x2F;summary&gt;
&lt;p&gt;Recall that &lt;code&gt;[of ...]&lt;&#x2F;code&gt; can be used to explicitly instantiate:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma without_forall&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; &amp;quot;A ∧ B ==&amp;gt; A&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (erule conjE [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;of&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; A&lt;&#x2F;span&gt;&lt;span&gt;]) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; succeeds &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lemma with_forall&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; &amp;quot;⋀ a b. a ∧ b ==&amp;gt; a&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (erule conjE [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;of&lt;&#x2F;span&gt;&lt;span&gt; a]) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; fails &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  apply (erule_tac &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;a &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt; conjE) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; succeeds &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;These lemmas are otherwise equivalent; only their presentation differs.&lt;&#x2F;p&gt;
&lt;&#x2F;details&gt;
&lt;p&gt;In general, these &lt;code&gt;_tac&lt;&#x2F;code&gt; methods have the form&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rule_tac v₁ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; t₁ and v₂ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; t₂ and &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt; and vₙ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; tₙ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; RULE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;where &lt;code&gt;vₙ&lt;&#x2F;code&gt; is a variable occuring in &lt;code&gt;RULE&lt;&#x2F;code&gt;, and &lt;code&gt;tₙ&lt;&#x2F;code&gt; is a locally bound variable or assumption. Any combination of zero or more of the variables occuring in &lt;code&gt;RULE&lt;&#x2F;code&gt; may be used, in any order.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;_tac&lt;&#x2F;code&gt; methods have an additional advantage, which is that they can be told to refer to a specific goal. If we have goals of the form&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ∧&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; B&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; R&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; P&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ∧&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; Q&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ==&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; R&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;erule conjE&lt;&#x2F;code&gt; and friends will by default refer to the first goal. Using &lt;code&gt;erule_tac [i] conjE&lt;&#x2F;code&gt;, we can refer to the &lt;code&gt;ith&lt;&#x2F;code&gt; goal (1-indexed.) When combining this with specifying variables, the goal specifier comes first. (i.e., &lt;code&gt;apply (erule_tac [1] P=a in conjE)&lt;&#x2F;code&gt;.)&lt;&#x2F;p&gt;
&lt;h1 id=&quot;rule-erule-drule-and-frule-more-formally&quot;&gt;&lt;code&gt;rule&lt;&#x2F;code&gt;, &lt;code&gt;erule&lt;&#x2F;code&gt;, &lt;code&gt;drule&lt;&#x2F;code&gt;, and &lt;code&gt;frule&lt;&#x2F;code&gt;, (more) formally&lt;&#x2F;h1&gt;
&lt;p&gt;This section is almost entirely copied from the aformentioned Isabelle&#x2F;HOL tutorial.&lt;&#x2F;p&gt;
&lt;p&gt;Given an arbitrary rule R of the form:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt;₁ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt;₂ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt; Pₙ&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;------------  R&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;      Q&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For elimination rules, &lt;code&gt;P₁&lt;&#x2F;code&gt; is referred to as the &quot;Major premise&quot;. This will usually be the object being eliminated. In &lt;code&gt;disjE&lt;&#x2F;code&gt; for example, it is &lt;code&gt;P ∨ Q&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Method &lt;code&gt;rule&lt;&#x2F;code&gt; unifies &lt;code&gt;Q&lt;&#x2F;code&gt; with the current subgoal, and replaces it with the &lt;code&gt;n&lt;&#x2F;code&gt; subgoals &lt;code&gt;P₁ ... Pₙ&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Method &lt;code&gt;erule&lt;&#x2F;code&gt; unifies &lt;code&gt;Q&lt;&#x2F;code&gt; with the current subgoal, and &lt;code&gt;P₁&lt;&#x2F;code&gt; with the first suitable assumption. The subgoal is then replaced with the &lt;code&gt;n - 1&lt;&#x2F;code&gt; subgoals &lt;code&gt;P₂ ... Pₙ&lt;&#x2F;code&gt;, and the assumption &lt;code&gt;P₁&lt;&#x2F;code&gt; is deleted.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Method &lt;code&gt;drule&lt;&#x2F;code&gt; unifies &lt;code&gt;P₁&lt;&#x2F;code&gt; with the first suitable assumption, which it then deletes. It then adds the &lt;code&gt;n - 1&lt;&#x2F;code&gt; subgoals &lt;code&gt;P₂ ... Pₙ&lt;&#x2F;code&gt;, and the original subgoal gains the assumption &lt;code&gt;Q&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Method &lt;code&gt;frule&lt;&#x2F;code&gt; is like &lt;code&gt;drule&lt;&#x2F;code&gt;, but it does not delete &lt;code&gt;P₁&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Crafting a dependent typechecker, part 1</title>
        <published>2025-07-19T00:00:00+00:00</published>
        <updated>2025-07-19T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/dependent-p1/"/>
        <id>https://blueberrywren.dev/blog/dependent-p1/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/dependent-p1/">&lt;p&gt;This series is intended to give an interested layperson some idea of what goes on behind-the-scenes in a dependent typechecker, and how they might implement one of their own.&lt;&#x2F;p&gt;
&lt;p&gt;I personally hold the belief that dependent languages (or similar) will eventually be the future of programming, so knowing this information seems worthwhile to me. One may also simply be interested for the sake of it, or may be interested in implementing their own dependent language.&lt;&#x2F;p&gt;
&lt;p&gt;This series does assume a small base amount of knowledge around dependent programming languages. There are many tutorials out there far better than I could provide, so I will refer the reader to the wider internet if they are curious. (Return here afterwards, though!).&lt;&#x2F;p&gt;
&lt;p&gt;Additionally, the code snippets will be in OCaml, although a Haskell or Rust version may be made available at a later date.&lt;&#x2F;p&gt;
&lt;p&gt;The technique we will implement in this series can most succinctly be described as &quot;Bidirectional typechecking, utilizing Normalization by Evaluation&quot;. I do not expect the reader to understand that sentence for at least a little while ;).&lt;&#x2F;p&gt;
&lt;p&gt;All code snippets will be collated at the end of each page, so scroll all the way down if you&#x27;re only interested in that.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;&#x2F;h2&gt;
&lt;p&gt;The following are resources I highly recommend for exploring this topic on your own.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;András Kovacs&#x27; &quot;Elaboration Zoo&quot;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;AndrasKovacs&#x2F;elaboration-zoo&quot;&gt;found here&lt;&#x2F;a&gt;. It was a primary source of inspiration for this series.&lt;&#x2F;li&gt;
&lt;li&gt;&quot;A tutorial implementation of a dependently typed lambda calculus&quot;, by Andres Löh, Conor McBride, and Wouter Swierstra; &lt;a href=&quot;https:&#x2F;&#x2F;www.andres-loeh.de&#x2F;LambdaPi&#x2F;LambdaPi.pdf&quot;&gt;found here&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&quot;Checking Dependent Types with Normalization by Evaluation: A Tutorial&quot;, by David Christiansen, &lt;a href=&quot;https:&#x2F;&#x2F;davidchristiansen.dk&#x2F;tutorials&#x2F;nbe&#x2F;&quot;&gt;found here&lt;&#x2F;a&gt;, for the more lisp-minded.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;the-fundamental-operation-of-typechecking&quot;&gt;The fundamental operation of typechecking&lt;&#x2F;h2&gt;
&lt;p&gt;If you have implemented a typechecker before, you may have come to the realization that deciding when two things are the same is a very large component of typechecking. Whether it be simply checking that two arguments to &lt;code&gt;+&lt;&#x2F;code&gt; are both integers, or larger problems with polymorphism, the arguable core of typechecking is deciding equality.&lt;&#x2F;p&gt;
&lt;p&gt;In a dependent language, our types can (and often do) contain expressions that must be evaluated. Therefore, in order to explore how we check equality in the presence of evaluation, we will first start by considering how we do this for a very simple language - integer arithmetic. Take two expressions:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;17&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;How might we decide whether these are equal? The obvious solution is to evaluate them. Indeed, (sparing the reader the derivation), we can see they both evaluate to &lt;code&gt;36&lt;&#x2F;code&gt;, and so they are equal.&lt;&#x2F;p&gt;
&lt;p&gt;Let us now introduce a small extension: Variables with a known value, using &quot;let&quot;. We will refer to the variables themselves as &quot;bound variables&quot;, as they are bound by the &quot;let&quot;. In this case, they are additionally bound to a value. Terms containing only bound variables are referred to &quot;closed&quot; terms - this alludes to, for example, closed and open systems in the real world. Getting back to evaluation, we could simply substitute the computed value:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;: x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 39&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;substitute&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;: (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 39&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then evaluate. (In this case, our result is 117.) However, what if the variable occurs multiple times? The following is a little bad, but not awful:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;: x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;substitute&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;: (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But what if &lt;code&gt;x&lt;&#x2F;code&gt; was the following?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ^&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;14&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;14&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ^&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 18&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ^&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 6&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 12&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ^&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 18&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 14&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ^&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ^&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 12&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 18&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Duplicating that would clearly not be ideal!&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps we could compute &lt;code&gt;x&lt;&#x2F;code&gt; in advance, and then substitute that result in. This is much better:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;evaluate and substitute&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 61&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;61&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 61&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(In fact, there is yet another optimization to do: What if we don&#x27;t need to compute it at all, say because it&#x27;s not used? We will explore this possibility later.)&lt;&#x2F;p&gt;
&lt;p&gt;A simple OCaml interpretation of the terms of this language may be the following.
(sidetrack: A &quot;term&quot; is some element of a language. Above, we have the language of (restricted) integer arithmetic, and our terms are expressions of said. Hence, we call our OCaml interpretation of this language &lt;code&gt;term&lt;&#x2F;code&gt;.)&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; variable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; term&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Literal&lt;&#x2F;span&gt;&lt;span&gt; of int &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt; of variable &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Mul&lt;&#x2F;span&gt;&lt;span&gt; of term&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; term &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Exp&lt;&#x2F;span&gt;&lt;span&gt; of term&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; term &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt; of term&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; term &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Sub&lt;&#x2F;span&gt;&lt;span&gt; of term&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; term &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Let&lt;&#x2F;span&gt;&lt;span&gt; of variable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; term&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; term &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;      (* let x = ...; ... *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We then must make an environment that associates, or &quot;binds&quot;, our names to terms. &lt;code&gt;Let&lt;&#x2F;code&gt; is often called a &quot;binder&quot; because it functions as the source of this binding. We will make our context a list of pairs &lt;code&gt;(variable name, term)&lt;&#x2F;code&gt;, and will reimpliement the lookup function for example&#x27;s sake, although a suitable function is available as &lt;code&gt;List.assoc&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; environment&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (variable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; term)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; rec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; lookup&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; environment) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; variable)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; term&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span&gt; env&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;    (* See note below. *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; []&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; failwith (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;&amp;quot;Variable &amp;quot; ^&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; ^ &amp;quot; not found.&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;nm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; value&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; ::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; rest&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; nm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            value&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;        else&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            lookup rest name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note: In this series, we will not be considering the possibility that a name is used without being previously defined in some way. This is an error, and can be handled via normal means, e.g. a suitable error message.&lt;&#x2F;p&gt;
&lt;p&gt;We now note something curious: Our lookup function need not return a fully computed value! It could return &lt;code&gt;7 + 2&lt;&#x2F;code&gt;, which we would have to further evaluate before we could do anything with. It would be possible of course to manually insert invariants ensuring that this is not the case, but we could still accidentally violate them.&lt;&#x2F;p&gt;
&lt;p&gt;Here we hit one of the most important distinctions in our exploration of dependent typechecking.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;terms-vs-values&quot;&gt;Terms vs. Values&lt;&#x2F;h2&gt;
&lt;p&gt;A &quot;term&quot;, as previously seen, is any element of a chosen language. Above, this was (some subset of) integer arithmetic. We could also consider the language of OCaml programs, of which the above examples would be terms. However, two terms are not always easy to compare. We may need to evaluate one, or both, and we don&#x27;t know whether that will be needed until we start comparing them.&lt;&#x2F;p&gt;
&lt;p&gt;Instead, what if we defined another type that was guaranteed to be reduced to some suitable level? For this simple case, we could restrict this to contain only fully evaluated terms (i.e., integers). We&#x27;ll call these &quot;values&quot;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; VLiteral&lt;&#x2F;span&gt;&lt;span&gt; of int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We prefix these constructors with &lt;code&gt;V&lt;&#x2F;code&gt; to ensure they&#x27;re distinct, and to remind us that they construct values. Then, we could modify our environment and lookup function to only deal with values:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; environment&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (variable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; term)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; environment&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (variable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; value)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; rec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; lookup&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; environment) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; variable)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; term&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; rec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; lookup&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; environment) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; variable)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and now we know that &lt;code&gt;lookup&lt;&#x2F;code&gt; will always return something we can handle immediately, with no further processing.&lt;&#x2F;p&gt;
&lt;p&gt;In the general case, we call this &quot;suitably-reduced&quot; constraint a &quot;normal form&quot;. We can say that &lt;code&gt;value&lt;&#x2F;code&gt; contains only elements of &lt;code&gt;term&lt;&#x2F;code&gt; in this chosen normal form.&lt;&#x2F;p&gt;
&lt;p&gt;Now we can finish our little evaluator. We do a slight hack to perform arithmetic inside values; if our value type contained more than just the constructor &lt;code&gt;VLiteral&lt;&#x2F;code&gt;, we would have to consider how to handle that case. This is something we will cover soon.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;(* OCaml does not have integer exponentiation by default. Definition omitted. *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; pow&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; int) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; int)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; rec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; do_op&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;op&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; int) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; value) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; value)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;    (* Hack: This is only valid because we know our value type has one constructor, VLiteral. *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; VLiteral&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; va&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; VLiteral&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; vb&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;    VLiteral&lt;&#x2F;span&gt;&lt;span&gt; (op va vb)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; rec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; eval&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; environment) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;tm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; term)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span&gt; tm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Literal&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; VLiteral&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; nm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; lookup env nm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Mul&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; do_op (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; ) (eval env a) (eval env b)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Exp&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; do_op pow   (eval env a) (eval env b)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; do_op (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; ) (eval env a) (eval env b)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Sub&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; do_op (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; ) (eval env a) (eval env b)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;nm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; rest&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; result&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; eval env def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; new_env&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (nm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; result)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; ::&lt;&#x2F;span&gt;&lt;span&gt; env&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        eval new_env rest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In the &lt;code&gt;Let&lt;&#x2F;code&gt; case, we compute the definition first, then extend our environment with the new name and value before computing the rest of the expression.&lt;&#x2F;p&gt;
&lt;p&gt;We then, by returning a &lt;code&gt;value&lt;&#x2F;code&gt;, have a guarantee that whatever comes out of &lt;code&gt;eval&lt;&#x2F;code&gt; is as simple as we want it to be.&lt;&#x2F;p&gt;
&lt;p&gt;Comparing for equality is then very simple: We use &lt;code&gt;eval&lt;&#x2F;code&gt; to evaluate our terms into values, then because our values are in a nice normal form, we have the guarantee that we can compare them easily, with no further evaluation needed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap up&lt;&#x2F;h2&gt;
&lt;p&gt;So far we have covered:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Languages and terms.&lt;&#x2F;li&gt;
&lt;li&gt;Simple evaluation strategies for let bound variables &amp;amp; closed terms.&lt;&#x2F;li&gt;
&lt;li&gt;Values and normal forms.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;In the next part, we will explore how to take these concepts and apply them to something much closer to a &quot;real&quot; programming language, with &lt;code&gt;lambda&lt;&#x2F;code&gt; expressions and application, which will require the introduction of a &quot;closure&quot;. From there, we can explore how to deal with open terms, containing free variables, and onwards to dependent types.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;code&quot;&gt;Code&lt;&#x2F;h2&gt;
&lt;details&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; variable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; term&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Literal&lt;&#x2F;span&gt;&lt;span&gt; of int &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span&gt; of variable &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Mul&lt;&#x2F;span&gt;&lt;span&gt; of term&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; term &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Exp&lt;&#x2F;span&gt;&lt;span&gt; of term&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; term &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt; of term&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; term &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Sub&lt;&#x2F;span&gt;&lt;span&gt; of term&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; term &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Let&lt;&#x2F;span&gt;&lt;span&gt; of variable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; term&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; term &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;      (* let x = ...; ...*)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; VLiteral&lt;&#x2F;span&gt;&lt;span&gt; of int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; environment&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (variable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; value)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; rec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; lookup&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; environment) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; variable)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span&gt; env&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;    (* See note below. *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; []&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; failwith (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;&amp;quot;Variable &amp;quot; ^&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; ^ &amp;quot; not found.&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;nm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; value&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; ::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; rest&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; nm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            value&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;        else&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            lookup rest name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;(* OCaml does not have integer exponentiation by default. Definition omitted. *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; pow&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; int) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; int)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; rec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; do_op&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;op&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; int) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; value) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; value)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;    (* Hack: This is only valid because we know our value type has one constructor, VLiteral. *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; VLiteral&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; va&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; VLiteral&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; vb&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;    VLiteral&lt;&#x2F;span&gt;&lt;span&gt; (op va vb)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; rec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; eval&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; environment) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;tm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; term)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span&gt; tm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Literal&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; VLiteral&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; nm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; lookup env nm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Mul&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; do_op (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; ) (eval env a) (eval env b)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Exp&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; do_op pow   (eval env a) (eval env b)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; do_op (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; ) (eval env a) (eval env b)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Sub&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; do_op (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; ) (eval env a) (eval env b)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; Let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt;nm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; rest&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; result&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; eval env def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; new_env&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (nm&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; result)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; ::&lt;&#x2F;span&gt;&lt;span&gt; env&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        eval new_env rest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;details&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Debruijn indexes and levels, and why they&#x27;re handy</title>
        <published>2025-05-26T00:00:00+00:00</published>
        <updated>2025-05-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/debruijn-explanation/"/>
        <id>https://blueberrywren.dev/blog/debruijn-explanation/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/debruijn-explanation/">&lt;script&gt;
 function r(str) {
while (str.charAt(0) == &#x27; &#x27;) {
  	str = str.slice(1);
  }
  return str;
}

function get_args(str) {
 	str = r(str);
  if (str == &quot;&quot;) {
  	return [&quot;&quot;, []]
  }
  else if (str.charAt(0) == &#x27;.&#x27;) {
  	return [str.slice(1), []];
  }
  let [rest, l] = get_args(str.slice(1));
  return [rest, [str.charAt(0)].concat(l)];
}

function parse_app(str) {
	str = r(str);
  if (str == &quot;&quot;) {
  	return [&quot;&quot;, []];
  }
  else if (str.charAt(0) == &#x27;(&#x27;) {
  	let [rest, l] = parse(str.slice(1));
    let [rest1, k] = parse_app(rest);
    return [rest1, [l].concat(k)];
  }
  else if (str.charAt(0) == &#x27;)&#x27;) {
  	return [str.slice(1), []]
  } else {
  	let c = str.charAt(0);
    let [rest, l] = parse_app(str.slice(1));
    return [rest, [c].concat(l)];
  }
}

function parse(str) {
	str = r(str);
  if (str == &quot;&quot;) {
  	return [&quot;&quot;, {}]
  }
  else if (str.charAt(0) == &#x27;\\&#x27;) {
  	let [rest, a] = get_args(str.slice(1));
    let [rest1, bd] = parse_app(rest);
    return [rest1, {args : a, bd}]
  } else {
  	return parse_app(str);
  }
}

function iso(x) {
return typeof x === &#x27;object&#x27; &amp;&amp; !Array.isArray(x) &amp;&amp; x !== null;
}

function islist(x) {
return (x.constructor.name == &quot;Array&quot;)
}

function helper(args, p) {
let r = [];
for (let l of p) {
  if (iso(l)) {
  	r.push(debru_h(args, l));
  } else if (islist(l)) {
  	r.push(helper(args, l));
  }
  else {
    	r.push(args.indexOf(l));
  }
  }
  return r;
}

function debru_h(arg, p) {
	let args = p.args.reverse().concat(arg);
 	return {l : p.args.length, bd : helper(args, p.bd)};
}

function debru(p) {
	let [_, bd] = p;
 	return debru_h([], bd);
}

function printer(p) {
	if (iso(p)) {
  	let rest = p.bd;
    return &quot;(&quot; + &quot;λ &quot;.repeat(p.l) + printer(rest) + &quot;)&quot;;
  }
  else if (islist(p)) {
  	k = &quot;&quot;;
  	for (let e of p) {
    	k += &quot; &quot; + printer(e);
    }
    return &quot;(&quot; + k.slice(1) + &quot;)&quot;;
  }
  else {
   	return p;
  }
}
&lt;&#x2F;script&gt;
&lt;h2 id=&quot;assumed-knowledge&quot;&gt;Assumed knowledge&lt;&#x2F;h2&gt;
&lt;p&gt;At least a familiarity with the lambda calculus, including how it is evaluated. Some base knowledge of programming languages is also assumed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;The problem&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s look at a little imaginary term, in some lambda-calculus-like language. For future note, we call the lambda a &quot;binder&quot;, as it binds a variable. There are other types of binders, e.g. &lt;code&gt;let&lt;&#x2F;code&gt;, but we will only consider lambdas for the moment.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;λ f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; (λ y f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; (f y)) f&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can perform what&#x27;s called &quot;beta reduction&quot; on this term — essentially, function application, applying &lt;code&gt;f&lt;&#x2F;code&gt; to the lambda.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;λ f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; (λ y f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; (f y)) (f)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;substitute [y &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:=&lt;&#x2F;span&gt;&lt;span&gt; f]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; λ y f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; (f y)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;λ f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; (λ f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; f f)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Uh oh. We&#x27;ve accidentally captured a variable! Instead of &lt;code&gt;f&lt;&#x2F;code&gt; referring to the outer &lt;code&gt;f&lt;&#x2F;code&gt;, now it refers to the inner &lt;code&gt;f&lt;&#x2F;code&gt;. This is &quot;the capture problem&quot;, and it is quite annoying. Generally to avoid this, we need to rename &lt;em&gt;everything&lt;&#x2F;em&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; in our &quot;substituted&quot; term to names that are free (do not occur) in the &quot;subsitutee&quot; so nothing is accidentally captured. What if we could introduce a notation that avoids this?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;presenting-de-bruijn-indexes&quot;&gt;Presenting: De Bruijn Indexes!&lt;&#x2F;h2&gt;
&lt;p&gt;De Bruijn indexes are a naming scheme where:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We use natural numbers to refer to lambdas, and&lt;&#x2F;li&gt;
&lt;li&gt;Zero refers to the &quot;most recent&quot; lambda; one refers to the second most recent, etc.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Let&#x27;s rewrite that term above using this system:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;λ (λ λ (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;0 1&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here&#x27;s some ascii art showing what refers to what:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; λ   (λ   λ   (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;0   1&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;   0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; |    |    \———&#x2F;   |     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; |    |            |     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; |    \————————————&#x2F;     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; \———————————————————————&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, how does this help us with our substitution problem? Surely if we naively subtitute we will still have binding issues - and indeed we do:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;λ (λ λ (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;0 1&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;λ (λ (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;0 0&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;No good!&lt;&#x2F;p&gt;
&lt;p&gt;What De Bruijn indexes allow us to do is simply avoid capturing. The rule is simple: Every time we go past a binder when substituting, we increment every free variable&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; in our substituted term by one, to avoid the new binder. Just once, we decrement every free varible in the substitutee, to account for the removal of the binder:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; λ (λ λ (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;1 2&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ^  ^ ^&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; a  b c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; λ (λ (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;1 1&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ^  ^  ^ ^&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; a  b  &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;| \&lt;&#x2F;span&gt;&lt;span&gt; decremented by one&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;       \&lt;&#x2F;span&gt;&lt;span&gt; incremented by one when we passed &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt;&amp;quot;through&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; lambda c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we&#x27;re cool! Everything works as expected, and it takes much less work (and is much more predictable!).&lt;&#x2F;p&gt;
&lt;p&gt;At the bottom of this post there&#x27;s a little widget that can convert terms to de Bruijn for you, if you want to play around!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;presenting-de-bruijn-levels&quot;&gt;Presenting: De Bruijn levels!&lt;&#x2F;h2&gt;
&lt;p&gt;De Bruijn levels work similar to De Bruijn indexes, in that we use numbers to refer to binders. However, in De Bruijn levels, the lowest number refers to the &lt;em&gt;least&lt;&#x2F;em&gt; recently bound item.&lt;&#x2F;p&gt;
&lt;p&gt;Recall that:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;Named&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;   λ f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; (λ y f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; (f y)) f&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;Indexes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; λ (λ λ (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;0 1&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, with levels:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;Levels&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;  λ (λ λ (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2 1&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This has the same diagram of what refers to what:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; λ   (λ   λ   (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2   1&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;   0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; |    |    \———&#x2F;   |     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; |    |            |     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; |    \————————————&#x2F;     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; \———————————————————————&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(As it should! These two representations represent the same term.)&lt;&#x2F;p&gt;
&lt;p&gt;As you might expect, de Bruijn indexes and levels are each beneficial in their own situations.&lt;&#x2F;p&gt;
&lt;p&gt;Generally, De Bruijn indexes are &quot;more useful&quot; than De Bruijn levels, as they&#x27;re &quot;more local&quot;. In order to work with levels, you need to know &quot;how deep&quot; you are in a term at all times.&lt;&#x2F;p&gt;
&lt;p&gt;De Bruijn indexes give us the advantage that we can freely create new binders without the need for any information about where in a term we are, whereas de Bruijn levels give us the advantage when moving a term under a binder, free variables in said term do not need to be modified. Generally, one has many more free variables in a term than bound ones.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; λ (λ λ (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2 1&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;               ^&lt;&#x2F;span&gt;&lt;span&gt; this zero&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; λ (λ (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;1 0&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;       ^ ^&lt;&#x2F;span&gt;&lt;span&gt; is still zero&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;       \&lt;&#x2F;span&gt;&lt;span&gt; we had to modify this one though&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;other-advantages&quot;&gt;Other advantages&lt;&#x2F;h2&gt;
&lt;p&gt;Something that can come up quite a lot in various contexts is comparing whether two terms are equal or not. There are many complicated ways to do so, but de Bruijn gives us an advantage in a critical one, called &quot;alpha-equivalence&quot;. Consider the following two terms:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;λf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; λx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; f x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;λg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; λy&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; g y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;These terms should clearly be equal, right? They do the exact same thing. In this case, we consider them &quot;alpha-equivalent&quot;, meaning they are equal up to the names of variables. Alpha renaming is the process of renaming one term to match the names of another, so that they are &quot;clearly&quot; equal.&lt;&#x2F;p&gt;
&lt;p&gt;Let us consider the de Bruijn index representation of both of these terms:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;λf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; λx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; f x &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; λ λ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;1 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;λg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; λy&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; g y &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; λ λ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;1 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Isn&#x27;t that nice? They&#x27;ve gone from being alpha-equivalent, but not quite equal, to being equal. de Bruijn gives us the ability to compare terms for equality without having to consider alpha-equivalence at all.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrapup&quot;&gt;Wrapup&lt;&#x2F;h2&gt;
&lt;p&gt;De Bruijn indexes and levels can also be summed up via the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;λa&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; λb&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; λc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;indexes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;λ λ λ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;^ ^ ^&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2 1 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;levels&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;λ λ λ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;^ ^ ^&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;0 1 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;if you’re “here”&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;λ λ λ&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;Using indexes, adding any binders further left doesn’t affect the current binder&#x27;s variables, or any further right.&lt;&#x2F;li&gt;
&lt;li&gt;Using levels, adding any binders further right doesn’t affect the current binder&#x27;s variables, or any further left.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;de-bruijn-index-widget&quot;&gt;De Bruijn index widget&lt;&#x2F;h2&gt;
&lt;p&gt;Try it out! Some example terms to try:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;\f x. f x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;\x x. x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;\x. (x (\y. y))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;\x. \y. y x -- will not work&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;do \x. (\y. y x) or \x y. y x instead&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(sorry, it does over-parenthesize a bit :P)&lt;&#x2F;p&gt;
&lt;input name=&quot;searchTxt&quot; type=&quot;text&quot; maxlength=&quot;512&quot; id=&quot;searchTxt&quot; class=&quot;searchField&quot; placeholder=&quot;Type here!&quot;&#x2F;&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot; id=&quot;goober&quot;&gt;
&lt;p&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;script&gt;
document.getElementById(&#x27;searchTxt&#x27;).style.height=&quot;100px&quot;;
document.getElementById(&#x27;searchTxt&#x27;).style.fontSize=&quot;14pt&quot;;

&#x2F;&#x2F;creates a listener for when you press a key
window.onkeyup = keyup;
 var inputTextValue;

function keyup(e) {
  &#x2F;&#x2F;setting your input text to the global Javascript Variable for every key press
  inputTextValue = document.getElementById(&#x27;searchTxt&#x27;).value;

  &#x2F;&#x2F;listens for you to press the ENTER key, at which point your web address will change to the one you have input in the search box
	
  let p = parse(&quot;\\_. (&quot; + inputTextValue + &quot;)&quot;);
	let k = debru(p);
  let s = printer(k);
	let sp = s.slice(5).slice(0,-3);
  const thing = document.getElementById(&#x27;goober&#x27;);
  thing.innerHTML = &quot;&lt;span&gt;&quot; + sp + &quot;&lt;&#x2F;span&gt;&quot;
}
&lt;&#x2F;script&gt;
&lt;h2 id=&quot;alternatives&quot;&gt;Alternatives&lt;&#x2F;h2&gt;
&lt;p&gt;It is worth noting that there are several other methods for gaining the same, or similar, advantages as de Bruijn gives. This post is not intended to explain them, but I will list several here so that the curious reader may read further (tip: when searching, append &quot;lambda calculus&quot; to find the right results quicker):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;HOAS, or &quot;Higher Order Abstract Syntax&quot;&lt;&#x2F;li&gt;
&lt;li&gt;PHOAS, or &quot;Parametric HOAS&quot;&lt;&#x2F;li&gt;
&lt;li&gt;Locally nameless&lt;&#x2F;li&gt;
&lt;li&gt;Nominal signatures&lt;&#x2F;li&gt;
&lt;li&gt;Well-scoped de Bruijn indices&lt;&#x2F;li&gt;
&lt;li&gt;Well-scoped names&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;doi.acm.org&#x2F;10.1145&#x2F;2034773.2034817&quot;&gt;“Nameless,
Painless”&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Abstract scope graphs&lt;&#x2F;li&gt;
&lt;li&gt;Abstract Binding Trees&lt;&#x2F;li&gt;
&lt;li&gt;Co-de Bruijn indices&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;As you can see, there are many approaches! Jesper Cockx has an excellent summary of almost all of these, which can be found &lt;a href=&quot;https:&#x2F;&#x2F;jesper.sikanda.be&#x2F;posts&#x2F;1001-syntax-representations.html&quot;&gt;here.&lt;&#x2F;a&gt; Notably, many are intended for formalization efforts rather than for computational usage.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes&lt;&#x2F;h2&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;Technically, this is not actually needed. It is sufficient to keep track of everything and rename only names that would overlap. See &lt;a href=&quot;https:&#x2F;&#x2F;www.microsoft.com&#x2F;en-us&#x2F;research&#x2F;wp-content&#x2F;uploads&#x2F;2002&#x2F;07&#x2F;inline.pdf&quot;&gt;here&lt;&#x2F;a&gt; for more. &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;A free variable is one that is not bound by the expression we are currently considering. For example, in &lt;code&gt;λ x. f x&lt;&#x2F;code&gt;, &lt;code&gt;f&lt;&#x2F;code&gt; is free, but &lt;code&gt;x&lt;&#x2F;code&gt; is not. &lt;a href=&quot;#fr-2-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Dependent types suck actually</title>
        <published>2025-04-01T00:00:00+00:00</published>
        <updated>2025-04-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/dependent-types-suck/"/>
        <id>https://blueberrywren.dev/blog/dependent-types-suck/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/dependent-types-suck/">&lt;p&gt;STOP DOING DEPENDENT TYPES&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Types were not supposed to be given computation!&lt;&#x2F;li&gt;
&lt;li&gt;YEARS of typechecking but NO real world use for going higher than GADTS&lt;&#x2F;li&gt;
&lt;li&gt;Wanted to go higher anyway for a laugh? We had a tool for that: It was called RUNTIME VERIFICATION&lt;&#x2F;li&gt;
&lt;li&gt;&quot;Yes please give me &lt;code&gt;Id A x x&lt;&#x2F;code&gt; of something. Please give me &lt;code&gt;Vec (m + n) A&lt;&#x2F;code&gt; of it.&quot; -- Statements dreamed up by the UTTERLY INSANE&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Look at what computer scientists have been doing, with all the languages and typecheckers we built for them:
(This is REAL dependent types, done by REAL computer scientists)&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sq2 : ◀.F-map-iso (◀.F-map-iso (ρ≅ Iso⁻¹)) ∙Iso α≅&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ≡ (α≅ ∙Iso α≅) ∙Iso ▶.F-map-iso (λ≅ Iso⁻¹)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sq2 = ≅-path $&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    α→ _ _ _ ∘ ((ρ← ⊗₁ id) ⊗₁ id)    ≡&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (ρ← ⊗₁ ⌜ id ⊗₁ id ⌝) ∘ α→ _ _ _  ≡&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (ρ← ⊗₁ id) ∘ α→ _ _ _            ≡˘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (id ⊗₁ λ←) ∘ α→ _ _ _ ∘ α→ _ _ _ ∎&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;lean&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;theorem&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; integral_re&lt;&#x2F;span&gt;&lt;span&gt; {f : X → 𝕜} (hf : Integrable f μ) :&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ∫ x, RCLike.re (f x) ∂μ = RCLike.re (∫ x, f x ∂μ) :=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (@RCLike.reCLM 𝕜 _).integral_comp_comm hf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;coq&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;Lemma&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; next_spoke_ring&lt;&#x2F;span&gt;&lt;span&gt; (y &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; G) &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; y \&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt; r &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; next r y &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; face (spoke y).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;Proof&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;move=&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; ry; have [cycFp Up] &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:=&lt;&#x2F;span&gt;&lt;span&gt; andP ucycFp.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;&quot;&gt;rewrite&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span&gt;[y]nodeK (next_map inj_spoke) ?rev_uniq &#x2F;&#x2F; (next_rev Up).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #66D9EF;&quot;&gt;rewrite&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt;[prev p &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;]faceK &#x2F;spoke ee &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;(canRL nodeK (nnn y)).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;by&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;&quot;&gt; rewrite&lt;&#x2F;span&gt;&lt;span&gt; (eqP (prev_cycle cycFp &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;)) &#x2F;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;Ep &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;Er.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;Qed&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&quot;Hello I would like &lt;code&gt;(p : f ∘ g ≡ h ∘ k)&lt;&#x2F;code&gt; apples please&quot;&lt;&#x2F;p&gt;
&lt;p&gt;they have played us for absolute fools
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;details&gt;
  &lt;summary&gt;credits&lt;&#x2F;summary&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Agda credit: &lt;a href=&quot;https:&#x2F;&#x2F;1lab.dev&#x2F;Cat.Monoidal.Base.html&quot;&gt;1Lab&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Lean credit: &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leanprover-community&#x2F;mathlib4&#x2F;blob&#x2F;362bdac45f1c3e9307252e394f8ecfff137c4d85&#x2F;Mathlib&#x2F;MeasureTheory&#x2F;Integral&#x2F;SetIntegral.lean#L1183-L1185&quot;&gt;Mathlib4&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Rocq credit: &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rocq-community&#x2F;fourcolor&#x2F;blob&#x2F;master&#x2F;theories&#x2F;proof&#x2F;birkhoff.v&quot;&gt;4 Color Theorem Proof&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;details&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A short excerpt on pattern unification</title>
        <published>2025-03-30T00:00:00+00:00</published>
        <updated>2025-03-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/pattern-unification-short/"/>
        <id>https://blueberrywren.dev/blog/pattern-unification-short/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/pattern-unification-short/">&lt;p&gt;Preface: Low effort post.&lt;&#x2F;p&gt;
&lt;p&gt;The following is an excerpt from a discord conversation about dependent pattern unification. In short, pattern unification is one method for solving
unification goals such as the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;id &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;id &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; B&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; id _ x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, we have that our type argument to &lt;code&gt;id&lt;&#x2F;code&gt; is a hole, so we must solve it.&lt;&#x2F;p&gt;
&lt;p&gt;We are working with a de Brujin representation, so the above actually looks something like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let :&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; λ λ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let :&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; Type&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; B&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; B&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; λ λ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt; _ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Once we&#x27;ve gotten to the point of writing that hole, what was once &lt;code&gt;id&lt;&#x2F;code&gt; is now &lt;code&gt;2&lt;&#x2F;code&gt; (Two levels of lambda binders in the way.). As such, performing this
solving takes slightly more work, as we can&#x27;t simply plug in the result of unification - the de Brujin wouldn&#x27;t line up.&lt;&#x2F;p&gt;
&lt;p&gt;In this conversation, we were discussing relative to András Kovács&#x27; excellent &quot;elab-zoo&quot;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;AndrasKovacs&#x2F;elaboration-zoo&#x2F;&quot;&gt;found here&lt;&#x2F;a&gt;.
We are discussing &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;AndrasKovacs&#x2F;elaboration-zoo&#x2F;blob&#x2F;master&#x2F;03-holes&#x2F;pattern-unification.txt&quot;&gt;&lt;code&gt;03-holes&#x2F;pattern-unification.txt&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;AndrasKovacs&#x2F;elaboration-zoo&#x2F;blob&#x2F;master&#x2F;03-holes&#x2F;Main.hs&quot;&gt;&lt;code&gt;&#x2F;03-holes&#x2F;Main.hs&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; in particular, the former being a formal treatment of what happens &lt;em&gt;after&lt;&#x2F;em&gt; you find a solution, and the latter being an implementation of pattern unification (amongst other things).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;comments-before-the-fact&quot;&gt;Comments before the fact&lt;&#x2F;h3&gt;
&lt;p&gt;I think this explanation is somewhat reasonable for what&#x27;s actually happening. Nothing will replace the original document, of course! Go give that a read (preferably before you read this.)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;warning&quot;&gt;Warning!&lt;&#x2F;h2&gt;
&lt;p&gt;This conversation is &lt;em&gt;only&lt;&#x2F;em&gt; going to make sense if you&#x27;ve had a look at at &lt;em&gt;least&lt;&#x2F;em&gt; the latter linked file above (&lt;code&gt;Main.hs&lt;&#x2F;code&gt;). I recommend also having a look at &lt;code&gt;pattern-unification.txt&lt;&#x2F;code&gt; if you really want to grasp it, though.&lt;&#x2F;p&gt;
&lt;p&gt;I also make no concrete warning that the below is 100% correct; while it is to the best of ability, i&#x27;m still learning this too!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-conversation-as-written-minorly-edited-to-exclude-comments-from-people-other-than-me&quot;&gt;The conversation as written, minorly edited to exclude comments from people other than me&lt;&#x2F;h3&gt;
&lt;p&gt;(In reference to &lt;code&gt;pattern-unification.txt&lt;&#x2F;code&gt;)&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;most of this is what you do &lt;em&gt;after&lt;&#x2F;em&gt; you&#x27;ve &quot;found the solution&quot;
finding the &quot;solution&quot; is vaguely your normal unification procedure
when you find a hole, you put a meta in it, when you unify something with that meta you &quot;solve&quot; it&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&quot;Normal unification&quot; here is your fairly traditional unification for typechecking; it is somewhat different in a dependent setting, but not
too different. (Look here later for a series on this!)&lt;&#x2F;p&gt;
&lt;p&gt;All of the following is then discussing &lt;code&gt;Main.hs&lt;&#x2F;code&gt; and the concrete implementation of solving a metavariable.
This maps somewhat closely from &lt;code&gt;pattern-unification.txt&lt;&#x2F;code&gt;, but can be understood standalone.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Andras&#x27; puts it better than i could:&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;{-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;The actual unification algorithm is fairly simple, it works in a structural&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;fashion, like conversion checking before.  The main complication, as we&amp;#39;ve seen,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;is the pattern unification case.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;-}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;A small break while I write the following&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;VFlex&lt;&#x2F;span&gt;&lt;span&gt; m sp , t&amp;#39;           )&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; solve l m sp t&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  (t          ,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; VFlex&lt;&#x2F;span&gt;&lt;span&gt; m&amp;#39; sp&amp;#39; )&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; solve l m&amp;#39; sp&amp;#39; t&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;VFlex&lt;&#x2F;code&gt; is what elab-zoo calls the thing holding an unsolved metavariable (here &lt;code&gt;m&lt;&#x2F;code&gt; or &lt;code&gt;m&#x27;&lt;&#x2F;code&gt;), and a &quot;spine&quot; &lt;code&gt;sp&lt;&#x2F;code&gt;, which is a list of everything bound in the context when &lt;code&gt;m&lt;&#x2F;code&gt; was created&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;you can then imagine the meta to be, essentially, a function, taking everything bound as arguments (which is what it actually is, in elab zoo)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;id &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; U&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;id &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; U&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; B&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; id _ y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;m &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;= ???&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; id (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;m &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y) y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;here our normal typechecking would try to unify &lt;code&gt;?m&lt;&#x2F;code&gt;&#x27;s &lt;code&gt;???&lt;&#x2F;code&gt; with &lt;code&gt;B&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;the actual solving is then handled by &lt;code&gt;solve&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #88846F;&quot;&gt;--       Γ      ?α         sp       rhs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt;solve&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; ::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; Lvl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; MetaVar&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; Spine&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; Val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;&quot;&gt; ()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;solve gamma m sp rhs &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;= do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  pren &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; invert gamma sp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  rhs  &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; rename m pren rhs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span&gt; solution &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; eval &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;[]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; $&lt;&#x2F;span&gt;&lt;span&gt; lams (dom pren) rhs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  modifyIORef&amp;#39; mcxt &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #000000;background-color: #FFFFFF;&quot;&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;text-decoration: underline;&quot;&gt;IM.&lt;&#x2F;span&gt;&lt;span&gt;insert (unMetaVar m) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;Solved&lt;&#x2F;span&gt;&lt;span&gt; solution)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;B&lt;&#x2F;code&gt; would be our &lt;code&gt;rhs&lt;&#x2F;code&gt; here&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;you need to remember we&#x27;re working with debrujin, so the solution to our metavariable (which may reference things in the context of where the meta was created, of course) should exist in a different context (a &quot;mostly&quot; empty one, with only the arguments to our meta).&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;invert&lt;&#x2F;code&gt;, which is &lt;code&gt;^⁻¹&lt;&#x2F;code&gt; in the pattern unification text, creates a renaming from our original context (&lt;code&gt;sp&lt;&#x2F;code&gt;) to the desired new context, with only our meta arguments&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;rename&lt;&#x2F;code&gt; takes our &lt;code&gt;rhs&lt;&#x2F;code&gt; and uses the renaming to take it to the new context (it takes &lt;code&gt;m&lt;&#x2F;code&gt; as an argument because it does an occurs check at the same time, recursive solutions are no good)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;finally we add the needed lambdas for our function meta (debrujin, remember), evaluate it in the empty context in order to take it into the value domain, and plug it in as the solution&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;so then our final solution is&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;id &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; U&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;id &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; U&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; B&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; id _ y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;m &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; id (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;m &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y) y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;?m is fully inline though, so&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;id &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; U&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;id &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; U&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; B&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; id ((λ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; B&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; B&lt;&#x2F;span&gt;&lt;span&gt; y) y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;which is obviously equal to the &quot;clear solution&quot;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; id &lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;and so clearly we&#x27;ve solved it!&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;comments-after-the-fact&quot;&gt;Comments after the fact&lt;&#x2F;h3&gt;
&lt;p&gt;I don&#x27;t really have any other comments. There will (hopefully shortly) start appearing a &quot;tutorial&quot; sort of series on writing a dependent language with holes, so some of this
will definitely come up in that, and I&#x27;ll probably write some more comments here after i&#x27;ve gone and written that tutorial.&lt;&#x2F;p&gt;
&lt;p&gt;Hope this helps somebody!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Welcome back.</title>
        <published>2025-03-27T00:00:00+00:00</published>
        <updated>2025-03-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/2025-03-27/"/>
        <id>https://blueberrywren.dev/blog/2025-03-27/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/2025-03-27/">&lt;h1 id=&quot;hey-hey&quot;&gt;hey hey&lt;&#x2F;h1&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Hi, world.</title>
        <published>2023-06-17T00:00:00+00:00</published>
        <updated>2023-06-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/first/"/>
        <id>https://blueberrywren.dev/blog/first/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/first/">&lt;p&gt;This is just a little blog i&#x27;m doing for the sake of spreading stuff I learn about. Fun, right?&lt;&#x2F;p&gt;
&lt;p&gt;There will be mostly math and programming. \(a \to b\)&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #272822;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E22E;&quot;&gt; fac&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FD971F;font-style: italic;&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #66D9EF;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; if&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; then&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F92672;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; fac (n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E6DB74;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #AE81FF;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;$$\forall a. \forall b. (\forall c. c \to c) \to (a, b) \to (a, b)$$&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
