<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Gyuri's blog</title><link>https://kuruczgy.com/</link><description>Recent content in Blogs on György Kurucz's blog</description><generator>Hugo -- gohugo.io</generator><lastBuildDate>Wed, 31 Jul 2024 00:00:00 +0000</lastBuildDate><atom:link href="https://kuruczgy.com/blog/index.xml" rel="self" type="application/rss+xml"/><item><title>Porting Lean to the ESP32-C3 RISC-V microcontroller</title><link>https://kuruczgy.com/blog/2024/07/31/lean-esp32/</link><pubDate>Wed, 31 Jul 2024 00:00:00 +0000</pubDate><guid>https://kuruczgy.com/blog/2024/07/31/lean-esp32/</guid><description>&lt;p>The goal of this project is to cross-compile Lean programs to the ESP32-C3. (You can find all the code &lt;a href="https://github.com/kuruczgy/lean-esp32/tree/for-blog">in this repository&lt;/a>.)&lt;/p>
&lt;p>Lean is a dependently typed pure functional programming language and a proof assistant, though in this article I will mostly be using it just as a programming language. Its compiler can either emit LLVM IR or C code. I will be using the C output for simplicity, but using the LLVM IR instead should just involve setting up the right compiler flags.&lt;/p>
&lt;p>The ESP32-C3 is a RISC-V microcontroller running at up to 160 MHz. Its main selling point is its integrated Wi-Fi peripheral, but I will not be using it for this project. It has 384 KiB of internal RAM, and I will be fitting everything into this including the program code, the heap and the stack. (Running code directly from flash memory would also be possible in order to save RAM, but it&amp;rsquo;s potentially slower than running from RAM.)&lt;/p>
&lt;p>What&amp;rsquo;s the motivation behind this project? While the Lean compiler is pretty good, Lean programs will never be as fast or as small as programs written in C. In an environment where every byte and every CPU clock cycle matters, wouldn&amp;rsquo;t it make sense to write everything in C?&lt;/p>
&lt;p>As far as microcontrollers go, the ESP32-C3 is actually a pretty beefy machine. 160 MHz and 384 KiB of RAM might seem tiny compared to the 3+ GHz and 8+ GB of RAM in your usual desktop machine, but it is significantly more than what e.g. the Commodore 64 or the original Game Boy had. Here is a table comparing the ESP32-C3 to some historical computers:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>&lt;/th>
&lt;th>CPU&lt;/th>
&lt;th>RAM&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Apollo Guidance Computer (1966)&lt;/td>
&lt;td>16 bit 2 MHz&lt;/td>
&lt;td>2 KiB&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Commodore 64 (1982)&lt;/td>
&lt;td>8 bit 1 MHz&lt;/td>
&lt;td>64 KiB&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Game Boy (1989)&lt;/td>
&lt;td>8 bit 4 MHz&lt;/td>
&lt;td>8 KiB + 8 KiB VRAM&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ESP32-C3 (2021)&lt;/td>
&lt;td>32 bit 160 MHz&lt;/td>
&lt;td>384 KiB&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Additionally, the success of projects like NodeMCU, MicroPython or Espruino show that running higher level languages on microcontrollers is very much feasible, and the developer effort saved by doing so can be worth it.&lt;/p>
&lt;p>With that said, I will jump into describing the whole stack that goes into getting Lean running on the ESP32-C3. You can use the table of contents below to jump to a particular section that interests you, I would say ~80% of any section should still be understandable without having read the preceding ones.&lt;/p>
&lt;ul>
&lt;li>&lt;a href="#lean-runtime">Lean runtime&lt;/a>: If you are interested in how the Lean runtime represents objects, and why its authors decided to use reference counting instead of a garbage collector for memory management, this is the section for you.&lt;/li>
&lt;li>&lt;a href="#toolchain-compiler-and-libraries">Toolchain: compiler and libraries&lt;/a>: Instead of downloading the prebuilt toolchain provided by Espressif, I decided to compile and configure everything for myself to have more control. If you are curious about my adventures compiling my own libc and libc++, read here.&lt;/li>
&lt;li>&lt;a href="#booting-and-application-initialization">Booting and application initialization&lt;/a>: Normally the boot loader provided by &lt;a href="https://github.com/espressif/esp-idf">ESP-IDF&lt;/a> handles setting up the hardware, but I decided to not use ESP-IDF. If you want to know how the boot chain and hardware setup works on the ESP32-C3, read this one.&lt;/li>
&lt;li>&lt;a href="#example-application-rgb-led-controller">Example application: RGB LED controller&lt;/a>: Now that I have a working Lean environment on the ESP32-C3, I wanted to write a demo application for this blog post. If you want to see some Lean code (&lt;a href="https://lean-lang.org/functional_programming_in_lean/">and maybe get inspired to try Lean, I would definitely recommend&lt;/a>), and want to know how to blink an LED in a very complicated way (with &lt;a href="https://kuruczgy.com/blog/2022/10/20/introduction-to-dependent-types/">dependent types&lt;/a>!), read here.&lt;/li>
&lt;li>&lt;a href="#results">Results&lt;/a>: If you just want to see some clips of colorful flashing LEDs that are underpinned by all this work.&lt;/li>
&lt;/ul>
&lt;div>
&lt;h2>Table Of Contents&lt;/h2>
&lt;nav id="TableOfContents">
&lt;ol>
&lt;li>&lt;a href="#lean-runtime">Lean runtime&lt;/a>
&lt;ol>
&lt;li>&lt;a href="#object-representation">Object representation&lt;/a>&lt;/li>
&lt;li>&lt;a href="#memory-management">Memory management&lt;/a>&lt;/li>
&lt;li>&lt;a href="#getting-the-runtime-to-compile--run-on-the-esp32-c3">Getting the runtime to compile &amp;amp; run on the ESP32-C3&lt;/a>&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;a href="#toolchain-compiler-and-libraries">Toolchain: compiler and libraries&lt;/a>
&lt;ol>
&lt;li>&lt;a href="#overview">Overview&lt;/a>&lt;/li>
&lt;li>&lt;a href="#the-nix-package-manager">The Nix package manager&lt;/a>&lt;/li>
&lt;li>&lt;a href="#targeting-the-esp32-c3-with-nixpkgs">Targeting the ESP32-C3 with &lt;code>nixpkgs&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#hacking-on-the-project-yourself">Hacking on the project yourself&lt;/a>&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;a href="#booting-and-application-initialization">Booting and application initialization&lt;/a>
&lt;ol>
&lt;li>&lt;a href="#memory-layout">Memory layout&lt;/a>&lt;/li>
&lt;li>&lt;a href="#booting">Booting&lt;/a>&lt;/li>
&lt;li>&lt;a href="#lean-startup">Lean startup&lt;/a>&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;a href="#example-application-rgb-led-controller">Example application: RGB LED controller&lt;/a>
&lt;ol>
&lt;li>&lt;a href="#results">Results&lt;/a>&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;a href="#conclusions">Conclusions&lt;/a>&lt;/li>
&lt;li>&lt;a href="#appendix-bit-banging-the-ws2812-protocol">Appendix: Bit banging the WS2812 protocol&lt;/a>&lt;/li>
&lt;li>&lt;a href="#bibliography">Bibliography&lt;/a>&lt;/li>
&lt;/ol>
&lt;/nav>
&lt;/div>
&lt;h1 id="lean-runtime">Lean runtime&lt;/h1>
&lt;p>In this section I will describe how Lean represents objects in memory, and how it uses reference counting to manage them. Note that I will assume a 32 bit architecture (as the ESP32-C3 has a 32 bit core), though Lean is more commonly used on 64 bit platforms.&lt;/p>
&lt;h2 id="object-representation">Object representation&lt;/h2>
&lt;p>Lean objects are allocated on the heap, and referenced by a pointer. They consist of a header containing a reference count and some other information, followed by some arbitrary contents:&lt;/p>
&lt;!-- This file was generated by dvisvgm 2.13.3 -->&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="310.633036pt" height="117.063512pt" viewBox="-72 -72 310.633036 117.063512">
&lt;defs>
&lt;path id="g0-2" d="m5.58067-3.988242l-2.869239-2.854893c-.172154-.172154-.200847-.200847-.315616-.200847c-.143462 0-.286924 .129116-.286924 .286924c0 .100423 .028692 .129116 .186501 .286924l2.869239 2.883585l-2.869239 2.883585c-.157808 .157808-.186501 .186501-.186501 .286924c0 .157808 .143462 .286924 .286924 .286924c.11477 0 .143462-.028692 .315616-.200847l2.854893-2.854893l2.969663 2.969663c.028692 .014346 .129116 .086077 .215193 .086077c.172154 0 .286924-.129116 .286924-.286924c0-.028692 0-.086077-.043039-.157808c-.014346-.028692-2.295391-2.281045-3.012701-3.012701l2.625354-2.625354c.071731-.086077 .286924-.272578 .358655-.358655c.014346-.028692 .071731-.086077 .071731-.186501c0-.157808-.11477-.286924-.286924-.286924c-.11477 0-.172154 .057385-.329963 .215193l-2.840547 2.840547z"/>
&lt;path id="g1-78" d="m10.616185-8.292101c.157808-.616886 .387347-1.047272 1.477658-1.090311c.043039 0 .215193-.014346 .215193-.258232c0-.157808-.129116-.157808-.186501-.157808c-.286924 0-1.01858 .028692-1.305504 .028692h-.688617c-.200847 0-.459078-.028692-.659925-.028692c-.086077 0-.258232 0-.258232 .272578c0 .143462 .11477 .143462 .215193 .143462c.860772 .028692 .918157 .358655 .918157 .616886c0 .129116-.014346 .172154-.057385 .373001l-1.62112 6.470134l-3.070086-7.632176c-.100423-.229539-.11477-.243885-.430386-.243885h-1.750236c-.286924 0-.41604 0-.41604 .272578c0 .143462 .100423 .143462 .373001 .143462c.071731 0 .918157 0 .918157 .129116c0 .028692-.028692 .143462-.043039 .186501l-1.908044 7.603484c-.172154 .702964-.516463 1.004234-1.463312 1.047272c-.071731 0-.215193 .014346-.215193 .272578c0 .143462 .143462 .143462 .186501 .143462c.286924 0 1.01858-.028692 1.305504-.028692h.688617c.200847 0 .444732 .028692 .645579 .028692c.100423 0 .258232 0 .258232-.272578c0-.129116-.143462-.143462-.200847-.143462c-.473424-.014346-.932503-.100423-.932503-.616886c0-.11477 .028692-.243885 .057385-.358655l1.936736-7.675215c.086077 .143462 .086077 .172154 .143462 .30127l3.414395 8.507294c.071731 .172154 .100423 .258232 .229539 .258232c.143462 0 .157808-.043039 .215193-.286924l2.008467-8.005177z"/>
&lt;path id="g2-48" d="m6.656635-4.37559c0-2.668392-1.420273-4.56209-2.969663-4.56209c-1.563735 0-2.969663 1.92239-2.969663 4.547744c0 2.668392 1.420273 4.56209 2.969663 4.56209c1.563735 0 2.969663-1.92239 2.969663-4.547744zm-2.969663 3.715665c-1.133349 0-2.03716-1.73589-2.03716-3.873473s.989888-3.572203 2.03716-3.572203s2.03716 1.43462 2.03716 3.572203c0 2.123237-.90381 3.873473-2.03716 3.873473z"/>
&lt;path id="g2-49" d="m4.361243-8.349486c0-.215193 0-.588194-.41604-.588194c-.243885 0-.329963 .129116-.41604 .315616c-.272578 .616886-.746002 1.377235-1.506351 1.43462c-.215193 .014346-.516463 .043039-.516463 .41604c0 .243885 .143462 .41604 .459078 .41604c.803387 0 1.420273-.60254 1.463312-.631233v6.154518h-1.262465c-.200847 0-.588194 0-.588194 .41604s.387347 .41604 .588194 .41604h3.457433c.200847 0 .588194 0 .588194-.41604s-.387347-.41604-.588194-.41604h-1.262465v-7.517407z"/>
&lt;path id="g2-50" d="m4.992476-3.156163c.200847-.172154 1.649813-1.405927 1.649813-2.998355c0-1.635466-1.348542-2.783162-3.141817-2.783162c-1.664159 0-2.768816 1.248119-2.768816 2.453199c0 .60254 .502117 .645579 .588194 .645579c.258232 0 .573848-.200847 .573848-.588194c0-.272578-.100423-.358655-.172154-.41604c.200847-.760348 .860772-1.262465 1.692851-1.262465c1.219427 0 2.295391 .702964 2.295391 1.951083c0 1.119003-.846426 1.979775-1.62112 2.654046l-3.156163 2.740123c-.157808 .129116-.200847 .172154-.200847 .344309c0 .41604 .387347 .41604 .588194 .41604h5.006822c.315616-.086077 .315616-.373001 .315616-.588194v-.30127c0-.258232 0-.588194-.459078-.588194c-.473424 0-.473424 .30127-.473424 .645579h-3.457433l2.740123-2.324084z"/>
&lt;path id="g2-51" d="m3.672626-4.318205c1.492004 0 2.151929 1.047272 2.151929 1.821967c0 .946849-.832079 1.836313-2.094545 1.836313c-1.43462 0-2.080198-.774695-2.080198-.975541c0-.028692 .014346-.057385 .028692-.071731c.057385-.100423 .100423-.215193 .100423-.344309c0-.30127-.229539-.573848-.573848-.573848c-.30127 0-.588194 .186501-.588194 .631233c0 1.248119 1.362889 2.166276 3.113124 2.166276c1.807621 0 3.027047-1.291158 3.027047-2.654046c0-.731656-.401693-1.750236-1.664159-2.295391c.875118-.545155 1.262465-1.405927 1.262465-2.151929c0-1.075965-1.075965-2.008467-2.625354-2.008467c-1.592428 0-2.711431 .688617-2.711431 1.750236c0 .473424 .358655 .616886 .588194 .616886c.258232 0 .573848-.200847 .573848-.588194c0-.229539-.11477-.358655-.11477-.373001c.430386-.545155 1.420273-.573848 1.664159-.573848c.975541 0 1.692851 .516463 1.692851 1.190734c0 .41604-.272578 1.606774-1.778928 1.707197c-.530809 .028692-.760348 .057385-.817733 .057385c-.286924 .028692-.358655 .215193-.358655 .41604c0 .41604 .30127 .41604 .545155 .41604h.659925z"/>
&lt;path id="g2-52" d="m.545155-3.443087c-.129116 .186501-.129116 .215193-.129116 .473424c0 .502117 .186501 .559502 .573848 .559502h3.514818v1.578082h-.860772c-.200847 0-.573848 0-.573848 .41604s.373001 .41604 .573848 .41604h2.52493c.200847 0 .573848 0 .573848-.41604s-.373001-.41604-.573848-.41604h-.860772v-1.578082h1.075965c.200847 0 .573848 0 .573848-.41604s-.373001-.41604-.573848-.41604h-1.075965v-5.135938c0-.473424-.100423-.588194-.588194-.588194h-.329963c-.344309 0-.41604 .014346-.588194 .286924l-3.256586 5.236361zm.832079 .200847l3.127471-5.021168v5.021168h-3.127471z"/>
&lt;path id="g2-56" d="m4.762937-4.734245c1.147696-.344309 1.793274-1.104657 1.793274-1.908044c0-1.176388-1.190734-2.295391-2.869239-2.295391s-2.869239 1.119003-2.869239 2.295391c0 .832079 .688617 1.578082 1.793274 1.908044c-1.448966 .459078-1.994121 1.448966-1.994121 2.252353c0 1.405927 1.31985 2.654046 3.070086 2.654046s3.070086-1.233773 3.070086-2.654046c0-.789041-.530809-1.793274-1.994121-2.252353zm-1.075965-.41604c-1.133349 0-1.936736-.702964-1.936736-1.477658c0-.789041 .832079-1.477658 1.936736-1.477658s1.936736 .688617 1.936736 1.477658c0 .774695-.817733 1.477658-1.936736 1.477658zm0 4.490359c-1.233773 0-2.137583-.875118-2.137583-1.821967c0-1.01858 .961195-1.836313 2.137583-1.836313c1.20508 0 2.137583 .860772 2.137583 1.821967c0 1.004234-.932503 1.836313-2.137583 1.836313z"/>
&lt;path id="g2-99" d="m6.541865-1.563735c0-.373001-.358655-.373001-.473424-.373001c-.329963 0-.387347 .11477-.459078 .315616c-.315616 .789041-1.01858 .875118-1.362889 .875118c-1.219427 0-2.252353-1.01858-2.252353-2.352776c0-.731656 .41604-2.381468 2.295391-2.381468c.387347 0 .688617 .028692 .817733 .043039c.100423 .028692 .11477 .043039 .11477 .11477c.043039 .588194 .487771 .60254 .573848 .60254c.315616 0 .588194-.215193 .588194-.60254c0-.989888-1.448966-.989888-2.080198-.989888c-2.453199 0-3.24224 2.008467-3.24224 3.213548c0 1.750236 1.334196 3.184855 3.05574 3.184855c1.92239 0 2.424507-1.420273 2.424507-1.649813z"/>
&lt;path id="g2-102" d="m3.54351-5.351131h1.73589c.200847 0 .573848 0 .573848-.41604s-.373001-.41604-.573848-.41604h-1.73589v-.71731c0-1.119003 1.004234-1.119003 1.463312-1.119003c0 .028692 .11477 .559502 .588194 .559502c.229539 0 .559502-.172154 .559502-.573848c0-.817733-1.090311-.817733-1.305504-.817733c-1.090311 0-2.238007 .616886-2.238007 1.893698v.774695h-1.420273c-.200847 0-.588194 0-.588194 .41604s.373001 .41604 .573848 .41604h1.43462v4.519052h-1.362889c-.200847 0-.573848 0-.573848 .41604s.373001 .41604 .573848 .41604h3.65828c.200847 0 .573848 0 .573848-.41604s-.373001-.41604-.573848-.41604h-1.362889v-4.519052z"/>
&lt;path id="g2-120" d="m4.045627-3.184855l1.649813-2.166276h.502117c.200847 0 .573848 0 .573848-.41604s-.373001-.41604-.573848-.41604h-1.592428c-.200847 0-.573848 0-.573848 .41604s.344309 .41604 .688617 .41604l-1.075965 1.477658l-1.104657-1.477658c.329963 0 .674271 0 .674271-.41604s-.373001-.41604-.573848-.41604h-1.592428c-.200847 0-.573848 0-.573848 .41604s.373001 .41604 .573848 .41604h.502117l1.707197 2.166276l-1.793274 2.352776h-.487771c-.200847 0-.588194 0-.588194 .41604s.387347 .41604 .588194 .41604h1.578082c.200847 0 .573848 0 .573848-.41604s-.329963-.41604-.71731-.41604l1.233773-1.807621l1.291158 1.807621c-.358655 0-.702964 0-.702964 .41604s.373001 .41604 .573848 .41604h1.592428c.200847 0 .573848 0 .573848-.41604s-.373001-.41604-.573848-.41604h-.502117l-1.850659-2.352776z"/>
&lt;path id="g3-50" d="m6.312326-2.410161h-.315616c-.043039 .243885-.157808 1.032926-.30127 1.262465c-.100423 .129116-.918157 .129116-1.348542 .129116h-2.654046c.387347-.329963 1.262465-1.248119 1.635466-1.592428c2.180622-2.008467 2.984009-2.75447 2.984009-4.174743c0-1.649813-1.305504-2.75447-2.969663-2.75447s-2.6397 1.420273-2.6397 2.654046c0 .731656 .631233 .731656 .674271 .731656c.30127 0 .674271-.215193 .674271-.674271c0-.401693-.272578-.674271-.674271-.674271c-.129116 0-.157808 0-.200847 .014346c.272578-.975541 1.047272-1.635466 1.979775-1.635466c1.219427 0 1.965429 1.01858 1.965429 2.33843c0 1.219427-.702964 2.281045-1.520697 3.199202l-2.897932 3.24224v.344309h5.236361l.373001-2.410161z"/>
&lt;path id="g3-51" d="m2.6397-5.150284c-.243885 .014346-.30127 .028692-.30127 .157808c0 .143462 .071731 .143462 .329963 .143462h.659925c1.219427 0 1.764582 1.004234 1.764582 2.381468c0 1.879352-.975541 2.381468-1.678505 2.381468c-.688617 0-1.865005-.329963-2.281045-1.276811c.459078 .071731 .875118-.186501 .875118-.702964c0-.41604-.30127-.702964-.702964-.702964c-.344309 0-.71731 .200847-.71731 .746002c0 1.276811 1.276811 2.324084 2.869239 2.324084c1.707197 0 2.969663-1.305504 2.969663-2.75447c0-1.31985-1.061618-2.352776-2.438853-2.596661c1.248119-.358655 2.051506-1.405927 2.051506-2.52493c0-1.133349-1.176388-1.965429-2.567969-1.965429c-1.43462 0-2.496238 .875118-2.496238 1.92239c0 .573848 .444732 .688617 .659925 .688617c.30127 0 .645579-.215193 .645579-.645579c0-.459078-.344309-.659925-.659925-.659925c-.086077 0-.11477 0-.157808 .014346c.545155-.975541 1.893698-.975541 1.965429-.975541c.473424 0 1.405927 .215193 1.405927 1.62112c0 .272578-.043039 1.075965-.459078 1.692851c-.430386 .631233-.918157 .674271-1.305504 .688617l-.430386 .043039z"/>
&lt;path id="g3-52" d="m5.178977-9.339373c0-.272578 0-.344309-.200847-.344309c-.11477 0-.157808 0-.272578 .172154l-4.318205 6.699673v.41604h3.773049v1.305504c0 .530809-.028692 .674271-1.075965 .674271h-.286924v.41604c.329963-.028692 1.463312-.028692 1.865005-.028692s1.549389 0 1.879352 .028692v-.41604h-.286924c-1.032926 0-1.075965-.143462-1.075965-.674271v-1.305504h1.448966v-.41604h-1.448966v-6.527519zm-.946849 1.119003v5.408516h-3.486126l3.486126-5.408516z"/>
&lt;path id="g3-56" d="m4.275166-5.178977c.71731-.387347 1.764582-1.047272 1.764582-2.252353c0-1.248119-1.20508-2.108891-2.52493-2.108891c-1.420273 0-2.539277 1.047272-2.539277 2.352776c0 .487771 .143462 .975541 .545155 1.463312c.157808 .186501 .172154 .200847 1.176388 .90381c-1.391581 .645579-2.108891 1.606774-2.108891 2.654046c0 1.520697 1.448966 2.467546 2.912278 2.467546c1.592428 0 2.926624-1.176388 2.926624-2.682739c0-1.463312-1.032926-2.108891-2.151929-2.797508zm-1.951083-1.291158c-.186501-.129116-.760348-.502117-.760348-1.20508c0-.932503 .975541-1.520697 1.936736-1.520697c1.032926 0 1.951083 .746002 1.951083 1.778928c0 .875118-.631233 1.578082-1.463312 2.03716l-1.664159-1.090311zm.674271 1.850659l1.73589 1.133349c.373001 .243885 1.032926 .688617 1.032926 1.563735c0 1.090311-1.104657 1.836313-2.252353 1.836313c-1.219427 0-2.266699-.889464-2.266699-2.080198c0-1.119003 .817733-2.022814 1.750236-2.453199z"/>
&lt;path id="g3-97" d="m5.537632-3.830434c0-.774695 0-1.348542-.631233-1.908044c-.502117-.459078-1.147696-.659925-1.778928-.659925c-1.176388 0-2.080198 .774695-2.080198 1.707197c0 .41604 .272578 .616886 .60254 .616886c.344309 0 .588194-.243885 .588194-.588194c0-.588194-.516463-.588194-.731656-.588194c.329963-.60254 1.01858-.860772 1.592428-.860772c.659925 0 1.506351 .545155 1.506351 1.836313v.573848c-2.883585 .043039-3.973896 1.248119-3.973896 2.352776c0 1.133349 1.31985 1.492004 2.194968 1.492004c.946849 0 1.592428-.573848 1.865005-1.262465c.057385 .674271 .502117 1.190734 1.119003 1.190734c.30127 0 1.133349-.200847 1.133349-1.348542v-.803387h-.315616v.803387c0 .817733-.344309 .932503-.545155 .932503c-.545155 0-.545155-.760348-.545155-.975541v-2.510584zm-.932503 1.807621c0 1.405927-1.047272 1.879352-1.664159 1.879352c-.702964 0-1.291158-.516463-1.291158-1.20508c0-1.893698 2.438853-2.065852 2.955316-2.094545v1.420273z"/>
&lt;path id="g3-98" d="m2.395815-9.95626l-1.994121 .157808v.41604c.975541 0 1.090311 .100423 1.090311 .803387v8.579025h.315616c.057385-.11477 .459078-.832079 .516463-.932503c.329963 .530809 .946849 1.075965 1.865005 1.075965c1.649813 0 3.098778-1.391581 3.098778-3.24224c0-1.821967-1.348542-3.227894-2.94097-3.227894c-.789041 0-1.463312 .358655-1.951083 .961195v-4.590783zm.028692 5.365477c0-.258232 0-.286924 .157808-.516463c.344309-.516463 .975541-.932503 1.678505-.932503c.430386 0 1.936736 .172154 1.936736 2.926624c0 .961195-.143462 1.563735-.487771 2.080198c-.286924 .444732-.860772 .889464-1.578082 .889464c-.774695 0-1.276811-.502117-1.520697-.889464c-.186501-.30127-.186501-.358655-.186501-.60254v-2.955316z"/>
&lt;path id="g3-99" d="m5.193323-5.308092c-.172154 0-.702964 0-.702964 .588194c0 .344309 .243885 .588194 .588194 .588194c.329963 0 .60254-.200847 .60254-.616886c0-.961195-1.004234-1.649813-2.166276-1.649813c-1.678505 0-3.012701 1.492004-3.012701 3.299625c0 1.836313 1.377235 3.24224 2.998355 3.24224c1.893698 0 2.324084-1.721543 2.324084-1.850659s-.100423-.129116-.143462-.129116c-.129116 0-.143462 .043039-.186501 .215193c-.315616 1.01858-1.090311 1.448966-1.865005 1.448966c-.875118 0-2.03716-.760348-2.03716-2.94097c0-2.381468 1.219427-2.969663 1.936736-2.969663c.545155 0 1.334196 .215193 1.664159 .774695z"/>
&lt;path id="g3-101" d="m5.494593-3.328317c.315616 0 .344309 0 .344309-.272578c0-1.448966-.774695-2.797508-2.510584-2.797508c-1.635466 0-2.897932 1.477658-2.897932 3.256586c0 1.893698 1.463312 3.285279 3.05574 3.285279c1.707197 0 2.352776-1.549389 2.352776-1.850659c0-.086077-.071731-.143462-.157808-.143462c-.11477 0-.143462 .071731-.172154 .143462c-.373001 1.20508-1.334196 1.535043-1.936736 1.535043s-2.051506-.401693-2.051506-2.883585v-.272578h3.973896zm-3.95955-.272578c.11477-2.252353 1.377235-2.510584 1.778928-2.510584c1.535043 0 1.62112 2.022814 1.635466 2.510584h-3.414395z"/>
&lt;path id="g3-102" d="m2.467546-5.767171h1.62112v-.41604h-1.649813v-1.678505c0-1.291158 .659925-1.951083 1.248119-1.951083c.11477 0 .329963 .028692 .502117 .11477c-.057385 .014346-.41604 .143462-.41604 .559502c0 .329963 .229539 .559502 .559502 .559502c.344309 0 .573848-.229539 .573848-.573848c0-.530809-.516463-.946849-1.20508-.946849c-1.004234 0-2.137583 .774695-2.137583 2.238007v1.678505h-1.119003v.41604h1.119003v4.705552c0 .645579-.157808 .645579-1.090311 .645579v.41604c.401693-.028692 1.190734-.028692 1.62112-.028692c.387347 0 1.405927 0 1.73589 .028692v-.41604h-.286924c-1.047272 0-1.075965-.157808-1.075965-.674271v-4.67686z"/>
&lt;path id="g3-103" d="m1.707197-2.596661c.674271 .444732 1.248119 .444732 1.405927 .444732c1.291158 0 2.252353-.975541 2.252353-2.080198c0-.387347-.11477-.932503-.573848-1.391581c.559502-.573848 1.233773-.573848 1.305504-.573848c.057385 0 .129116 0 .186501 .028692c-.143462 .057385-.215193 .200847-.215193 .358655c0 .200847 .143462 .373001 .373001 .373001c.11477 0 .373001-.071731 .373001-.387347c0-.258232-.200847-.659925-.702964-.659925c-.746002 0-1.305504 .459078-1.506351 .674271c-.430386-.329963-.932503-.516463-1.477658-.516463c-1.291158 0-2.252353 .975541-2.252353 2.080198c0 .817733 .502117 1.348542 .645579 1.477658c-.172154 .215193-.430386 .631233-.430386 1.190734c0 .832079 .502117 1.190734 .616886 1.262465c-.659925 .186501-1.31985 .702964-1.31985 1.448966c0 .989888 1.348542 1.807621 3.113124 1.807621c1.707197 0 3.127471-.760348 3.127471-1.836313c0-.358655-.100423-1.20508-.961195-1.649813c-.731656-.373001-1.448966-.373001-2.682739-.373001c-.875118 0-.975541 0-1.233773-.272578c-.143462-.143462-.272578-.41604-.272578-.71731c0-.243885 .086077-.487771 .229539-.688617zm1.420273 .143462c-1.262465 0-1.262465-1.448966-1.262465-1.778928c0-.258232 0-.846426 .243885-1.233773c.272578-.41604 .702964-.559502 1.004234-.559502c1.262465 0 1.262465 1.448966 1.262465 1.778928c0 .258232 0 .846426-.243885 1.233773c-.272578 .41604-.702964 .559502-1.004234 .559502zm.387347 5.092899c-1.377235 0-2.424507-.702964-2.424507-1.520697c0-.11477 .028692-.674271 .573848-1.047272c.315616-.200847 .444732-.200847 1.448966-.200847c1.190734 0 2.811854 0 2.811854 1.248119c0 .846426-1.090311 1.520697-2.410161 1.520697z"/>
&lt;path id="g3-104" d="m6.384057-3.486126c0-1.334196 0-1.73589-.329963-2.194968c-.41604-.559502-1.090311-.645579-1.578082-.645579c-1.233773 0-1.807621 .932503-2.008467 1.377235h-.014346v-5.006822l-1.994121 .157808v.41604c.975541 0 1.090311 .100423 1.090311 .803387v7.517407c0 .645579-.157808 .645579-1.090311 .645579v.41604c.373001-.028692 1.147696-.028692 1.549389-.028692c.41604 0 1.190734 0 1.563735 .028692v-.41604c-.918157 0-1.090311 0-1.090311-.645579v-2.668392c0-1.506351 .989888-2.309738 1.879352-2.309738s1.090311 .731656 1.090311 1.606774v3.371356c0 .645579-.157808 .645579-1.090311 .645579v.41604c.373001-.028692 1.147696-.028692 1.549389-.028692c.41604 0 1.190734 0 1.563735 .028692v-.41604c-.71731 0-1.075965 0-1.090311-.430386v-2.6397z"/>
&lt;path id="g3-105" d="m2.496238-8.837257c0-.373001-.30127-.702964-.702964-.702964c-.373001 0-.688617 .30127-.688617 .688617c0 .430386 .344309 .702964 .688617 .702964c.444732 0 .702964-.373001 .702964-.688617zm-1.979775 2.668392v.41604c.918157 0 1.047272 .086077 1.047272 .789041v3.902165c0 .645579-.157808 .645579-1.090311 .645579v.41604c.401693-.028692 1.090311-.028692 1.506351-.028692c.157808 0 .989888 0 1.477658 .028692v-.41604c-.932503 0-.989888-.071731-.989888-.631233v-5.2794l-1.951083 .157808z"/>
&lt;path id="g3-110" d="m6.384057-3.486126c0-1.334196 0-1.73589-.329963-2.194968c-.41604-.559502-1.090311-.645579-1.578082-.645579c-1.391581 0-1.936736 1.190734-2.051506 1.477658h-.014346v-1.477658l-1.951083 .157808v.41604c.975541 0 1.090311 .100423 1.090311 .803387v3.887819c0 .645579-.157808 .645579-1.090311 .645579v.41604c.373001-.028692 1.147696-.028692 1.549389-.028692c.41604 0 1.190734 0 1.563735 .028692v-.41604c-.918157 0-1.090311 0-1.090311-.645579v-2.668392c0-1.506351 .989888-2.309738 1.879352-2.309738s1.090311 .731656 1.090311 1.606774v3.371356c0 .645579-.157808 .645579-1.090311 .645579v.41604c.373001-.028692 1.147696-.028692 1.549389-.028692c.41604 0 1.190734 0 1.563735 .028692v-.41604c-.71731 0-1.075965 0-1.090311-.430386v-2.6397z"/>
&lt;path id="g3-111" d="m6.584904-3.070086c0-1.850659-1.405927-3.328317-3.070086-3.328317c-1.721543 0-3.084432 1.520697-3.084432 3.328317c0 1.836313 1.43462 3.213548 3.070086 3.213548c1.692851 0 3.084432-1.405927 3.084432-3.213548zm-3.070086 2.897932c-.530809 0-1.176388-.229539-1.592428-.932503c-.387347-.645579-.401693-1.492004-.401693-2.094545c0-.545155 0-1.420273 .444732-2.065852c.401693-.616886 1.032926-.846426 1.535043-.846426c.559502 0 1.162042 .258232 1.549389 .817733c.444732 .659925 .444732 1.563735 .444732 2.094545c0 .502117 0 1.391581-.373001 2.065852c-.401693 .688617-1.061618 .961195-1.606774 .961195z"/>
&lt;path id="g3-114" d="m2.395815-3.342664c0-1.391581 .573848-2.697085 1.678505-2.697085c.11477 0 .143462 0 .200847 .014346c-.11477 .057385-.344309 .143462-.344309 .530809c0 .41604 .329963 .573848 .559502 .573848c.286924 0 .573848-.186501 .573848-.573848c0-.430386-.387347-.832079-1.004234-.832079c-1.219427 0-1.635466 1.31985-1.721543 1.592428h-.014346v-1.592428l-1.92239 .157808v.41604c.975541 0 1.090311 .100423 1.090311 .803387v3.887819c0 .645579-.157808 .645579-1.090311 .645579v.41604c.401693-.028692 1.190734-.028692 1.62112-.028692c.387347 0 1.405927 0 1.73589 .028692v-.41604h-.286924c-1.047272 0-1.075965-.157808-1.075965-.674271v-2.252353z"/>
&lt;path id="g3-115" d="m4.705552-6.068441c0-.258232 0-.329963-.143462-.329963c-.11477 0-.387347 .315616-.487771 .444732c-.444732-.358655-.889464-.444732-1.348542-.444732c-1.73589 0-2.252353 .946849-2.252353 1.73589c0 .157808 0 .659925 .545155 1.162042c.459078 .401693 .946849 .502117 1.606774 .631233c.789041 .157808 .975541 .200847 1.334196 .487771c.258232 .215193 .444732 .530809 .444732 .932503c0 .616886-.358655 1.305504-1.62112 1.305504c-.946849 0-1.635466-.545155-1.951083-1.979775c-.057385-.258232-.057385-.272578-.071731-.286924c-.028692-.057385-.086077-.057385-.129116-.057385c-.157808 0-.157808 .071731-.157808 .329963v1.951083c0 .258232 0 .329963 .143462 .329963c.071731 0 .086077-.014346 .329963-.315616c.071731-.100423 .071731-.129116 .286924-.358655c.545155 .674271 1.31985 .674271 1.563735 .674271c1.506351 0 2.252353-.832079 2.252353-1.965429c0-.774695-.473424-1.233773-.60254-1.362889c-.516463-.444732-.90381-.530809-1.850659-.702964c-.430386-.086077-1.477658-.286924-1.477658-1.147696c0-.444732 .30127-1.104657 1.592428-1.104657c1.563735 0 1.649813 1.334196 1.678505 1.778928c.014346 .11477 .11477 .11477 .157808 .11477c.157808 0 .157808-.071731 .157808-.329963v-1.492004z"/>
&lt;path id="g3-116" d="m2.410161-5.767171h2.022814v-.41604h-2.022814v-2.6397h-.315616c-.014346 1.348542-.530809 2.725777-1.836313 2.768816v.286924h1.219427v3.988242c0 1.592428 1.061618 1.92239 1.821967 1.92239c.90381 0 1.377235-.889464 1.377235-1.92239v-.817733h-.315616v.789041c0 1.032926-.41604 1.635466-.975541 1.635466c-.975541 0-.975541-1.334196-.975541-1.578082v-4.016935z"/>
&lt;path id="g3-117" d="m4.361243-6.168864v.41604c.975541 0 1.090311 .100423 1.090311 .803387v2.567969c0 1.219427-.645579 2.238007-1.721543 2.238007c-1.176388 0-1.248119-.674271-1.248119-1.43462v-4.748591l-2.022814 .157808v.41604c1.090311 0 1.090311 .043039 1.090311 1.31985v2.151929c0 .889464 0 1.405927 .430386 1.879352c.344309 .373001 .932503 .545155 1.664159 .545155c.243885 0 .702964 0 1.190734-.41604c.41604-.329963 .645579-.875118 .645579-.875118v1.291158l1.994121-.143462v-.41604c-.975541 0-1.090311-.100423-1.090311-.803387v-5.107246l-2.022814 .157808z"/>
&lt;/defs>
&lt;g id="page1">
&lt;path d="m37.6601-51.79293h113.3868v-16.60157h-113.3868z" fill="none" stroke-width=".56693" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(-103.4113 30.9938)" style="fill: var(--color-fg);">
&lt;use x="151.330156" y="-86.106255" xlink:href="#g3-114"/>
&lt;use x="156.792945" y="-86.106255" xlink:href="#g3-101"/>
&lt;use x="163.036131" y="-86.106255" xlink:href="#g3-102"/>
&lt;use x="167.328323" y="-86.106255" xlink:href="#g3-101"/>
&lt;use x="173.571509" y="-86.106255" xlink:href="#g3-114"/>
&lt;use x="179.034298" y="-86.106255" xlink:href="#g3-101"/>
&lt;use x="185.277485" y="-86.106255" xlink:href="#g3-110"/>
&lt;use x="193.081469" y="-86.106255" xlink:href="#g3-99"/>
&lt;use x="199.324656" y="-86.106255" xlink:href="#g3-101"/>
&lt;use x="210.25022" y="-86.106255" xlink:href="#g3-99"/>
&lt;use x="216.493407" y="-86.106255" xlink:href="#g3-111"/>
&lt;use x="223.516992" y="-86.106255" xlink:href="#g3-117"/>
&lt;use x="231.320976" y="-86.106255" xlink:href="#g3-110"/>
&lt;use x="238.73476" y="-86.106255" xlink:href="#g3-116"/>
&lt;/g>
&lt;path d="m37.6601-34.62105h113.3868v-16.60545h-113.3868z" fill="none" stroke-width=".56693" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(-72.9754 30.9938)" style="fill: var(--color-fg);">
&lt;use x="151.330156" y="-68.93569" xlink:href="#g3-111"/>
&lt;use x="158.353741" y="-68.93569" xlink:href="#g3-116"/>
&lt;use x="163.81653" y="-68.93569" xlink:href="#g3-104"/>
&lt;use x="171.620514" y="-68.93569" xlink:href="#g3-101"/>
&lt;use x="177.863701" y="-68.93569" xlink:href="#g3-114"/>
&lt;/g>
&lt;path d="m37.6601-15.80074h113.3868v-18.25386h-113.3868z" fill="none" stroke-width=".56693" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(-66.7321 30.9938)" style="fill: var(--color-fg);">
&lt;use x="151.330156" y="-52.903677" xlink:href="#g3-116"/>
&lt;use x="156.792945" y="-52.903677" xlink:href="#g3-97"/>
&lt;use x="163.81653" y="-52.903677" xlink:href="#g3-103"/>
&lt;/g>
&lt;path d="m37.6601 41.461h113.3868v-56.6953h-113.3868z" fill="none" stroke-width=".56693" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(-82.3793 30.9938)" style="fill: var(--color-fg);">
&lt;use x="151.330156" y="-13.468247" xlink:href="#g3-99"/>
&lt;use x="157.573343" y="-13.468247" xlink:href="#g3-111"/>
&lt;use x="164.596928" y="-13.468247" xlink:href="#g3-110"/>
&lt;use x="172.010713" y="-13.468247" xlink:href="#g3-116"/>
&lt;use x="177.473501" y="-13.468247" xlink:href="#g3-101"/>
&lt;use x="183.716688" y="-13.468247" xlink:href="#g3-110"/>
&lt;use x="191.130472" y="-13.468247" xlink:href="#g3-116"/>
&lt;use x="196.593261" y="-13.468247" xlink:href="#g3-115"/>
&lt;/g>
&lt;path d="m-71.7192-52.3906h80.4653v-15.4102h-80.4653z" fill="none" stroke-width=".56693" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(-162.7519 -42.2429)" style="fill: var(--color-fg);">
&lt;use x="94.3538" y="-13.468247" xlink:href="#g2-48"/>
&lt;use x="101.736116" y="-13.468247" xlink:href="#g2-120"/>
&lt;use x="109.118433" y="-13.468247" xlink:href="#g2-51"/>
&lt;use x="116.50075" y="-13.468247" xlink:href="#g2-102"/>
&lt;use x="123.883067" y="-13.468247" xlink:href="#g2-99"/>
&lt;use x="131.265384" y="-13.468247" xlink:href="#g2-56"/>
&lt;use x="138.647701" y="-13.468247" xlink:href="#g2-49"/>
&lt;use x="146.030017" y="-13.468247" xlink:href="#g2-50"/>
&lt;use x="153.412334" y="-13.468247" xlink:href="#g2-51"/>
&lt;use x="160.794651" y="-13.468247" xlink:href="#g2-52"/>
&lt;/g>
&lt;g fill="none" stroke-miterlimit="10" style="stroke: var(--color-fg);">
&lt;path d="m9.0313-60.0937h27.7812" stroke-width=".56693"/>
&lt;path d="m35.46488-61.89058c.11328 .67187 1.347652 1.683591 1.68359 1.796872c-.335938 .109375-1.57031 1.121098-1.68359 1.796878" stroke-width=".45352" stroke-linecap="round" stroke-linejoin="round"/>
&lt;path d="m152.75-68.6797c1.6992 .6445 2.832 2.1445 2.832 4.293c0 2.1445 1.1328 3.6484 2.836 4.293c-1.7032 .6445-2.836 2.1445-2.836 4.2929c0 2.1446-1.1328 3.6485-2.832 4.293" stroke-width=".56693"/>
&lt;/g>
&lt;g transform="translate(66.2502 -41.6452)" style="fill: var(--color-fg);">
&lt;use x="94.3538" y="-13.468247" xlink:href="#g3-51"/>
&lt;use x="101.377385" y="-13.468247" xlink:href="#g3-50"/>
&lt;use x="113.083347" y="-13.468247" xlink:href="#g3-98"/>
&lt;use x="120.887331" y="-13.468247" xlink:href="#g3-105"/>
&lt;use x="124.789323" y="-13.468247" xlink:href="#g3-116"/>
&lt;use x="130.252111" y="-13.468247" xlink:href="#g3-115"/>
&lt;/g>
&lt;path d="m152.75-51.5078c1.6992 .6406 2.832 2.1445 2.832 4.293c0 2.1445 1.1328 3.6484 2.836 4.289c-1.7032 .6446-2.836 2.1485-2.836 4.293c0 2.1484-1.1328 3.6523-2.832 4.293" fill="none" stroke-width=".56693" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(66.2502 -24.4744)" style="fill: var(--color-fg);">
&lt;use x="94.3538" y="-13.468247" xlink:href="#g3-50"/>
&lt;use x="101.377385" y="-13.468247" xlink:href="#g3-52"/>
&lt;use x="113.083347" y="-13.468247" xlink:href="#g3-98"/>
&lt;use x="120.887331" y="-13.468247" xlink:href="#g3-105"/>
&lt;use x="124.789323" y="-13.468247" xlink:href="#g3-116"/>
&lt;use x="130.252111" y="-13.468247" xlink:href="#g3-115"/>
&lt;/g>
&lt;path d="m152.75-34.3398c1.6992 .707 2.832 2.3554 2.832 4.707c0 2.3515 1.1328 4 2.836 4.707c-1.7032 .7031-2.836 2.35158-2.836 4.70314c0 2.35157-1.1328 4-2.832 4.70703" fill="none" stroke-width=".56693" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(66.2502 -6.4781)" style="fill: var(--color-fg);">
&lt;use x="94.3538" y="-13.468247" xlink:href="#g3-56"/>
&lt;use x="106.059762" y="-13.468247" xlink:href="#g3-98"/>
&lt;use x="113.863746" y="-13.468247" xlink:href="#g3-105"/>
&lt;use x="117.765737" y="-13.468247" xlink:href="#g3-116"/>
&lt;use x="123.228526" y="-13.468247" xlink:href="#g3-115"/>
&lt;/g>
&lt;path d="m152.75-15.51563c1.6992 .84766 2.832 2.832036 2.832 5.66797v17.29296c0 2.832 1.1328 4.8164 2.836 5.668c-1.7032 .8515-2.836 2.8359-2.836 5.668v17.2929c0 2.836-1.1328 4.8203-2.832 5.668" fill="none" stroke-width=".56693" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(66.2502 30.9653)" style="fill: var(--color-fg);">
&lt;use x="94.3538" y="-13.468247" xlink:href="#g1-78"/>
&lt;use x="111.783295" y="-13.468247" xlink:href="#g0-2"/>
&lt;use x="127.623864" y="-13.468247" xlink:href="#g3-51"/>
&lt;use x="134.647449" y="-13.468247" xlink:href="#g3-50"/>
&lt;use x="146.353411" y="-13.468247" xlink:href="#g3-98"/>
&lt;use x="154.157395" y="-13.468247" xlink:href="#g3-105"/>
&lt;use x="158.059387" y="-13.468247" xlink:href="#g3-116"/>
&lt;use x="163.522176" y="-13.468247" xlink:href="#g3-115"/>
&lt;/g>
&lt;/g>
&lt;/svg>
&lt;p>Unfortunately, this can be quite inefficient for small objects. For example, it does not make sense to allocate small integers or booleans on the heap. As an optimization, certain small objects are stored directly as a value representing themselves (instead of a pointer pointing to them). For example, the number 13 would be represented directly by the constant &lt;code>0x1b&lt;/code>:&lt;/p>
&lt;!-- This file was generated by dvisvgm 2.13.3 -->&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="81.031004pt" height="15.975064pt" viewBox="-72 -72 81.031004 15.975064">
&lt;defs>
&lt;path id="g0-48" d="m6.656635-4.37559c0-2.668392-1.420273-4.56209-2.969663-4.56209c-1.563735 0-2.969663 1.92239-2.969663 4.547744c0 2.668392 1.420273 4.56209 2.969663 4.56209c1.563735 0 2.969663-1.92239 2.969663-4.547744zm-2.969663 3.715665c-1.133349 0-2.03716-1.73589-2.03716-3.873473s.989888-3.572203 2.03716-3.572203s2.03716 1.43462 2.03716 3.572203c0 2.123237-.90381 3.873473-2.03716 3.873473z"/>
&lt;path id="g0-49" d="m4.361243-8.349486c0-.215193 0-.588194-.41604-.588194c-.243885 0-.329963 .129116-.41604 .315616c-.272578 .616886-.746002 1.377235-1.506351 1.43462c-.215193 .014346-.516463 .043039-.516463 .41604c0 .243885 .143462 .41604 .459078 .41604c.803387 0 1.420273-.60254 1.463312-.631233v6.154518h-1.262465c-.200847 0-.588194 0-.588194 .41604s.387347 .41604 .588194 .41604h3.457433c.200847 0 .588194 0 .588194-.41604s-.387347-.41604-.588194-.41604h-1.262465v-7.517407z"/>
&lt;path id="g0-98" d="m2.309738-8.177332c0-.444732-.086077-.588194-.573848-.588194h-.946849c-.200847 0-.573848 0-.573848 .41604s.373001 .41604 .573848 .41604h.588194v7.345252c0 .258232 0 .588194 .473424 .588194c.459078 0 .459078-.30127 .459078-.71731c.344309 .387347 .875118 .803387 1.678505 .803387c1.520697 0 2.854893-1.362889 2.854893-3.184855c0-1.764582-1.20508-3.170509-2.697085-3.170509c-1.047272 0-1.707197 .631233-1.836313 .774695v-2.682739zm0 4.361243c0-.817733 .803387-1.62112 1.73589-1.62112c1.032926 0 1.865005 1.047272 1.865005 2.33843c0 1.377235-.975541 2.352776-1.994121 2.352776c-1.075965 0-1.606774-1.219427-1.606774-1.936736v-1.133349z"/>
&lt;path id="g0-120" d="m4.045627-3.184855l1.649813-2.166276h.502117c.200847 0 .573848 0 .573848-.41604s-.373001-.41604-.573848-.41604h-1.592428c-.200847 0-.573848 0-.573848 .41604s.344309 .41604 .688617 .41604l-1.075965 1.477658l-1.104657-1.477658c.329963 0 .674271 0 .674271-.41604s-.373001-.41604-.573848-.41604h-1.592428c-.200847 0-.573848 0-.573848 .41604s.373001 .41604 .573848 .41604h.502117l1.707197 2.166276l-1.793274 2.352776h-.487771c-.200847 0-.588194 0-.588194 .41604s.387347 .41604 .588194 .41604h1.578082c.200847 0 .573848 0 .573848-.41604s-.329963-.41604-.71731-.41604l1.233773-1.807621l1.291158 1.807621c-.358655 0-.702964 0-.702964 .41604s.373001 .41604 .573848 .41604h1.592428c.200847 0 .573848 0 .573848-.41604s-.373001-.41604-.573848-.41604h-.502117l-1.850659-2.352776z"/>
&lt;/defs>
&lt;g id="page1">
&lt;path d="m-71.7187-56.3086h80.4687v-15.40625h-80.4687z" fill="none" stroke-width=".56693" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(-36.912 4.3836)" style="fill: var(--color-fg);">
&lt;use x="-31.484503" y="-64.012471" xlink:href="#g0-48"/>
&lt;use x="-24.102186" y="-64.012471" xlink:href="#g0-120"/>
&lt;use x="-16.719869" y="-64.012471" xlink:href="#g0-48"/>
&lt;use x="-9.337552" y="-64.012471" xlink:href="#g0-48"/>
&lt;use x="-1.955235" y="-64.012471" xlink:href="#g0-48"/>
&lt;use x="5.427081" y="-64.012471" xlink:href="#g0-48"/>
&lt;use x="12.809398" y="-64.012471" xlink:href="#g0-48"/>
&lt;use x="20.191715" y="-64.012471" xlink:href="#g0-48"/>
&lt;use x="27.574032" y="-64.012471" xlink:href="#g0-49"/>
&lt;use x="34.956349" y="-64.012471" xlink:href="#g0-98"/>
&lt;/g>
&lt;/g>
&lt;/svg>
&lt;p>But wait, how did 13 turn into 27? It turns out that in order to distinguish pointers from these so-called &lt;em>scalar&lt;/em> values, the LSB (least significant bit) needs to be set to 1. The actual value is shifted left by one, so that the value &lt;code>n&lt;/code> is encoded as &lt;code>(n &amp;lt;&amp;lt; 1) | 1&lt;/code>. This is how the value 13 is encoded:&lt;/p>
&lt;!-- This file was generated by dvisvgm 2.13.3 -->&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="120.323626pt" height="43.030177pt" viewBox="-72 -72 120.323626 43.030177">
&lt;defs>
&lt;path id="g0-58" d="m2.6397-.688617c0-.41604-.344309-.702964-.688617-.702964c-.41604 0-.702964 .344309-.702964 .688617c0 .41604 .344309 .702964 .688617 .702964c.41604 0 .702964-.344309 .702964-.688617z"/>
&lt;path id="g1-48" d="m6.427096-4.590783c0-1.190734-.071731-2.352776-.588194-3.443087c-.588194-1.190734-1.62112-1.506351-2.324084-1.506351c-.832079 0-1.850659 .41604-2.381468 1.606774c-.401693 .90381-.545155 1.793274-.545155 3.342664c0 1.391581 .100423 2.438853 .616886 3.457433c.559502 1.090311 1.549389 1.43462 2.295391 1.43462c1.248119 0 1.965429-.746002 2.381468-1.578082c.516463-1.075965 .545155-2.481892 .545155-3.313971zm-2.926624 4.605129c-.459078 0-1.391581-.258232-1.664159-1.821967c-.157808-.860772-.157808-1.951083-.157808-2.955316c0-1.176388 0-2.238007 .229539-3.084432c.243885-.961195 .975541-1.405927 1.592428-1.405927c.545155 0 1.377235 .329963 1.649813 1.563735c.186501 .817733 .186501 1.951083 .186501 2.926624c0 .961195 0 2.051506-.157808 2.926624c-.272578 1.578082-1.176388 1.850659-1.678505 1.850659z"/>
&lt;path id="g1-49" d="m4.131704-9.195911c0-.329963 0-.344309-.286924-.344309c-.344309 .387347-1.061618 .918157-2.539277 .918157v.41604c.329963 0 1.047272 0 1.836313-.373001v7.474368c0 .516463-.043039 .688617-1.305504 .688617h-.444732v.41604c.387347-.028692 1.778928-.028692 2.252353-.028692s1.850659 0 2.238007 .028692v-.41604h-.444732c-1.262465 0-1.305504-.172154-1.305504-.688617v-8.091254z"/>
&lt;path id="g1-51" d="m2.6397-5.150284c-.243885 .014346-.30127 .028692-.30127 .157808c0 .143462 .071731 .143462 .329963 .143462h.659925c1.219427 0 1.764582 1.004234 1.764582 2.381468c0 1.879352-.975541 2.381468-1.678505 2.381468c-.688617 0-1.865005-.329963-2.281045-1.276811c.459078 .071731 .875118-.186501 .875118-.702964c0-.41604-.30127-.702964-.702964-.702964c-.344309 0-.71731 .200847-.71731 .746002c0 1.276811 1.276811 2.324084 2.869239 2.324084c1.707197 0 2.969663-1.305504 2.969663-2.75447c0-1.31985-1.061618-2.352776-2.438853-2.596661c1.248119-.358655 2.051506-1.405927 2.051506-2.52493c0-1.133349-1.176388-1.965429-2.567969-1.965429c-1.43462 0-2.496238 .875118-2.496238 1.92239c0 .573848 .444732 .688617 .659925 .688617c.30127 0 .645579-.215193 .645579-.645579c0-.459078-.344309-.659925-.659925-.659925c-.086077 0-.11477 0-.157808 .014346c.545155-.975541 1.893698-.975541 1.965429-.975541c.473424 0 1.405927 .215193 1.405927 1.62112c0 .272578-.043039 1.075965-.459078 1.692851c-.430386 .631233-.918157 .674271-1.305504 .688617l-.430386 .043039z"/>
&lt;path id="g1-61" d="m9.683682-4.648167c.200847 0 .459078 0 .459078-.258232c0-.272578-.243885-.272578-.459078-.272578h-8.449909c-.200847 0-.459078 0-.459078 .258232c0 .272578 .243885 .272578 .459078 .272578h8.449909zm0 2.668392c.200847 0 .459078 0 .459078-.258232c0-.272578-.243885-.272578-.459078-.272578h-8.449909c-.200847 0-.459078 0-.459078 .258232c0 .272578 .243885 .272578 .459078 .272578h8.449909z"/>
&lt;/defs>
&lt;g id="page1">
&lt;path d="m-68.39839-52.50781h41.9609v-15.88669h-41.9609z" fill="none" stroke-width=".56693" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(-74.50071 4.6227)" style="fill: var(--color-fg);">
&lt;use x="9.424315" y="-60.452852" xlink:href="#g1-48"/>
&lt;use x="18.838897" y="-60.452852" xlink:href="#g0-58"/>
&lt;use x="25.131886" y="-60.452852" xlink:href="#g0-58"/>
&lt;use x="31.424875" y="-60.452852" xlink:href="#g0-58"/>
&lt;use x="37.717823" y="-60.452852" xlink:href="#g1-48"/>
&lt;/g>
&lt;path d="m-25.87109-52.50781h13.66406v-15.88669h-13.66406z" fill="none" stroke-width=".56693" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(-60.3538 4.6227)" style="fill: var(--color-fg);">
&lt;use x="37.802576" y="-60.452852" xlink:href="#g1-49"/>
&lt;/g>
&lt;path d="m-11.64062-52.50781h13.66406v-15.88669h-13.66406z" fill="none" stroke-width=".56693" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(-60.35382 4.6227)" style="fill: var(--color-fg);">
&lt;use x="52.03409" y="-60.452852" xlink:href="#g1-49"/>
&lt;/g>
&lt;path d="m2.58985-52.50781h13.66797v-15.88669h-13.66797z" fill="none" stroke-width=".56693" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(-60.35381 4.6227)" style="fill: var(--color-fg);">
&lt;use x="66.265603" y="-60.452852" xlink:href="#g1-48"/>
&lt;/g>
&lt;path d="m16.82422-52.50781h13.66407v-15.88669h-13.66407z" fill="none" stroke-width=".56693" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(-60.3538 4.6227)" style="fill: var(--color-fg);">
&lt;use x="80.497117" y="-60.452852" xlink:href="#g1-49"/>
&lt;/g>
&lt;path d="m31.05469-52.50781h13.66407v-15.88669h-13.66407z" fill="none" stroke-width=".56693" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(-60.3538 4.6227)" style="fill: var(--color-keyword);">
&lt;use x="94.72863" y="-60.452852" xlink:href="#g1-49"/>
&lt;/g>
&lt;path d="m-68.6797-49.3906c.8516 1.6992 2.8359 2.832 5.668 2.832h38.3867c2.83594 0 4.82031 1.1367 5.67187 2.8359c.84766-1.6992 2.83204-2.8359 5.66797-2.8359h38.38676c2.8359 0 4.8203-1.1328 5.6718-2.832" fill="none" stroke-width=".56693" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(-21.5949 28.1629)" style="fill: var(--color-fg);">
&lt;use x="-11.83819" y="-60.452852" xlink:href="#g1-61"/>
&lt;use x="3.072382" y="-60.452852" xlink:href="#g1-49"/>
&lt;use x="10.095967" y="-60.452852" xlink:href="#g1-51"/>
&lt;/g>
&lt;/g>
&lt;/svg>
&lt;p>Note that the LSB of pointers is guaranteed to be 0, since the objects in the heap are always aligned to 4 bytes. This way, scalars and pointers can be clearly distinguished based on their LSB.&lt;/p>
&lt;h2 id="memory-management">Memory management&lt;/h2>
&lt;p>Most managed languages nowadays use some sort of tracing garbage collector to automatically clean up unused objects. Lean uses reference counting instead. The header of each heap allocated object contains a reference count. It gets incremented if there is a new reference to the object, and decremented when a reference is no longer needed. When the reference count reaches zero, the object is freed.&lt;/p>
&lt;p>Lean opts to use reference counting for two major reasons. First, a big weakness of reference counting, the handling of cycles, is not an issue, since due to immutability it is guaranteed that the object graph is acyclic.&lt;/p>
&lt;p>Second, it allows for an optimization that is particularly useful for languages where all values are immutable. Take the following Lean code:&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code>&lt;span class="hljs-theorem">&lt;span class="hljs-keyword">def&lt;/span> &lt;span class="hljs-title">rep&lt;/span> &lt;span class="hljs-params">(n : Nat)&lt;/span> &lt;span class="hljs-params">(v : α)&lt;/span> &lt;span class="hljs-symbol">:=&lt;/span>&lt;/span>
&lt;span class="hljs-keyword">match&lt;/span> n &lt;span class="hljs-built_in">with&lt;/span>
| &lt;span class="hljs-number">0&lt;/span> =&amp;gt; #[]
| n + &lt;span class="hljs-number">1&lt;/span> =&amp;gt; Array.push (rep n v) v
&lt;/code>&lt;/pre>&lt;/div>
&lt;p>This returns an array containing the value &lt;code>v&lt;/code> &lt;code>n&lt;/code> times. But since the array is immutable, it is created and destroyed &lt;code>n&lt;/code> times, always with one extra element.&lt;/p>
&lt;p>As a special optimization, when the &lt;code>Array.push&lt;/code> builtin function receives an argument with a reference count of exactly 1, it can mutate the existing array instead of having to create a new one. Since the reference count guarantees that this mutation cannot be observed by any other part of the code, this does not violate functional purity.&lt;/p>
&lt;p>You can read more about this specific optimization, and much more in this paper: &lt;span class="hugo-cite-intext" itemprop="citation">&lt;span class="tooltip-trigger">&lt;a href="#cite:1">[1]&lt;/a>&lt;span class="tooltip">S. Ullrich and L. de Moura, &lt;span>“Counting immutable beans: Reference counting optimized for purely functional programming.”&lt;/span> 2020. Available: &lt;a href="https://arxiv.org/abs/1908.05647">&lt;a href="https://arxiv.org/abs/1908.05647">https://arxiv.org/abs/1908.05647&lt;/a>&lt;/a>&lt;/span>&lt;/span>&lt;/span>.&lt;/p>
&lt;h2 id="getting-the-runtime-to-compile--run-on-the-esp32-c3">Getting the runtime to compile &amp;amp; run on the ESP32-C3&lt;/h2>
&lt;p>The runtime includes its own special allocator to speed up the allocation of small objects. It &lt;a href="https://github.com/leanprover/lean4/blob/v4.8.0/src/runtime/alloc.cpp#L26">allocates 8 MiB segments&lt;/a> from the system to then suballocate the objects. This is many times larger than the whole 384 KiB of RAM we have, so it definitely won&amp;rsquo;t cut it. The easiest solution is to just disable this special allocator, and rely on the &lt;code>malloc&lt;/code> implementation being fast enough.&lt;/p>
&lt;p>The next challenge is that the runtime is written in C++. If possible I would like to avoid having to deal with exceptions and vtables and other C++ features requiring special runtime considerations compared to C.&lt;/p>
&lt;p>I went on a quest to slim down the runtime, and removed as many unnecessary things as possible:&lt;/p>
&lt;ul>
&lt;li>There were some uses of C++ exceptions, but none of them were hard to remove.&lt;/li>
&lt;li>I removed a bunch of unneeded features, like multithreading or debugging support.&lt;/li>
&lt;li>Removed library functions assuming the presence of an OS, like file IO or process management.&lt;/li>
&lt;/ul>
&lt;p>What remains is mostly the core functionality used by compiled Lean programs:&lt;/p>
&lt;ul>
&lt;li>Primitives for allocating objects and manipulating reference counts.&lt;/li>
&lt;li>Optimized functions for calling closures.&lt;/li>
&lt;li>Implementations for special-case types like strings, arrays, and natural number.&lt;/li>
&lt;li>IO primitives, so things like &lt;code>IO.print&lt;/code> work.&lt;/li>
&lt;/ul>
&lt;h1 id="toolchain-compiler-and-libraries">Toolchain: compiler and libraries&lt;/h1>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>I wanted to have full control over the whole toolchain to be able to customize things if necessary, so I decided to build the standard C and C++ libraries for myself. I compiled everything with the &lt;code>-ffunction-sections&lt;/code> flag, which allows garbage collection of individual functions at link time, reducing code size. The full tech-stack ended up being the following:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>C/C++ compiler: Clang version 18.&lt;/p>
&lt;p>Clang is a multi-target compiler, so unlike GCC, I don&amp;rsquo;t have to build a special RISC-V cross-compiler. I just pass the &lt;code>-target riscv32-none-elf -march=rv32imczicsr&lt;/code>&lt;sup id="fnref:1">&lt;a href="#fn:1" role="doc-noteref">1&lt;/a>&lt;span class="footnote-tooltip">Just rolls off the tongue, right? &lt;code>rv32&lt;/code> stands for &amp;ldquo;RISC-V 32 bit&amp;rdquo;, &lt;code>i&lt;/code> is the base integer instruction set, &lt;code>m&lt;/code> is the extension with multiplication and division instructions, &lt;code>c&lt;/code> signifies support for compressed instruction encoding, and finally &lt;code>zicsr&lt;/code> signals support for &amp;ldquo;Control and Status Register&amp;rdquo; (CSR) instructions.&lt;/span>&lt;/sup> flags and it works.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>C standard library: &lt;a href="https://github.com/picolibc/picolibc">picolibc&lt;/a>.&lt;/p>
&lt;p>Picolibc is specifically designed for small embedded systems with limited RAM. It includes a &lt;code>malloc&lt;/code> implementation, which is needed for the Lean runtime. It also includes standard input/output functions, which are also used by the Lean runtime to implement &lt;code>IO.print&lt;/code>. I hooked them up to the built-in USB serial peripheral on the ESP32-C3.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>C++ standard library: &lt;a href="https://libcxx.llvm.org/">libc++&lt;/a>.&lt;/p>
&lt;p>libc++ is developed under the umbrella of the LLVM project, and so is a natural choice to use together with clang.&lt;/p>
&lt;p>C++ is needed to compile the Lean runtime. I think &lt;code>std::vector&lt;/code> is the most important thing it needs from the C++ standard library. (Which uses C++&amp;rsquo;s &lt;code>new&lt;/code> operator, which uses &lt;code>malloc&lt;/code> under the hood. Fortunately all the C++ stuff I needed ended up just working relatively painlessly.)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Lean compiler: No custom modifications.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Lean runtime: My own slimmed down version, &lt;a href="#getting-the-runtime-to-compile--run-on-the-esp32-c3">discussed above&lt;/a>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Lean standard library (&lt;code>Init&lt;/code>): No modifications. (Though I do have a dirty hack to reduce its code size massively, &lt;a href="#lean-startup">see below&lt;/a>.)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>QEMU for testing: &lt;a href="https://github.com/espressif/qemu">Espressif&amp;rsquo;s QEMU branch&lt;/a> with support for the ESP32-C3.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="the-nix-package-manager">The Nix package manager&lt;/h2>
&lt;p>If you ever tried to put together some software project with multiple customized dependencies that need to be compiled, you know how painful it can be. And even if you manage to get it working, and document how you did it, the chances of someone else getting it working on the first try (or even you yourself on another computer) is basically zero.&lt;/p>
&lt;p>You did not forget to record all the custom build system flags you used, right? Also project X needs a one line modification to get it to compile in your environment, don&amp;rsquo;t forget about that. Also project Y needs an older version of dependency Z, so you have to temporarily downgrade it while compiling that one project, you recorded the exact version needed, right?&lt;/p>
&lt;p>And even if you documented every step perfectly, some project is bound to depend on something in your environment you did not notice, but someone else might not have installed.&lt;/p>
&lt;p>Also if you want to take your project and continue working on it let&amp;rsquo;s say 1 or 2 years later, chances are that something will have gotten broken by then. Even if you recorded the versions of ALL packages installed on your system, reproducing the exact same environment is impossible on most operating systems.&lt;/p>
&lt;p>Nix is a package manager that builds packages in a reproducible manner. Every build is isolated from the rest of the world and only supplied with dependencies that were explicitly declared, so that it&amp;rsquo;s not possible to forget declaring a dependency. Every external input (e.g. source code downloaded from a git repository) must be pinned by its hash so that it cannot change implicitly.&lt;/p>
&lt;p>If a nix package works today, it is pretty much guaranteed to continue working many years into the future without any changes.&lt;/p>
&lt;p>Nix also makes it very easy to define one&amp;rsquo;s own packages using its package definition DSL called the &lt;em>nix language&lt;/em>.&lt;/p>
&lt;p>Because of these aforementioned advantages, I decided to use Nix for this project from the very start. This guarantees that anyone (either you, or future me many years from now) can just clone the &lt;a href="https://github.com/kuruczgy/lean-esp32/tree/for-blog">project repository&lt;/a>, and run &lt;code>nix build&lt;/code> to compile the exact versions of everything I used for the project, including the final binary that runs on the ESP32-C3.&lt;/p>
&lt;h2 id="targeting-the-esp32-c3-with-nixpkgs">Targeting the ESP32-C3 with &lt;code>nixpkgs&lt;/code>&lt;/h2>
&lt;p>The main package collection for Nix is called &lt;code>nixpkgs&lt;/code>, which I will be using as a base to build my packages on.&lt;/p>
&lt;p>If the description above made it seem like Nix is a magic bullet and everything is perfect and beautiful in the Nix ecosystem, I have some bad news, building software for embedded targets is not a very common (or commonly tested) use-case of &lt;code>nixpkgs&lt;/code>, and some hacks will be needed. But importantly, these are reproducible hacks! Once they are working we can just shove them into a git repository and forget about them, they will keep working no matter how ugly they are.&lt;/p>
&lt;p>With all that said, let&amp;rsquo;s see what it takes to target an embedded system with &lt;code>nixpkgs&lt;/code>. &lt;code>nixpkgs&lt;/code> has an &lt;em>stdenv&lt;/em> (standard environment) for building packages that includes common dependencies like a C compiler and a libc. I want to instantiate a package set with an stdenv that comes with clang, picolibc, libc++, and preconfigured compiler flags which are needed to compile code for the ESP32-C3.&lt;/p>
&lt;p>The most important compiler flag is the exact target processor architecture, which &lt;a href="https://github.com/kuruczgy/lean-esp32/blob/for-blog/flake.nix#L125">is configured&lt;/a> as &lt;code>rv32imczicsr&lt;/code>.&lt;sup id="fnref1:1">&lt;a href="#fn:1" role="doc-noteref">1&lt;/a>&lt;span class="footnote-tooltip">Just rolls off the tongue, right? &lt;code>rv32&lt;/code> stands for &amp;ldquo;RISC-V 32 bit&amp;rdquo;, &lt;code>i&lt;/code> is the base integer instruction set, &lt;code>m&lt;/code> is the extension with multiplication and division instructions, &lt;code>c&lt;/code> signifies support for compressed instruction encoding, and finally &lt;code>zicsr&lt;/code> signals support for &amp;ldquo;Control and Status Register&amp;rdquo; (CSR) instructions.&lt;/span>&lt;/sup>&lt;/p>
&lt;p>&lt;a href="https://github.com/kuruczgy/lean-esp32/blob/for-blog/flake.nix#L19">The package definition for picolibc&lt;/a> is fairly straightforward. To get libc++ to compile we &lt;a href="https://github.com/kuruczgy/lean-esp32/blob/for-blog/patches/nixpkgs.patch">have to apply some patches to &lt;code>nixpkgs&lt;/code>&lt;/a>: this consists of turning on some options that are only enabled for WebAssembly in stock &lt;code>nixpkgs&lt;/code> (I guess embedded environments and WebAssembly have quite a bit in common), and adding some extra flags on top to turn off some more libc++ features (like locale support, which we definitely don&amp;rsquo;t need) to get it to compile.&lt;/p>
&lt;p>Building the customized Lean runtime is &lt;a href="https://github.com/kuruczgy/lean-esp32/blob/for-blog/flake.nix#L40">moderately involved&lt;/a>, the solution is graft it onto the original Lean source tree so that we can use the build system that&amp;rsquo;s already in place.&lt;/p>
&lt;p>Lean likes to use its own C compiler wrapper to apply some extra flags, and it takes &lt;a href="https://github.com/kuruczgy/lean-esp32/blob/for-blog/flake.nix#L75">quite a bit of work&lt;/a> to convince it that this is really rather not a good idea in this situation. (It tries to do things like link with &lt;code>stdc++&lt;/code> which is the GNU version of the standard C library which we don&amp;rsquo;t have, or turn on threading support.)&lt;/p>
&lt;p>&lt;a href="https://github.com/kuruczgy/lean-esp32/blob/for-blog/flake.nix#L94">Compiling Lean&amp;rsquo;s &lt;code>Init&lt;/code> library&lt;/a> is fairly easy compared to everything else, though I don&amp;rsquo;t think compiling it separately from the rest of Lean is an intended use-case.&lt;/p>
&lt;p>Finally, &lt;a href="https://github.com/kuruczgy/lean-esp32/blob/for-blog/flake.nix#L190">building the example app itself&lt;/a> is not too hard either (though it still does take a moderately sized list of carefully crafted compiler flags), since all the hard work has already been done by setting up the stdenv and Lean.&lt;/p>
&lt;h2 id="hacking-on-the-project-yourself">Hacking on the project yourself&lt;/h2>
&lt;p>The project also contains a QEMU version compiled from &lt;a href="https://github.com/espressif/qemu">Espressif&amp;rsquo;s repository&lt;/a>, with support for the ESP32-C3, so you don&amp;rsquo;t even need a real device to try it out. Just run &lt;code>nix run .#qemu&lt;/code> in the project root. You should see a message printed by the main function written in Lean.&lt;/p>
&lt;p>For further information, see the &lt;a href="https://github.com/kuruczgy/lean-esp32/blob/for-blog/README.md">README&lt;/a> file.&lt;/p>
&lt;h1 id="booting-and-application-initialization">Booting and application initialization&lt;/h1>
&lt;h2 id="memory-layout">Memory layout&lt;/h2>
&lt;p>Here is how I decided to lay out the 384 KiB of RAM:&lt;/p>
&lt;!-- This file was generated by dvisvgm 2.13.3 -->&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="401.428742pt" height="154.855791pt" viewBox="-72 -72 401.428742 154.855791">
&lt;defs>
&lt;path id="g0-48" d="m6.656635-4.37559c0-2.668392-1.420273-4.56209-2.969663-4.56209c-1.563735 0-2.969663 1.92239-2.969663 4.547744c0 2.668392 1.420273 4.56209 2.969663 4.56209c1.563735 0 2.969663-1.92239 2.969663-4.547744zm-2.969663 3.715665c-1.133349 0-2.03716-1.73589-2.03716-3.873473s.989888-3.572203 2.03716-3.572203s2.03716 1.43462 2.03716 3.572203c0 2.123237-.90381 3.873473-2.03716 3.873473z"/>
&lt;path id="g0-51" d="m3.672626-4.318205c1.492004 0 2.151929 1.047272 2.151929 1.821967c0 .946849-.832079 1.836313-2.094545 1.836313c-1.43462 0-2.080198-.774695-2.080198-.975541c0-.028692 .014346-.057385 .028692-.071731c.057385-.100423 .100423-.215193 .100423-.344309c0-.30127-.229539-.573848-.573848-.573848c-.30127 0-.588194 .186501-.588194 .631233c0 1.248119 1.362889 2.166276 3.113124 2.166276c1.807621 0 3.027047-1.291158 3.027047-2.654046c0-.731656-.401693-1.750236-1.664159-2.295391c.875118-.545155 1.262465-1.405927 1.262465-2.151929c0-1.075965-1.075965-2.008467-2.625354-2.008467c-1.592428 0-2.711431 .688617-2.711431 1.750236c0 .473424 .358655 .616886 .588194 .616886c.258232 0 .573848-.200847 .573848-.588194c0-.229539-.11477-.358655-.11477-.373001c.430386-.545155 1.420273-.573848 1.664159-.573848c.975541 0 1.692851 .516463 1.692851 1.190734c0 .41604-.272578 1.606774-1.778928 1.707197c-.530809 .028692-.760348 .057385-.817733 .057385c-.286924 .028692-.358655 .215193-.358655 .41604c0 .41604 .30127 .41604 .545155 .41604h.659925z"/>
&lt;path id="g0-56" d="m4.762937-4.734245c1.147696-.344309 1.793274-1.104657 1.793274-1.908044c0-1.176388-1.190734-2.295391-2.869239-2.295391s-2.869239 1.119003-2.869239 2.295391c0 .832079 .688617 1.578082 1.793274 1.908044c-1.448966 .459078-1.994121 1.448966-1.994121 2.252353c0 1.405927 1.31985 2.654046 3.070086 2.654046s3.070086-1.233773 3.070086-2.654046c0-.789041-.530809-1.793274-1.994121-2.252353zm-1.075965-.41604c-1.133349 0-1.936736-.702964-1.936736-1.477658c0-.789041 .832079-1.477658 1.936736-1.477658s1.936736 .688617 1.936736 1.477658c0 .774695-.817733 1.477658-1.936736 1.477658zm0 4.490359c-1.233773 0-2.137583-.875118-2.137583-1.821967c0-1.01858 .961195-1.836313 2.137583-1.836313c1.20508 0 2.137583 .860772 2.137583 1.821967c0 1.004234-.932503 1.836313-2.137583 1.836313z"/>
&lt;path id="g0-99" d="m6.541865-1.563735c0-.373001-.358655-.373001-.473424-.373001c-.329963 0-.387347 .11477-.459078 .315616c-.315616 .789041-1.01858 .875118-1.362889 .875118c-1.219427 0-2.252353-1.01858-2.252353-2.352776c0-.731656 .41604-2.381468 2.295391-2.381468c.387347 0 .688617 .028692 .817733 .043039c.100423 .028692 .11477 .043039 .11477 .11477c.043039 .588194 .487771 .60254 .573848 .60254c.315616 0 .588194-.215193 .588194-.60254c0-.989888-1.448966-.989888-2.080198-.989888c-2.453199 0-3.24224 2.008467-3.24224 3.213548c0 1.750236 1.334196 3.184855 3.05574 3.184855c1.92239 0 2.424507-1.420273 2.424507-1.649813z"/>
&lt;path id="g0-100" d="m5.99671-8.177332c0-.444732-.086077-.588194-.573848-.588194h-.946849c-.200847 0-.573848 0-.573848 .41604s.373001 .41604 .573848 .41604h.588194v2.381468c-.229539-.229539-.817733-.71731-1.692851-.71731c-1.520697 0-2.840547 1.377235-2.840547 3.184855c0 1.764582 1.233773 3.170509 2.711431 3.170509c.932503 0 1.549389-.559502 1.821967-.875118c0 .60254 0 .789041 .573848 .789041h.946849c.200847 0 .573848 0 .573848-.41604s-.373001-.41604-.573848-.41604h-.588194v-7.345252zm-.932503 5.451554c0 .803387-.659925 1.979775-1.73589 1.979775c-1.032926 0-1.865005-1.047272-1.865005-2.33843c0-1.377235 .975541-2.352776 1.994121-2.352776c.932503 0 1.606774 .846426 1.606774 1.592428v1.119003z"/>
&lt;path id="g0-102" d="m3.54351-5.351131h1.73589c.200847 0 .573848 0 .573848-.41604s-.373001-.41604-.573848-.41604h-1.73589v-.71731c0-1.119003 1.004234-1.119003 1.463312-1.119003c0 .028692 .11477 .559502 .588194 .559502c.229539 0 .559502-.172154 .559502-.573848c0-.817733-1.090311-.817733-1.305504-.817733c-1.090311 0-2.238007 .616886-2.238007 1.893698v.774695h-1.420273c-.200847 0-.588194 0-.588194 .41604s.373001 .41604 .573848 .41604h1.43462v4.519052h-1.362889c-.200847 0-.573848 0-.573848 .41604s.373001 .41604 .573848 .41604h3.65828c.200847 0 .573848 0 .573848-.41604s-.373001-.41604-.573848-.41604h-1.362889v-4.519052z"/>
&lt;path id="g0-120" d="m4.045627-3.184855l1.649813-2.166276h.502117c.200847 0 .573848 0 .573848-.41604s-.373001-.41604-.573848-.41604h-1.592428c-.200847 0-.573848 0-.573848 .41604s.344309 .41604 .688617 .41604l-1.075965 1.477658l-1.104657-1.477658c.329963 0 .674271 0 .674271-.41604s-.373001-.41604-.573848-.41604h-1.592428c-.200847 0-.573848 0-.573848 .41604s.373001 .41604 .573848 .41604h.502117l1.707197 2.166276l-1.793274 2.352776h-.487771c-.200847 0-.588194 0-.588194 .41604s.387347 .41604 .588194 .41604h1.578082c.200847 0 .573848 0 .573848-.41604s-.329963-.41604-.71731-.41604l1.233773-1.807621l1.291158 1.807621c-.358655 0-.702964 0-.702964 .41604s.373001 .41604 .573848 .41604h1.592428c.200847 0 .573848 0 .573848-.41604s-.373001-.41604-.573848-.41604h-.502117l-1.850659-2.352776z"/>
&lt;path id="g1-50" d="m6.312326-2.410161h-.315616c-.043039 .243885-.157808 1.032926-.30127 1.262465c-.100423 .129116-.918157 .129116-1.348542 .129116h-2.654046c.387347-.329963 1.262465-1.248119 1.635466-1.592428c2.180622-2.008467 2.984009-2.75447 2.984009-4.174743c0-1.649813-1.305504-2.75447-2.969663-2.75447s-2.6397 1.420273-2.6397 2.654046c0 .731656 .631233 .731656 .674271 .731656c.30127 0 .674271-.215193 .674271-.674271c0-.401693-.272578-.674271-.674271-.674271c-.129116 0-.157808 0-.200847 .014346c.272578-.975541 1.047272-1.635466 1.979775-1.635466c1.219427 0 1.965429 1.01858 1.965429 2.33843c0 1.219427-.702964 2.281045-1.520697 3.199202l-2.897932 3.24224v.344309h5.236361l.373001-2.410161z"/>
&lt;path id="g1-51" d="m2.6397-5.150284c-.243885 .014346-.30127 .028692-.30127 .157808c0 .143462 .071731 .143462 .329963 .143462h.659925c1.219427 0 1.764582 1.004234 1.764582 2.381468c0 1.879352-.975541 2.381468-1.678505 2.381468c-.688617 0-1.865005-.329963-2.281045-1.276811c.459078 .071731 .875118-.186501 .875118-.702964c0-.41604-.30127-.702964-.702964-.702964c-.344309 0-.71731 .200847-.71731 .746002c0 1.276811 1.276811 2.324084 2.869239 2.324084c1.707197 0 2.969663-1.305504 2.969663-2.75447c0-1.31985-1.061618-2.352776-2.438853-2.596661c1.248119-.358655 2.051506-1.405927 2.051506-2.52493c0-1.133349-1.176388-1.965429-2.567969-1.965429c-1.43462 0-2.496238 .875118-2.496238 1.92239c0 .573848 .444732 .688617 .659925 .688617c.30127 0 .645579-.215193 .645579-.645579c0-.459078-.344309-.659925-.659925-.659925c-.086077 0-.11477 0-.157808 .014346c.545155-.975541 1.893698-.975541 1.965429-.975541c.473424 0 1.405927 .215193 1.405927 1.62112c0 .272578-.043039 1.075965-.459078 1.692851c-.430386 .631233-.918157 .674271-1.305504 .688617l-.430386 .043039z"/>
&lt;path id="g1-66" d="m.616886-9.798452v.41604h.286924c1.032926 0 1.075965 .143462 1.075965 .674271v7.61783c0 .530809-.043039 .674271-1.075965 .674271h-.286924v.41604h5.39417c1.850659 0 3.141817-1.248119 3.141817-2.625354c0-1.162042-1.047272-2.309738-2.75447-2.496238c1.362889-.258232 2.352776-1.176388 2.352776-2.252353c0-1.233773-1.248119-2.424507-3.127471-2.424507h-5.006822zm2.453199 4.56209v-3.572203c0-.473424 .028692-.573848 .659925-.573848h1.807621c1.43462 0 1.951083 1.233773 1.951083 2.008467c0 .946849-.746002 2.137583-2.33843 2.137583h-2.080198zm.659925 4.820322c-.631233 0-.659925-.100423-.659925-.573848v-3.95955h2.682739c1.377235 0 2.094545 1.20508 2.094545 2.309738c0 1.162042-.875118 2.22366-2.281045 2.22366h-1.836313z"/>
&lt;path id="g1-75" d="m5.609363-6.011056c.215193-.229539 .774695-.760348 1.004234-.975541c1.979775-1.965429 2.381468-2.367122 3.514818-2.395815v-.41604c-.41604 .028692-.588194 .028692-1.233773 .028692c-.373001 0-1.219427 0-1.549389-.028692v.41604c.30127 .014346 .559502 .143462 .559502 .459078c0 .215193-.100423 .344309-.41604 .645579l-4.37559 4.232128v-4.633821c0-.702964 .157808-.702964 1.362889-.702964v-.41604c-.344309 .028692-1.520697 .028692-1.936736 .028692c-.430386 0-1.606774 0-1.951083-.028692v.41604c1.20508 0 1.362889 0 1.362889 .702964v7.560445c0 .702964-.157808 .702964-1.362889 .702964v.41604c.344309-.028692 1.520697-.028692 1.936736-.028692c.430386 0 1.606774 0 1.951083 .028692v-.41604c-1.20508 0-1.362889 0-1.362889-.702964v-2.496238l1.707197-1.649813l2.654046 3.973896c.057385 .086077 .11477 .186501 .143462 .258232c.028692 .057385 .043039 .129116 .043039 .215193c0 .401693-.516463 .401693-.746002 .401693v.41604c.344309-.028692 1.391581-.028692 1.807621-.028692c.373001 0 1.090311 0 1.592428 .028692v-.41604c-.774695 0-1.01858-.071731-1.477658-.760348l-3.227894-4.834668z"/>
&lt;path id="g1-97" d="m5.537632-3.830434c0-.774695 0-1.348542-.631233-1.908044c-.502117-.459078-1.147696-.659925-1.778928-.659925c-1.176388 0-2.080198 .774695-2.080198 1.707197c0 .41604 .272578 .616886 .60254 .616886c.344309 0 .588194-.243885 .588194-.588194c0-.588194-.516463-.588194-.731656-.588194c.329963-.60254 1.01858-.860772 1.592428-.860772c.659925 0 1.506351 .545155 1.506351 1.836313v.573848c-2.883585 .043039-3.973896 1.248119-3.973896 2.352776c0 1.133349 1.31985 1.492004 2.194968 1.492004c.946849 0 1.592428-.573848 1.865005-1.262465c.057385 .674271 .502117 1.190734 1.119003 1.190734c.30127 0 1.133349-.200847 1.133349-1.348542v-.803387h-.315616v.803387c0 .817733-.344309 .932503-.545155 .932503c-.545155 0-.545155-.760348-.545155-.975541v-2.510584zm-.932503 1.807621c0 1.405927-1.047272 1.879352-1.664159 1.879352c-.702964 0-1.291158-.516463-1.291158-1.20508c0-1.893698 2.438853-2.065852 2.955316-2.094545v1.420273z"/>
&lt;path id="g1-98" d="m2.395815-9.95626l-1.994121 .157808v.41604c.975541 0 1.090311 .100423 1.090311 .803387v8.579025h.315616c.057385-.11477 .459078-.832079 .516463-.932503c.329963 .530809 .946849 1.075965 1.865005 1.075965c1.649813 0 3.098778-1.391581 3.098778-3.24224c0-1.821967-1.348542-3.227894-2.94097-3.227894c-.789041 0-1.463312 .358655-1.951083 .961195v-4.590783zm.028692 5.365477c0-.258232 0-.286924 .157808-.516463c.344309-.516463 .975541-.932503 1.678505-.932503c.430386 0 1.936736 .172154 1.936736 2.926624c0 .961195-.143462 1.563735-.487771 2.080198c-.286924 .444732-.860772 .889464-1.578082 .889464c-.774695 0-1.276811-.502117-1.520697-.889464c-.186501-.30127-.186501-.358655-.186501-.60254v-2.955316z"/>
&lt;path id="g1-99" d="m5.193323-5.308092c-.172154 0-.702964 0-.702964 .588194c0 .344309 .243885 .588194 .588194 .588194c.329963 0 .60254-.200847 .60254-.616886c0-.961195-1.004234-1.649813-2.166276-1.649813c-1.678505 0-3.012701 1.492004-3.012701 3.299625c0 1.836313 1.377235 3.24224 2.998355 3.24224c1.893698 0 2.324084-1.721543 2.324084-1.850659s-.100423-.129116-.143462-.129116c-.129116 0-.143462 .043039-.186501 .215193c-.315616 1.01858-1.090311 1.448966-1.865005 1.448966c-.875118 0-2.03716-.760348-2.03716-2.94097c0-2.381468 1.219427-2.969663 1.936736-2.969663c.545155 0 1.334196 .215193 1.664159 .774695z"/>
&lt;path id="g1-100" d="m4.303859-9.798452v.41604c.975541 0 1.090311 .100423 1.090311 .803387v3.170509c-.30127-.41604-.918157-.918157-1.793274-.918157c-1.664159 0-3.098778 1.405927-3.098778 3.24224c0 1.821967 1.362889 3.227894 2.94097 3.227894c1.090311 0 1.721543-.71731 1.92239-.989888v.989888l2.022814-.143462v-.41604c-.975541 0-1.090311-.100423-1.090311-.803387v-8.736833l-1.994121 .157808zm1.061618 8.119947c0 .258232 0 .30127-.200847 .616886c-.344309 .502117-.932503 .918157-1.649813 .918157c-.373001 0-1.92239-.143462-1.92239-2.926624c0-1.032926 .172154-1.606774 .487771-2.080198c.286924-.444732 .860772-.889464 1.578082-.889464c.889464 0 1.391581 .645579 1.535043 .875118c.172154 .243885 .172154 .272578 .172154 .530809v2.955316z"/>
&lt;path id="g1-101" d="m5.494593-3.328317c.315616 0 .344309 0 .344309-.272578c0-1.448966-.774695-2.797508-2.510584-2.797508c-1.635466 0-2.897932 1.477658-2.897932 3.256586c0 1.893698 1.463312 3.285279 3.05574 3.285279c1.707197 0 2.352776-1.549389 2.352776-1.850659c0-.086077-.071731-.143462-.157808-.143462c-.11477 0-.143462 .071731-.172154 .143462c-.373001 1.20508-1.334196 1.535043-1.936736 1.535043s-2.051506-.401693-2.051506-2.883585v-.272578h3.973896zm-3.95955-.272578c.11477-2.252353 1.377235-2.510584 1.778928-2.510584c1.535043 0 1.62112 2.022814 1.635466 2.510584h-3.414395z"/>
&lt;path id="g1-104" d="m6.384057-3.486126c0-1.334196 0-1.73589-.329963-2.194968c-.41604-.559502-1.090311-.645579-1.578082-.645579c-1.233773 0-1.807621 .932503-2.008467 1.377235h-.014346v-5.006822l-1.994121 .157808v.41604c.975541 0 1.090311 .100423 1.090311 .803387v7.517407c0 .645579-.157808 .645579-1.090311 .645579v.41604c.373001-.028692 1.147696-.028692 1.549389-.028692c.41604 0 1.190734 0 1.563735 .028692v-.41604c-.918157 0-1.090311 0-1.090311-.645579v-2.668392c0-1.506351 .989888-2.309738 1.879352-2.309738s1.090311 .731656 1.090311 1.606774v3.371356c0 .645579-.157808 .645579-1.090311 .645579v.41604c.373001-.028692 1.147696-.028692 1.549389-.028692c.41604 0 1.190734 0 1.563735 .028692v-.41604c-.71731 0-1.075965 0-1.090311-.430386v-2.6397z"/>
&lt;path id="g1-105" d="m2.496238-8.837257c0-.373001-.30127-.702964-.702964-.702964c-.373001 0-.688617 .30127-.688617 .688617c0 .430386 .344309 .702964 .688617 .702964c.444732 0 .702964-.373001 .702964-.688617zm-1.979775 2.668392v.41604c.918157 0 1.047272 .086077 1.047272 .789041v3.902165c0 .645579-.157808 .645579-1.090311 .645579v.41604c.401693-.028692 1.090311-.028692 1.506351-.028692c.157808 0 .989888 0 1.477658 .028692v-.41604c-.932503 0-.989888-.071731-.989888-.631233v-5.2794l-1.951083 .157808z"/>
&lt;path id="g1-107" d="m4.016935-3.801742c0-.014346-.100423-.129116-.100423-.143462c0-.043039 .90381-.817733 1.01858-.932503c.989888-.860772 1.62112-.875118 1.92239-.889464v-.41604c-.286924 .028692-.659925 .028692-1.090311 .028692c-.373001 0-1.104657 0-1.43462-.028692v.41604c.243885 .014346 .41604 .143462 .41604 .373001c0 .286924-.286924 .545155-.30127 .545155l-2.051506 1.807621v-6.914866l-1.994121 .157808v.41604c.975541 0 1.090311 .100423 1.090311 .803387v7.517407c0 .645579-.157808 .645579-1.090311 .645579v.41604c.401693-.028692 1.090311-.028692 1.520697-.028692s1.119003 0 1.520697 .028692v-.41604c-.918157 0-1.090311 0-1.090311-.645579v-1.520697l.918157-.803387l1.377235 1.979775c.215193 .30127 .315616 .459078 .315616 .659925c0 .258232-.200847 .329963-.502117 .329963v.41604c.358655-.028692 1.061618-.028692 1.448966-.028692c.616886 0 .645579 0 1.262465 .028692v-.41604c-.387347 0-.832079 0-1.233773-.588194l-1.92239-2.797508z"/>
&lt;path id="g1-111" d="m6.584904-3.070086c0-1.850659-1.405927-3.328317-3.070086-3.328317c-1.721543 0-3.084432 1.520697-3.084432 3.328317c0 1.836313 1.43462 3.213548 3.070086 3.213548c1.692851 0 3.084432-1.405927 3.084432-3.213548zm-3.070086 2.897932c-.530809 0-1.176388-.229539-1.592428-.932503c-.387347-.645579-.401693-1.492004-.401693-2.094545c0-.545155 0-1.420273 .444732-2.065852c.401693-.616886 1.032926-.846426 1.535043-.846426c.559502 0 1.162042 .258232 1.549389 .817733c.444732 .659925 .444732 1.563735 .444732 2.094545c0 .502117 0 1.391581-.373001 2.065852c-.401693 .688617-1.061618 .961195-1.606774 .961195z"/>
&lt;path id="g1-112" d="m3.514818 2.367122c-.918157 0-1.090311 0-1.090311-.645579v-2.496238c.258232 .358655 .846426 .918157 1.764582 .918157c1.649813 0 3.098778-1.391581 3.098778-3.24224c0-1.821967-1.348542-3.227894-2.912278-3.227894c-1.262465 0-1.936736 .90381-1.979775 .961195v-.961195l-1.994121 .157808v.41604c1.004234 0 1.090311 .100423 1.090311 .731656v6.742712c0 .645579-.157808 .645579-1.090311 .645579v.41604c.373001-.028692 1.147696-.028692 1.549389-.028692c.41604 0 1.190734 0 1.563735 .028692v-.41604zm-1.090311-6.943559c0-.272578 0-.286924 .157808-.516463c.430386-.645579 1.133349-.918157 1.678505-.918157c1.075965 0 1.936736 1.305504 1.936736 2.912278c0 1.707197-.975541 2.955316-2.080198 2.955316c-.444732 0-.860772-.186501-1.147696-.459078c-.329963-.329963-.545155-.616886-.545155-1.01858v-2.955316z"/>
&lt;path id="g1-115" d="m4.705552-6.068441c0-.258232 0-.329963-.143462-.329963c-.11477 0-.387347 .315616-.487771 .444732c-.444732-.358655-.889464-.444732-1.348542-.444732c-1.73589 0-2.252353 .946849-2.252353 1.73589c0 .157808 0 .659925 .545155 1.162042c.459078 .401693 .946849 .502117 1.606774 .631233c.789041 .157808 .975541 .200847 1.334196 .487771c.258232 .215193 .444732 .530809 .444732 .932503c0 .616886-.358655 1.305504-1.62112 1.305504c-.946849 0-1.635466-.545155-1.951083-1.979775c-.057385-.258232-.057385-.272578-.071731-.286924c-.028692-.057385-.086077-.057385-.129116-.057385c-.157808 0-.157808 .071731-.157808 .329963v1.951083c0 .258232 0 .329963 .143462 .329963c.071731 0 .086077-.014346 .329963-.315616c.071731-.100423 .071731-.129116 .286924-.358655c.545155 .674271 1.31985 .674271 1.563735 .674271c1.506351 0 2.252353-.832079 2.252353-1.965429c0-.774695-.473424-1.233773-.60254-1.362889c-.516463-.444732-.90381-.530809-1.850659-.702964c-.430386-.086077-1.477658-.286924-1.477658-1.147696c0-.444732 .30127-1.104657 1.592428-1.104657c1.563735 0 1.649813 1.334196 1.678505 1.778928c.014346 .11477 .11477 .11477 .157808 .11477c.157808 0 .157808-.071731 .157808-.329963v-1.492004z"/>
&lt;path id="g1-116" d="m2.410161-5.767171h2.022814v-.41604h-2.022814v-2.6397h-.315616c-.014346 1.348542-.530809 2.725777-1.836313 2.768816v.286924h1.219427v3.988242c0 1.592428 1.061618 1.92239 1.821967 1.92239c.90381 0 1.377235-.889464 1.377235-1.92239v-.817733h-.315616v.789041c0 1.032926-.41604 1.635466-.975541 1.635466c-.975541 0-.975541-1.334196-.975541-1.578082v-4.016935z"/>
&lt;/defs>
&lt;g id="page1">
&lt;path d="m-65.1875 58.75784h56.6914v-56.691434h-56.6914z" fill="none" stroke-width=".56693" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(-189.5758 4.9814)" style="fill: var(--color-fg);">
&lt;use x="137.086512" y="30.411546" xlink:href="#g1-115"/>
&lt;use x="142.62734" y="30.411546" xlink:href="#g1-116"/>
&lt;use x="148.090129" y="30.411546" xlink:href="#g1-97"/>
&lt;use x="155.113714" y="30.411546" xlink:href="#g1-99"/>
&lt;use x="160.966701" y="30.411546" xlink:href="#g1-107"/>
&lt;/g>
&lt;path d="m-7.9301 58.7578h85.043v-56.691434h-85.043z" fill="none" stroke-width=".56693" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(-187.7808 4.9814)" style="fill: var(--color-fg);">
&lt;use x="208.519535" y="30.411546" xlink:href="#g1-99"/>
&lt;use x="214.762722" y="30.411546" xlink:href="#g1-111"/>
&lt;use x="222.176491" y="30.411546" xlink:href="#g1-100"/>
&lt;use x="229.980475" y="30.411546" xlink:href="#g1-101"/>
&lt;/g>
&lt;path d="m77.67543 2.066366v56.691434h16.60547v-56.691434z" fill="none" stroke-width=".56693" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="matrix(0 -1 1 0 60.5492 303.9766)" style="fill: var(--color-fg);">
&lt;use x="259.907944" y="30.411546" xlink:href="#g1-100"/>
&lt;use x="267.711928" y="30.411546" xlink:href="#g1-97"/>
&lt;use x="274.735513" y="30.411546" xlink:href="#g1-116"/>
&lt;use x="280.198302" y="30.411546" xlink:href="#g1-97"/>
&lt;/g>
&lt;path d="m94.84728 2.066366v56.691434h16.60547v-56.691434z" fill="none" stroke-width=".56693" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="matrix(0 -1 1 0 77.7205 316.9334)" style="fill: var(--color-fg);">
&lt;use x="277.078509" y="30.411546" xlink:href="#g1-98"/>
&lt;use x="284.882493" y="30.411546" xlink:href="#g1-115"/>
&lt;use x="290.423321" y="30.411546" xlink:href="#g1-115"/>
&lt;/g>
&lt;path d="m112.0192 58.7578h170.0781v-56.691434h-170.0781z" fill="none" stroke-width=".56693" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g style="fill: var(--color-fg);">
&lt;g transform="translate(-188.366 3.5866)">
&lt;use x="370.986608" y="30.411546" xlink:href="#g1-104"/>
&lt;use x="378.790592" y="30.411546" xlink:href="#g1-101"/>
&lt;use x="385.033778" y="30.411546" xlink:href="#g1-97"/>
&lt;use x="392.057364" y="30.411546" xlink:href="#g1-112"/>
&lt;/g>
&lt;g transform="matrix(.5 -.86603 .86603 .5 -140.439071 79.573137)">
&lt;use x="108.456615" y="30.411546" xlink:href="#g0-48"/>
&lt;use x="115.838932" y="30.411546" xlink:href="#g0-120"/>
&lt;use x="123.221248" y="30.411546" xlink:href="#g0-51"/>
&lt;use x="130.603565" y="30.411546" xlink:href="#g0-102"/>
&lt;use x="137.985882" y="30.411546" xlink:href="#g0-99"/>
&lt;use x="145.368199" y="30.411546" xlink:href="#g0-56"/>
&lt;use x="152.750516" y="30.411546" xlink:href="#g0-48"/>
&lt;use x="160.132833" y="30.411546" xlink:href="#g0-48"/>
&lt;use x="167.515149" y="30.411546" xlink:href="#g0-48"/>
&lt;use x="174.897466" y="30.411546" xlink:href="#g0-48"/>
&lt;/g>
&lt;g transform="matrix(.5 -.86603 .86603 .5 207.418229 79.573137)">
&lt;use x="108.456615" y="30.411546" xlink:href="#g0-48"/>
&lt;use x="115.838932" y="30.411546" xlink:href="#g0-120"/>
&lt;use x="123.221248" y="30.411546" xlink:href="#g0-51"/>
&lt;use x="130.603565" y="30.411546" xlink:href="#g0-102"/>
&lt;use x="137.985882" y="30.411546" xlink:href="#g0-99"/>
&lt;use x="145.368199" y="30.411546" xlink:href="#g0-100"/>
&lt;use x="152.750516" y="30.411546" xlink:href="#g0-102"/>
&lt;use x="160.132833" y="30.411546" xlink:href="#g0-102"/>
&lt;use x="167.515149" y="30.411546" xlink:href="#g0-102"/>
&lt;use x="174.897466" y="30.411546" xlink:href="#g0-102"/>
&lt;/g>
&lt;/g>
&lt;path d="m-65.473 61.875c.852 1.7031 2.836 2.8359 5.672 2.8359h17.289c2.836 0 4.821 1.1329 5.672 2.836c.848-1.7031 2.832-2.836 5.668-2.836h17.293c2.832 0 4.816-1.1328 5.668-2.8359" fill="none" stroke-width=".56693" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(-167.0485 49.1243)" style="fill: var(--color-fg);">
&lt;use x="108.456615" y="30.411546" xlink:href="#g1-51"/>
&lt;use x="115.4802" y="30.411546" xlink:href="#g1-50"/>
&lt;use x="127.186162" y="30.411546" xlink:href="#g1-75"/>
&lt;use x="138.106773" y="30.411546" xlink:href="#g1-105"/>
&lt;use x="142.008765" y="30.411546" xlink:href="#g1-66"/>
&lt;/g>
&lt;/g>
&lt;/svg>
&lt;p>I decided to place the stack at the start so that a stack overflow can&amp;rsquo;t corrupt anything else (the stack grows downwards). I am not sure why placing it at the end of the RAM is the common practice, since that way it could silently corrupt the heap.&lt;/p>
&lt;p>The code section (usually called &lt;code>.text&lt;/code> by the compiler) is pretty self explanatory, the example application I will be showing later weighs in at around 64 KiB. One notable thing about the code section is that it needs to be accessed through a different address space, in somewhat of a Harvard architecture style. On the ESP32-C3 the range &lt;code>0x40380000&lt;/code>-&lt;code>0x403dffff&lt;/code> is used to access the RAM for code execution, while &lt;code>0x3fc80000&lt;/code>-&lt;code>0x3fcdffff&lt;/code> is used for regular data access. (So the above code section starts at &lt;code>0x40388000&lt;/code> in this mapping.) Some linker script trickery is needed to make sure that all the addresses in the linked code are correct.&lt;/p>
&lt;p>The data section contains read only constants (such as strings) and global variables with a defined value.&lt;/p>
&lt;p>The bss section contains zero initialized global variables. (Don&amp;rsquo;t know what the name &amp;ldquo;bss&amp;rdquo; stands for though.) Forgetting to zero this actually caused me to spend a day debugging seemingly unrelated malloc issues, which only manifested on real hardware and not in QEMU. It turns out that malloc &lt;a href="https://github.com/picolibc/picolibc/blob/1.8.6/newlib/libc/stdlib/nano-mallocr.c#L220">stores the head of the free list in a global variable&lt;/a> which it expects to be &lt;code>NULL&lt;/code> by default. In QEMU all RAM is zeroed by default, but on real hardware it could be full of random junk values. Adding &lt;code>memset(&amp;amp;_bss_start, 0, (&amp;amp;_bss_end - &amp;amp;_bss_start));&lt;/code> to zero the bss section fixed the issue. Oops.&lt;/p>
&lt;p>Finally, the remaining space is designated as the heap. All we have to do in the linker script is to specify the &lt;code>__heap_start&lt;/code> and &lt;code>__heap_end&lt;/code> symbols, and from there &lt;a href="https://github.com/picolibc/picolibc/blob/1.8.6/newlib/libc/stdlib/nano-mallocr.c">picolibc&amp;rsquo;s malloc implementation&lt;/a> knows that it can allocate memory in this range. In my example application around 284 KiB is left for the heap, which is plenty.&lt;/p>
&lt;p>To run our program, the code and data sections need to be copied to their specific addresses, and then execution needs to begin from a specific entry address. This can be achieved by packaging our application in the &lt;a href="https://docs.espressif.com/projects/esptool/en/latest/esp32c3/advanced-topics/firmware-image-format.html">firmware image format&lt;/a> expected by the ROM boot loader.&lt;/p>
&lt;h2 id="booting">Booting&lt;/h2>
&lt;p>Booting on the ESP32-C3 happens through the following steps:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>On CPU Reset, the program counter is set to &lt;code>0x40000000&lt;/code>, and the CPU starts executing.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>At &lt;code>0x40000000&lt;/code> the chip&amp;rsquo;s internal ROM is located. The values on various GPIO pins can affect what happens, but by default, the ROM code loads the application code from the external SPI flash memory to RAM. The application in the specific &lt;a href="https://docs.espressif.com/projects/esptool/en/latest/esp32c3/advanced-topics/firmware-image-format.html">firmware image format&lt;/a> is expected to be located at the beginning of the flash.&lt;/p>
&lt;p>The firmware image contains a number of segments to be loaded to specific addresses in RAM. The ROM code goes through them, and copies each segment to RAM.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Finally, the firmware image also contains an entry point address. The ROM code jumps to it, and from here we have full responsibility over execution.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>Note that unfortunately the ROM code is not open source, but parts of it have been reverse engineered, for example for &lt;a href="https://courk.cc/esp32-c3-c6-fault-injection">security analysis&lt;/a>. The ROM and the Wi-Fi MAC are the only non-open source software parts in the ESP32 ecosystem that I am aware of.&lt;/p>
&lt;p>The entry point of my application is named &lt;code>call_start_cpu0&lt;/code> (this could be any name, it&amp;rsquo;s specified in the linker script). Here is the entry point function (we could also be using picolibc&amp;rsquo;s crt0 instead, but I was too lazy to set it up):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="kt">void&lt;/span> &lt;span class="nf">__attribute__&lt;/span>&lt;span class="p">((&lt;/span>&lt;span class="n">noreturn&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="nf">call_start_cpu0&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">__asm__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;la sp, _stack_end;&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">memset&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">_bss_start&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">_bss_end&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">_bss_start&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">disable_wdt&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">main&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">true&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The very first thing we do is load the stack pointer to the &lt;code>sp&lt;/code> register so that we can call functions and have local variables, pretty important things for most programs. Next, we zero the bss section, which as I already mentioned, is pretty important. We also disable the default watchdog timers. Next, we call the &lt;code>main&lt;/code> function, which is the entry point generated by the Lean compiler. In case &lt;code>main&lt;/code> were to return, we enter a busy loop. (Trying to return here would probably lead to a &lt;em>stack underflow&lt;/em>, followed by the CPU going off trying to execute some random code.)&lt;/p>
&lt;h2 id="lean-startup">Lean startup&lt;/h2>
&lt;p>The &lt;code>main&lt;/code> function emitted by the Lean compiler looks something like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">argc&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">char&lt;/span> &lt;span class="o">**&lt;/span>&lt;span class="n">argv&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">lean_object&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">in&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">lean_object&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">res&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">lean_initialize_runtime_module&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">lean_set_panic_messages&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">false&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">res&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nf">initialize_Main&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span> &lt;span class="cm">/* builtin */&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nf">lean_io_mk_world&lt;/span>&lt;span class="p">());&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">lean_set_panic_messages&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">true&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">lean_io_mark_end_initialization&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">lean_io_result_is_ok&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">res&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">lean_dec_ref&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">res&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">lean_init_task_manager&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">res&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nf">_lean_main&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">lean_io_mk_world&lt;/span>&lt;span class="p">());&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">lean_finalize_task_manager&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">lean_io_result_is_ok&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">res&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int&lt;/span> &lt;span class="n">ret&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">lean_dec_ref&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">res&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">ret&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">lean_io_result_show_error&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">res&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">lean_dec_ref&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">res&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Notable parts are:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>The call to &lt;code>lean_initialize_runtime_module&lt;/code> to do any initialization needed by the runtime. As I mentioned already I slimmed down the runtime a lot, so this doesn&amp;rsquo;t do too much.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>initialize_Main&lt;/code> initializes some global constants of the &lt;code>Main&lt;/code> module. It also calls &lt;code>initialize_Init&lt;/code> to initialize the standard library. The standard library initialization turned out to be an issue, since apparently Lean does not remove the initialization code for unused constants. The standard library is fairly big, and leaving its initialization as-is makes the code size of the application larger than the 384 KiB size of our whole RAM, so we clearly need to do something about this. My trick is override the &lt;code>initialize_Init&lt;/code> function with a stub implementation that does nothing:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="n">lean_object&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="nf">initialize_Init&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">uint8_t&lt;/span> &lt;span class="n">builtin&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">lean_object&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">w&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nf">lean_io_result_mk_ok&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">lean_box&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>As long as we carefully avoid using any constants from the standard library that would have needed initialization, this seems to just work. (Though it&amp;rsquo;s definitely not a safe solution.)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Finally, the call to &lt;code>_lean_main&lt;/code> executes the &lt;code>main&lt;/code> IO monad of our Lean program. This is what a hello world program in Lean would look like:&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code>&lt;span class="hljs-theorem">&lt;span class="hljs-keyword">def&lt;/span> &lt;span class="hljs-title">main&lt;/span> &lt;span class="hljs-symbol">:&lt;/span>&lt;/span> IO Unit &lt;span class="hljs-symbol">:=&lt;/span> &lt;span class="hljs-keyword">do&lt;/span>
IO.println &lt;span class="hljs-string">&amp;quot;hello world&amp;quot;&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>
&lt;/li>
&lt;/ul>
&lt;h1 id="example-application-rgb-led-controller">Example application: RGB LED controller&lt;/h1>
&lt;p>The development board I have has a WS2812B RGB LED, so making it light up in various patterns was a pretty obvious choice for an example application.&lt;/p>
&lt;p>First, I define an interface for arbitrary lighting patterns:&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code>&lt;span class="hljs-theorem">&lt;span class="hljs-keyword">structure&lt;/span> &lt;span class="hljs-title">LightPattern&lt;/span> &lt;span class="hljs-title">where&lt;/span>
&lt;span class="hljs-title">State&lt;/span> &lt;span class="hljs-symbol">:&lt;/span>&lt;/span> &lt;span class="hljs-built_in">Type&lt;/span>
init : State
step : State → State
color : State → Color
&lt;/code>&lt;/pre>&lt;/div>
&lt;ul>
&lt;li>&lt;code>State&lt;/code> is the type of the internal state of the pattern. For example, for a simple blinking pattern it could be a &lt;code>Bool&lt;/code>.&lt;/li>
&lt;li>&lt;code>init&lt;/code> is the initial state.&lt;/li>
&lt;li>&lt;code>step&lt;/code> is a function to compute the next state from the current one.&lt;/li>
&lt;li>&lt;code>color&lt;/code> is the function to get the current output color of the LED based on the state.&lt;/li>
&lt;/ul>
&lt;p>And yes, all the fields after &lt;code>State&lt;/code> can refer to its value (a type) to define their own types, this is what dependent typing is all about.&lt;/p>
&lt;p>To make this a little less abstract, let&amp;rsquo;s define a simple blinking pattern with an arbitrary color:&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code>&lt;span class="hljs-theorem">&lt;span class="hljs-keyword">def&lt;/span> &lt;span class="hljs-title">LightPattern&lt;/span>.&lt;span class="hljs-title">blink&lt;/span> &lt;span class="hljs-params">(c : Color)&lt;/span> &lt;span class="hljs-symbol">:&lt;/span>&lt;/span> LightPattern &lt;span class="hljs-symbol">:=&lt;/span> {
State &lt;span class="hljs-symbol">:=&lt;/span> Bool
init &lt;span class="hljs-symbol">:=&lt;/span> true
step &lt;span class="hljs-symbol">:=&lt;/span> Bool.not
color &lt;span class="hljs-symbol">:=&lt;/span> (if · then c else default)
}
&lt;/code>&lt;/pre>&lt;/div>
&lt;p>&lt;code>State&lt;/code> is a &lt;code>Bool&lt;/code>, as I already mentioned previously. &lt;code>step&lt;/code> is simply the boolean negation. &lt;code>color&lt;/code> will be &lt;code>c&lt;/code> when the state is &lt;code>true&lt;/code>, and off otherwise. (&lt;code>default&lt;/code> is defined as &lt;code>{ red := 0, green := 0, blue := 0 }&lt;/code>.) The syntax for defining &lt;code>color&lt;/code> might be a little confusing, the &lt;code>·&lt;/code> shorthand is used to define the function, which is equivalent to &lt;code>fun s =&amp;gt; if s then c else default&lt;/code>.&lt;/p>
&lt;p>Let&amp;rsquo;s define a more advanced pattern, which cycles through the three color channels:&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code>&lt;span class="hljs-keyword">inductive&lt;/span> ColorChannel &lt;span class="hljs-symbol">:=&lt;/span> | Red | Green | Blue
&lt;span class="hljs-theorem">&lt;span class="hljs-keyword">def&lt;/span> &lt;span class="hljs-title">ColorChannel&lt;/span>.&lt;span class="hljs-title">toColor&lt;/span> &lt;span class="hljs-symbol">:&lt;/span>&lt;/span> ColorChannel → Color
| Red =&amp;gt; { red &lt;span class="hljs-symbol">:=&lt;/span> &lt;span class="hljs-number">0&lt;/span>xFF, green &lt;span class="hljs-symbol">:=&lt;/span> &lt;span class="hljs-number">0&lt;/span>, blue &lt;span class="hljs-symbol">:=&lt;/span> &lt;span class="hljs-number">0&lt;/span> }
| Green =&amp;gt; { red &lt;span class="hljs-symbol">:=&lt;/span> &lt;span class="hljs-number">0&lt;/span>, green &lt;span class="hljs-symbol">:=&lt;/span> &lt;span class="hljs-number">0&lt;/span>xFF, blue &lt;span class="hljs-symbol">:=&lt;/span> &lt;span class="hljs-number">0&lt;/span> }
| Blue =&amp;gt; { red &lt;span class="hljs-symbol">:=&lt;/span> &lt;span class="hljs-number">0&lt;/span>, green &lt;span class="hljs-symbol">:=&lt;/span> &lt;span class="hljs-number">0&lt;/span>, blue &lt;span class="hljs-symbol">:=&lt;/span> &lt;span class="hljs-number">0&lt;/span>xFF }
&lt;span class="hljs-theorem">&lt;span class="hljs-keyword">def&lt;/span> &lt;span class="hljs-title">LightPattern&lt;/span>.&lt;span class="hljs-title">cycle&lt;/span> &lt;span class="hljs-symbol">:&lt;/span>&lt;/span> LightPattern &lt;span class="hljs-symbol">:=&lt;/span> {
State &lt;span class="hljs-symbol">:=&lt;/span> ColorChannel
init &lt;span class="hljs-symbol">:=&lt;/span> .Red
step &lt;span class="hljs-symbol">:=&lt;/span> &lt;span class="hljs-keyword">fun&lt;/span>
| .Red =&amp;gt; .Green
| .Green =&amp;gt; .Blue
| .Blue =&amp;gt; .Red
color &lt;span class="hljs-symbol">:=&lt;/span> ColorChannel.toColor
}
&lt;/code>&lt;/pre>&lt;/div>
&lt;p>Next, let&amp;rsquo;s define a &amp;ldquo;light pattern transformer&amp;rdquo;, that takes an existing pattern and modifies it. In particular I want to be able to tune the speed of these patterns. I will be running the update loop at around a 1000 Hz, which would be much too fast to see the blinking pattern for instance. The following pattern will only run the &lt;code>step&lt;/code> function of the underlying pattern &lt;code>p&lt;/code> every &lt;code>n&lt;/code> steps:&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code>&lt;span class="hljs-theorem">&lt;span class="hljs-keyword">def&lt;/span> &lt;span class="hljs-title">LightPattern&lt;/span>.&lt;span class="hljs-title">every&lt;/span> &lt;span class="hljs-params">(n : UInt16)&lt;/span> &lt;span class="hljs-params">(p : LightPattern)&lt;/span> &lt;span class="hljs-symbol">:&lt;/span>&lt;/span> LightPattern &lt;span class="hljs-symbol">:=&lt;/span> {
State &lt;span class="hljs-symbol">:=&lt;/span> UInt16 × p.State,
init &lt;span class="hljs-symbol">:=&lt;/span> (&lt;span class="hljs-number">0&lt;/span>, p.init),
step &lt;span class="hljs-symbol">:=&lt;/span> &lt;span class="hljs-keyword">fun&lt;/span> (i, s) =&amp;gt; if i == n then (&lt;span class="hljs-number">0&lt;/span>, p.step s) else (i + &lt;span class="hljs-number">1&lt;/span>, s),
color &lt;span class="hljs-symbol">:=&lt;/span> &lt;span class="hljs-keyword">fun&lt;/span> (_, s) =&amp;gt; p.color s
}
&lt;/code>&lt;/pre>&lt;/div>
&lt;p>Let&amp;rsquo;s unpack this:&lt;/p>
&lt;ul>
&lt;li>We define the state to be a 16 bit counter&lt;sup id="fnref:2">&lt;a href="#fn:2" role="doc-noteref">2&lt;/a>&lt;span class="footnote-tooltip">I use a 16 instead of a 32 bit counter since a 32 bit value would have to be allocated on the heap due to the way Lean&amp;rsquo;s object representation works, whereas a 16 bit value will be a scalar. It would be nice if Lean also had 31 bit integers like OCaml.&lt;/span>&lt;/sup>, plus whatever state &lt;code>p&lt;/code> has. &lt;code>×&lt;/code> denotes a product type, a.k.a. a pair.&lt;/li>
&lt;li>&lt;code>init&lt;/code> is zero and the initial state of &lt;code>p&lt;/code>.&lt;/li>
&lt;li>&lt;code>step&lt;/code> is the core of the logic: when the counter reaches &lt;code>n&lt;/code>, we call the &lt;code>step&lt;/code> of the underlying &lt;code>p&lt;/code>. Otherwise, we just increment the counter, and leave the state of &lt;code>p&lt;/code> as-is.&lt;/li>
&lt;li>&lt;code>color&lt;/code> just outputs the color of &lt;code>p&lt;/code>.&lt;/li>
&lt;/ul>
&lt;p>Finally, I wanted to also have a candle-like flicker effect. First, we need a (pseudo) random number generator for this (&lt;a href="https://gist.github.com/tommyettinger/46a874533244883189143505d203312c?permalink_comment_id=4365431#gistcomment-4365431">source&lt;/a>):&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code>abbrev Prng.State &lt;span class="hljs-symbol">:=&lt;/span> UInt32
&lt;span class="hljs-theorem">&lt;span class="hljs-keyword">def&lt;/span> &lt;span class="hljs-title">Prng&lt;/span>.&lt;span class="hljs-title">step&lt;/span> &lt;span class="hljs-params">(state : Prng.State)&lt;/span> &lt;span class="hljs-symbol">:&lt;/span>&lt;/span> Prng.State &lt;span class="hljs-symbol">:=&lt;/span> state + &lt;span class="hljs-number">0&lt;/span>x9E3779B9
&lt;span class="hljs-theorem">&lt;span class="hljs-keyword">def&lt;/span> &lt;span class="hljs-title">Prng&lt;/span>.&lt;span class="hljs-title">get&lt;/span> &lt;span class="hljs-params">(z : Prng.State)&lt;/span> &lt;span class="hljs-symbol">:&lt;/span>&lt;/span> UInt32 &lt;span class="hljs-symbol">:=&lt;/span>
&lt;span class="hljs-keyword">let&lt;/span> z &lt;span class="hljs-symbol">:=&lt;/span> z ^^^ (z &amp;gt;&amp;gt;&amp;gt; &lt;span class="hljs-number">16&lt;/span>)
&lt;span class="hljs-keyword">let&lt;/span> z &lt;span class="hljs-symbol">:=&lt;/span> z * &lt;span class="hljs-number">0&lt;/span>x21F0AAAD
&lt;span class="hljs-keyword">let&lt;/span> z &lt;span class="hljs-symbol">:=&lt;/span> z ^^^ (z &amp;gt;&amp;gt;&amp;gt; &lt;span class="hljs-number">15&lt;/span>)
&lt;span class="hljs-keyword">let&lt;/span> z &lt;span class="hljs-symbol">:=&lt;/span> z * &lt;span class="hljs-number">0&lt;/span>x735A2D97
z ^^^ (z &amp;gt;&amp;gt;&amp;gt; &lt;span class="hljs-number">15&lt;/span>)
&lt;/code>&lt;/pre>&lt;/div>
&lt;p>The only state of our candle will be the 32 bit PRNG state. (Unfortunately, this will be allocated on the heap since it&amp;rsquo;s a 32 bit value.) Here is the code for the candle:&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code>&lt;span class="hljs-theorem">&lt;span class="hljs-keyword">def&lt;/span> &lt;span class="hljs-title">LightPattern&lt;/span>.&lt;span class="hljs-title">flicker&lt;/span> &lt;span class="hljs-symbol">:&lt;/span>&lt;/span> LightPattern &lt;span class="hljs-symbol">:=&lt;/span> {
State &lt;span class="hljs-symbol">:=&lt;/span> Prng.State
init &lt;span class="hljs-symbol">:=&lt;/span> &lt;span class="hljs-number">0&lt;/span>
step &lt;span class="hljs-symbol">:=&lt;/span> Prng.step
color &lt;span class="hljs-symbol">:=&lt;/span> &lt;span class="hljs-keyword">fun&lt;/span> state =&amp;gt;
&lt;span class="hljs-keyword">let&lt;/span> random &lt;span class="hljs-symbol">:=&lt;/span> Prng.get state
&lt;span class="hljs-keyword">let&lt;/span> brighness &lt;span class="hljs-symbol">:=&lt;/span> &lt;span class="hljs-number">0&lt;/span>x80 + random &amp;amp;&amp;amp;&amp;amp; &lt;span class="hljs-number">0&lt;/span>x7F
{
red &lt;span class="hljs-symbol">:=&lt;/span> brighness.toUInt8,
green &lt;span class="hljs-symbol">:=&lt;/span> &lt;span class="hljs-number">150&lt;/span> * brighness / &lt;span class="hljs-number">255&lt;/span> |&amp;gt;.toUInt8,
blue &lt;span class="hljs-symbol">:=&lt;/span> &lt;span class="hljs-number">50&lt;/span> * brighness / &lt;span class="hljs-number">255&lt;/span> |&amp;gt;.toUInt8,
}
}
&lt;/code>&lt;/pre>&lt;/div>
&lt;p>All the candle-specific logic happens in the &lt;code>color&lt;/code> function. We get the current value of the PRNG, calculate a brightness between 128 and 255 with it, and then mix up a warm white looking color while being very careful to avoid floating point maths. (Floating point has some issue I haven&amp;rsquo;t looked into yet and calculates bad values.)&lt;/p>
&lt;p>Next, let&amp;rsquo;s define our application. We want to dynamically switch between patterns from a predefined array, which we parameterize our app over:&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code>&lt;span class="hljs-theorem">&lt;span class="hljs-keyword">structure&lt;/span> &lt;span class="hljs-title">AppState&lt;/span> &lt;span class="hljs-params">(patterns : Array LightPattern)&lt;/span> &lt;span class="hljs-title">where&lt;/span>
&lt;span class="hljs-title">patternIndex&lt;/span> &lt;span class="hljs-symbol">:&lt;/span>&lt;/span> Fin patterns.size
state : (patterns.get patternIndex).State
&lt;/code>&lt;/pre>&lt;/div>
&lt;p>&lt;code>patternIndex&lt;/code> is the index of the currently playing light pattern, while &lt;code>state&lt;/code> is the current state of the current light pattern, and its type depends on the current &lt;code>patternIndex&lt;/code>.&lt;/p>
&lt;p>Here is the rest of the app implementation, understanding it is an exercise left to the reader:&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code>&lt;span class="hljs-keyword">variable&lt;/span> (patterns : Array LightPattern)
&lt;span class="hljs-doctag">/-- Switch to the next pattern. -/&lt;/span>
&lt;span class="hljs-theorem">&lt;span class="hljs-keyword">def&lt;/span> &lt;span class="hljs-title">AppState&lt;/span>.&lt;span class="hljs-title">nextPattern&lt;/span> &lt;span class="hljs-params">(s : AppState patterns)&lt;/span> &lt;span class="hljs-symbol">:&lt;/span>&lt;/span> AppState patterns &lt;span class="hljs-symbol">:=&lt;/span>
&lt;span class="hljs-keyword">let&lt;/span> patternIndex &lt;span class="hljs-symbol">:=&lt;/span> s.patternIndex + Fin.ofNat&amp;#x27; &lt;span class="hljs-number">1&lt;/span> (
&lt;span class="hljs-keyword">match&lt;/span> e : patterns.size &lt;span class="hljs-built_in">with&lt;/span>
| &lt;span class="hljs-number">0&lt;/span> =&amp;gt; Fin.elim0 (e ▸ s.patternIndex)
| _ + &lt;span class="hljs-number">1&lt;/span> =&amp;gt; (&lt;span class="hljs-keyword">by&lt;/span> omega))
{
patternIndex,
state &lt;span class="hljs-symbol">:=&lt;/span> (patterns.get patternIndex).init,
}
&lt;span class="hljs-doctag">/-- Update the state of the current pattern. -/&lt;/span>
&lt;span class="hljs-theorem">&lt;span class="hljs-keyword">def&lt;/span> &lt;span class="hljs-title">AppState&lt;/span>.&lt;span class="hljs-title">step&lt;/span> &lt;span class="hljs-params">(s : AppState patterns)&lt;/span> &lt;span class="hljs-symbol">:&lt;/span>&lt;/span> AppState patterns &lt;span class="hljs-symbol">:=&lt;/span>
{ s &lt;span class="hljs-built_in">with&lt;/span> state &lt;span class="hljs-symbol">:=&lt;/span> (patterns.get s.patternIndex).step s.state }
&lt;span class="hljs-doctag">/-- Get the current output color. -/&lt;/span>
&lt;span class="hljs-theorem">&lt;span class="hljs-keyword">def&lt;/span> &lt;span class="hljs-title">AppState&lt;/span>.&lt;span class="hljs-title">color&lt;/span> &lt;span class="hljs-params">(s : AppState patterns)&lt;/span> &lt;span class="hljs-symbol">:&lt;/span>&lt;/span> Color &lt;span class="hljs-symbol">:=&lt;/span>
(patterns.get s.patternIndex).color s.state
&lt;span class="hljs-doctag">/-- Initialize a new app state. -/&lt;/span>
&lt;span class="hljs-theorem">&lt;span class="hljs-keyword">def&lt;/span> &lt;span class="hljs-title">AppState&lt;/span>.&lt;span class="hljs-title">init&lt;/span> &lt;span class="hljs-params">(hPatterns : patterns.size &amp;gt; 0)&lt;/span> &lt;span class="hljs-symbol">:&lt;/span>&lt;/span> AppState patterns &lt;span class="hljs-symbol">:=&lt;/span>
&lt;span class="hljs-keyword">let&lt;/span> patternIndex &lt;span class="hljs-symbol">:=&lt;/span> Fin.ofNat&amp;#x27; &lt;span class="hljs-number">0&lt;/span> hPatterns
{
patternIndex,
state &lt;span class="hljs-symbol">:=&lt;/span> (patterns.get patternIndex).init,
}
&lt;/code>&lt;/pre>&lt;/div>
&lt;p>Next, we define our array of light patterns (assuming a 1000 Hz update frequency):&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code>&lt;span class="hljs-theorem">&lt;span class="hljs-keyword">def&lt;/span> &lt;span class="hljs-title">patterns&lt;/span> &lt;span class="hljs-symbol">:&lt;/span>&lt;/span> Array LightPattern &lt;span class="hljs-symbol">:=&lt;/span> #[
every &lt;span class="hljs-number">500&lt;/span> (blink white),
every &lt;span class="hljs-number">100&lt;/span> (blink white),
every &lt;span class="hljs-number">500&lt;/span> (blink red),
every &lt;span class="hljs-number">100&lt;/span> (blink red),
every &lt;span class="hljs-number">500&lt;/span> (blink green),
every &lt;span class="hljs-number">100&lt;/span> (blink green),
every &lt;span class="hljs-number">500&lt;/span> (blink blue),
every &lt;span class="hljs-number">100&lt;/span> (blink blue),
every &lt;span class="hljs-number">500&lt;/span> cycle,
every &lt;span class="hljs-number">100&lt;/span> cycle,
every &lt;span class="hljs-number">50&lt;/span> flicker,
breathe &lt;span class="hljs-number">1000&lt;/span> .Red,
breathe &lt;span class="hljs-number">1000&lt;/span> .Green,
breathe &lt;span class="hljs-number">1000&lt;/span> .Blue
]
&lt;/code>&lt;/pre>&lt;/div>
&lt;p>And finally, we are ready to define our main loop:&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code>&lt;span class="hljs-theorem">&lt;span class="hljs-keyword">def&lt;/span> &lt;span class="hljs-title">main&lt;/span> &lt;span class="hljs-symbol">:&lt;/span>&lt;/span> IO Unit &lt;span class="hljs-symbol">:=&lt;/span> &lt;span class="hljs-keyword">do&lt;/span>
&lt;span class="hljs-keyword">let&lt;/span> mut appState : AppState patterns
&lt;span class="hljs-symbol">:=&lt;/span> AppState.init patterns (&lt;span class="hljs-keyword">by&lt;/span> &lt;span class="hljs-built_in">simp&lt;/span> [patterns])
&lt;span class="hljs-keyword">let&lt;/span> mut buttonPressedPrev &lt;span class="hljs-symbol">:=&lt;/span> false
while true &lt;span class="hljs-keyword">do&lt;/span>
&lt;span class="hljs-comment">-- Read the button state, advance to the next pattern when pressed&lt;/span>
&lt;span class="hljs-keyword">let&lt;/span> buttonPressed &lt;span class="hljs-symbol">:=&lt;/span> !(← readGpio &lt;span class="hljs-number">9&lt;/span>)
if !buttonPressedPrev &amp;amp;&amp;amp; buttonPressed then
appState &lt;span class="hljs-symbol">:=&lt;/span> appState.nextPattern
buttonPressedPrev &lt;span class="hljs-symbol">:=&lt;/span> buttonPressed
&lt;span class="hljs-comment">-- Update the pattern state and output the current color to the LED&lt;/span>
appState &lt;span class="hljs-symbol">:=&lt;/span> appState.step
setLedState appState.color
&lt;span class="hljs-comment">-- &lt;span class="hljs-doctag">TODO:&lt;/span>&lt;/span>
&lt;span class="hljs-comment">-- Use proper timer instead of just a wait, so the frequency does not&lt;/span>
&lt;span class="hljs-comment">-- depend on the time it takes to do the update.&lt;/span>
delayUs &lt;span class="hljs-number">1000&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>
&lt;p>Wait, didn&amp;rsquo;t I say that Lean was a &lt;em>pure&lt;/em> language? What are these mutable variables and while loop doing here? As it turns out it&amp;rsquo;s all syntax sugar, and a pretty advanced one at that. All the &amp;ldquo;impure&amp;rdquo; features are compiled down to pure monadic code by Lean. You can learn more by reading the &lt;a href="https://lean-lang.org/lean4/doc/do.html">relevant chapter of the Lean manual&lt;/a>.&lt;/p>
&lt;p>&lt;code>readGpio&lt;/code>, &lt;code>setLedState&lt;/code>, and &lt;code>delayUs&lt;/code> are implemented in C:&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code>&lt;span class="hljs-meta">@[extern &amp;quot;c_read_gpio&amp;quot;]&lt;/span>
opaque readGpio : Fin &lt;span class="hljs-number">22&lt;/span> → IO Bool
&lt;span class="hljs-meta">@[extern &amp;quot;c_set_led_state&amp;quot;]&lt;/span>
opaque setLedState : (@&amp;amp; Color) → IO Unit
&lt;span class="hljs-meta">@[extern &amp;quot;c_delay_us&amp;quot;]&lt;/span>
opaque delayUs : Nat → IO Unit
&lt;/code>&lt;/pre>&lt;/div>
&lt;p>For example, here is what the &lt;code>c_set_led_state&lt;/code> function looks like:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="n">lean_object&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="nf">c_set_led_state&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">lean_object&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">lean_object&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">w&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">uint32_t&lt;/span> &lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nf">lean_ctor_get_uint8&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="mi">16&lt;/span> &lt;span class="o">|&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">lean_ctor_get_uint8&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="mi">8&lt;/span> &lt;span class="o">|&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">lean_ctor_get_uint8&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">state&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">send_led_data&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nf">lean_io_result_mk_ok&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">lean_box&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>See &lt;a href="#appendix-bit-banging-the-ws2812-protocol">the appendix below&lt;/a> for how the &lt;code>send_led_data&lt;/code> function works.&lt;/p>
&lt;h2 id="results">Results&lt;/h2>
&lt;p>Here are some clips of some LED patterns (in particular &lt;code>every 100 cycle&lt;/code>, &lt;code>breathe 1000 .Blue&lt;/code>, and &lt;code>every 50 flicker&lt;/code>) on my &lt;a href="https://www.waveshare.com/wiki/ESP32-C3-Zero">Waveshare ESP32-C3-Zero&lt;/a> development board:&lt;/p>
&lt;div class="horizontal-even-split">
&lt;div class="video-container">
&lt;video src="https://kuruczgy.com/video/rgb.webm
" autoplay loop muted>&lt;/video>
&lt;/div>
&lt;div class="video-container">
&lt;video src="https://kuruczgy.com/video/blue_breathing.webm
" autoplay loop muted>&lt;/video>
&lt;/div>
&lt;div class="video-container">
&lt;video src="https://kuruczgy.com/video/flicker.webm
" autoplay loop muted>&lt;/video>
&lt;/div>
&lt;/div>
&lt;h1 id="conclusions">Conclusions&lt;/h1>
&lt;p>Overall I am pleased with the results, beforehand I wasn&amp;rsquo;t even quite sure if running Lean in such a constrained environment would be possible. For now this is still very much just a proof-of-concept, though in the future I might try to build something actually useful with an ESP32 and Lean. Here is a list of ideas for how this project could be taken further:&lt;/p>
&lt;ul>
&lt;li>Transition to first compiling everything to LLVM bitcode instead of directly to machine code, this would enable link-time optimization to further reduce code size, and might simplify the cross-compilation setup.&lt;/li>
&lt;li>Use &lt;a href="https://github.com/espressif/esp-idf">ESP-IDF&lt;/a>, it already has a bunch of useful hardware abstractions, and could potentially make supporting other devices from the ESP32 family much easier.&lt;/li>
&lt;li>Get threading support by putting FreeRTOS into the stack. (ESP-IDF already uses it.)&lt;/li>
&lt;li>Get Wi-Fi working, would be pretty important for real-world applications.&lt;/li>
&lt;li>Try upstreaming some of the needed modifications to Lean.
&lt;ul>
&lt;li>Investigate if unused initialization code could somehow be detected and removed, this is definitely a big pain point.&lt;/li>
&lt;li>I think adding flags to make some features optional in the runtime (e.g. C++ exceptions, threads, and various OS interfaces) should be relatively uncontroversial.&lt;/li>
&lt;li>Make the build system in general behave a bit better when cross-compiling.&lt;/li>
&lt;li>Add 31 bit integers. (Maybe by special casing the &lt;code>Fin&lt;/code> type?)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Debug why floating point operations are giving bad results.&lt;/li>
&lt;/ul>
&lt;p>Finally, if you are interested in any of the topics mentioned in this article, here are some useful resources:&lt;/p>
&lt;ul>
&lt;li>Lean: I recommend the &lt;a href="https://lean-lang.org/functional_programming_in_lean/">Functional Programming in Lean&lt;/a> book, it&amp;rsquo;s a quite comprehensive introduction to programming in Lean. If you are by chance interested in using Lean as a proof assistant, take a look at the separate book titled &lt;a href="https://lean-lang.org/theorem_proving_in_lean4/title_page.html">Theorem Proving in Lean 4&lt;/a>.&lt;/li>
&lt;li>ESP32: If you want to program in a memory safe language for the ESP32 family of devices, I would recommend trying Rust, specifically the &lt;a href="https://docs.esp-rs.org/book/">esp-rs&lt;/a> project, which seems to have an active community around it.&lt;/li>
&lt;li>Nix: Not going to lie, I find the resources in the Nix ecosystem to be pretty lacking if you want to do anything somewhat non-trivial. Be prepared to read a lot of &lt;code>nixpkgs&lt;/code> source code if you want to do something on the level presented in this article. The best I can do is link you to the &lt;a href="https://nixos.org/learn/">official learning resource collection on the NixOS website&lt;/a>, but I cannot vouch for the quality of anything there.&lt;/li>
&lt;/ul>
&lt;h1 id="appendix-bit-banging-the-ws2812-protocol">Appendix: Bit banging the WS2812 protocol&lt;/h1>
&lt;p>The WS2812 family of addressable LEDs need to be driven with very particular timing constraints. A &lt;code>1&lt;/code> is signaled with the data line being high for 800 ns and low for 450 ns, while a &lt;code>0&lt;/code> is signaled by it being high for 400 ns and low for 850 ns. We need to transfer 24 bits like this, 8 for each color channel.&lt;/p>
&lt;p>Using a 20 MHz CPU clock, a single clock cycle is 50 ns, meaning that the transfer of a single bit needs to take exactly 25 cycles.&lt;/p>
&lt;p>Most instructions take 1 clock cycle on the ESP32-C3, except for branch instructions, which take 1 cycle if the branch is not taken, but take 3 if the branch is taken! (At least according to &lt;a href="https://ctrlsrc.io/posts/2023/counting-cpu-cycles-on-esp32c3-esp32c6/">this article&lt;/a> I found on the topic.) And be thankful that the ESP32-C3 does not have a branch predictor, so that even if the timings are somewhat complicated, they are at least deterministic.&lt;/p>
&lt;p>With all that said, here is the working code that I ended up with:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">__attribute__&lt;/span>&lt;span class="p">((&lt;/span>&lt;span class="n">noinline&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">send_led_data&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">uint32_t&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">const&lt;/span> &lt;span class="kt">size_t&lt;/span> &lt;span class="n">gpio&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">size_t&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">24&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">const&lt;/span> &lt;span class="kt">uint32_t&lt;/span> &lt;span class="n">bit&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="mi">23&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">));&lt;/span> &lt;span class="c1">// shift + and: 2 cycles
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">GPIO_OUT_W1TS_REG&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">gpio&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// GPIO high: 1 cycle
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">bit&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// if branch not taken: 1 cycles
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="nf">__asm__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;nop; nop; nop; nop; nop;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;nop; nop; nop; nop; nop;&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// wait: 10 cycles
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">GPIO_OUT_W1TC_REG&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">gpio&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// GPIO low: 1 cycle
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="nf">__asm__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;nop;&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// wait: 1 cycle
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// loop variable inc + jump taken: 4 cycles
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// if branch taken: 3 cycles
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="nf">__asm__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;nop; nop;&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// wait: 2 cycles
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">GPIO_OUT_W1TC_REG&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">gpio&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// GPIO low: 1 cycle
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="nf">__asm__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;nop; nop; nop; nop; nop; nop; nop; nop; nop;&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// wait: 9 cycles
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// loop variable inc + jump not taken: 2 cycles
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Writing it took some effort involving constantly looking at the disassembly to see what smart ways clang managed to come up with to helpfully &amp;ldquo;optimize&amp;rdquo; my code, and then accounting for them. E.g. you might notice that the jump back to the beginning of the loop takes a different number of cycles in the two branches of the &lt;code>if&lt;/code>! It turns out that clang laid out the code in such a way that the &lt;code>else&lt;/code> branch of the &lt;code>if&lt;/code> is placed before the beginning of the loop, so execution just falls through into the beginning of the loop again without having to jump back. This is faster, as you can see, it saved 2 clock cycles for us&amp;hellip;&lt;/p>
&lt;p>This code will probably keep working up until I upgrade to the next version of clang, and it comes up with some other way to outsmart us.&lt;/p>
&lt;p>Also you might notice that the clock cycles in an iteration above only add up to 20, and not 25. I had to take out a few &lt;code>nop&lt;/code>s, becuase the LED was not working with 25 for some reason. I still don&amp;rsquo;t know what the issue is, either there are still some clock cycles that I am not accounting for, or maybe the clock is slightly slower than 20 MHz for some reason. (I would need an oscilloscope or logic analyzer to debug this, which I don&amp;rsquo;t have.)&lt;/p>
&lt;p>Overall, I would rate the experience of writing this function 0/10. If I ever need to write such timing sensitive code again I will make sure to do it in assembly, because that will probably cause much fewer headaches. Optimizing compilers are awesome, except in rare cases like this, when they are working actively against you.&lt;/p>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>Just rolls off the tongue, right? &lt;code>rv32&lt;/code> stands for &amp;ldquo;RISC-V 32 bit&amp;rdquo;, &lt;code>i&lt;/code> is the base integer instruction set, &lt;code>m&lt;/code> is the extension with multiplication and division instructions, &lt;code>c&lt;/code> signifies support for compressed instruction encoding, and finally &lt;code>zicsr&lt;/code> signals support for &amp;ldquo;Control and Status Register&amp;rdquo; (CSR) instructions.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&amp;#160;&lt;a href="#fnref1:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>I use a 16 instead of a 32 bit counter since a 32 bit value would have to be allocated on the heap due to the way Lean&amp;rsquo;s object representation works, whereas a 16 bit value will be a scalar. It would be nice if Lean also had 31 bit integers like OCaml.&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div>
&lt;h1 id="bibliography">Bibliography&lt;/h1>
&lt;div class="bibliography">&lt;div id="cite:1">
&lt;div>[1]&lt;/div>
&lt;div>S. Ullrich and L. de Moura, &lt;span>&amp;#8220;Counting immutable beans: Reference counting optimized for purely functional programming.&amp;#8221;&lt;/span> 2020. Available: &lt;a href="https://arxiv.org/abs/1908.05647">https://arxiv.org/abs/1908.05647&lt;/a>&lt;/div>
&lt;/div>&lt;/div></description></item><item><title>A formally verified R-tree implementation</title><link>https://kuruczgy.com/blog/2023/11/12/verified-rtree/</link><pubDate>Sun, 12 Nov 2023 00:00:00 +0000</pubDate><guid>https://kuruczgy.com/blog/2023/11/12/verified-rtree/</guid><description>
&lt;div>
&lt;h2>Table Of Contents&lt;/h2>
&lt;nav id="TableOfContents">
&lt;ol>
&lt;li>&lt;a href="#introduction">Introduction&lt;/a>&lt;/li>
&lt;li>&lt;a href="#r-trees">R-trees&lt;/a>
&lt;ol>
&lt;li>&lt;a href="#insertion">Insertion&lt;/a>&lt;/li>
&lt;li>&lt;a href="#deletion">Deletion&lt;/a>&lt;/li>
&lt;li>&lt;a href="#complexity">Complexity&lt;/a>&lt;/li>
&lt;li>&lt;a href="#specification">Specification&lt;/a>
&lt;ol>
&lt;li>&lt;a href="#informal-specification">Informal specification&lt;/a>&lt;/li>
&lt;li>&lt;a href="#formal-specification-in-coq">Formal specification in Coq&lt;/a>&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;a href="#techniques">Techniques&lt;/a>
&lt;ol>
&lt;li>&lt;a href="#extraction">Extraction&lt;/a>
&lt;ol>
&lt;li>&lt;a href="#erasing-proofs">Erasing proofs&lt;/a>&lt;/li>
&lt;li>&lt;a href="#dependent-types">Dependent types&lt;/a>&lt;/li>
&lt;li>&lt;a href="#arithmetic">Arithmetic&lt;/a>&lt;/li>
&lt;li>&lt;a href="#transpiling-to-javascript">Transpiling to JavaScript&lt;/a>&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;a href="#the-sig-type">The &lt;code>sig&lt;/code> type&lt;/a>&lt;/li>
&lt;li>&lt;a href="#coqs-program-attribute">Coq&amp;rsquo;s &lt;code>#[program]&lt;/code> attribute&lt;/a>&lt;/li>
&lt;li>&lt;a href="#termination">Termination&lt;/a>
&lt;ol>
&lt;li>&lt;a href="#proving-termination-manually">Proving termination manually&lt;/a>&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;a href="#rewriting-with-permutations">Rewriting with permutations&lt;/a>
&lt;ol>
&lt;li>&lt;a href="#rewriting-with-morphisms">Rewriting with morphisms&lt;/a>&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;a href="#proof-automation">Proof automation&lt;/a>
&lt;ol>
&lt;li>&lt;a href="#reflection-for-use-with-lia">Reflection for use with &lt;code>lia&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#solving-permutations">Solving permutations&lt;/a>&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;a href="#implementation">Implementation&lt;/a>
&lt;ol>
&lt;li>&lt;a href="#axis-aligned-bounding-boxes">Axis-aligned bounding boxes&lt;/a>&lt;/li>
&lt;li>&lt;a href="#list-utility-functions">List utility functions&lt;/a>
&lt;ol>
&lt;li>&lt;a href="#removing-items-from-a-list">Removing items from a list&lt;/a>&lt;/li>
&lt;li>&lt;a href="#finding-minimal-items-in-a-list">Finding minimal items in a list&lt;/a>&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;a href="#partitioning-for-node-splitting">Partitioning (for node splitting)&lt;/a>&lt;/li>
&lt;li>&lt;a href="#the-tree-data-structure">The tree data structure&lt;/a>&lt;/li>
&lt;li>&lt;a href="#tree-operations">Tree operations&lt;/a>
&lt;ol>
&lt;li>&lt;a href="#insertion-1">Insertion&lt;/a>&lt;/li>
&lt;li>&lt;a href="#search">Search&lt;/a>&lt;/li>
&lt;li>&lt;a href="#deletion-1">Deletion&lt;/a>&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;a href="#putting-everything-together">Putting everything together&lt;/a>&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;a href="#benchmarks">Benchmarks&lt;/a>&lt;/li>
&lt;li>&lt;a href="#conclusions">Conclusions&lt;/a>&lt;/li>
&lt;li>&lt;a href="#bibliography">Bibliography&lt;/a>&lt;/li>
&lt;/ol>
&lt;/nav>
&lt;/div>
&lt;h1 id="introduction">Introduction&lt;/h1>
&lt;p>Bugs are ubiquitous in computer programming. Widely applied solutions exist to verify certain properties like memory or type safety. On the other hand, most programming languages only offer very rudimentary tools to enforce logical properties.&lt;/p>
&lt;p>Proof assistants offer a potential solution, and significant portion of them today is based on the Curry&amp;ndash;Howard isomorphism &lt;span class="hugo-cite-intext" itemprop="citation">&lt;span class="tooltip-trigger">&lt;a href="#cite:1">[1]&lt;/a>&lt;span class="tooltip">H. B. Curry, J. R. Hindley, and J. P. Seldin, Eds., &lt;em>To H.B. Curry: Essays on combinatory logic, lambda calculus, and formalism&lt;/em>. London ; New York: Academic Press, 1980.&lt;/span>&lt;/span>&lt;/span>. The idea behind using the Curry&amp;ndash;Howard isomorphism for theorem proving is that strongly typed functional programs can also be interpreted as proofs of mathematical theorems. As such, proof assistants based on the Curry&amp;ndash;Howard isomorphism are just as powerful functional programming languages as they are proof assistants.&lt;/p>
&lt;p>Coq is a proof assistant and a programming language based on Martin-Löf type theory. It allows arbitrary logical propositions to be stated and proved about programs.&lt;/p>
&lt;p>Proving the correctness of algorithms in proof assistants is still very labor intensive, and an active research area. I present an implementation of the R-tree data structure and its correctness proof in Coq. (This is the first correctness proof of an R-tree specifically that I am aware of.) You can find the source code for this project &lt;a href="https://git.sr.ht/~kuruczgy/verified-rtree/tree/for-blog/item/RTree.v">here&lt;/a>.&lt;/p>
&lt;p>The reader is referred to &lt;a href="https://kuruczgy.com/blog/2022/10/20/introduction-to-dependent-types/">my previous article&lt;/a> for an introduction to type theory and its use for theorem proving, and &lt;a href="https://kuruczgy.com/blog/2023/06/18/theorem-proving-in-coq/">this article&lt;/a> for an introduction to the specific features of Coq.&lt;/p>
&lt;h1 id="r-trees">R-trees&lt;/h1>
&lt;p>An R-tree &lt;span class="hugo-cite-intext" itemprop="citation">&lt;span class="tooltip-trigger">&lt;a href="#cite:2">[2]&lt;/a>&lt;span class="tooltip">A. Guttman, &lt;span>“R-trees: A dynamic index structure for spatial searching,”&lt;/span> in &lt;em>Proceedings of the 1984 ACM SIGMOD international conference on Management of data - SIGMOD ’84&lt;/em>, Boston, Massachusetts: ACM Press, 1984, p. 47. doi: &lt;a href="https://doi.org/10.1145/602259.602266">10.1145/602259.602266&lt;/a>.&lt;/span>&lt;/span>&lt;/span> is a data structure that can efficiently query a set of axis-aligned bounding boxes (AABBs) in &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;msup>&lt;mi mathvariant="double-struck">R&lt;/mi>&lt;mi>d&lt;/mi>&lt;/msup>&lt;/mrow>&lt;annotation encoding="application/x-tex">\mathbb{R}^d&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.8491em;">&lt;/span>&lt;span class="mord">&lt;span class="mord mathbb">R&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.8491em;">&lt;span style="top:-3.063em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mathnormal mtight">d&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span> that intersect a query box &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>γ&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">\gamma&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.625em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.05556em;">γ&lt;/span>&lt;/span>&lt;/span>&lt;/span>.&lt;/p>
&lt;p>The R-tree is a &lt;em>bounding volume hierarchy&lt;/em>, meaning that each node in the tree has an associated volume, and each child is completely contained in its parent&amp;rsquo;s volume. In the case of the R-tree, all of the volumes are AABBs, and each non-leaf node&amp;rsquo;s volume is simply the minimum bounding rectangle of the volumes of its children.&lt;/p>
&lt;p>The number of children of each non-leaf non-root node should be between &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>m&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">m&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">m&lt;/span>&lt;/span>&lt;/span>&lt;/span> and &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>M&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">M&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.10903em;">M&lt;/span>&lt;/span>&lt;/span>&lt;/span>, which are freely chosen parameters of a particular R-tree. (In the example below &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>m&lt;/mi>&lt;mo>=&lt;/mo>&lt;mn>2&lt;/mn>&lt;/mrow>&lt;annotation encoding="application/x-tex">m=2&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">m&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6444em;">&lt;/span>&lt;span class="mord">2&lt;/span>&lt;/span>&lt;/span>&lt;/span> and &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>M&lt;/mi>&lt;mo>=&lt;/mo>&lt;mn>4&lt;/mn>&lt;/mrow>&lt;annotation encoding="application/x-tex">M=4&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.10903em;">M&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6444em;">&lt;/span>&lt;span class="mord">4&lt;/span>&lt;/span>&lt;/span>&lt;/span>.) It&amp;rsquo;s the job of the insertion and deletion procedures to make sure that these bounds are respected. They also make sure that the tree is balanced. (That is, each leaf node is at the same height.)&lt;/p>
&lt;p>In the example below, we are storing the rectangles &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo stretchy="false">{&lt;/mo>&lt;mi>A&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>B&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>C&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>D&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>E&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>F&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>G&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>H&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>I&lt;/mi>&lt;mo stretchy="false">}&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\{A,B,C,D,E,F,G,H,I\}&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mopen">{&lt;/span>&lt;span class="mord mathnormal">A&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.05017em;">B&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.07153em;">C&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.02778em;">D&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.05764em;">E&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.13889em;">F&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal">G&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.08125em;">H&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.07847em;">I&lt;/span>&lt;span class="mclose">}&lt;/span>&lt;/span>&lt;/span>&lt;/span> in the tree, while &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo stretchy="false">{&lt;/mo>&lt;mi>X&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>Y&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>Z&lt;/mi>&lt;mo stretchy="false">}&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\{X,Y,Z\}&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mopen">{&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.07847em;">X&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.22222em;">Y&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.07153em;">Z&lt;/span>&lt;span class="mclose">}&lt;/span>&lt;/span>&lt;/span>&lt;/span> and the root are inner nodes that were generated during the insertion procedure.&lt;/p>
&lt;div class="side-by-side">
&lt;!-- This file was generated by dvisvgm 2.13.3 -->&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="228.472329pt" height="228.472329pt" viewBox="-72 -72 228.472329 228.472329">
&lt;defs>
&lt;path id="g0-65" d="m2.438853-1.592428c-.502117 .846426-.989888 1.133349-1.678505 1.176388c-.157808 .014346-.272578 .014346-.272578 .272578c0 .086077 .071731 .143462 .172154 .143462c.258232 0 .90381-.028692 1.162042-.028692c.41604 0 .875118 .028692 1.276811 .028692c.086077 0 .258232 0 .258232-.272578c0-.129116-.11477-.143462-.200847-.143462c-.329963-.028692-.60254-.143462-.60254-.487771c0-.200847 .086077-.358655 .272578-.674271l1.090311-1.807621h3.65828c.014346 .129116 .014346 .243885 .028692 .373001c.043039 .373001 .215193 1.865005 .215193 2.137583c0 .430386-.731656 .459078-.961195 .459078c-.157808 0-.315616 0-.315616 .258232c0 .157808 .129116 .157808 .215193 .157808c.243885 0 .530809-.028692 .774695-.028692h.817733c.875118 0 1.506351 .028692 1.520697 .028692c.100423 0 .258232 0 .258232-.272578c0-.143462-.129116-.143462-.344309-.143462c-.789041 0-.803387-.129116-.846426-.559502l-.875118-8.952026c-.028692-.286924-.086077-.315616-.243885-.315616c-.143462 0-.229539 .028692-.358655 .243885l-5.021168 8.406871zm1.721543-2.209314l2.883585-4.820322l.487771 4.820322h-3.371356z"/>
&lt;path id="g0-66" d="m5.250708-8.82291c.129116-.530809 .186501-.559502 .746002-.559502h1.865005c1.62112 0 1.62112 1.377235 1.62112 1.506351c0 1.162042-1.162042 2.6397-3.05574 2.6397h-2.065852l.889464-3.586549zm2.424507 3.701318c1.563735-.286924 2.984009-1.377235 2.984009-2.697085c0-1.119003-.989888-1.979775-2.611008-1.979775h-4.605129c-.272578 0-.401693 0-.401693 .272578c0 .143462 .129116 .143462 .344309 .143462c.875118 0 .875118 .11477 .875118 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h4.920745c2.194968 0 3.887819-1.664159 3.887819-3.113124c0-1.176388-1.032926-1.893698-2.194968-2.008467zm-2.03716 4.705552h-1.936736c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l1.004234-4.045627h2.697085c1.692851 0 1.692851 1.578082 1.692851 1.692851c0 1.377235-1.248119 2.840547-3.027047 2.840547z"/>
&lt;path id="g0-67" d="m10.716608-9.970606c0-.129116-.100423-.129116-.129116-.129116s-.086077 0-.200847 .143462l-.989888 1.20508c-.502117-.860772-1.291158-1.348542-2.367122-1.348542c-3.098778 0-6.312326 3.141817-6.312326 6.513173c0 2.395815 1.678505 3.887819 3.773049 3.887819c1.147696 0 2.151929-.487771 2.984009-1.190734c1.248119-1.047272 1.62112-2.438853 1.62112-2.553623c0-.129116-.11477-.129116-.157808-.129116c-.129116 0-.143462 .086077-.172154 .143462c-.659925 2.238007-2.596661 3.313971-4.031281 3.313971c-1.520697 0-2.840547-.975541-2.840547-3.012701c0-.459078 .143462-2.955316 1.764582-4.834668c.789041-.918157 2.137583-1.721543 3.500472-1.721543c1.578082 0 2.281045 1.305504 2.281045 2.768816c0 .373001-.043039 .688617-.043039 .746002c0 .129116 .143462 .129116 .186501 .129116c.157808 0 .172154-.014346 .229539-.272578l.90381-3.65828z"/>
&lt;path id="g0-68" d="m2.252353-1.061618c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h4.547744c2.897932 0 5.724132-2.998355 5.724132-6.197557c0-2.065852-1.233773-3.600895-3.285279-3.600895h-4.605129c-.272578 0-.401693 0-.401693 .272578c0 .143462 .129116 .143462 .344309 .143462c.875118 0 .875118 .11477 .875118 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253zm3.027047-7.761292c.129116-.530809 .186501-.559502 .746002-.559502h1.578082c1.348542 0 2.582315 .731656 2.582315 2.711431c0 .71731-.286924 3.213548-1.678505 4.791629c-.401693 .473424-1.492004 1.463312-3.141817 1.463312h-1.635466c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l1.979775-7.9191z"/>
&lt;path id="g0-69" d="m9.970606-3.328317c.014346-.043039 .057385-.143462 .057385-.200847c0-.071731-.057385-.143462-.143462-.143462c-.057385 0-.086077 .014346-.129116 .057385c-.028692 .014346-.028692 .043039-.157808 .329963c-.846426 2.008467-1.463312 2.869239-3.758703 2.869239h-2.094545c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l.989888-3.95955h1.420273c1.119003 0 1.20508 .243885 1.20508 .674271c0 .143462 0 .272578-.100423 .702964c-.028692 .057385-.043039 .11477-.043039 .157808c0 .100423 .071731 .143462 .157808 .143462c.129116 0 .143462-.100423 .200847-.30127l.817733-3.328317c0-.071731-.057385-.143462-.143462-.143462c-.129116 0-.143462 .057385-.200847 .258232c-.286924 1.104657-.573848 1.420273-1.850659 1.420273h-1.362889l.889464-3.529164c.129116-.502117 .157808-.545155 .746002-.545155h2.051506c1.764582 0 2.123237 .473424 2.123237 1.563735c0 .014346 0 .41604-.057385 .889464c-.014346 .057385-.028692 .143462-.028692 .172154c0 .11477 .071731 .157808 .157808 .157808c.100423 0 .157808-.057385 .186501-.315616l.30127-2.510584c0-.043039 .028692-.186501 .028692-.215193c0-.157808-.129116-.157808-.387347-.157808h-7.000943c-.272578 0-.41604 0-.41604 .258232c0 .157808 .100423 .157808 .344309 .157808c.889464 0 .889464 .100423 .889464 .258232c0 .071731-.014346 .129116-.057385 .286924l-1.936736 7.746946c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h7.20179c.315616 0 .329963-.014346 .430386-.243885l1.305504-3.084432z"/>
&lt;path id="g0-70" d="m4.26082-4.67686h1.377235c1.090311 0 1.176388 .243885 1.176388 .659925c0 .186501-.028692 .387347-.100423 .702964c-.028692 .057385-.043039 .129116-.043039 .157808c0 .100423 .057385 .157808 .157808 .157808c.11477 0 .129116-.057385 .186501-.286924l.832079-3.342664c0-.057385-.043039-.143462-.143462-.143462c-.129116 0-.143462 .057385-.200847 .30127c-.30127 1.075965-.588194 1.377235-1.836313 1.377235h-1.305504l.932503-3.715665c.129116-.502117 .157808-.545155 .746002-.545155h1.92239c1.793274 0 2.051506 .530809 2.051506 1.549389c0 .086077 0 .401693-.043039 .774695c-.014346 .057385-.043039 .243885-.043039 .30127c0 .11477 .071731 .157808 .157808 .157808c.100423 0 .157808-.057385 .186501-.315616l.30127-2.510584c0-.043039 .028692-.186501 .028692-.215193c0-.157808-.129116-.157808-.387347-.157808h-6.800097c-.272578 0-.41604 0-.41604 .258232c0 .157808 .100423 .157808 .344309 .157808c.889464 0 .889464 .100423 .889464 .258232c0 .071731-.014346 .129116-.057385 .286924l-1.936736 7.746946c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .129116 .157808 .215193 .157808c.272578 0 .559502-.028692 .832079-.028692h1.865005c.315616 0 .659925 .028692 .975541 .028692c.129116 0 .30127 0 .30127-.258232c0-.157808-.086077-.157808-.401693-.157808c-1.133349 0-1.162042-.100423-1.162042-.315616c0-.071731 .028692-.186501 .057385-.286924l.918157-3.65828z"/>
&lt;path id="g0-71" d="m10.702262-9.970606c0-.129116-.100423-.129116-.129116-.129116s-.086077 0-.200847 .143462l-.989888 1.190734c-.071731-.11477-.358655-.616886-.918157-.946849c-.616886-.387347-1.233773-.387347-1.448966-.387347c-3.070086 0-6.29798 3.127471-6.29798 6.513173c0 2.367122 1.635466 3.887819 3.787396 3.887819c1.032926 0 2.33843-.344309 3.05574-1.248119c.157808 .545155 .473424 .932503 .573848 .932503c.071731 0 .086077-.043039 .100423-.043039c.014346-.028692 .129116-.530809 .200847-.789041l.229539-.918157c.11477-.473424 .172154-.674271 .272578-1.104657c.143462-.545155 .172154-.588194 .961195-.60254c.057385 0 .229539 0 .229539-.272578c0-.143462-.143462-.143462-.186501-.143462c-.243885 0-.516463 .028692-.774695 .028692h-.774695c-.60254 0-1.233773-.028692-1.821967-.028692c-.129116 0-.30127 0-.30127 .258232c0 .143462 .11477 .143462 .11477 .157808h.358655c1.133349 0 1.133349 .11477 1.133349 .329963c0 .014346-.272578 1.463312-.545155 1.893698c-.545155 .803387-1.678505 1.133349-2.52493 1.133349c-1.104657 0-2.897932-.573848-2.897932-3.05574c0-.961195 .344309-3.156163 1.73589-4.777283c.90381-1.032926 2.238007-1.73589 3.500472-1.73589c1.692851 0 2.295391 1.448966 2.295391 2.768816c0 .229539-.057385 .545155-.057385 .746002c0 .129116 .143462 .129116 .186501 .129116c.157808 0 .172154-.014346 .229539-.272578l.90381-3.65828z"/>
&lt;path id="g0-72" d="m10.730954-8.751179c.129116-.487771 .157808-.631233 1.176388-.631233c.258232 0 .401693 0 .401693-.258232c0-.157808-.129116-.157808-.215193-.157808c-.258232 0-.559502 .028692-.832079 .028692h-1.692851c-.272578 0-.573848-.028692-.846426-.028692c-.100423 0-.272578 0-.272578 .272578c0 .143462 .100423 .143462 .373001 .143462c.860772 0 .860772 .11477 .860772 .272578c0 .028692 0 .11477-.057385 .329963l-.875118 3.471779h-4.332551l.860772-3.443087c.129116-.487771 .157808-.631233 1.176388-.631233c.258232 0 .401693 0 .401693-.258232c0-.157808-.129116-.157808-.215193-.157808c-.258232 0-.559502 .028692-.832079 .028692h-1.692851c-.272578 0-.573848-.028692-.846426-.028692c-.100423 0-.272578 0-.272578 .272578c0 .143462 .100423 .143462 .373001 .143462c.860772 0 .860772 .11477 .860772 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253c-.129116 .502117-.157808 .645579-1.147696 .645579c-.329963 0-.430386 0-.430386 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.272578 0 .573848 .028692 .846426 .028692c.11477 0 .272578 0 .272578-.272578c0-.143462-.129116-.143462-.344309-.143462c-.875118 0-.875118-.11477-.875118-.258232c0-.014346 0-.11477 .028692-.229539l.989888-3.988242h4.346897c-.243885 .946849-.975541 3.945204-1.004234 4.031281c-.157808 .430386-.387347 .430386-1.233773 .444732c-.172154 0-.30127 0-.30127 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.272578 0 .573848 .028692 .846426 .028692c.11477 0 .272578 0 .272578-.272578c0-.143462-.129116-.143462-.344309-.143462c-.875118 0-.875118-.11477-.875118-.258232c0-.014346 0-.11477 .028692-.229539l1.965429-7.847369z"/>
&lt;path id="g0-73" d="m5.2794-8.736833c.129116-.502117 .157808-.645579 1.20508-.645579c.315616 0 .430386 0 .430386-.272578c0-.143462-.157808-.143462-.200847-.143462c-.258232 0-.573848 .028692-.832079 .028692h-1.764582c-.286924 0-.616886-.028692-.90381-.028692c-.11477 0-.272578 0-.272578 .272578c0 .143462 .11477 .143462 .401693 .143462c.889464 0 .889464 .11477 .889464 .272578c0 .100423-.028692 .186501-.057385 .315616l-1.936736 7.732599c-.129116 .502117-.157808 .645579-1.20508 .645579c-.315616 0-.444732 0-.444732 .272578c0 .143462 .143462 .143462 .215193 .143462c.258232 0 .573848-.028692 .832079-.028692h1.764582c.286924 0 .60254 .028692 .889464 .028692c.11477 0 .286924 0 .286924-.258232c0-.157808-.086077-.157808-.401693-.157808c-.889464 0-.889464-.11477-.889464-.286924c0-.028692 0-.100423 .057385-.329963l1.936736-7.703907z"/>
&lt;path id="g0-88" d="m6.814443-5.824555l-1.348542-3.141817c.186501-.344309 .616886-.401693 .789041-.41604c.086077 0 .243885-.014346 .243885-.258232c0-.157808-.129116-.157808-.215193-.157808c-.243885 0-.530809 .028692-.774695 .028692h-.832079c-.875118 0-1.506351-.028692-1.520697-.028692c-.11477 0-.258232 0-.258232 .272578c0 .143462 .129116 .143462 .315616 .143462c.832079 0 .889464 .143462 1.032926 .487771l1.707197 3.988242l-3.113124 3.328317c-.516463 .559502-1.133349 1.104657-2.194968 1.162042c-.172154 .014346-.286924 .014346-.286924 .272578c0 .043039 .014346 .143462 .172154 .143462c.200847 0 .41604-.028692 .616886-.028692h.674271c.459078 0 .961195 .028692 1.405927 .028692c.100423 0 .272578 0 .272578-.258232c0-.143462-.100423-.157808-.186501-.157808c-.286924-.028692-.473424-.186501-.473424-.41604c0-.243885 .172154-.41604 .588194-.846426l1.276811-1.391581c.315616-.329963 1.075965-1.162042 1.391581-1.477658l1.506351 3.529164c.014346 .028692 .071731 .172154 .071731 .186501c0 .129116-.315616 .387347-.774695 .41604c-.086077 0-.243885 .014346-.243885 .272578c0 .143462 .143462 .143462 .215193 .143462c.243885 0 .530809-.028692 .774695-.028692h1.578082c.258232 0 .530809 .028692 .774695 .028692c.100423 0 .258232 0 .258232-.272578c0-.143462-.143462-.143462-.272578-.143462c-.860772-.014346-.889464-.086077-1.133349-.616886l-1.893698-4.447321l1.821967-1.951083c.143462-.143462 .473424-.502117 .60254-.645579c.616886-.645579 1.190734-1.233773 2.352776-1.305504c.143462-.014346 .286924-.014346 .286924-.258232c0-.157808-.129116-.157808-.186501-.157808c-.200847 0-.41604 .028692-.616886 .028692h-.659925c-.459078 0-.961195-.028692-1.405927-.028692c-.100423 0-.272578 0-.272578 .258232c0 .143462 .100423 .157808 .186501 .157808c.229539 .028692 .473424 .143462 .473424 .41604l-.014346 .028692c-.014346 .100423-.043039 .243885-.200847 .41604l-2.510584 2.697085z"/>
&lt;path id="g0-89" d="m8.435563-8.206024l.329963-.329963c.631233-.645579 1.162042-.803387 1.664159-.846426c.157808-.014346 .286924-.028692 .286924-.272578c0-.143462-.143462-.143462-.172154-.143462c-.172154 0-.358655 .028692-.530809 .028692h-.588194c-.41604 0-.860772-.028692-1.262465-.028692c-.100423 0-.258232 0-.258232 .272578c0 .129116 .143462 .143462 .186501 .143462c.430386 .028692 .430386 .243885 .430386 .329963c0 .157808-.11477 .373001-.401693 .702964l-3.414395 3.916511l-1.62112-4.361243c-.086077-.200847-.086077-.229539-.086077-.258232c0-.30127 .588194-.329963 .760348-.329963s.329963 0 .329963-.258232c0-.157808-.129116-.157808-.215193-.157808c-.243885 0-.530809 .028692-.774695 .028692h-1.592428c-.258232 0-.530809-.028692-.774695-.028692c-.100423 0-.258232 0-.258232 .272578c0 .143462 .129116 .143462 .344309 .143462c.702964 0 .832079 .129116 .961195 .459078l1.778928 4.777283c.014346 .043039 .057385 .200847 .057385 .243885s-.702964 2.869239-.746002 3.012701c-.11477 .387347-.258232 .459078-1.176388 .473424c-.243885 0-.358655 0-.358655 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.258232 0 .559502 .028692 .817733 .028692c.100423 0 .272578 0 .272578-.258232c0-.157808-.100423-.157808-.344309-.157808c-.889464 0-.889464-.100423-.889464-.258232c0-.100423 .11477-.559502 .186501-.846426l.516463-2.065852c.086077-.30127 .086077-.329963 .215193-.473424l3.600895-4.146051z"/>
&lt;path id="g0-90" d="m10.042337-9.35372c.086077-.100423 .157808-.186501 .157808-.329963c0-.100423-.014346-.11477-.344309-.11477h-5.924979c-.329963 0-.344309 .014346-.430386 .272578l-.789041 2.582315c-.043039 .143462-.043039 .172154-.043039 .200847c0 .057385 .043039 .143462 .143462 .143462c.11477 0 .143462-.057385 .200847-.243885c.530809-1.549389 1.233773-2.539277 3.500472-2.539277h2.352776l-7.861715 8.894641c-.129116 .157808-.186501 .215193-.186501 .373001c0 .11477 .071731 .11477 .344309 .11477h6.125826c.329963 0 .344309-.014346 .430386-.272578l1.004234-3.170509c.014346-.043039 .043039-.143462 .043039-.200847c0-.071731-.057385-.143462-.143462-.143462c-.11477 0-.129116 .014346-.243885 .373001c-.60254 1.850659-1.233773 2.969663-3.730011 2.969663h-2.481892l7.876061-8.908988z"/>
&lt;/defs>
&lt;g id="page1">
&lt;path d="m-71.1484 155.6211v-226.7731h226.7733v226.7731h-226.7733z" fill="none" stroke-width="1.7008" style="stroke: var(--color-fg);"/>
&lt;path d="m-65.4805 149.9531v-107.7191h107.7184v107.7191h-107.7184z" fill="none" stroke-width="1.7008" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(38.187 -127.7597)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-88"/>
&lt;/g>
&lt;path d="m-59.8125 144.2812v-45.3554h19.8438v45.3554h-19.8438z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(43.8563 -71.066)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-65"/>
&lt;/g>
&lt;path d="m-34.2969 141.4492v-56.6953h48.1878v56.6953h-48.1878z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(69.3687 -85.2395)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-66"/>
&lt;/g>
&lt;path d="m-14.457 127.2734v-79.3714h51.0269v79.3714h-51.0269z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(89.2114 -122.0904)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-67"/>
&lt;/g>
&lt;path d="m-65.4805 13.887v-79.371h79.3714v79.371h-79.3714z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(38.187 -235.4777)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-89"/>
&lt;/g>
&lt;path d="m-59.8125 8.219v-28.348h45.3555v28.348h-45.3555z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(43.8563 -190.1226)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-68"/>
&lt;/g>
&lt;path d="m-14.457-37.137v-22.679h22.6799v22.679h-22.6799z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(89.2114 -229.8084)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-69"/>
&lt;/g>
&lt;path d="m-42.8008 70.582v-113.387h192.7577v113.387h-192.7577z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(60.8646 -212.8001)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-90"/>
&lt;/g>
&lt;path d="m-37.1328 64.91v-79.371h87.8747v79.371h-87.8747z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(66.5339 -184.453336)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-70"/>
&lt;/g>
&lt;path d="m113.1059-.285v-36.852h31.179v36.852h-31.179z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(216.7721 -207.1309)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-71"/>
&lt;/g>
&lt;path d="m98.9299 42.234v-28.347h28.347v28.347h-28.347z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(202.5991 -156.1065)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-72"/>
&lt;/g>
&lt;path d="m70.5859-.285v-22.68h28.344v22.68h-28.344z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(174.2518 -192.95746)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-73"/>
&lt;/g>
&lt;/g>
&lt;/svg>
&lt;!-- This file was generated by dvisvgm 2.13.3 -->&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="255.401494pt" height="106.582615pt" viewBox="-72 -72 255.401494 106.582615">
&lt;defs>
&lt;path id="g0-65" d="m2.438853-1.592428c-.502117 .846426-.989888 1.133349-1.678505 1.176388c-.157808 .014346-.272578 .014346-.272578 .272578c0 .086077 .071731 .143462 .172154 .143462c.258232 0 .90381-.028692 1.162042-.028692c.41604 0 .875118 .028692 1.276811 .028692c.086077 0 .258232 0 .258232-.272578c0-.129116-.11477-.143462-.200847-.143462c-.329963-.028692-.60254-.143462-.60254-.487771c0-.200847 .086077-.358655 .272578-.674271l1.090311-1.807621h3.65828c.014346 .129116 .014346 .243885 .028692 .373001c.043039 .373001 .215193 1.865005 .215193 2.137583c0 .430386-.731656 .459078-.961195 .459078c-.157808 0-.315616 0-.315616 .258232c0 .157808 .129116 .157808 .215193 .157808c.243885 0 .530809-.028692 .774695-.028692h.817733c.875118 0 1.506351 .028692 1.520697 .028692c.100423 0 .258232 0 .258232-.272578c0-.143462-.129116-.143462-.344309-.143462c-.789041 0-.803387-.129116-.846426-.559502l-.875118-8.952026c-.028692-.286924-.086077-.315616-.243885-.315616c-.143462 0-.229539 .028692-.358655 .243885l-5.021168 8.406871zm1.721543-2.209314l2.883585-4.820322l.487771 4.820322h-3.371356z"/>
&lt;path id="g0-66" d="m5.250708-8.82291c.129116-.530809 .186501-.559502 .746002-.559502h1.865005c1.62112 0 1.62112 1.377235 1.62112 1.506351c0 1.162042-1.162042 2.6397-3.05574 2.6397h-2.065852l.889464-3.586549zm2.424507 3.701318c1.563735-.286924 2.984009-1.377235 2.984009-2.697085c0-1.119003-.989888-1.979775-2.611008-1.979775h-4.605129c-.272578 0-.401693 0-.401693 .272578c0 .143462 .129116 .143462 .344309 .143462c.875118 0 .875118 .11477 .875118 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h4.920745c2.194968 0 3.887819-1.664159 3.887819-3.113124c0-1.176388-1.032926-1.893698-2.194968-2.008467zm-2.03716 4.705552h-1.936736c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l1.004234-4.045627h2.697085c1.692851 0 1.692851 1.578082 1.692851 1.692851c0 1.377235-1.248119 2.840547-3.027047 2.840547z"/>
&lt;path id="g0-67" d="m10.716608-9.970606c0-.129116-.100423-.129116-.129116-.129116s-.086077 0-.200847 .143462l-.989888 1.20508c-.502117-.860772-1.291158-1.348542-2.367122-1.348542c-3.098778 0-6.312326 3.141817-6.312326 6.513173c0 2.395815 1.678505 3.887819 3.773049 3.887819c1.147696 0 2.151929-.487771 2.984009-1.190734c1.248119-1.047272 1.62112-2.438853 1.62112-2.553623c0-.129116-.11477-.129116-.157808-.129116c-.129116 0-.143462 .086077-.172154 .143462c-.659925 2.238007-2.596661 3.313971-4.031281 3.313971c-1.520697 0-2.840547-.975541-2.840547-3.012701c0-.459078 .143462-2.955316 1.764582-4.834668c.789041-.918157 2.137583-1.721543 3.500472-1.721543c1.578082 0 2.281045 1.305504 2.281045 2.768816c0 .373001-.043039 .688617-.043039 .746002c0 .129116 .143462 .129116 .186501 .129116c.157808 0 .172154-.014346 .229539-.272578l.90381-3.65828z"/>
&lt;path id="g0-68" d="m2.252353-1.061618c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h4.547744c2.897932 0 5.724132-2.998355 5.724132-6.197557c0-2.065852-1.233773-3.600895-3.285279-3.600895h-4.605129c-.272578 0-.401693 0-.401693 .272578c0 .143462 .129116 .143462 .344309 .143462c.875118 0 .875118 .11477 .875118 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253zm3.027047-7.761292c.129116-.530809 .186501-.559502 .746002-.559502h1.578082c1.348542 0 2.582315 .731656 2.582315 2.711431c0 .71731-.286924 3.213548-1.678505 4.791629c-.401693 .473424-1.492004 1.463312-3.141817 1.463312h-1.635466c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l1.979775-7.9191z"/>
&lt;path id="g0-69" d="m9.970606-3.328317c.014346-.043039 .057385-.143462 .057385-.200847c0-.071731-.057385-.143462-.143462-.143462c-.057385 0-.086077 .014346-.129116 .057385c-.028692 .014346-.028692 .043039-.157808 .329963c-.846426 2.008467-1.463312 2.869239-3.758703 2.869239h-2.094545c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l.989888-3.95955h1.420273c1.119003 0 1.20508 .243885 1.20508 .674271c0 .143462 0 .272578-.100423 .702964c-.028692 .057385-.043039 .11477-.043039 .157808c0 .100423 .071731 .143462 .157808 .143462c.129116 0 .143462-.100423 .200847-.30127l.817733-3.328317c0-.071731-.057385-.143462-.143462-.143462c-.129116 0-.143462 .057385-.200847 .258232c-.286924 1.104657-.573848 1.420273-1.850659 1.420273h-1.362889l.889464-3.529164c.129116-.502117 .157808-.545155 .746002-.545155h2.051506c1.764582 0 2.123237 .473424 2.123237 1.563735c0 .014346 0 .41604-.057385 .889464c-.014346 .057385-.028692 .143462-.028692 .172154c0 .11477 .071731 .157808 .157808 .157808c.100423 0 .157808-.057385 .186501-.315616l.30127-2.510584c0-.043039 .028692-.186501 .028692-.215193c0-.157808-.129116-.157808-.387347-.157808h-7.000943c-.272578 0-.41604 0-.41604 .258232c0 .157808 .100423 .157808 .344309 .157808c.889464 0 .889464 .100423 .889464 .258232c0 .071731-.014346 .129116-.057385 .286924l-1.936736 7.746946c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h7.20179c.315616 0 .329963-.014346 .430386-.243885l1.305504-3.084432z"/>
&lt;path id="g0-70" d="m4.26082-4.67686h1.377235c1.090311 0 1.176388 .243885 1.176388 .659925c0 .186501-.028692 .387347-.100423 .702964c-.028692 .057385-.043039 .129116-.043039 .157808c0 .100423 .057385 .157808 .157808 .157808c.11477 0 .129116-.057385 .186501-.286924l.832079-3.342664c0-.057385-.043039-.143462-.143462-.143462c-.129116 0-.143462 .057385-.200847 .30127c-.30127 1.075965-.588194 1.377235-1.836313 1.377235h-1.305504l.932503-3.715665c.129116-.502117 .157808-.545155 .746002-.545155h1.92239c1.793274 0 2.051506 .530809 2.051506 1.549389c0 .086077 0 .401693-.043039 .774695c-.014346 .057385-.043039 .243885-.043039 .30127c0 .11477 .071731 .157808 .157808 .157808c.100423 0 .157808-.057385 .186501-.315616l.30127-2.510584c0-.043039 .028692-.186501 .028692-.215193c0-.157808-.129116-.157808-.387347-.157808h-6.800097c-.272578 0-.41604 0-.41604 .258232c0 .157808 .100423 .157808 .344309 .157808c.889464 0 .889464 .100423 .889464 .258232c0 .071731-.014346 .129116-.057385 .286924l-1.936736 7.746946c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .129116 .157808 .215193 .157808c.272578 0 .559502-.028692 .832079-.028692h1.865005c.315616 0 .659925 .028692 .975541 .028692c.129116 0 .30127 0 .30127-.258232c0-.157808-.086077-.157808-.401693-.157808c-1.133349 0-1.162042-.100423-1.162042-.315616c0-.071731 .028692-.186501 .057385-.286924l.918157-3.65828z"/>
&lt;path id="g0-71" d="m10.702262-9.970606c0-.129116-.100423-.129116-.129116-.129116s-.086077 0-.200847 .143462l-.989888 1.190734c-.071731-.11477-.358655-.616886-.918157-.946849c-.616886-.387347-1.233773-.387347-1.448966-.387347c-3.070086 0-6.29798 3.127471-6.29798 6.513173c0 2.367122 1.635466 3.887819 3.787396 3.887819c1.032926 0 2.33843-.344309 3.05574-1.248119c.157808 .545155 .473424 .932503 .573848 .932503c.071731 0 .086077-.043039 .100423-.043039c.014346-.028692 .129116-.530809 .200847-.789041l.229539-.918157c.11477-.473424 .172154-.674271 .272578-1.104657c.143462-.545155 .172154-.588194 .961195-.60254c.057385 0 .229539 0 .229539-.272578c0-.143462-.143462-.143462-.186501-.143462c-.243885 0-.516463 .028692-.774695 .028692h-.774695c-.60254 0-1.233773-.028692-1.821967-.028692c-.129116 0-.30127 0-.30127 .258232c0 .143462 .11477 .143462 .11477 .157808h.358655c1.133349 0 1.133349 .11477 1.133349 .329963c0 .014346-.272578 1.463312-.545155 1.893698c-.545155 .803387-1.678505 1.133349-2.52493 1.133349c-1.104657 0-2.897932-.573848-2.897932-3.05574c0-.961195 .344309-3.156163 1.73589-4.777283c.90381-1.032926 2.238007-1.73589 3.500472-1.73589c1.692851 0 2.295391 1.448966 2.295391 2.768816c0 .229539-.057385 .545155-.057385 .746002c0 .129116 .143462 .129116 .186501 .129116c.157808 0 .172154-.014346 .229539-.272578l.90381-3.65828z"/>
&lt;path id="g0-72" d="m10.730954-8.751179c.129116-.487771 .157808-.631233 1.176388-.631233c.258232 0 .401693 0 .401693-.258232c0-.157808-.129116-.157808-.215193-.157808c-.258232 0-.559502 .028692-.832079 .028692h-1.692851c-.272578 0-.573848-.028692-.846426-.028692c-.100423 0-.272578 0-.272578 .272578c0 .143462 .100423 .143462 .373001 .143462c.860772 0 .860772 .11477 .860772 .272578c0 .028692 0 .11477-.057385 .329963l-.875118 3.471779h-4.332551l.860772-3.443087c.129116-.487771 .157808-.631233 1.176388-.631233c.258232 0 .401693 0 .401693-.258232c0-.157808-.129116-.157808-.215193-.157808c-.258232 0-.559502 .028692-.832079 .028692h-1.692851c-.272578 0-.573848-.028692-.846426-.028692c-.100423 0-.272578 0-.272578 .272578c0 .143462 .100423 .143462 .373001 .143462c.860772 0 .860772 .11477 .860772 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253c-.129116 .502117-.157808 .645579-1.147696 .645579c-.329963 0-.430386 0-.430386 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.272578 0 .573848 .028692 .846426 .028692c.11477 0 .272578 0 .272578-.272578c0-.143462-.129116-.143462-.344309-.143462c-.875118 0-.875118-.11477-.875118-.258232c0-.014346 0-.11477 .028692-.229539l.989888-3.988242h4.346897c-.243885 .946849-.975541 3.945204-1.004234 4.031281c-.157808 .430386-.387347 .430386-1.233773 .444732c-.172154 0-.30127 0-.30127 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.272578 0 .573848 .028692 .846426 .028692c.11477 0 .272578 0 .272578-.272578c0-.143462-.129116-.143462-.344309-.143462c-.875118 0-.875118-.11477-.875118-.258232c0-.014346 0-.11477 .028692-.229539l1.965429-7.847369z"/>
&lt;path id="g0-73" d="m5.2794-8.736833c.129116-.502117 .157808-.645579 1.20508-.645579c.315616 0 .430386 0 .430386-.272578c0-.143462-.157808-.143462-.200847-.143462c-.258232 0-.573848 .028692-.832079 .028692h-1.764582c-.286924 0-.616886-.028692-.90381-.028692c-.11477 0-.272578 0-.272578 .272578c0 .143462 .11477 .143462 .401693 .143462c.889464 0 .889464 .11477 .889464 .272578c0 .100423-.028692 .186501-.057385 .315616l-1.936736 7.732599c-.129116 .502117-.157808 .645579-1.20508 .645579c-.315616 0-.444732 0-.444732 .272578c0 .143462 .143462 .143462 .215193 .143462c.258232 0 .573848-.028692 .832079-.028692h1.764582c.286924 0 .60254 .028692 .889464 .028692c.11477 0 .286924 0 .286924-.258232c0-.157808-.086077-.157808-.401693-.157808c-.889464 0-.889464-.11477-.889464-.286924c0-.028692 0-.100423 .057385-.329963l1.936736-7.703907z"/>
&lt;path id="g0-88" d="m6.814443-5.824555l-1.348542-3.141817c.186501-.344309 .616886-.401693 .789041-.41604c.086077 0 .243885-.014346 .243885-.258232c0-.157808-.129116-.157808-.215193-.157808c-.243885 0-.530809 .028692-.774695 .028692h-.832079c-.875118 0-1.506351-.028692-1.520697-.028692c-.11477 0-.258232 0-.258232 .272578c0 .143462 .129116 .143462 .315616 .143462c.832079 0 .889464 .143462 1.032926 .487771l1.707197 3.988242l-3.113124 3.328317c-.516463 .559502-1.133349 1.104657-2.194968 1.162042c-.172154 .014346-.286924 .014346-.286924 .272578c0 .043039 .014346 .143462 .172154 .143462c.200847 0 .41604-.028692 .616886-.028692h.674271c.459078 0 .961195 .028692 1.405927 .028692c.100423 0 .272578 0 .272578-.258232c0-.143462-.100423-.157808-.186501-.157808c-.286924-.028692-.473424-.186501-.473424-.41604c0-.243885 .172154-.41604 .588194-.846426l1.276811-1.391581c.315616-.329963 1.075965-1.162042 1.391581-1.477658l1.506351 3.529164c.014346 .028692 .071731 .172154 .071731 .186501c0 .129116-.315616 .387347-.774695 .41604c-.086077 0-.243885 .014346-.243885 .272578c0 .143462 .143462 .143462 .215193 .143462c.243885 0 .530809-.028692 .774695-.028692h1.578082c.258232 0 .530809 .028692 .774695 .028692c.100423 0 .258232 0 .258232-.272578c0-.143462-.143462-.143462-.272578-.143462c-.860772-.014346-.889464-.086077-1.133349-.616886l-1.893698-4.447321l1.821967-1.951083c.143462-.143462 .473424-.502117 .60254-.645579c.616886-.645579 1.190734-1.233773 2.352776-1.305504c.143462-.014346 .286924-.014346 .286924-.258232c0-.157808-.129116-.157808-.186501-.157808c-.200847 0-.41604 .028692-.616886 .028692h-.659925c-.459078 0-.961195-.028692-1.405927-.028692c-.100423 0-.272578 0-.272578 .258232c0 .143462 .100423 .157808 .186501 .157808c.229539 .028692 .473424 .143462 .473424 .41604l-.014346 .028692c-.014346 .100423-.043039 .243885-.200847 .41604l-2.510584 2.697085z"/>
&lt;path id="g0-89" d="m8.435563-8.206024l.329963-.329963c.631233-.645579 1.162042-.803387 1.664159-.846426c.157808-.014346 .286924-.028692 .286924-.272578c0-.143462-.143462-.143462-.172154-.143462c-.172154 0-.358655 .028692-.530809 .028692h-.588194c-.41604 0-.860772-.028692-1.262465-.028692c-.100423 0-.258232 0-.258232 .272578c0 .129116 .143462 .143462 .186501 .143462c.430386 .028692 .430386 .243885 .430386 .329963c0 .157808-.11477 .373001-.401693 .702964l-3.414395 3.916511l-1.62112-4.361243c-.086077-.200847-.086077-.229539-.086077-.258232c0-.30127 .588194-.329963 .760348-.329963s.329963 0 .329963-.258232c0-.157808-.129116-.157808-.215193-.157808c-.243885 0-.530809 .028692-.774695 .028692h-1.592428c-.258232 0-.530809-.028692-.774695-.028692c-.100423 0-.258232 0-.258232 .272578c0 .143462 .129116 .143462 .344309 .143462c.702964 0 .832079 .129116 .961195 .459078l1.778928 4.777283c.014346 .043039 .057385 .200847 .057385 .243885s-.702964 2.869239-.746002 3.012701c-.11477 .387347-.258232 .459078-1.176388 .473424c-.243885 0-.358655 0-.358655 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.258232 0 .559502 .028692 .817733 .028692c.100423 0 .272578 0 .272578-.258232c0-.157808-.100423-.157808-.344309-.157808c-.889464 0-.889464-.100423-.889464-.258232c0-.100423 .11477-.559502 .186501-.846426l.516463-2.065852c.086077-.30127 .086077-.329963 .215193-.473424l3.600895-4.146051z"/>
&lt;path id="g0-90" d="m10.042337-9.35372c.086077-.100423 .157808-.186501 .157808-.329963c0-.100423-.014346-.11477-.344309-.11477h-5.924979c-.329963 0-.344309 .014346-.430386 .272578l-.789041 2.582315c-.043039 .143462-.043039 .172154-.043039 .200847c0 .057385 .043039 .143462 .143462 .143462c.11477 0 .143462-.057385 .200847-.243885c.530809-1.549389 1.233773-2.539277 3.500472-2.539277h2.352776l-7.861715 8.894641c-.129116 .157808-.186501 .215193-.186501 .373001c0 .11477 .071731 .11477 .344309 .11477h6.125826c.329963 0 .344309-.014346 .430386-.272578l1.004234-3.170509c.014346-.043039 .043039-.143462 .043039-.200847c0-.071731-.057385-.143462-.143462-.143462c-.11477 0-.129116 .014346-.243885 .373001c-.60254 1.850659-1.233773 2.969663-3.730011 2.969663h-2.481892l7.876061-8.908988z"/>
&lt;path id="g1-111" d="m6.584904-3.070086c0-1.850659-1.405927-3.328317-3.070086-3.328317c-1.721543 0-3.084432 1.520697-3.084432 3.328317c0 1.836313 1.43462 3.213548 3.070086 3.213548c1.692851 0 3.084432-1.405927 3.084432-3.213548zm-3.070086 2.897932c-.530809 0-1.176388-.229539-1.592428-.932503c-.387347-.645579-.401693-1.492004-.401693-2.094545c0-.545155 0-1.420273 .444732-2.065852c.401693-.616886 1.032926-.846426 1.535043-.846426c.559502 0 1.162042 .258232 1.549389 .817733c.444732 .659925 .444732 1.563735 .444732 2.094545c0 .502117 0 1.391581-.373001 2.065852c-.401693 .688617-1.061618 .961195-1.606774 .961195z"/>
&lt;path id="g1-114" d="m2.395815-3.342664c0-1.391581 .573848-2.697085 1.678505-2.697085c.11477 0 .143462 0 .200847 .014346c-.11477 .057385-.344309 .143462-.344309 .530809c0 .41604 .329963 .573848 .559502 .573848c.286924 0 .573848-.186501 .573848-.573848c0-.430386-.387347-.832079-1.004234-.832079c-1.219427 0-1.635466 1.31985-1.721543 1.592428h-.014346v-1.592428l-1.92239 .157808v.41604c.975541 0 1.090311 .100423 1.090311 .803387v3.887819c0 .645579-.157808 .645579-1.090311 .645579v.41604c.401693-.028692 1.190734-.028692 1.62112-.028692c.387347 0 1.405927 0 1.73589 .028692v-.41604h-.286924c-1.047272 0-1.075965-.157808-1.075965-.674271v-2.252353z"/>
&lt;path id="g1-116" d="m2.410161-5.767171h2.022814v-.41604h-2.022814v-2.6397h-.315616c-.014346 1.348542-.530809 2.725777-1.836313 2.768816v.286924h1.219427v3.988242c0 1.592428 1.061618 1.92239 1.821967 1.92239c.90381 0 1.377235-.889464 1.377235-1.92239v-.817733h-.315616v.789041c0 1.032926-.41604 1.635466-.975541 1.635466c-.975541 0-.975541-1.334196-.975541-1.578082v-4.016935z"/>
&lt;/defs>
&lt;g id="page1">
&lt;path d="m33.324-51.312h32.008v-19.84h-32.008z" fill="none" stroke-width="1.7008" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(412.5205 -279.056)" style="fill: var(--color-fg);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g1-114"/>
&lt;use x="-370.411147" y="222.236073" xlink:href="#g1-111"/>
&lt;use x="-362.997377" y="222.236073" xlink:href="#g1-111"/>
&lt;use x="-355.973792" y="222.236073" xlink:href="#g1-116"/>
&lt;/g>
&lt;path d="m-45.633-8.789h19.844v-19.844h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(333.7686 -236.0462)" style="fill: var(--color-fg);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-88"/>
&lt;/g>
&lt;path d="m32.477-52.805l-57.418 28.711" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m-71.145 33.73h19.84v-19.843h-19.84z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(309.3843 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-65"/>
&lt;/g>
&lt;path d="m-42.176-7.941l-12.59 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m-45.633 33.73h19.844v-19.843h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(334.4639 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-66"/>
&lt;/g>
&lt;path d="m-35.711-7.941v20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m-20.121 33.73h19.844v-19.843h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(360.1336 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-67"/>
&lt;/g>
&lt;path d="m-29.25-7.941l12.59 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m39.406-8.789h19.844v-19.844h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(419.5662 -236.0462)" style="fill: var(--color-fg);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-89"/>
&lt;/g>
&lt;path d="m49.328-50.461v20.977" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m26.652 33.73h19.84v-19.843h-19.84z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(406.4194 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-68"/>
&lt;/g>
&lt;path d="m46.098-7.941l-6.297 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m52.164 33.73h19.84v-19.843h-19.84z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(432.3385 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-69"/>
&lt;/g>
&lt;path d="m52.559-7.941l6.296 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m124.449-8.789h19.84v-19.844h-19.84z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(504.92 -236.0462)" style="fill: var(--color-fg);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-90"/>
&lt;/g>
&lt;path d="m66.18-52.805l57.418 28.711" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m86.18 33.73h19.843v-19.843h-19.843z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(466.4523 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-70"/>
&lt;/g>
&lt;path d="m124.676-7.941l-18.883 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m111.691 33.73h19.844v-19.843h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(491.946 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-71"/>
&lt;/g>
&lt;path d="m131.137-7.941l-6.293 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m137.203 33.73h19.844v-19.843h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(516.625 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-72"/>
&lt;/g>
&lt;path d="m137.602-7.941l6.293 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m162.715 33.73h19.844v-19.843h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(544.849 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-73"/>
&lt;/g>
&lt;path d="m144.063-7.941l18.882 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;/g>
&lt;/svg>
&lt;/div>
&lt;div class="figcaption">
&lt;p>A visualization of the bounding boxes associated with the nodes in the tree, and a visualization of the tree hierarchy.&lt;/p>
&lt;/div>
&lt;p>Note that in bounding volume hierarchies there is nothing preventing sibling nodes from overlapping. While the R-tree insertion procedure does try to minimize overlaps, in most cases it can&amp;rsquo;t completely eliminate them.&lt;/p>
&lt;p>First, let&amp;rsquo;s look at how querying works using an example. We want to find all rectangles that intersect a query rectangle &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>γ&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">\gamma&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.625em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.05556em;">γ&lt;/span>&lt;/span>&lt;/span>&lt;/span>:&lt;/p>
&lt;!-- This file was generated by dvisvgm 2.13.3 -->&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="228.472329pt" height="228.472329pt" viewBox="-72 -72 228.472329 228.472329">
&lt;defs>
&lt;path id="g0-13" d="m5.422862-1.750236c-.028692-.702964-.057385-1.807621-.60254-3.098778c-.286924-.71731-.774695-1.477658-1.821967-1.477658c-1.764582 0-2.725777 2.252353-2.725777 2.625354c0 .129116 .100423 .129116 .143462 .129116c.129116 0 .129116-.028692 .200847-.215193c.30127-.889464 1.219427-1.592428 2.209314-1.592428c1.994121 0 2.281045 2.22366 2.281045 3.643934c0 .90381-.100423 1.20508-.186501 1.492004c-.272578 .889464-.746002 2.668392-.746002 3.070086c0 .11477 .043039 .243885 .157808 .243885c.215193 0 .344309-.473424 .502117-1.047272c.344309-1.262465 .430386-1.893698 .502117-2.467546c.043039-.344309 .860772-2.711431 1.994121-4.963784c.100423-.229539 .30127-.616886 .30127-.659925c0-.014346-.014346-.11477-.143462-.11477c-.028692 0-.100423 0-.129116 .057385c-.028692 .028692-.530809 1.004234-.961195 1.979775c-.215193 .487771-.502117 1.133349-.975541 2.395815z"/>
&lt;path id="g0-65" d="m2.438853-1.592428c-.502117 .846426-.989888 1.133349-1.678505 1.176388c-.157808 .014346-.272578 .014346-.272578 .272578c0 .086077 .071731 .143462 .172154 .143462c.258232 0 .90381-.028692 1.162042-.028692c.41604 0 .875118 .028692 1.276811 .028692c.086077 0 .258232 0 .258232-.272578c0-.129116-.11477-.143462-.200847-.143462c-.329963-.028692-.60254-.143462-.60254-.487771c0-.200847 .086077-.358655 .272578-.674271l1.090311-1.807621h3.65828c.014346 .129116 .014346 .243885 .028692 .373001c.043039 .373001 .215193 1.865005 .215193 2.137583c0 .430386-.731656 .459078-.961195 .459078c-.157808 0-.315616 0-.315616 .258232c0 .157808 .129116 .157808 .215193 .157808c.243885 0 .530809-.028692 .774695-.028692h.817733c.875118 0 1.506351 .028692 1.520697 .028692c.100423 0 .258232 0 .258232-.272578c0-.143462-.129116-.143462-.344309-.143462c-.789041 0-.803387-.129116-.846426-.559502l-.875118-8.952026c-.028692-.286924-.086077-.315616-.243885-.315616c-.143462 0-.229539 .028692-.358655 .243885l-5.021168 8.406871zm1.721543-2.209314l2.883585-4.820322l.487771 4.820322h-3.371356z"/>
&lt;path id="g0-66" d="m5.250708-8.82291c.129116-.530809 .186501-.559502 .746002-.559502h1.865005c1.62112 0 1.62112 1.377235 1.62112 1.506351c0 1.162042-1.162042 2.6397-3.05574 2.6397h-2.065852l.889464-3.586549zm2.424507 3.701318c1.563735-.286924 2.984009-1.377235 2.984009-2.697085c0-1.119003-.989888-1.979775-2.611008-1.979775h-4.605129c-.272578 0-.401693 0-.401693 .272578c0 .143462 .129116 .143462 .344309 .143462c.875118 0 .875118 .11477 .875118 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h4.920745c2.194968 0 3.887819-1.664159 3.887819-3.113124c0-1.176388-1.032926-1.893698-2.194968-2.008467zm-2.03716 4.705552h-1.936736c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l1.004234-4.045627h2.697085c1.692851 0 1.692851 1.578082 1.692851 1.692851c0 1.377235-1.248119 2.840547-3.027047 2.840547z"/>
&lt;path id="g0-67" d="m10.716608-9.970606c0-.129116-.100423-.129116-.129116-.129116s-.086077 0-.200847 .143462l-.989888 1.20508c-.502117-.860772-1.291158-1.348542-2.367122-1.348542c-3.098778 0-6.312326 3.141817-6.312326 6.513173c0 2.395815 1.678505 3.887819 3.773049 3.887819c1.147696 0 2.151929-.487771 2.984009-1.190734c1.248119-1.047272 1.62112-2.438853 1.62112-2.553623c0-.129116-.11477-.129116-.157808-.129116c-.129116 0-.143462 .086077-.172154 .143462c-.659925 2.238007-2.596661 3.313971-4.031281 3.313971c-1.520697 0-2.840547-.975541-2.840547-3.012701c0-.459078 .143462-2.955316 1.764582-4.834668c.789041-.918157 2.137583-1.721543 3.500472-1.721543c1.578082 0 2.281045 1.305504 2.281045 2.768816c0 .373001-.043039 .688617-.043039 .746002c0 .129116 .143462 .129116 .186501 .129116c.157808 0 .172154-.014346 .229539-.272578l.90381-3.65828z"/>
&lt;path id="g0-68" d="m2.252353-1.061618c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h4.547744c2.897932 0 5.724132-2.998355 5.724132-6.197557c0-2.065852-1.233773-3.600895-3.285279-3.600895h-4.605129c-.272578 0-.401693 0-.401693 .272578c0 .143462 .129116 .143462 .344309 .143462c.875118 0 .875118 .11477 .875118 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253zm3.027047-7.761292c.129116-.530809 .186501-.559502 .746002-.559502h1.578082c1.348542 0 2.582315 .731656 2.582315 2.711431c0 .71731-.286924 3.213548-1.678505 4.791629c-.401693 .473424-1.492004 1.463312-3.141817 1.463312h-1.635466c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l1.979775-7.9191z"/>
&lt;path id="g0-69" d="m9.970606-3.328317c.014346-.043039 .057385-.143462 .057385-.200847c0-.071731-.057385-.143462-.143462-.143462c-.057385 0-.086077 .014346-.129116 .057385c-.028692 .014346-.028692 .043039-.157808 .329963c-.846426 2.008467-1.463312 2.869239-3.758703 2.869239h-2.094545c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l.989888-3.95955h1.420273c1.119003 0 1.20508 .243885 1.20508 .674271c0 .143462 0 .272578-.100423 .702964c-.028692 .057385-.043039 .11477-.043039 .157808c0 .100423 .071731 .143462 .157808 .143462c.129116 0 .143462-.100423 .200847-.30127l.817733-3.328317c0-.071731-.057385-.143462-.143462-.143462c-.129116 0-.143462 .057385-.200847 .258232c-.286924 1.104657-.573848 1.420273-1.850659 1.420273h-1.362889l.889464-3.529164c.129116-.502117 .157808-.545155 .746002-.545155h2.051506c1.764582 0 2.123237 .473424 2.123237 1.563735c0 .014346 0 .41604-.057385 .889464c-.014346 .057385-.028692 .143462-.028692 .172154c0 .11477 .071731 .157808 .157808 .157808c.100423 0 .157808-.057385 .186501-.315616l.30127-2.510584c0-.043039 .028692-.186501 .028692-.215193c0-.157808-.129116-.157808-.387347-.157808h-7.000943c-.272578 0-.41604 0-.41604 .258232c0 .157808 .100423 .157808 .344309 .157808c.889464 0 .889464 .100423 .889464 .258232c0 .071731-.014346 .129116-.057385 .286924l-1.936736 7.746946c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h7.20179c.315616 0 .329963-.014346 .430386-.243885l1.305504-3.084432z"/>
&lt;path id="g0-70" d="m4.26082-4.67686h1.377235c1.090311 0 1.176388 .243885 1.176388 .659925c0 .186501-.028692 .387347-.100423 .702964c-.028692 .057385-.043039 .129116-.043039 .157808c0 .100423 .057385 .157808 .157808 .157808c.11477 0 .129116-.057385 .186501-.286924l.832079-3.342664c0-.057385-.043039-.143462-.143462-.143462c-.129116 0-.143462 .057385-.200847 .30127c-.30127 1.075965-.588194 1.377235-1.836313 1.377235h-1.305504l.932503-3.715665c.129116-.502117 .157808-.545155 .746002-.545155h1.92239c1.793274 0 2.051506 .530809 2.051506 1.549389c0 .086077 0 .401693-.043039 .774695c-.014346 .057385-.043039 .243885-.043039 .30127c0 .11477 .071731 .157808 .157808 .157808c.100423 0 .157808-.057385 .186501-.315616l.30127-2.510584c0-.043039 .028692-.186501 .028692-.215193c0-.157808-.129116-.157808-.387347-.157808h-6.800097c-.272578 0-.41604 0-.41604 .258232c0 .157808 .100423 .157808 .344309 .157808c.889464 0 .889464 .100423 .889464 .258232c0 .071731-.014346 .129116-.057385 .286924l-1.936736 7.746946c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .129116 .157808 .215193 .157808c.272578 0 .559502-.028692 .832079-.028692h1.865005c.315616 0 .659925 .028692 .975541 .028692c.129116 0 .30127 0 .30127-.258232c0-.157808-.086077-.157808-.401693-.157808c-1.133349 0-1.162042-.100423-1.162042-.315616c0-.071731 .028692-.186501 .057385-.286924l.918157-3.65828z"/>
&lt;path id="g0-71" d="m10.702262-9.970606c0-.129116-.100423-.129116-.129116-.129116s-.086077 0-.200847 .143462l-.989888 1.190734c-.071731-.11477-.358655-.616886-.918157-.946849c-.616886-.387347-1.233773-.387347-1.448966-.387347c-3.070086 0-6.29798 3.127471-6.29798 6.513173c0 2.367122 1.635466 3.887819 3.787396 3.887819c1.032926 0 2.33843-.344309 3.05574-1.248119c.157808 .545155 .473424 .932503 .573848 .932503c.071731 0 .086077-.043039 .100423-.043039c.014346-.028692 .129116-.530809 .200847-.789041l.229539-.918157c.11477-.473424 .172154-.674271 .272578-1.104657c.143462-.545155 .172154-.588194 .961195-.60254c.057385 0 .229539 0 .229539-.272578c0-.143462-.143462-.143462-.186501-.143462c-.243885 0-.516463 .028692-.774695 .028692h-.774695c-.60254 0-1.233773-.028692-1.821967-.028692c-.129116 0-.30127 0-.30127 .258232c0 .143462 .11477 .143462 .11477 .157808h.358655c1.133349 0 1.133349 .11477 1.133349 .329963c0 .014346-.272578 1.463312-.545155 1.893698c-.545155 .803387-1.678505 1.133349-2.52493 1.133349c-1.104657 0-2.897932-.573848-2.897932-3.05574c0-.961195 .344309-3.156163 1.73589-4.777283c.90381-1.032926 2.238007-1.73589 3.500472-1.73589c1.692851 0 2.295391 1.448966 2.295391 2.768816c0 .229539-.057385 .545155-.057385 .746002c0 .129116 .143462 .129116 .186501 .129116c.157808 0 .172154-.014346 .229539-.272578l.90381-3.65828z"/>
&lt;path id="g0-72" d="m10.730954-8.751179c.129116-.487771 .157808-.631233 1.176388-.631233c.258232 0 .401693 0 .401693-.258232c0-.157808-.129116-.157808-.215193-.157808c-.258232 0-.559502 .028692-.832079 .028692h-1.692851c-.272578 0-.573848-.028692-.846426-.028692c-.100423 0-.272578 0-.272578 .272578c0 .143462 .100423 .143462 .373001 .143462c.860772 0 .860772 .11477 .860772 .272578c0 .028692 0 .11477-.057385 .329963l-.875118 3.471779h-4.332551l.860772-3.443087c.129116-.487771 .157808-.631233 1.176388-.631233c.258232 0 .401693 0 .401693-.258232c0-.157808-.129116-.157808-.215193-.157808c-.258232 0-.559502 .028692-.832079 .028692h-1.692851c-.272578 0-.573848-.028692-.846426-.028692c-.100423 0-.272578 0-.272578 .272578c0 .143462 .100423 .143462 .373001 .143462c.860772 0 .860772 .11477 .860772 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253c-.129116 .502117-.157808 .645579-1.147696 .645579c-.329963 0-.430386 0-.430386 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.272578 0 .573848 .028692 .846426 .028692c.11477 0 .272578 0 .272578-.272578c0-.143462-.129116-.143462-.344309-.143462c-.875118 0-.875118-.11477-.875118-.258232c0-.014346 0-.11477 .028692-.229539l.989888-3.988242h4.346897c-.243885 .946849-.975541 3.945204-1.004234 4.031281c-.157808 .430386-.387347 .430386-1.233773 .444732c-.172154 0-.30127 0-.30127 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.272578 0 .573848 .028692 .846426 .028692c.11477 0 .272578 0 .272578-.272578c0-.143462-.129116-.143462-.344309-.143462c-.875118 0-.875118-.11477-.875118-.258232c0-.014346 0-.11477 .028692-.229539l1.965429-7.847369z"/>
&lt;path id="g0-73" d="m5.2794-8.736833c.129116-.502117 .157808-.645579 1.20508-.645579c.315616 0 .430386 0 .430386-.272578c0-.143462-.157808-.143462-.200847-.143462c-.258232 0-.573848 .028692-.832079 .028692h-1.764582c-.286924 0-.616886-.028692-.90381-.028692c-.11477 0-.272578 0-.272578 .272578c0 .143462 .11477 .143462 .401693 .143462c.889464 0 .889464 .11477 .889464 .272578c0 .100423-.028692 .186501-.057385 .315616l-1.936736 7.732599c-.129116 .502117-.157808 .645579-1.20508 .645579c-.315616 0-.444732 0-.444732 .272578c0 .143462 .143462 .143462 .215193 .143462c.258232 0 .573848-.028692 .832079-.028692h1.764582c.286924 0 .60254 .028692 .889464 .028692c.11477 0 .286924 0 .286924-.258232c0-.157808-.086077-.157808-.401693-.157808c-.889464 0-.889464-.11477-.889464-.286924c0-.028692 0-.100423 .057385-.329963l1.936736-7.703907z"/>
&lt;path id="g0-88" d="m6.814443-5.824555l-1.348542-3.141817c.186501-.344309 .616886-.401693 .789041-.41604c.086077 0 .243885-.014346 .243885-.258232c0-.157808-.129116-.157808-.215193-.157808c-.243885 0-.530809 .028692-.774695 .028692h-.832079c-.875118 0-1.506351-.028692-1.520697-.028692c-.11477 0-.258232 0-.258232 .272578c0 .143462 .129116 .143462 .315616 .143462c.832079 0 .889464 .143462 1.032926 .487771l1.707197 3.988242l-3.113124 3.328317c-.516463 .559502-1.133349 1.104657-2.194968 1.162042c-.172154 .014346-.286924 .014346-.286924 .272578c0 .043039 .014346 .143462 .172154 .143462c.200847 0 .41604-.028692 .616886-.028692h.674271c.459078 0 .961195 .028692 1.405927 .028692c.100423 0 .272578 0 .272578-.258232c0-.143462-.100423-.157808-.186501-.157808c-.286924-.028692-.473424-.186501-.473424-.41604c0-.243885 .172154-.41604 .588194-.846426l1.276811-1.391581c.315616-.329963 1.075965-1.162042 1.391581-1.477658l1.506351 3.529164c.014346 .028692 .071731 .172154 .071731 .186501c0 .129116-.315616 .387347-.774695 .41604c-.086077 0-.243885 .014346-.243885 .272578c0 .143462 .143462 .143462 .215193 .143462c.243885 0 .530809-.028692 .774695-.028692h1.578082c.258232 0 .530809 .028692 .774695 .028692c.100423 0 .258232 0 .258232-.272578c0-.143462-.143462-.143462-.272578-.143462c-.860772-.014346-.889464-.086077-1.133349-.616886l-1.893698-4.447321l1.821967-1.951083c.143462-.143462 .473424-.502117 .60254-.645579c.616886-.645579 1.190734-1.233773 2.352776-1.305504c.143462-.014346 .286924-.014346 .286924-.258232c0-.157808-.129116-.157808-.186501-.157808c-.200847 0-.41604 .028692-.616886 .028692h-.659925c-.459078 0-.961195-.028692-1.405927-.028692c-.100423 0-.272578 0-.272578 .258232c0 .143462 .100423 .157808 .186501 .157808c.229539 .028692 .473424 .143462 .473424 .41604l-.014346 .028692c-.014346 .100423-.043039 .243885-.200847 .41604l-2.510584 2.697085z"/>
&lt;path id="g0-89" d="m8.435563-8.206024l.329963-.329963c.631233-.645579 1.162042-.803387 1.664159-.846426c.157808-.014346 .286924-.028692 .286924-.272578c0-.143462-.143462-.143462-.172154-.143462c-.172154 0-.358655 .028692-.530809 .028692h-.588194c-.41604 0-.860772-.028692-1.262465-.028692c-.100423 0-.258232 0-.258232 .272578c0 .129116 .143462 .143462 .186501 .143462c.430386 .028692 .430386 .243885 .430386 .329963c0 .157808-.11477 .373001-.401693 .702964l-3.414395 3.916511l-1.62112-4.361243c-.086077-.200847-.086077-.229539-.086077-.258232c0-.30127 .588194-.329963 .760348-.329963s.329963 0 .329963-.258232c0-.157808-.129116-.157808-.215193-.157808c-.243885 0-.530809 .028692-.774695 .028692h-1.592428c-.258232 0-.530809-.028692-.774695-.028692c-.100423 0-.258232 0-.258232 .272578c0 .143462 .129116 .143462 .344309 .143462c.702964 0 .832079 .129116 .961195 .459078l1.778928 4.777283c.014346 .043039 .057385 .200847 .057385 .243885s-.702964 2.869239-.746002 3.012701c-.11477 .387347-.258232 .459078-1.176388 .473424c-.243885 0-.358655 0-.358655 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.258232 0 .559502 .028692 .817733 .028692c.100423 0 .272578 0 .272578-.258232c0-.157808-.100423-.157808-.344309-.157808c-.889464 0-.889464-.100423-.889464-.258232c0-.100423 .11477-.559502 .186501-.846426l.516463-2.065852c.086077-.30127 .086077-.329963 .215193-.473424l3.600895-4.146051z"/>
&lt;path id="g0-90" d="m10.042337-9.35372c.086077-.100423 .157808-.186501 .157808-.329963c0-.100423-.014346-.11477-.344309-.11477h-5.924979c-.329963 0-.344309 .014346-.430386 .272578l-.789041 2.582315c-.043039 .143462-.043039 .172154-.043039 .200847c0 .057385 .043039 .143462 .143462 .143462c.11477 0 .143462-.057385 .200847-.243885c.530809-1.549389 1.233773-2.539277 3.500472-2.539277h2.352776l-7.861715 8.894641c-.129116 .157808-.186501 .215193-.186501 .373001c0 .11477 .071731 .11477 .344309 .11477h6.125826c.329963 0 .344309-.014346 .430386-.272578l1.004234-3.170509c.014346-.043039 .043039-.143462 .043039-.200847c0-.071731-.057385-.143462-.143462-.143462c-.11477 0-.129116 .014346-.243885 .373001c-.60254 1.850659-1.233773 2.969663-3.730011 2.969663h-2.481892l7.876061-8.908988z"/>
&lt;/defs>
&lt;g id="page1">
&lt;path d="m-71.1484 155.6211v-226.7731h226.7733v226.7731h-226.7733z" fill="none" stroke-width="1.7008" style="stroke: var(--color-fg);"/>
&lt;path d="m-65.4805 149.9531v-107.7191h107.7184v107.7191h-107.7184z" fill="none" stroke-width="1.7008" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(38.187 -127.7597)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-88"/>
&lt;/g>
&lt;path d="m-59.8125 144.2812v-45.3554h19.8438v45.3554h-19.8438z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(43.8563 -71.066)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-65"/>
&lt;/g>
&lt;path d="m-34.2969 141.4492v-56.6953h48.1878v56.6953h-48.1878z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(69.3687 -85.2395)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-66"/>
&lt;/g>
&lt;path d="m-14.457 127.2734v-79.3714h51.0269v79.3714h-51.0269z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(89.2114 -122.0904)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-67"/>
&lt;/g>
&lt;path d="m-65.4805 13.887v-79.371h79.3714v79.371h-79.3714z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(38.187 -235.4777)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-89"/>
&lt;/g>
&lt;path d="m-59.8125 8.219v-28.348h45.3555v28.348h-45.3555z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(43.8563 -190.1226)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-68"/>
&lt;/g>
&lt;path d="m-14.457-37.137v-22.679h22.6799v22.679h-22.6799z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(89.2114 -229.8084)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-69"/>
&lt;/g>
&lt;path d="m-42.8008 70.582v-113.387h192.7577v113.387h-192.7577z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(60.8646 -212.8001)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-90"/>
&lt;/g>
&lt;path d="m-37.1328 64.91v-79.371h87.8747v79.371h-87.8747z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(66.5339 -184.453336)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-70"/>
&lt;/g>
&lt;path d="m113.1059-.285v-36.852h31.179v36.852h-31.179z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(216.7721 -207.1309)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-71"/>
&lt;/g>
&lt;path d="m98.9299 42.234v-28.347h28.347v28.347h-28.347z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(202.5991 -156.1065)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-72"/>
&lt;/g>
&lt;path d="m70.5859-.285v-22.68h28.344v22.68h-28.344z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(174.2518 -192.95746)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-73"/>
&lt;/g>
&lt;path d="m-28.6289 79.086v-56.695h56.6958v56.695h-56.6958z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-keyword);"/>
&lt;g transform="translate(75.038 -151.2288)" style="fill: var(--color-keyword);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-13"/>
&lt;/g>
&lt;/g>
&lt;/svg>
&lt;p>First we check whether it intersects the root node, which it does in this case. Next, we look at the children of the root node. &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>γ&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">\gamma&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.625em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.05556em;">γ&lt;/span>&lt;/span>&lt;/span>&lt;/span> intersects &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>X&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">X&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.07847em;">X&lt;/span>&lt;/span>&lt;/span>&lt;/span> and &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>Z&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">Z&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.07153em;">Z&lt;/span>&lt;/span>&lt;/span>&lt;/span>, but it does not intersect &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>Y&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">Y&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.22222em;">Y&lt;/span>&lt;/span>&lt;/span>&lt;/span>. Since all descendants of &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>Y&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">Y&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.22222em;">Y&lt;/span>&lt;/span>&lt;/span>&lt;/span> are completely contained within &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>Y&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">Y&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.22222em;">Y&lt;/span>&lt;/span>&lt;/span>&lt;/span>, we can be sure that no descendant of &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>Y&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">Y&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.22222em;">Y&lt;/span>&lt;/span>&lt;/span>&lt;/span> intersects &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>γ&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">\gamma&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.625em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.05556em;">γ&lt;/span>&lt;/span>&lt;/span>&lt;/span>, and can completely skip searching its subtree. The same search procedure is now repeated recursively for &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>X&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">X&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.07847em;">X&lt;/span>&lt;/span>&lt;/span>&lt;/span> and &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>Z&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">Z&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.07153em;">Z&lt;/span>&lt;/span>&lt;/span>&lt;/span>. In the end, we find that the rectangles intersecting &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>γ&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">\gamma&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.625em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.05556em;">γ&lt;/span>&lt;/span>&lt;/span>&lt;/span> were &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>C&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">C&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.07153em;">C&lt;/span>&lt;/span>&lt;/span>&lt;/span> and &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>F&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">F&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.13889em;">F&lt;/span>&lt;/span>&lt;/span>&lt;/span>. Here is a visualization of how we searched the tree:&lt;/p>
&lt;!-- This file was generated by dvisvgm 2.13.3 -->&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="255.401494pt" height="106.582615pt" viewBox="-72 -72 255.401494 106.582615">
&lt;defs>
&lt;path id="g0-65" d="m2.438853-1.592428c-.502117 .846426-.989888 1.133349-1.678505 1.176388c-.157808 .014346-.272578 .014346-.272578 .272578c0 .086077 .071731 .143462 .172154 .143462c.258232 0 .90381-.028692 1.162042-.028692c.41604 0 .875118 .028692 1.276811 .028692c.086077 0 .258232 0 .258232-.272578c0-.129116-.11477-.143462-.200847-.143462c-.329963-.028692-.60254-.143462-.60254-.487771c0-.200847 .086077-.358655 .272578-.674271l1.090311-1.807621h3.65828c.014346 .129116 .014346 .243885 .028692 .373001c.043039 .373001 .215193 1.865005 .215193 2.137583c0 .430386-.731656 .459078-.961195 .459078c-.157808 0-.315616 0-.315616 .258232c0 .157808 .129116 .157808 .215193 .157808c.243885 0 .530809-.028692 .774695-.028692h.817733c.875118 0 1.506351 .028692 1.520697 .028692c.100423 0 .258232 0 .258232-.272578c0-.143462-.129116-.143462-.344309-.143462c-.789041 0-.803387-.129116-.846426-.559502l-.875118-8.952026c-.028692-.286924-.086077-.315616-.243885-.315616c-.143462 0-.229539 .028692-.358655 .243885l-5.021168 8.406871zm1.721543-2.209314l2.883585-4.820322l.487771 4.820322h-3.371356z"/>
&lt;path id="g0-66" d="m5.250708-8.82291c.129116-.530809 .186501-.559502 .746002-.559502h1.865005c1.62112 0 1.62112 1.377235 1.62112 1.506351c0 1.162042-1.162042 2.6397-3.05574 2.6397h-2.065852l.889464-3.586549zm2.424507 3.701318c1.563735-.286924 2.984009-1.377235 2.984009-2.697085c0-1.119003-.989888-1.979775-2.611008-1.979775h-4.605129c-.272578 0-.401693 0-.401693 .272578c0 .143462 .129116 .143462 .344309 .143462c.875118 0 .875118 .11477 .875118 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h4.920745c2.194968 0 3.887819-1.664159 3.887819-3.113124c0-1.176388-1.032926-1.893698-2.194968-2.008467zm-2.03716 4.705552h-1.936736c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l1.004234-4.045627h2.697085c1.692851 0 1.692851 1.578082 1.692851 1.692851c0 1.377235-1.248119 2.840547-3.027047 2.840547z"/>
&lt;path id="g0-67" d="m10.716608-9.970606c0-.129116-.100423-.129116-.129116-.129116s-.086077 0-.200847 .143462l-.989888 1.20508c-.502117-.860772-1.291158-1.348542-2.367122-1.348542c-3.098778 0-6.312326 3.141817-6.312326 6.513173c0 2.395815 1.678505 3.887819 3.773049 3.887819c1.147696 0 2.151929-.487771 2.984009-1.190734c1.248119-1.047272 1.62112-2.438853 1.62112-2.553623c0-.129116-.11477-.129116-.157808-.129116c-.129116 0-.143462 .086077-.172154 .143462c-.659925 2.238007-2.596661 3.313971-4.031281 3.313971c-1.520697 0-2.840547-.975541-2.840547-3.012701c0-.459078 .143462-2.955316 1.764582-4.834668c.789041-.918157 2.137583-1.721543 3.500472-1.721543c1.578082 0 2.281045 1.305504 2.281045 2.768816c0 .373001-.043039 .688617-.043039 .746002c0 .129116 .143462 .129116 .186501 .129116c.157808 0 .172154-.014346 .229539-.272578l.90381-3.65828z"/>
&lt;path id="g0-68" d="m2.252353-1.061618c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h4.547744c2.897932 0 5.724132-2.998355 5.724132-6.197557c0-2.065852-1.233773-3.600895-3.285279-3.600895h-4.605129c-.272578 0-.401693 0-.401693 .272578c0 .143462 .129116 .143462 .344309 .143462c.875118 0 .875118 .11477 .875118 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253zm3.027047-7.761292c.129116-.530809 .186501-.559502 .746002-.559502h1.578082c1.348542 0 2.582315 .731656 2.582315 2.711431c0 .71731-.286924 3.213548-1.678505 4.791629c-.401693 .473424-1.492004 1.463312-3.141817 1.463312h-1.635466c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l1.979775-7.9191z"/>
&lt;path id="g0-69" d="m9.970606-3.328317c.014346-.043039 .057385-.143462 .057385-.200847c0-.071731-.057385-.143462-.143462-.143462c-.057385 0-.086077 .014346-.129116 .057385c-.028692 .014346-.028692 .043039-.157808 .329963c-.846426 2.008467-1.463312 2.869239-3.758703 2.869239h-2.094545c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l.989888-3.95955h1.420273c1.119003 0 1.20508 .243885 1.20508 .674271c0 .143462 0 .272578-.100423 .702964c-.028692 .057385-.043039 .11477-.043039 .157808c0 .100423 .071731 .143462 .157808 .143462c.129116 0 .143462-.100423 .200847-.30127l.817733-3.328317c0-.071731-.057385-.143462-.143462-.143462c-.129116 0-.143462 .057385-.200847 .258232c-.286924 1.104657-.573848 1.420273-1.850659 1.420273h-1.362889l.889464-3.529164c.129116-.502117 .157808-.545155 .746002-.545155h2.051506c1.764582 0 2.123237 .473424 2.123237 1.563735c0 .014346 0 .41604-.057385 .889464c-.014346 .057385-.028692 .143462-.028692 .172154c0 .11477 .071731 .157808 .157808 .157808c.100423 0 .157808-.057385 .186501-.315616l.30127-2.510584c0-.043039 .028692-.186501 .028692-.215193c0-.157808-.129116-.157808-.387347-.157808h-7.000943c-.272578 0-.41604 0-.41604 .258232c0 .157808 .100423 .157808 .344309 .157808c.889464 0 .889464 .100423 .889464 .258232c0 .071731-.014346 .129116-.057385 .286924l-1.936736 7.746946c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h7.20179c.315616 0 .329963-.014346 .430386-.243885l1.305504-3.084432z"/>
&lt;path id="g0-70" d="m4.26082-4.67686h1.377235c1.090311 0 1.176388 .243885 1.176388 .659925c0 .186501-.028692 .387347-.100423 .702964c-.028692 .057385-.043039 .129116-.043039 .157808c0 .100423 .057385 .157808 .157808 .157808c.11477 0 .129116-.057385 .186501-.286924l.832079-3.342664c0-.057385-.043039-.143462-.143462-.143462c-.129116 0-.143462 .057385-.200847 .30127c-.30127 1.075965-.588194 1.377235-1.836313 1.377235h-1.305504l.932503-3.715665c.129116-.502117 .157808-.545155 .746002-.545155h1.92239c1.793274 0 2.051506 .530809 2.051506 1.549389c0 .086077 0 .401693-.043039 .774695c-.014346 .057385-.043039 .243885-.043039 .30127c0 .11477 .071731 .157808 .157808 .157808c.100423 0 .157808-.057385 .186501-.315616l.30127-2.510584c0-.043039 .028692-.186501 .028692-.215193c0-.157808-.129116-.157808-.387347-.157808h-6.800097c-.272578 0-.41604 0-.41604 .258232c0 .157808 .100423 .157808 .344309 .157808c.889464 0 .889464 .100423 .889464 .258232c0 .071731-.014346 .129116-.057385 .286924l-1.936736 7.746946c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .129116 .157808 .215193 .157808c.272578 0 .559502-.028692 .832079-.028692h1.865005c.315616 0 .659925 .028692 .975541 .028692c.129116 0 .30127 0 .30127-.258232c0-.157808-.086077-.157808-.401693-.157808c-1.133349 0-1.162042-.100423-1.162042-.315616c0-.071731 .028692-.186501 .057385-.286924l.918157-3.65828z"/>
&lt;path id="g0-71" d="m10.702262-9.970606c0-.129116-.100423-.129116-.129116-.129116s-.086077 0-.200847 .143462l-.989888 1.190734c-.071731-.11477-.358655-.616886-.918157-.946849c-.616886-.387347-1.233773-.387347-1.448966-.387347c-3.070086 0-6.29798 3.127471-6.29798 6.513173c0 2.367122 1.635466 3.887819 3.787396 3.887819c1.032926 0 2.33843-.344309 3.05574-1.248119c.157808 .545155 .473424 .932503 .573848 .932503c.071731 0 .086077-.043039 .100423-.043039c.014346-.028692 .129116-.530809 .200847-.789041l.229539-.918157c.11477-.473424 .172154-.674271 .272578-1.104657c.143462-.545155 .172154-.588194 .961195-.60254c.057385 0 .229539 0 .229539-.272578c0-.143462-.143462-.143462-.186501-.143462c-.243885 0-.516463 .028692-.774695 .028692h-.774695c-.60254 0-1.233773-.028692-1.821967-.028692c-.129116 0-.30127 0-.30127 .258232c0 .143462 .11477 .143462 .11477 .157808h.358655c1.133349 0 1.133349 .11477 1.133349 .329963c0 .014346-.272578 1.463312-.545155 1.893698c-.545155 .803387-1.678505 1.133349-2.52493 1.133349c-1.104657 0-2.897932-.573848-2.897932-3.05574c0-.961195 .344309-3.156163 1.73589-4.777283c.90381-1.032926 2.238007-1.73589 3.500472-1.73589c1.692851 0 2.295391 1.448966 2.295391 2.768816c0 .229539-.057385 .545155-.057385 .746002c0 .129116 .143462 .129116 .186501 .129116c.157808 0 .172154-.014346 .229539-.272578l.90381-3.65828z"/>
&lt;path id="g0-72" d="m10.730954-8.751179c.129116-.487771 .157808-.631233 1.176388-.631233c.258232 0 .401693 0 .401693-.258232c0-.157808-.129116-.157808-.215193-.157808c-.258232 0-.559502 .028692-.832079 .028692h-1.692851c-.272578 0-.573848-.028692-.846426-.028692c-.100423 0-.272578 0-.272578 .272578c0 .143462 .100423 .143462 .373001 .143462c.860772 0 .860772 .11477 .860772 .272578c0 .028692 0 .11477-.057385 .329963l-.875118 3.471779h-4.332551l.860772-3.443087c.129116-.487771 .157808-.631233 1.176388-.631233c.258232 0 .401693 0 .401693-.258232c0-.157808-.129116-.157808-.215193-.157808c-.258232 0-.559502 .028692-.832079 .028692h-1.692851c-.272578 0-.573848-.028692-.846426-.028692c-.100423 0-.272578 0-.272578 .272578c0 .143462 .100423 .143462 .373001 .143462c.860772 0 .860772 .11477 .860772 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253c-.129116 .502117-.157808 .645579-1.147696 .645579c-.329963 0-.430386 0-.430386 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.272578 0 .573848 .028692 .846426 .028692c.11477 0 .272578 0 .272578-.272578c0-.143462-.129116-.143462-.344309-.143462c-.875118 0-.875118-.11477-.875118-.258232c0-.014346 0-.11477 .028692-.229539l.989888-3.988242h4.346897c-.243885 .946849-.975541 3.945204-1.004234 4.031281c-.157808 .430386-.387347 .430386-1.233773 .444732c-.172154 0-.30127 0-.30127 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.272578 0 .573848 .028692 .846426 .028692c.11477 0 .272578 0 .272578-.272578c0-.143462-.129116-.143462-.344309-.143462c-.875118 0-.875118-.11477-.875118-.258232c0-.014346 0-.11477 .028692-.229539l1.965429-7.847369z"/>
&lt;path id="g0-73" d="m5.2794-8.736833c.129116-.502117 .157808-.645579 1.20508-.645579c.315616 0 .430386 0 .430386-.272578c0-.143462-.157808-.143462-.200847-.143462c-.258232 0-.573848 .028692-.832079 .028692h-1.764582c-.286924 0-.616886-.028692-.90381-.028692c-.11477 0-.272578 0-.272578 .272578c0 .143462 .11477 .143462 .401693 .143462c.889464 0 .889464 .11477 .889464 .272578c0 .100423-.028692 .186501-.057385 .315616l-1.936736 7.732599c-.129116 .502117-.157808 .645579-1.20508 .645579c-.315616 0-.444732 0-.444732 .272578c0 .143462 .143462 .143462 .215193 .143462c.258232 0 .573848-.028692 .832079-.028692h1.764582c.286924 0 .60254 .028692 .889464 .028692c.11477 0 .286924 0 .286924-.258232c0-.157808-.086077-.157808-.401693-.157808c-.889464 0-.889464-.11477-.889464-.286924c0-.028692 0-.100423 .057385-.329963l1.936736-7.703907z"/>
&lt;path id="g0-88" d="m6.814443-5.824555l-1.348542-3.141817c.186501-.344309 .616886-.401693 .789041-.41604c.086077 0 .243885-.014346 .243885-.258232c0-.157808-.129116-.157808-.215193-.157808c-.243885 0-.530809 .028692-.774695 .028692h-.832079c-.875118 0-1.506351-.028692-1.520697-.028692c-.11477 0-.258232 0-.258232 .272578c0 .143462 .129116 .143462 .315616 .143462c.832079 0 .889464 .143462 1.032926 .487771l1.707197 3.988242l-3.113124 3.328317c-.516463 .559502-1.133349 1.104657-2.194968 1.162042c-.172154 .014346-.286924 .014346-.286924 .272578c0 .043039 .014346 .143462 .172154 .143462c.200847 0 .41604-.028692 .616886-.028692h.674271c.459078 0 .961195 .028692 1.405927 .028692c.100423 0 .272578 0 .272578-.258232c0-.143462-.100423-.157808-.186501-.157808c-.286924-.028692-.473424-.186501-.473424-.41604c0-.243885 .172154-.41604 .588194-.846426l1.276811-1.391581c.315616-.329963 1.075965-1.162042 1.391581-1.477658l1.506351 3.529164c.014346 .028692 .071731 .172154 .071731 .186501c0 .129116-.315616 .387347-.774695 .41604c-.086077 0-.243885 .014346-.243885 .272578c0 .143462 .143462 .143462 .215193 .143462c.243885 0 .530809-.028692 .774695-.028692h1.578082c.258232 0 .530809 .028692 .774695 .028692c.100423 0 .258232 0 .258232-.272578c0-.143462-.143462-.143462-.272578-.143462c-.860772-.014346-.889464-.086077-1.133349-.616886l-1.893698-4.447321l1.821967-1.951083c.143462-.143462 .473424-.502117 .60254-.645579c.616886-.645579 1.190734-1.233773 2.352776-1.305504c.143462-.014346 .286924-.014346 .286924-.258232c0-.157808-.129116-.157808-.186501-.157808c-.200847 0-.41604 .028692-.616886 .028692h-.659925c-.459078 0-.961195-.028692-1.405927-.028692c-.100423 0-.272578 0-.272578 .258232c0 .143462 .100423 .157808 .186501 .157808c.229539 .028692 .473424 .143462 .473424 .41604l-.014346 .028692c-.014346 .100423-.043039 .243885-.200847 .41604l-2.510584 2.697085z"/>
&lt;path id="g0-89" d="m8.435563-8.206024l.329963-.329963c.631233-.645579 1.162042-.803387 1.664159-.846426c.157808-.014346 .286924-.028692 .286924-.272578c0-.143462-.143462-.143462-.172154-.143462c-.172154 0-.358655 .028692-.530809 .028692h-.588194c-.41604 0-.860772-.028692-1.262465-.028692c-.100423 0-.258232 0-.258232 .272578c0 .129116 .143462 .143462 .186501 .143462c.430386 .028692 .430386 .243885 .430386 .329963c0 .157808-.11477 .373001-.401693 .702964l-3.414395 3.916511l-1.62112-4.361243c-.086077-.200847-.086077-.229539-.086077-.258232c0-.30127 .588194-.329963 .760348-.329963s.329963 0 .329963-.258232c0-.157808-.129116-.157808-.215193-.157808c-.243885 0-.530809 .028692-.774695 .028692h-1.592428c-.258232 0-.530809-.028692-.774695-.028692c-.100423 0-.258232 0-.258232 .272578c0 .143462 .129116 .143462 .344309 .143462c.702964 0 .832079 .129116 .961195 .459078l1.778928 4.777283c.014346 .043039 .057385 .200847 .057385 .243885s-.702964 2.869239-.746002 3.012701c-.11477 .387347-.258232 .459078-1.176388 .473424c-.243885 0-.358655 0-.358655 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.258232 0 .559502 .028692 .817733 .028692c.100423 0 .272578 0 .272578-.258232c0-.157808-.100423-.157808-.344309-.157808c-.889464 0-.889464-.100423-.889464-.258232c0-.100423 .11477-.559502 .186501-.846426l.516463-2.065852c.086077-.30127 .086077-.329963 .215193-.473424l3.600895-4.146051z"/>
&lt;path id="g0-90" d="m10.042337-9.35372c.086077-.100423 .157808-.186501 .157808-.329963c0-.100423-.014346-.11477-.344309-.11477h-5.924979c-.329963 0-.344309 .014346-.430386 .272578l-.789041 2.582315c-.043039 .143462-.043039 .172154-.043039 .200847c0 .057385 .043039 .143462 .143462 .143462c.11477 0 .143462-.057385 .200847-.243885c.530809-1.549389 1.233773-2.539277 3.500472-2.539277h2.352776l-7.861715 8.894641c-.129116 .157808-.186501 .215193-.186501 .373001c0 .11477 .071731 .11477 .344309 .11477h6.125826c.329963 0 .344309-.014346 .430386-.272578l1.004234-3.170509c.014346-.043039 .043039-.143462 .043039-.200847c0-.071731-.057385-.143462-.143462-.143462c-.11477 0-.129116 .014346-.243885 .373001c-.60254 1.850659-1.233773 2.969663-3.730011 2.969663h-2.481892l7.876061-8.908988z"/>
&lt;path id="g1-111" d="m6.584904-3.070086c0-1.850659-1.405927-3.328317-3.070086-3.328317c-1.721543 0-3.084432 1.520697-3.084432 3.328317c0 1.836313 1.43462 3.213548 3.070086 3.213548c1.692851 0 3.084432-1.405927 3.084432-3.213548zm-3.070086 2.897932c-.530809 0-1.176388-.229539-1.592428-.932503c-.387347-.645579-.401693-1.492004-.401693-2.094545c0-.545155 0-1.420273 .444732-2.065852c.401693-.616886 1.032926-.846426 1.535043-.846426c.559502 0 1.162042 .258232 1.549389 .817733c.444732 .659925 .444732 1.563735 .444732 2.094545c0 .502117 0 1.391581-.373001 2.065852c-.401693 .688617-1.061618 .961195-1.606774 .961195z"/>
&lt;path id="g1-114" d="m2.395815-3.342664c0-1.391581 .573848-2.697085 1.678505-2.697085c.11477 0 .143462 0 .200847 .014346c-.11477 .057385-.344309 .143462-.344309 .530809c0 .41604 .329963 .573848 .559502 .573848c.286924 0 .573848-.186501 .573848-.573848c0-.430386-.387347-.832079-1.004234-.832079c-1.219427 0-1.635466 1.31985-1.721543 1.592428h-.014346v-1.592428l-1.92239 .157808v.41604c.975541 0 1.090311 .100423 1.090311 .803387v3.887819c0 .645579-.157808 .645579-1.090311 .645579v.41604c.401693-.028692 1.190734-.028692 1.62112-.028692c.387347 0 1.405927 0 1.73589 .028692v-.41604h-.286924c-1.047272 0-1.075965-.157808-1.075965-.674271v-2.252353z"/>
&lt;path id="g1-116" d="m2.410161-5.767171h2.022814v-.41604h-2.022814v-2.6397h-.315616c-.014346 1.348542-.530809 2.725777-1.836313 2.768816v.286924h1.219427v3.988242c0 1.592428 1.061618 1.92239 1.821967 1.92239c.90381 0 1.377235-.889464 1.377235-1.92239v-.817733h-.315616v.789041c0 1.032926-.41604 1.635466-.975541 1.635466c-.975541 0-.975541-1.334196-.975541-1.578082v-4.016935z"/>
&lt;/defs>
&lt;g id="page1">
&lt;path d="m33.324-51.312h32.008v-19.84h-32.008z" fill="none" stroke-width="1.7008" style="stroke: var(--color-keyword);"/>
&lt;g transform="translate(412.5205 -279.056)" style="fill: var(--color-keyword);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g1-114"/>
&lt;use x="-370.411147" y="222.236073" xlink:href="#g1-111"/>
&lt;use x="-362.997377" y="222.236073" xlink:href="#g1-111"/>
&lt;use x="-355.973792" y="222.236073" xlink:href="#g1-116"/>
&lt;/g>
&lt;path d="m-45.633-8.789h19.844v-19.844h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-keyword);"/>
&lt;g transform="translate(333.7686 -236.0462)" style="fill: var(--color-keyword);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-88"/>
&lt;/g>
&lt;path d="m32.477-52.805l-57.418 28.711" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-keyword);"/>
&lt;path d="m-71.145 33.73h19.84v-19.843h-19.84z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(309.3843 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-65"/>
&lt;/g>
&lt;path d="m-42.176-7.941l-12.59 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m-45.633 33.73h19.844v-19.843h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(334.4639 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-66"/>
&lt;/g>
&lt;path d="m-35.711-7.941v20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m-20.121 33.73h19.844v-19.843h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-keyword);"/>
&lt;g transform="translate(360.1336 -193.526)" style="fill: var(--color-keyword);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-67"/>
&lt;/g>
&lt;path d="m-29.25-7.941l12.59 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-keyword);"/>
&lt;path d="m39.406-8.789h19.844v-19.844h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(419.5662 -236.0462)" style="fill: var(--color-fg);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-89"/>
&lt;/g>
&lt;path d="m49.328-50.461v20.977" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m26.652 33.73h19.84v-19.843h-19.84z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-comment);"/>
&lt;g transform="translate(406.4194 -193.526)" style="fill: var(--color-comment);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-68"/>
&lt;/g>
&lt;path d="m46.098-7.941l-6.297 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-comment);"/>
&lt;path d="m52.164 33.73h19.84v-19.843h-19.84z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-comment);"/>
&lt;g transform="translate(432.3385 -193.526)" style="fill: var(--color-comment);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-69"/>
&lt;/g>
&lt;path d="m52.559-7.941l6.296 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-comment);"/>
&lt;path d="m124.449-8.789h19.84v-19.844h-19.84z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-keyword);"/>
&lt;g transform="translate(504.92 -236.0462)" style="fill: var(--color-keyword);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-90"/>
&lt;/g>
&lt;path d="m66.18-52.805l57.418 28.711" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-keyword);"/>
&lt;path d="m86.18 33.73h19.843v-19.843h-19.843z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-keyword);"/>
&lt;g transform="translate(466.4523 -193.526)" style="fill: var(--color-keyword);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-70"/>
&lt;/g>
&lt;path d="m124.676-7.941l-18.883 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-keyword);"/>
&lt;path d="m111.691 33.73h19.844v-19.843h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(491.946 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-71"/>
&lt;/g>
&lt;path d="m131.137-7.941l-6.293 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m137.203 33.73h19.844v-19.843h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(516.625 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-72"/>
&lt;/g>
&lt;path d="m137.602-7.941l6.293 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m162.715 33.73h19.844v-19.843h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(544.849 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-375.873935" y="222.236073" xlink:href="#g0-73"/>
&lt;/g>
&lt;path d="m144.063-7.941l18.882 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;/g>
&lt;/svg>
&lt;p>In this particular case, the R-tree didn&amp;rsquo;t save us anything compared to brute force search: we had to do 11 intersection tests, while brute force would have only done 9. Gains are achieved when we can throw away large subtrees during search, which may or may not be the case even with larger trees, depending on their structure. Unfortunately, there is no complexity guarantee better than &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>O&lt;/mi>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>n&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">O(n)&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.02778em;">O&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;span class="mclose">)&lt;/span>&lt;/span>&lt;/span>&lt;/span> for the plain R-tree.&lt;/p>
&lt;h2 id="insertion">Insertion&lt;/h2>
&lt;p>Let&amp;rsquo;s say we want to insert a new item &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>J&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">J&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.09618em;">J&lt;/span>&lt;/span>&lt;/span>&lt;/span> into the tree:&lt;/p>
&lt;!-- This file was generated by dvisvgm 2.13.3 -->&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="228.472329pt" height="228.472329pt" viewBox="-72 -72 228.472329 228.472329">
&lt;defs>
&lt;path id="g0-65" d="m2.438853-1.592428c-.502117 .846426-.989888 1.133349-1.678505 1.176388c-.157808 .014346-.272578 .014346-.272578 .272578c0 .086077 .071731 .143462 .172154 .143462c.258232 0 .90381-.028692 1.162042-.028692c.41604 0 .875118 .028692 1.276811 .028692c.086077 0 .258232 0 .258232-.272578c0-.129116-.11477-.143462-.200847-.143462c-.329963-.028692-.60254-.143462-.60254-.487771c0-.200847 .086077-.358655 .272578-.674271l1.090311-1.807621h3.65828c.014346 .129116 .014346 .243885 .028692 .373001c.043039 .373001 .215193 1.865005 .215193 2.137583c0 .430386-.731656 .459078-.961195 .459078c-.157808 0-.315616 0-.315616 .258232c0 .157808 .129116 .157808 .215193 .157808c.243885 0 .530809-.028692 .774695-.028692h.817733c.875118 0 1.506351 .028692 1.520697 .028692c.100423 0 .258232 0 .258232-.272578c0-.143462-.129116-.143462-.344309-.143462c-.789041 0-.803387-.129116-.846426-.559502l-.875118-8.952026c-.028692-.286924-.086077-.315616-.243885-.315616c-.143462 0-.229539 .028692-.358655 .243885l-5.021168 8.406871zm1.721543-2.209314l2.883585-4.820322l.487771 4.820322h-3.371356z"/>
&lt;path id="g0-66" d="m5.250708-8.82291c.129116-.530809 .186501-.559502 .746002-.559502h1.865005c1.62112 0 1.62112 1.377235 1.62112 1.506351c0 1.162042-1.162042 2.6397-3.05574 2.6397h-2.065852l.889464-3.586549zm2.424507 3.701318c1.563735-.286924 2.984009-1.377235 2.984009-2.697085c0-1.119003-.989888-1.979775-2.611008-1.979775h-4.605129c-.272578 0-.401693 0-.401693 .272578c0 .143462 .129116 .143462 .344309 .143462c.875118 0 .875118 .11477 .875118 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h4.920745c2.194968 0 3.887819-1.664159 3.887819-3.113124c0-1.176388-1.032926-1.893698-2.194968-2.008467zm-2.03716 4.705552h-1.936736c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l1.004234-4.045627h2.697085c1.692851 0 1.692851 1.578082 1.692851 1.692851c0 1.377235-1.248119 2.840547-3.027047 2.840547z"/>
&lt;path id="g0-67" d="m10.716608-9.970606c0-.129116-.100423-.129116-.129116-.129116s-.086077 0-.200847 .143462l-.989888 1.20508c-.502117-.860772-1.291158-1.348542-2.367122-1.348542c-3.098778 0-6.312326 3.141817-6.312326 6.513173c0 2.395815 1.678505 3.887819 3.773049 3.887819c1.147696 0 2.151929-.487771 2.984009-1.190734c1.248119-1.047272 1.62112-2.438853 1.62112-2.553623c0-.129116-.11477-.129116-.157808-.129116c-.129116 0-.143462 .086077-.172154 .143462c-.659925 2.238007-2.596661 3.313971-4.031281 3.313971c-1.520697 0-2.840547-.975541-2.840547-3.012701c0-.459078 .143462-2.955316 1.764582-4.834668c.789041-.918157 2.137583-1.721543 3.500472-1.721543c1.578082 0 2.281045 1.305504 2.281045 2.768816c0 .373001-.043039 .688617-.043039 .746002c0 .129116 .143462 .129116 .186501 .129116c.157808 0 .172154-.014346 .229539-.272578l.90381-3.65828z"/>
&lt;path id="g0-68" d="m2.252353-1.061618c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h4.547744c2.897932 0 5.724132-2.998355 5.724132-6.197557c0-2.065852-1.233773-3.600895-3.285279-3.600895h-4.605129c-.272578 0-.401693 0-.401693 .272578c0 .143462 .129116 .143462 .344309 .143462c.875118 0 .875118 .11477 .875118 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253zm3.027047-7.761292c.129116-.530809 .186501-.559502 .746002-.559502h1.578082c1.348542 0 2.582315 .731656 2.582315 2.711431c0 .71731-.286924 3.213548-1.678505 4.791629c-.401693 .473424-1.492004 1.463312-3.141817 1.463312h-1.635466c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l1.979775-7.9191z"/>
&lt;path id="g0-69" d="m9.970606-3.328317c.014346-.043039 .057385-.143462 .057385-.200847c0-.071731-.057385-.143462-.143462-.143462c-.057385 0-.086077 .014346-.129116 .057385c-.028692 .014346-.028692 .043039-.157808 .329963c-.846426 2.008467-1.463312 2.869239-3.758703 2.869239h-2.094545c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l.989888-3.95955h1.420273c1.119003 0 1.20508 .243885 1.20508 .674271c0 .143462 0 .272578-.100423 .702964c-.028692 .057385-.043039 .11477-.043039 .157808c0 .100423 .071731 .143462 .157808 .143462c.129116 0 .143462-.100423 .200847-.30127l.817733-3.328317c0-.071731-.057385-.143462-.143462-.143462c-.129116 0-.143462 .057385-.200847 .258232c-.286924 1.104657-.573848 1.420273-1.850659 1.420273h-1.362889l.889464-3.529164c.129116-.502117 .157808-.545155 .746002-.545155h2.051506c1.764582 0 2.123237 .473424 2.123237 1.563735c0 .014346 0 .41604-.057385 .889464c-.014346 .057385-.028692 .143462-.028692 .172154c0 .11477 .071731 .157808 .157808 .157808c.100423 0 .157808-.057385 .186501-.315616l.30127-2.510584c0-.043039 .028692-.186501 .028692-.215193c0-.157808-.129116-.157808-.387347-.157808h-7.000943c-.272578 0-.41604 0-.41604 .258232c0 .157808 .100423 .157808 .344309 .157808c.889464 0 .889464 .100423 .889464 .258232c0 .071731-.014346 .129116-.057385 .286924l-1.936736 7.746946c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h7.20179c.315616 0 .329963-.014346 .430386-.243885l1.305504-3.084432z"/>
&lt;path id="g0-70" d="m4.26082-4.67686h1.377235c1.090311 0 1.176388 .243885 1.176388 .659925c0 .186501-.028692 .387347-.100423 .702964c-.028692 .057385-.043039 .129116-.043039 .157808c0 .100423 .057385 .157808 .157808 .157808c.11477 0 .129116-.057385 .186501-.286924l.832079-3.342664c0-.057385-.043039-.143462-.143462-.143462c-.129116 0-.143462 .057385-.200847 .30127c-.30127 1.075965-.588194 1.377235-1.836313 1.377235h-1.305504l.932503-3.715665c.129116-.502117 .157808-.545155 .746002-.545155h1.92239c1.793274 0 2.051506 .530809 2.051506 1.549389c0 .086077 0 .401693-.043039 .774695c-.014346 .057385-.043039 .243885-.043039 .30127c0 .11477 .071731 .157808 .157808 .157808c.100423 0 .157808-.057385 .186501-.315616l.30127-2.510584c0-.043039 .028692-.186501 .028692-.215193c0-.157808-.129116-.157808-.387347-.157808h-6.800097c-.272578 0-.41604 0-.41604 .258232c0 .157808 .100423 .157808 .344309 .157808c.889464 0 .889464 .100423 .889464 .258232c0 .071731-.014346 .129116-.057385 .286924l-1.936736 7.746946c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .129116 .157808 .215193 .157808c.272578 0 .559502-.028692 .832079-.028692h1.865005c.315616 0 .659925 .028692 .975541 .028692c.129116 0 .30127 0 .30127-.258232c0-.157808-.086077-.157808-.401693-.157808c-1.133349 0-1.162042-.100423-1.162042-.315616c0-.071731 .028692-.186501 .057385-.286924l.918157-3.65828z"/>
&lt;path id="g0-71" d="m10.702262-9.970606c0-.129116-.100423-.129116-.129116-.129116s-.086077 0-.200847 .143462l-.989888 1.190734c-.071731-.11477-.358655-.616886-.918157-.946849c-.616886-.387347-1.233773-.387347-1.448966-.387347c-3.070086 0-6.29798 3.127471-6.29798 6.513173c0 2.367122 1.635466 3.887819 3.787396 3.887819c1.032926 0 2.33843-.344309 3.05574-1.248119c.157808 .545155 .473424 .932503 .573848 .932503c.071731 0 .086077-.043039 .100423-.043039c.014346-.028692 .129116-.530809 .200847-.789041l.229539-.918157c.11477-.473424 .172154-.674271 .272578-1.104657c.143462-.545155 .172154-.588194 .961195-.60254c.057385 0 .229539 0 .229539-.272578c0-.143462-.143462-.143462-.186501-.143462c-.243885 0-.516463 .028692-.774695 .028692h-.774695c-.60254 0-1.233773-.028692-1.821967-.028692c-.129116 0-.30127 0-.30127 .258232c0 .143462 .11477 .143462 .11477 .157808h.358655c1.133349 0 1.133349 .11477 1.133349 .329963c0 .014346-.272578 1.463312-.545155 1.893698c-.545155 .803387-1.678505 1.133349-2.52493 1.133349c-1.104657 0-2.897932-.573848-2.897932-3.05574c0-.961195 .344309-3.156163 1.73589-4.777283c.90381-1.032926 2.238007-1.73589 3.500472-1.73589c1.692851 0 2.295391 1.448966 2.295391 2.768816c0 .229539-.057385 .545155-.057385 .746002c0 .129116 .143462 .129116 .186501 .129116c.157808 0 .172154-.014346 .229539-.272578l.90381-3.65828z"/>
&lt;path id="g0-72" d="m10.730954-8.751179c.129116-.487771 .157808-.631233 1.176388-.631233c.258232 0 .401693 0 .401693-.258232c0-.157808-.129116-.157808-.215193-.157808c-.258232 0-.559502 .028692-.832079 .028692h-1.692851c-.272578 0-.573848-.028692-.846426-.028692c-.100423 0-.272578 0-.272578 .272578c0 .143462 .100423 .143462 .373001 .143462c.860772 0 .860772 .11477 .860772 .272578c0 .028692 0 .11477-.057385 .329963l-.875118 3.471779h-4.332551l.860772-3.443087c.129116-.487771 .157808-.631233 1.176388-.631233c.258232 0 .401693 0 .401693-.258232c0-.157808-.129116-.157808-.215193-.157808c-.258232 0-.559502 .028692-.832079 .028692h-1.692851c-.272578 0-.573848-.028692-.846426-.028692c-.100423 0-.272578 0-.272578 .272578c0 .143462 .100423 .143462 .373001 .143462c.860772 0 .860772 .11477 .860772 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253c-.129116 .502117-.157808 .645579-1.147696 .645579c-.329963 0-.430386 0-.430386 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.272578 0 .573848 .028692 .846426 .028692c.11477 0 .272578 0 .272578-.272578c0-.143462-.129116-.143462-.344309-.143462c-.875118 0-.875118-.11477-.875118-.258232c0-.014346 0-.11477 .028692-.229539l.989888-3.988242h4.346897c-.243885 .946849-.975541 3.945204-1.004234 4.031281c-.157808 .430386-.387347 .430386-1.233773 .444732c-.172154 0-.30127 0-.30127 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.272578 0 .573848 .028692 .846426 .028692c.11477 0 .272578 0 .272578-.272578c0-.143462-.129116-.143462-.344309-.143462c-.875118 0-.875118-.11477-.875118-.258232c0-.014346 0-.11477 .028692-.229539l1.965429-7.847369z"/>
&lt;path id="g0-73" d="m5.2794-8.736833c.129116-.502117 .157808-.645579 1.20508-.645579c.315616 0 .430386 0 .430386-.272578c0-.143462-.157808-.143462-.200847-.143462c-.258232 0-.573848 .028692-.832079 .028692h-1.764582c-.286924 0-.616886-.028692-.90381-.028692c-.11477 0-.272578 0-.272578 .272578c0 .143462 .11477 .143462 .401693 .143462c.889464 0 .889464 .11477 .889464 .272578c0 .100423-.028692 .186501-.057385 .315616l-1.936736 7.732599c-.129116 .502117-.157808 .645579-1.20508 .645579c-.315616 0-.444732 0-.444732 .272578c0 .143462 .143462 .143462 .215193 .143462c.258232 0 .573848-.028692 .832079-.028692h1.764582c.286924 0 .60254 .028692 .889464 .028692c.11477 0 .286924 0 .286924-.258232c0-.157808-.086077-.157808-.401693-.157808c-.889464 0-.889464-.11477-.889464-.286924c0-.028692 0-.100423 .057385-.329963l1.936736-7.703907z"/>
&lt;path id="g0-74" d="m7.660868-8.808564c.11477-.430386 .143462-.573848 .846426-.573848c.229539 0 .373001 0 .373001-.258232c0-.157808-.129116-.157808-.186501-.157808c-.243885 0-.516463 .028692-.774695 .028692h-.789041c-.60254 0-1.233773-.028692-1.836313-.028692c-.129116 0-.30127 0-.30127 .258232c0 .143462 .11477 .143462 .11477 .157808h.358655c1.147696 0 1.147696 .11477 1.147696 .329963c0 .014346 0 .11477-.057385 .344309l-1.649813 6.556211c-.373001 1.463312-1.334196 2.166276-2.022814 2.166276c-.487771 0-1.176388-.229539-1.348542-.989888c.057385 .014346 .129116 .028692 .186501 .028692c.473424 0 .846426-.41604 .846426-.832079c0-.229539-.143462-.530809-.573848-.530809c-.258232 0-.860772 .143462-.860772 1.075965c0 .90381 .746002 1.535043 1.778928 1.535043c1.305504 0 2.711431-.989888 3.05574-2.352776l1.692851-6.757058z"/>
&lt;path id="g0-88" d="m6.814443-5.824555l-1.348542-3.141817c.186501-.344309 .616886-.401693 .789041-.41604c.086077 0 .243885-.014346 .243885-.258232c0-.157808-.129116-.157808-.215193-.157808c-.243885 0-.530809 .028692-.774695 .028692h-.832079c-.875118 0-1.506351-.028692-1.520697-.028692c-.11477 0-.258232 0-.258232 .272578c0 .143462 .129116 .143462 .315616 .143462c.832079 0 .889464 .143462 1.032926 .487771l1.707197 3.988242l-3.113124 3.328317c-.516463 .559502-1.133349 1.104657-2.194968 1.162042c-.172154 .014346-.286924 .014346-.286924 .272578c0 .043039 .014346 .143462 .172154 .143462c.200847 0 .41604-.028692 .616886-.028692h.674271c.459078 0 .961195 .028692 1.405927 .028692c.100423 0 .272578 0 .272578-.258232c0-.143462-.100423-.157808-.186501-.157808c-.286924-.028692-.473424-.186501-.473424-.41604c0-.243885 .172154-.41604 .588194-.846426l1.276811-1.391581c.315616-.329963 1.075965-1.162042 1.391581-1.477658l1.506351 3.529164c.014346 .028692 .071731 .172154 .071731 .186501c0 .129116-.315616 .387347-.774695 .41604c-.086077 0-.243885 .014346-.243885 .272578c0 .143462 .143462 .143462 .215193 .143462c.243885 0 .530809-.028692 .774695-.028692h1.578082c.258232 0 .530809 .028692 .774695 .028692c.100423 0 .258232 0 .258232-.272578c0-.143462-.143462-.143462-.272578-.143462c-.860772-.014346-.889464-.086077-1.133349-.616886l-1.893698-4.447321l1.821967-1.951083c.143462-.143462 .473424-.502117 .60254-.645579c.616886-.645579 1.190734-1.233773 2.352776-1.305504c.143462-.014346 .286924-.014346 .286924-.258232c0-.157808-.129116-.157808-.186501-.157808c-.200847 0-.41604 .028692-.616886 .028692h-.659925c-.459078 0-.961195-.028692-1.405927-.028692c-.100423 0-.272578 0-.272578 .258232c0 .143462 .100423 .157808 .186501 .157808c.229539 .028692 .473424 .143462 .473424 .41604l-.014346 .028692c-.014346 .100423-.043039 .243885-.200847 .41604l-2.510584 2.697085z"/>
&lt;path id="g0-89" d="m8.435563-8.206024l.329963-.329963c.631233-.645579 1.162042-.803387 1.664159-.846426c.157808-.014346 .286924-.028692 .286924-.272578c0-.143462-.143462-.143462-.172154-.143462c-.172154 0-.358655 .028692-.530809 .028692h-.588194c-.41604 0-.860772-.028692-1.262465-.028692c-.100423 0-.258232 0-.258232 .272578c0 .129116 .143462 .143462 .186501 .143462c.430386 .028692 .430386 .243885 .430386 .329963c0 .157808-.11477 .373001-.401693 .702964l-3.414395 3.916511l-1.62112-4.361243c-.086077-.200847-.086077-.229539-.086077-.258232c0-.30127 .588194-.329963 .760348-.329963s.329963 0 .329963-.258232c0-.157808-.129116-.157808-.215193-.157808c-.243885 0-.530809 .028692-.774695 .028692h-1.592428c-.258232 0-.530809-.028692-.774695-.028692c-.100423 0-.258232 0-.258232 .272578c0 .143462 .129116 .143462 .344309 .143462c.702964 0 .832079 .129116 .961195 .459078l1.778928 4.777283c.014346 .043039 .057385 .200847 .057385 .243885s-.702964 2.869239-.746002 3.012701c-.11477 .387347-.258232 .459078-1.176388 .473424c-.243885 0-.358655 0-.358655 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.258232 0 .559502 .028692 .817733 .028692c.100423 0 .272578 0 .272578-.258232c0-.157808-.100423-.157808-.344309-.157808c-.889464 0-.889464-.100423-.889464-.258232c0-.100423 .11477-.559502 .186501-.846426l.516463-2.065852c.086077-.30127 .086077-.329963 .215193-.473424l3.600895-4.146051z"/>
&lt;path id="g0-90" d="m10.042337-9.35372c.086077-.100423 .157808-.186501 .157808-.329963c0-.100423-.014346-.11477-.344309-.11477h-5.924979c-.329963 0-.344309 .014346-.430386 .272578l-.789041 2.582315c-.043039 .143462-.043039 .172154-.043039 .200847c0 .057385 .043039 .143462 .143462 .143462c.11477 0 .143462-.057385 .200847-.243885c.530809-1.549389 1.233773-2.539277 3.500472-2.539277h2.352776l-7.861715 8.894641c-.129116 .157808-.186501 .215193-.186501 .373001c0 .11477 .071731 .11477 .344309 .11477h6.125826c.329963 0 .344309-.014346 .430386-.272578l1.004234-3.170509c.014346-.043039 .043039-.143462 .043039-.200847c0-.071731-.057385-.143462-.143462-.143462c-.11477 0-.129116 .014346-.243885 .373001c-.60254 1.850659-1.233773 2.969663-3.730011 2.969663h-2.481892l7.876061-8.908988z"/>
&lt;/defs>
&lt;g id="page1">
&lt;path d="m-71.1484 155.6211v-226.7731h226.7733v226.7731h-226.7733z" fill="none" stroke-width="1.7008" style="stroke: var(--color-fg);"/>
&lt;path d="m-65.4805 149.9531v-107.7191h107.7184v107.7191h-107.7184z" fill="none" stroke-width="1.7008" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(38.187 -127.7597)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-88"/>
&lt;/g>
&lt;path d="m-59.8125 144.2812v-45.3554h19.8438v45.3554h-19.8438z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(43.8563 -71.066)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-65"/>
&lt;/g>
&lt;path d="m-34.2969 141.4492v-56.6953h48.1878v56.6953h-48.1878z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(69.3687 -85.2395)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-66"/>
&lt;/g>
&lt;path d="m-14.457 127.2734v-79.3714h51.0269v79.3714h-51.0269z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(89.2114 -122.0904)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-67"/>
&lt;/g>
&lt;path d="m-65.4805 13.887v-79.371h79.3714v79.371h-79.3714z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(38.187 -235.4777)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-89"/>
&lt;/g>
&lt;path d="m-59.8125 8.219v-28.348h45.3555v28.348h-45.3555z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(43.8563 -190.1226)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-68"/>
&lt;/g>
&lt;path d="m-14.457-37.137v-22.679h22.6799v22.679h-22.6799z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(89.2114 -229.8084)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-69"/>
&lt;/g>
&lt;path d="m-42.8008 70.582v-113.387h192.7577v113.387h-192.7577z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(60.8646 -212.8001)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-90"/>
&lt;/g>
&lt;path d="m-37.1328 64.91v-79.371h87.8747v79.371h-87.8747z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(66.5339 -184.453336)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-70"/>
&lt;/g>
&lt;path d="m113.1059-.285v-36.852h31.179v36.852h-31.179z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(216.7721 -207.1309)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-71"/>
&lt;/g>
&lt;path d="m98.9299 42.234v-28.347h28.347v28.347h-28.347z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(202.5991 -156.1065)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-72"/>
&lt;/g>
&lt;path d="m70.5859-.285v-22.68h28.344v22.68h-28.344z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(174.2518 -192.95746)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-73"/>
&lt;/g>
&lt;path d="m22.3949 13.887v-48.188h22.679v48.188h-22.679z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-keyword);"/>
&lt;g transform="translate(126.0623 -204.296)" style="fill: var(--color-keyword);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-74"/>
&lt;/g>
&lt;/g>
&lt;/svg>
&lt;p>The insertion algorithm will traverse the tree, and find that &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>Z&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">Z&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.07153em;">Z&lt;/span>&lt;/span>&lt;/span>&lt;/span> is the best leaf node to put it in, since it already fully contains it. (The actual algorithm is to look for the leaf node that needs the &lt;em>minimum area enlargement&lt;/em> to contain the new item. In this case, &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>Z&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">Z&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.07153em;">Z&lt;/span>&lt;/span>&lt;/span>&lt;/span> needs zero enlargement, so it&amp;rsquo;s the best choice.) Let&amp;rsquo;s insert &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>J&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">J&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.09618em;">J&lt;/span>&lt;/span>&lt;/span>&lt;/span> into &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>Z&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">Z&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.07153em;">Z&lt;/span>&lt;/span>&lt;/span>&lt;/span>:&lt;/p>
&lt;!-- This file was generated by dvisvgm 2.13.3 -->&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="296.503861pt" height="106.582615pt" viewBox="-72 -72 296.503861 106.582615">
&lt;defs>
&lt;path id="g0-65" d="m2.438853-1.592428c-.502117 .846426-.989888 1.133349-1.678505 1.176388c-.157808 .014346-.272578 .014346-.272578 .272578c0 .086077 .071731 .143462 .172154 .143462c.258232 0 .90381-.028692 1.162042-.028692c.41604 0 .875118 .028692 1.276811 .028692c.086077 0 .258232 0 .258232-.272578c0-.129116-.11477-.143462-.200847-.143462c-.329963-.028692-.60254-.143462-.60254-.487771c0-.200847 .086077-.358655 .272578-.674271l1.090311-1.807621h3.65828c.014346 .129116 .014346 .243885 .028692 .373001c.043039 .373001 .215193 1.865005 .215193 2.137583c0 .430386-.731656 .459078-.961195 .459078c-.157808 0-.315616 0-.315616 .258232c0 .157808 .129116 .157808 .215193 .157808c.243885 0 .530809-.028692 .774695-.028692h.817733c.875118 0 1.506351 .028692 1.520697 .028692c.100423 0 .258232 0 .258232-.272578c0-.143462-.129116-.143462-.344309-.143462c-.789041 0-.803387-.129116-.846426-.559502l-.875118-8.952026c-.028692-.286924-.086077-.315616-.243885-.315616c-.143462 0-.229539 .028692-.358655 .243885l-5.021168 8.406871zm1.721543-2.209314l2.883585-4.820322l.487771 4.820322h-3.371356z"/>
&lt;path id="g0-66" d="m5.250708-8.82291c.129116-.530809 .186501-.559502 .746002-.559502h1.865005c1.62112 0 1.62112 1.377235 1.62112 1.506351c0 1.162042-1.162042 2.6397-3.05574 2.6397h-2.065852l.889464-3.586549zm2.424507 3.701318c1.563735-.286924 2.984009-1.377235 2.984009-2.697085c0-1.119003-.989888-1.979775-2.611008-1.979775h-4.605129c-.272578 0-.401693 0-.401693 .272578c0 .143462 .129116 .143462 .344309 .143462c.875118 0 .875118 .11477 .875118 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h4.920745c2.194968 0 3.887819-1.664159 3.887819-3.113124c0-1.176388-1.032926-1.893698-2.194968-2.008467zm-2.03716 4.705552h-1.936736c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l1.004234-4.045627h2.697085c1.692851 0 1.692851 1.578082 1.692851 1.692851c0 1.377235-1.248119 2.840547-3.027047 2.840547z"/>
&lt;path id="g0-67" d="m10.716608-9.970606c0-.129116-.100423-.129116-.129116-.129116s-.086077 0-.200847 .143462l-.989888 1.20508c-.502117-.860772-1.291158-1.348542-2.367122-1.348542c-3.098778 0-6.312326 3.141817-6.312326 6.513173c0 2.395815 1.678505 3.887819 3.773049 3.887819c1.147696 0 2.151929-.487771 2.984009-1.190734c1.248119-1.047272 1.62112-2.438853 1.62112-2.553623c0-.129116-.11477-.129116-.157808-.129116c-.129116 0-.143462 .086077-.172154 .143462c-.659925 2.238007-2.596661 3.313971-4.031281 3.313971c-1.520697 0-2.840547-.975541-2.840547-3.012701c0-.459078 .143462-2.955316 1.764582-4.834668c.789041-.918157 2.137583-1.721543 3.500472-1.721543c1.578082 0 2.281045 1.305504 2.281045 2.768816c0 .373001-.043039 .688617-.043039 .746002c0 .129116 .143462 .129116 .186501 .129116c.157808 0 .172154-.014346 .229539-.272578l.90381-3.65828z"/>
&lt;path id="g0-68" d="m2.252353-1.061618c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h4.547744c2.897932 0 5.724132-2.998355 5.724132-6.197557c0-2.065852-1.233773-3.600895-3.285279-3.600895h-4.605129c-.272578 0-.401693 0-.401693 .272578c0 .143462 .129116 .143462 .344309 .143462c.875118 0 .875118 .11477 .875118 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253zm3.027047-7.761292c.129116-.530809 .186501-.559502 .746002-.559502h1.578082c1.348542 0 2.582315 .731656 2.582315 2.711431c0 .71731-.286924 3.213548-1.678505 4.791629c-.401693 .473424-1.492004 1.463312-3.141817 1.463312h-1.635466c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l1.979775-7.9191z"/>
&lt;path id="g0-69" d="m9.970606-3.328317c.014346-.043039 .057385-.143462 .057385-.200847c0-.071731-.057385-.143462-.143462-.143462c-.057385 0-.086077 .014346-.129116 .057385c-.028692 .014346-.028692 .043039-.157808 .329963c-.846426 2.008467-1.463312 2.869239-3.758703 2.869239h-2.094545c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l.989888-3.95955h1.420273c1.119003 0 1.20508 .243885 1.20508 .674271c0 .143462 0 .272578-.100423 .702964c-.028692 .057385-.043039 .11477-.043039 .157808c0 .100423 .071731 .143462 .157808 .143462c.129116 0 .143462-.100423 .200847-.30127l.817733-3.328317c0-.071731-.057385-.143462-.143462-.143462c-.129116 0-.143462 .057385-.200847 .258232c-.286924 1.104657-.573848 1.420273-1.850659 1.420273h-1.362889l.889464-3.529164c.129116-.502117 .157808-.545155 .746002-.545155h2.051506c1.764582 0 2.123237 .473424 2.123237 1.563735c0 .014346 0 .41604-.057385 .889464c-.014346 .057385-.028692 .143462-.028692 .172154c0 .11477 .071731 .157808 .157808 .157808c.100423 0 .157808-.057385 .186501-.315616l.30127-2.510584c0-.043039 .028692-.186501 .028692-.215193c0-.157808-.129116-.157808-.387347-.157808h-7.000943c-.272578 0-.41604 0-.41604 .258232c0 .157808 .100423 .157808 .344309 .157808c.889464 0 .889464 .100423 .889464 .258232c0 .071731-.014346 .129116-.057385 .286924l-1.936736 7.746946c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h7.20179c.315616 0 .329963-.014346 .430386-.243885l1.305504-3.084432z"/>
&lt;path id="g0-70" d="m4.26082-4.67686h1.377235c1.090311 0 1.176388 .243885 1.176388 .659925c0 .186501-.028692 .387347-.100423 .702964c-.028692 .057385-.043039 .129116-.043039 .157808c0 .100423 .057385 .157808 .157808 .157808c.11477 0 .129116-.057385 .186501-.286924l.832079-3.342664c0-.057385-.043039-.143462-.143462-.143462c-.129116 0-.143462 .057385-.200847 .30127c-.30127 1.075965-.588194 1.377235-1.836313 1.377235h-1.305504l.932503-3.715665c.129116-.502117 .157808-.545155 .746002-.545155h1.92239c1.793274 0 2.051506 .530809 2.051506 1.549389c0 .086077 0 .401693-.043039 .774695c-.014346 .057385-.043039 .243885-.043039 .30127c0 .11477 .071731 .157808 .157808 .157808c.100423 0 .157808-.057385 .186501-.315616l.30127-2.510584c0-.043039 .028692-.186501 .028692-.215193c0-.157808-.129116-.157808-.387347-.157808h-6.800097c-.272578 0-.41604 0-.41604 .258232c0 .157808 .100423 .157808 .344309 .157808c.889464 0 .889464 .100423 .889464 .258232c0 .071731-.014346 .129116-.057385 .286924l-1.936736 7.746946c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .129116 .157808 .215193 .157808c.272578 0 .559502-.028692 .832079-.028692h1.865005c.315616 0 .659925 .028692 .975541 .028692c.129116 0 .30127 0 .30127-.258232c0-.157808-.086077-.157808-.401693-.157808c-1.133349 0-1.162042-.100423-1.162042-.315616c0-.071731 .028692-.186501 .057385-.286924l.918157-3.65828z"/>
&lt;path id="g0-71" d="m10.702262-9.970606c0-.129116-.100423-.129116-.129116-.129116s-.086077 0-.200847 .143462l-.989888 1.190734c-.071731-.11477-.358655-.616886-.918157-.946849c-.616886-.387347-1.233773-.387347-1.448966-.387347c-3.070086 0-6.29798 3.127471-6.29798 6.513173c0 2.367122 1.635466 3.887819 3.787396 3.887819c1.032926 0 2.33843-.344309 3.05574-1.248119c.157808 .545155 .473424 .932503 .573848 .932503c.071731 0 .086077-.043039 .100423-.043039c.014346-.028692 .129116-.530809 .200847-.789041l.229539-.918157c.11477-.473424 .172154-.674271 .272578-1.104657c.143462-.545155 .172154-.588194 .961195-.60254c.057385 0 .229539 0 .229539-.272578c0-.143462-.143462-.143462-.186501-.143462c-.243885 0-.516463 .028692-.774695 .028692h-.774695c-.60254 0-1.233773-.028692-1.821967-.028692c-.129116 0-.30127 0-.30127 .258232c0 .143462 .11477 .143462 .11477 .157808h.358655c1.133349 0 1.133349 .11477 1.133349 .329963c0 .014346-.272578 1.463312-.545155 1.893698c-.545155 .803387-1.678505 1.133349-2.52493 1.133349c-1.104657 0-2.897932-.573848-2.897932-3.05574c0-.961195 .344309-3.156163 1.73589-4.777283c.90381-1.032926 2.238007-1.73589 3.500472-1.73589c1.692851 0 2.295391 1.448966 2.295391 2.768816c0 .229539-.057385 .545155-.057385 .746002c0 .129116 .143462 .129116 .186501 .129116c.157808 0 .172154-.014346 .229539-.272578l.90381-3.65828z"/>
&lt;path id="g0-72" d="m10.730954-8.751179c.129116-.487771 .157808-.631233 1.176388-.631233c.258232 0 .401693 0 .401693-.258232c0-.157808-.129116-.157808-.215193-.157808c-.258232 0-.559502 .028692-.832079 .028692h-1.692851c-.272578 0-.573848-.028692-.846426-.028692c-.100423 0-.272578 0-.272578 .272578c0 .143462 .100423 .143462 .373001 .143462c.860772 0 .860772 .11477 .860772 .272578c0 .028692 0 .11477-.057385 .329963l-.875118 3.471779h-4.332551l.860772-3.443087c.129116-.487771 .157808-.631233 1.176388-.631233c.258232 0 .401693 0 .401693-.258232c0-.157808-.129116-.157808-.215193-.157808c-.258232 0-.559502 .028692-.832079 .028692h-1.692851c-.272578 0-.573848-.028692-.846426-.028692c-.100423 0-.272578 0-.272578 .272578c0 .143462 .100423 .143462 .373001 .143462c.860772 0 .860772 .11477 .860772 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253c-.129116 .502117-.157808 .645579-1.147696 .645579c-.329963 0-.430386 0-.430386 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.272578 0 .573848 .028692 .846426 .028692c.11477 0 .272578 0 .272578-.272578c0-.143462-.129116-.143462-.344309-.143462c-.875118 0-.875118-.11477-.875118-.258232c0-.014346 0-.11477 .028692-.229539l.989888-3.988242h4.346897c-.243885 .946849-.975541 3.945204-1.004234 4.031281c-.157808 .430386-.387347 .430386-1.233773 .444732c-.172154 0-.30127 0-.30127 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.272578 0 .573848 .028692 .846426 .028692c.11477 0 .272578 0 .272578-.272578c0-.143462-.129116-.143462-.344309-.143462c-.875118 0-.875118-.11477-.875118-.258232c0-.014346 0-.11477 .028692-.229539l1.965429-7.847369z"/>
&lt;path id="g0-73" d="m5.2794-8.736833c.129116-.502117 .157808-.645579 1.20508-.645579c.315616 0 .430386 0 .430386-.272578c0-.143462-.157808-.143462-.200847-.143462c-.258232 0-.573848 .028692-.832079 .028692h-1.764582c-.286924 0-.616886-.028692-.90381-.028692c-.11477 0-.272578 0-.272578 .272578c0 .143462 .11477 .143462 .401693 .143462c.889464 0 .889464 .11477 .889464 .272578c0 .100423-.028692 .186501-.057385 .315616l-1.936736 7.732599c-.129116 .502117-.157808 .645579-1.20508 .645579c-.315616 0-.444732 0-.444732 .272578c0 .143462 .143462 .143462 .215193 .143462c.258232 0 .573848-.028692 .832079-.028692h1.764582c.286924 0 .60254 .028692 .889464 .028692c.11477 0 .286924 0 .286924-.258232c0-.157808-.086077-.157808-.401693-.157808c-.889464 0-.889464-.11477-.889464-.286924c0-.028692 0-.100423 .057385-.329963l1.936736-7.703907z"/>
&lt;path id="g0-74" d="m7.660868-8.808564c.11477-.430386 .143462-.573848 .846426-.573848c.229539 0 .373001 0 .373001-.258232c0-.157808-.129116-.157808-.186501-.157808c-.243885 0-.516463 .028692-.774695 .028692h-.789041c-.60254 0-1.233773-.028692-1.836313-.028692c-.129116 0-.30127 0-.30127 .258232c0 .143462 .11477 .143462 .11477 .157808h.358655c1.147696 0 1.147696 .11477 1.147696 .329963c0 .014346 0 .11477-.057385 .344309l-1.649813 6.556211c-.373001 1.463312-1.334196 2.166276-2.022814 2.166276c-.487771 0-1.176388-.229539-1.348542-.989888c.057385 .014346 .129116 .028692 .186501 .028692c.473424 0 .846426-.41604 .846426-.832079c0-.229539-.143462-.530809-.573848-.530809c-.258232 0-.860772 .143462-.860772 1.075965c0 .90381 .746002 1.535043 1.778928 1.535043c1.305504 0 2.711431-.989888 3.05574-2.352776l1.692851-6.757058z"/>
&lt;path id="g0-88" d="m6.814443-5.824555l-1.348542-3.141817c.186501-.344309 .616886-.401693 .789041-.41604c.086077 0 .243885-.014346 .243885-.258232c0-.157808-.129116-.157808-.215193-.157808c-.243885 0-.530809 .028692-.774695 .028692h-.832079c-.875118 0-1.506351-.028692-1.520697-.028692c-.11477 0-.258232 0-.258232 .272578c0 .143462 .129116 .143462 .315616 .143462c.832079 0 .889464 .143462 1.032926 .487771l1.707197 3.988242l-3.113124 3.328317c-.516463 .559502-1.133349 1.104657-2.194968 1.162042c-.172154 .014346-.286924 .014346-.286924 .272578c0 .043039 .014346 .143462 .172154 .143462c.200847 0 .41604-.028692 .616886-.028692h.674271c.459078 0 .961195 .028692 1.405927 .028692c.100423 0 .272578 0 .272578-.258232c0-.143462-.100423-.157808-.186501-.157808c-.286924-.028692-.473424-.186501-.473424-.41604c0-.243885 .172154-.41604 .588194-.846426l1.276811-1.391581c.315616-.329963 1.075965-1.162042 1.391581-1.477658l1.506351 3.529164c.014346 .028692 .071731 .172154 .071731 .186501c0 .129116-.315616 .387347-.774695 .41604c-.086077 0-.243885 .014346-.243885 .272578c0 .143462 .143462 .143462 .215193 .143462c.243885 0 .530809-.028692 .774695-.028692h1.578082c.258232 0 .530809 .028692 .774695 .028692c.100423 0 .258232 0 .258232-.272578c0-.143462-.143462-.143462-.272578-.143462c-.860772-.014346-.889464-.086077-1.133349-.616886l-1.893698-4.447321l1.821967-1.951083c.143462-.143462 .473424-.502117 .60254-.645579c.616886-.645579 1.190734-1.233773 2.352776-1.305504c.143462-.014346 .286924-.014346 .286924-.258232c0-.157808-.129116-.157808-.186501-.157808c-.200847 0-.41604 .028692-.616886 .028692h-.659925c-.459078 0-.961195-.028692-1.405927-.028692c-.100423 0-.272578 0-.272578 .258232c0 .143462 .100423 .157808 .186501 .157808c.229539 .028692 .473424 .143462 .473424 .41604l-.014346 .028692c-.014346 .100423-.043039 .243885-.200847 .41604l-2.510584 2.697085z"/>
&lt;path id="g0-89" d="m8.435563-8.206024l.329963-.329963c.631233-.645579 1.162042-.803387 1.664159-.846426c.157808-.014346 .286924-.028692 .286924-.272578c0-.143462-.143462-.143462-.172154-.143462c-.172154 0-.358655 .028692-.530809 .028692h-.588194c-.41604 0-.860772-.028692-1.262465-.028692c-.100423 0-.258232 0-.258232 .272578c0 .129116 .143462 .143462 .186501 .143462c.430386 .028692 .430386 .243885 .430386 .329963c0 .157808-.11477 .373001-.401693 .702964l-3.414395 3.916511l-1.62112-4.361243c-.086077-.200847-.086077-.229539-.086077-.258232c0-.30127 .588194-.329963 .760348-.329963s.329963 0 .329963-.258232c0-.157808-.129116-.157808-.215193-.157808c-.243885 0-.530809 .028692-.774695 .028692h-1.592428c-.258232 0-.530809-.028692-.774695-.028692c-.100423 0-.258232 0-.258232 .272578c0 .143462 .129116 .143462 .344309 .143462c.702964 0 .832079 .129116 .961195 .459078l1.778928 4.777283c.014346 .043039 .057385 .200847 .057385 .243885s-.702964 2.869239-.746002 3.012701c-.11477 .387347-.258232 .459078-1.176388 .473424c-.243885 0-.358655 0-.358655 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.258232 0 .559502 .028692 .817733 .028692c.100423 0 .272578 0 .272578-.258232c0-.157808-.100423-.157808-.344309-.157808c-.889464 0-.889464-.100423-.889464-.258232c0-.100423 .11477-.559502 .186501-.846426l.516463-2.065852c.086077-.30127 .086077-.329963 .215193-.473424l3.600895-4.146051z"/>
&lt;path id="g0-90" d="m10.042337-9.35372c.086077-.100423 .157808-.186501 .157808-.329963c0-.100423-.014346-.11477-.344309-.11477h-5.924979c-.329963 0-.344309 .014346-.430386 .272578l-.789041 2.582315c-.043039 .143462-.043039 .172154-.043039 .200847c0 .057385 .043039 .143462 .143462 .143462c.11477 0 .143462-.057385 .200847-.243885c.530809-1.549389 1.233773-2.539277 3.500472-2.539277h2.352776l-7.861715 8.894641c-.129116 .157808-.186501 .215193-.186501 .373001c0 .11477 .071731 .11477 .344309 .11477h6.125826c.329963 0 .344309-.014346 .430386-.272578l1.004234-3.170509c.014346-.043039 .043039-.143462 .043039-.200847c0-.071731-.057385-.143462-.143462-.143462c-.11477 0-.129116 .014346-.243885 .373001c-.60254 1.850659-1.233773 2.969663-3.730011 2.969663h-2.481892l7.876061-8.908988z"/>
&lt;path id="g1-33" d="m2.6397-9.583259c0-.459078-.387347-.674271-.688617-.674271s-.746002 .200847-.702964 .803387l.516463 6.570558c.014346 .243885 .043039 .30127 .172154 .30127c.143462 0 .172154-.043039 .186501-.30127l.516463-6.699673zm0 8.880295c0-.373001-.315616-.688617-.688617-.688617c-.401693 0-.702964 .315616-.702964 .702964c0 .373001 .315616 .688617 .688617 .688617c.401693 0 .702964-.315616 .702964-.702964z"/>
&lt;path id="g1-111" d="m6.584904-3.070086c0-1.850659-1.405927-3.328317-3.070086-3.328317c-1.721543 0-3.084432 1.520697-3.084432 3.328317c0 1.836313 1.43462 3.213548 3.070086 3.213548c1.692851 0 3.084432-1.405927 3.084432-3.213548zm-3.070086 2.897932c-.530809 0-1.176388-.229539-1.592428-.932503c-.387347-.645579-.401693-1.492004-.401693-2.094545c0-.545155 0-1.420273 .444732-2.065852c.401693-.616886 1.032926-.846426 1.535043-.846426c.559502 0 1.162042 .258232 1.549389 .817733c.444732 .659925 .444732 1.563735 .444732 2.094545c0 .502117 0 1.391581-.373001 2.065852c-.401693 .688617-1.061618 .961195-1.606774 .961195z"/>
&lt;path id="g1-114" d="m2.395815-3.342664c0-1.391581 .573848-2.697085 1.678505-2.697085c.11477 0 .143462 0 .200847 .014346c-.11477 .057385-.344309 .143462-.344309 .530809c0 .41604 .329963 .573848 .559502 .573848c.286924 0 .573848-.186501 .573848-.573848c0-.430386-.387347-.832079-1.004234-.832079c-1.219427 0-1.635466 1.31985-1.721543 1.592428h-.014346v-1.592428l-1.92239 .157808v.41604c.975541 0 1.090311 .100423 1.090311 .803387v3.887819c0 .645579-.157808 .645579-1.090311 .645579v.41604c.401693-.028692 1.190734-.028692 1.62112-.028692c.387347 0 1.405927 0 1.73589 .028692v-.41604h-.286924c-1.047272 0-1.075965-.157808-1.075965-.674271v-2.252353z"/>
&lt;path id="g1-116" d="m2.410161-5.767171h2.022814v-.41604h-2.022814v-2.6397h-.315616c-.014346 1.348542-.530809 2.725777-1.836313 2.768816v.286924h1.219427v3.988242c0 1.592428 1.061618 1.92239 1.821967 1.92239c.90381 0 1.377235-.889464 1.377235-1.92239v-.817733h-.315616v.789041c0 1.032926-.41604 1.635466-.975541 1.635466c-.975541 0-.975541-1.334196-.975541-1.578082v-4.016935z"/>
&lt;/defs>
&lt;g id="page1">
&lt;path d="m47.5-51.312h32.004v-19.84h-32.004z" fill="none" stroke-width="1.7008" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(412.5205 -279.056)" style="fill: var(--color-fg);">
&lt;use x="-361.700705" y="222.236073" xlink:href="#g1-114"/>
&lt;use x="-356.237917" y="222.236073" xlink:href="#g1-111"/>
&lt;use x="-348.824147" y="222.236073" xlink:href="#g1-111"/>
&lt;use x="-341.800562" y="222.236073" xlink:href="#g1-116"/>
&lt;/g>
&lt;path d="m-45.633-8.789h19.84v-19.844h-19.84z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(319.5952 -236.0462)" style="fill: var(--color-fg);">
&lt;use x="-361.700705" y="222.236073" xlink:href="#g0-88"/>
&lt;/g>
&lt;path d="m46.648-54.012l-71.589 30.684" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m-71.145 33.73h19.84v-19.843h-19.84z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(295.2109 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-361.700705" y="222.236073" xlink:href="#g0-65"/>
&lt;/g>
&lt;path d="m-42.176-7.941l-12.59 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m-45.633 33.73h19.84v-19.843h-19.84z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(320.2905 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-361.700705" y="222.236073" xlink:href="#g0-66"/>
&lt;/g>
&lt;path d="m-35.711-7.941v20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m-20.121 33.73h19.844v-19.843h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(345.9602 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-361.700705" y="222.236073" xlink:href="#g0-67"/>
&lt;/g>
&lt;path d="m-29.25-7.941l12.59 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m53.578-8.789h19.844v-19.844h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(419.5662 -236.0462)" style="fill: var(--color-fg);">
&lt;use x="-361.700705" y="222.236073" xlink:href="#g0-89"/>
&lt;/g>
&lt;path d="m63.5-50.461v20.977" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m40.824 33.73h19.844v-19.843h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(406.4194 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-361.700705" y="222.236073" xlink:href="#g0-68"/>
&lt;/g>
&lt;path d="m60.27-7.941l-6.293 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m66.336 33.73h19.844v-19.843h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(432.3385 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-361.700705" y="222.236073" xlink:href="#g0-69"/>
&lt;/g>
&lt;path d="m66.73-7.941l6.297 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m152.793-8.789h19.844v-19.844h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(519.094 -236.0462)" style="fill: var(--color-fg);">
&lt;use x="-361.700705" y="222.236073" xlink:href="#g0-90"/>
&lt;/g>
&lt;path d="m80.355-54.012l71.586 30.684" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m101.77 33.73h19.843v-19.843h-19.843z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(467.87 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-361.700705" y="222.236073" xlink:href="#g0-70"/>
&lt;/g>
&lt;path d="m151.941-9.734l-29.48 24.57" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m127.281 33.73h19.844v-19.843h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(493.364 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-361.700705" y="222.236073" xlink:href="#g0-71"/>
&lt;/g>
&lt;path d="m156.254-7.941l-12.59 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m152.793 33.73h19.844v-19.843h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(518.042 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-361.700705" y="222.236073" xlink:href="#g0-72"/>
&lt;/g>
&lt;path d="m162.715-7.941v20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m178.305 33.73h19.843v-19.843h-19.843z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(546.266 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-361.700705" y="222.236073" xlink:href="#g0-73"/>
&lt;/g>
&lt;path d="m169.176-7.941l12.59 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m203.816 33.73h19.844v-19.843h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-keyword);"/>
&lt;g transform="translate(570.894 -193.526)" style="fill: var(--color-keyword);">
&lt;use x="-361.700705" y="222.236073" xlink:href="#g0-74"/>
&lt;/g>
&lt;path d="m173.488-9.734l29.481 24.57" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-keyword);"/>
&lt;g transform="translate(539.359 -255.8906)" style="fill: var(--color-keyword);">
&lt;use x="-361.700705" y="222.236073" xlink:href="#g1-33"/>
&lt;/g>
&lt;/g>
&lt;/svg>
&lt;p>Now we encounter an issue with &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>Z&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">Z&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.07153em;">Z&lt;/span>&lt;/span>&lt;/span>&lt;/span>: we said at the beginning that each node can have a maximum of &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>M&lt;/mi>&lt;mo>=&lt;/mo>&lt;mn>4&lt;/mn>&lt;/mrow>&lt;annotation encoding="application/x-tex">M=4&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.10903em;">M&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6444em;">&lt;/span>&lt;span class="mord">4&lt;/span>&lt;/span>&lt;/span>&lt;/span> children.&lt;/p>
&lt;p>The insertion algorithm&amp;rsquo;s solution is to recursively &lt;em>split&lt;/em> the nodes going up the tree until the constraint imposed by &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>M&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">M&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.10903em;">M&lt;/span>&lt;/span>&lt;/span>&lt;/span> is satisfied again for all of the nodes.&lt;/p>
&lt;p>In this case, splitting only &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>Z&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">Z&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.07153em;">Z&lt;/span>&lt;/span>&lt;/span>&lt;/span> will be enough:&lt;/p>
&lt;div class="side-by-side">
&lt;!-- This file was generated by dvisvgm 2.13.3 -->&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="228.472329pt" height="228.472329pt" viewBox="-72 -72 228.472329 228.472329">
&lt;defs>
&lt;path id="g1-48" d="m2.520548-4.732254c.049813-.119552 .089664-.209215 .089664-.308842c0-.288917-.259029-.52802-.56787-.52802c-.278954 0-.458281 .18929-.52802 .448319l-1.185554 4.353674c0 .019925-.039851 .129514-.039851 .139477c0 .109589 .259029 .179328 .33873 .179328c.059776 0 .069738-.029888 .129514-.159402l1.763387-4.124533z"/>
&lt;path id="g0-65" d="m2.438853-1.592428c-.502117 .846426-.989888 1.133349-1.678505 1.176388c-.157808 .014346-.272578 .014346-.272578 .272578c0 .086077 .071731 .143462 .172154 .143462c.258232 0 .90381-.028692 1.162042-.028692c.41604 0 .875118 .028692 1.276811 .028692c.086077 0 .258232 0 .258232-.272578c0-.129116-.11477-.143462-.200847-.143462c-.329963-.028692-.60254-.143462-.60254-.487771c0-.200847 .086077-.358655 .272578-.674271l1.090311-1.807621h3.65828c.014346 .129116 .014346 .243885 .028692 .373001c.043039 .373001 .215193 1.865005 .215193 2.137583c0 .430386-.731656 .459078-.961195 .459078c-.157808 0-.315616 0-.315616 .258232c0 .157808 .129116 .157808 .215193 .157808c.243885 0 .530809-.028692 .774695-.028692h.817733c.875118 0 1.506351 .028692 1.520697 .028692c.100423 0 .258232 0 .258232-.272578c0-.143462-.129116-.143462-.344309-.143462c-.789041 0-.803387-.129116-.846426-.559502l-.875118-8.952026c-.028692-.286924-.086077-.315616-.243885-.315616c-.143462 0-.229539 .028692-.358655 .243885l-5.021168 8.406871zm1.721543-2.209314l2.883585-4.820322l.487771 4.820322h-3.371356z"/>
&lt;path id="g0-66" d="m5.250708-8.82291c.129116-.530809 .186501-.559502 .746002-.559502h1.865005c1.62112 0 1.62112 1.377235 1.62112 1.506351c0 1.162042-1.162042 2.6397-3.05574 2.6397h-2.065852l.889464-3.586549zm2.424507 3.701318c1.563735-.286924 2.984009-1.377235 2.984009-2.697085c0-1.119003-.989888-1.979775-2.611008-1.979775h-4.605129c-.272578 0-.401693 0-.401693 .272578c0 .143462 .129116 .143462 .344309 .143462c.875118 0 .875118 .11477 .875118 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h4.920745c2.194968 0 3.887819-1.664159 3.887819-3.113124c0-1.176388-1.032926-1.893698-2.194968-2.008467zm-2.03716 4.705552h-1.936736c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l1.004234-4.045627h2.697085c1.692851 0 1.692851 1.578082 1.692851 1.692851c0 1.377235-1.248119 2.840547-3.027047 2.840547z"/>
&lt;path id="g0-67" d="m10.716608-9.970606c0-.129116-.100423-.129116-.129116-.129116s-.086077 0-.200847 .143462l-.989888 1.20508c-.502117-.860772-1.291158-1.348542-2.367122-1.348542c-3.098778 0-6.312326 3.141817-6.312326 6.513173c0 2.395815 1.678505 3.887819 3.773049 3.887819c1.147696 0 2.151929-.487771 2.984009-1.190734c1.248119-1.047272 1.62112-2.438853 1.62112-2.553623c0-.129116-.11477-.129116-.157808-.129116c-.129116 0-.143462 .086077-.172154 .143462c-.659925 2.238007-2.596661 3.313971-4.031281 3.313971c-1.520697 0-2.840547-.975541-2.840547-3.012701c0-.459078 .143462-2.955316 1.764582-4.834668c.789041-.918157 2.137583-1.721543 3.500472-1.721543c1.578082 0 2.281045 1.305504 2.281045 2.768816c0 .373001-.043039 .688617-.043039 .746002c0 .129116 .143462 .129116 .186501 .129116c.157808 0 .172154-.014346 .229539-.272578l.90381-3.65828z"/>
&lt;path id="g0-68" d="m2.252353-1.061618c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h4.547744c2.897932 0 5.724132-2.998355 5.724132-6.197557c0-2.065852-1.233773-3.600895-3.285279-3.600895h-4.605129c-.272578 0-.401693 0-.401693 .272578c0 .143462 .129116 .143462 .344309 .143462c.875118 0 .875118 .11477 .875118 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253zm3.027047-7.761292c.129116-.530809 .186501-.559502 .746002-.559502h1.578082c1.348542 0 2.582315 .731656 2.582315 2.711431c0 .71731-.286924 3.213548-1.678505 4.791629c-.401693 .473424-1.492004 1.463312-3.141817 1.463312h-1.635466c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l1.979775-7.9191z"/>
&lt;path id="g0-69" d="m9.970606-3.328317c.014346-.043039 .057385-.143462 .057385-.200847c0-.071731-.057385-.143462-.143462-.143462c-.057385 0-.086077 .014346-.129116 .057385c-.028692 .014346-.028692 .043039-.157808 .329963c-.846426 2.008467-1.463312 2.869239-3.758703 2.869239h-2.094545c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l.989888-3.95955h1.420273c1.119003 0 1.20508 .243885 1.20508 .674271c0 .143462 0 .272578-.100423 .702964c-.028692 .057385-.043039 .11477-.043039 .157808c0 .100423 .071731 .143462 .157808 .143462c.129116 0 .143462-.100423 .200847-.30127l.817733-3.328317c0-.071731-.057385-.143462-.143462-.143462c-.129116 0-.143462 .057385-.200847 .258232c-.286924 1.104657-.573848 1.420273-1.850659 1.420273h-1.362889l.889464-3.529164c.129116-.502117 .157808-.545155 .746002-.545155h2.051506c1.764582 0 2.123237 .473424 2.123237 1.563735c0 .014346 0 .41604-.057385 .889464c-.014346 .057385-.028692 .143462-.028692 .172154c0 .11477 .071731 .157808 .157808 .157808c.100423 0 .157808-.057385 .186501-.315616l.30127-2.510584c0-.043039 .028692-.186501 .028692-.215193c0-.157808-.129116-.157808-.387347-.157808h-7.000943c-.272578 0-.41604 0-.41604 .258232c0 .157808 .100423 .157808 .344309 .157808c.889464 0 .889464 .100423 .889464 .258232c0 .071731-.014346 .129116-.057385 .286924l-1.936736 7.746946c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h7.20179c.315616 0 .329963-.014346 .430386-.243885l1.305504-3.084432z"/>
&lt;path id="g0-70" d="m4.26082-4.67686h1.377235c1.090311 0 1.176388 .243885 1.176388 .659925c0 .186501-.028692 .387347-.100423 .702964c-.028692 .057385-.043039 .129116-.043039 .157808c0 .100423 .057385 .157808 .157808 .157808c.11477 0 .129116-.057385 .186501-.286924l.832079-3.342664c0-.057385-.043039-.143462-.143462-.143462c-.129116 0-.143462 .057385-.200847 .30127c-.30127 1.075965-.588194 1.377235-1.836313 1.377235h-1.305504l.932503-3.715665c.129116-.502117 .157808-.545155 .746002-.545155h1.92239c1.793274 0 2.051506 .530809 2.051506 1.549389c0 .086077 0 .401693-.043039 .774695c-.014346 .057385-.043039 .243885-.043039 .30127c0 .11477 .071731 .157808 .157808 .157808c.100423 0 .157808-.057385 .186501-.315616l.30127-2.510584c0-.043039 .028692-.186501 .028692-.215193c0-.157808-.129116-.157808-.387347-.157808h-6.800097c-.272578 0-.41604 0-.41604 .258232c0 .157808 .100423 .157808 .344309 .157808c.889464 0 .889464 .100423 .889464 .258232c0 .071731-.014346 .129116-.057385 .286924l-1.936736 7.746946c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .129116 .157808 .215193 .157808c.272578 0 .559502-.028692 .832079-.028692h1.865005c.315616 0 .659925 .028692 .975541 .028692c.129116 0 .30127 0 .30127-.258232c0-.157808-.086077-.157808-.401693-.157808c-1.133349 0-1.162042-.100423-1.162042-.315616c0-.071731 .028692-.186501 .057385-.286924l.918157-3.65828z"/>
&lt;path id="g0-71" d="m10.702262-9.970606c0-.129116-.100423-.129116-.129116-.129116s-.086077 0-.200847 .143462l-.989888 1.190734c-.071731-.11477-.358655-.616886-.918157-.946849c-.616886-.387347-1.233773-.387347-1.448966-.387347c-3.070086 0-6.29798 3.127471-6.29798 6.513173c0 2.367122 1.635466 3.887819 3.787396 3.887819c1.032926 0 2.33843-.344309 3.05574-1.248119c.157808 .545155 .473424 .932503 .573848 .932503c.071731 0 .086077-.043039 .100423-.043039c.014346-.028692 .129116-.530809 .200847-.789041l.229539-.918157c.11477-.473424 .172154-.674271 .272578-1.104657c.143462-.545155 .172154-.588194 .961195-.60254c.057385 0 .229539 0 .229539-.272578c0-.143462-.143462-.143462-.186501-.143462c-.243885 0-.516463 .028692-.774695 .028692h-.774695c-.60254 0-1.233773-.028692-1.821967-.028692c-.129116 0-.30127 0-.30127 .258232c0 .143462 .11477 .143462 .11477 .157808h.358655c1.133349 0 1.133349 .11477 1.133349 .329963c0 .014346-.272578 1.463312-.545155 1.893698c-.545155 .803387-1.678505 1.133349-2.52493 1.133349c-1.104657 0-2.897932-.573848-2.897932-3.05574c0-.961195 .344309-3.156163 1.73589-4.777283c.90381-1.032926 2.238007-1.73589 3.500472-1.73589c1.692851 0 2.295391 1.448966 2.295391 2.768816c0 .229539-.057385 .545155-.057385 .746002c0 .129116 .143462 .129116 .186501 .129116c.157808 0 .172154-.014346 .229539-.272578l.90381-3.65828z"/>
&lt;path id="g0-72" d="m10.730954-8.751179c.129116-.487771 .157808-.631233 1.176388-.631233c.258232 0 .401693 0 .401693-.258232c0-.157808-.129116-.157808-.215193-.157808c-.258232 0-.559502 .028692-.832079 .028692h-1.692851c-.272578 0-.573848-.028692-.846426-.028692c-.100423 0-.272578 0-.272578 .272578c0 .143462 .100423 .143462 .373001 .143462c.860772 0 .860772 .11477 .860772 .272578c0 .028692 0 .11477-.057385 .329963l-.875118 3.471779h-4.332551l.860772-3.443087c.129116-.487771 .157808-.631233 1.176388-.631233c.258232 0 .401693 0 .401693-.258232c0-.157808-.129116-.157808-.215193-.157808c-.258232 0-.559502 .028692-.832079 .028692h-1.692851c-.272578 0-.573848-.028692-.846426-.028692c-.100423 0-.272578 0-.272578 .272578c0 .143462 .100423 .143462 .373001 .143462c.860772 0 .860772 .11477 .860772 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253c-.129116 .502117-.157808 .645579-1.147696 .645579c-.329963 0-.430386 0-.430386 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.272578 0 .573848 .028692 .846426 .028692c.11477 0 .272578 0 .272578-.272578c0-.143462-.129116-.143462-.344309-.143462c-.875118 0-.875118-.11477-.875118-.258232c0-.014346 0-.11477 .028692-.229539l.989888-3.988242h4.346897c-.243885 .946849-.975541 3.945204-1.004234 4.031281c-.157808 .430386-.387347 .430386-1.233773 .444732c-.172154 0-.30127 0-.30127 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.272578 0 .573848 .028692 .846426 .028692c.11477 0 .272578 0 .272578-.272578c0-.143462-.129116-.143462-.344309-.143462c-.875118 0-.875118-.11477-.875118-.258232c0-.014346 0-.11477 .028692-.229539l1.965429-7.847369z"/>
&lt;path id="g0-73" d="m5.2794-8.736833c.129116-.502117 .157808-.645579 1.20508-.645579c.315616 0 .430386 0 .430386-.272578c0-.143462-.157808-.143462-.200847-.143462c-.258232 0-.573848 .028692-.832079 .028692h-1.764582c-.286924 0-.616886-.028692-.90381-.028692c-.11477 0-.272578 0-.272578 .272578c0 .143462 .11477 .143462 .401693 .143462c.889464 0 .889464 .11477 .889464 .272578c0 .100423-.028692 .186501-.057385 .315616l-1.936736 7.732599c-.129116 .502117-.157808 .645579-1.20508 .645579c-.315616 0-.444732 0-.444732 .272578c0 .143462 .143462 .143462 .215193 .143462c.258232 0 .573848-.028692 .832079-.028692h1.764582c.286924 0 .60254 .028692 .889464 .028692c.11477 0 .286924 0 .286924-.258232c0-.157808-.086077-.157808-.401693-.157808c-.889464 0-.889464-.11477-.889464-.286924c0-.028692 0-.100423 .057385-.329963l1.936736-7.703907z"/>
&lt;path id="g0-74" d="m7.660868-8.808564c.11477-.430386 .143462-.573848 .846426-.573848c.229539 0 .373001 0 .373001-.258232c0-.157808-.129116-.157808-.186501-.157808c-.243885 0-.516463 .028692-.774695 .028692h-.789041c-.60254 0-1.233773-.028692-1.836313-.028692c-.129116 0-.30127 0-.30127 .258232c0 .143462 .11477 .143462 .11477 .157808h.358655c1.147696 0 1.147696 .11477 1.147696 .329963c0 .014346 0 .11477-.057385 .344309l-1.649813 6.556211c-.373001 1.463312-1.334196 2.166276-2.022814 2.166276c-.487771 0-1.176388-.229539-1.348542-.989888c.057385 .014346 .129116 .028692 .186501 .028692c.473424 0 .846426-.41604 .846426-.832079c0-.229539-.143462-.530809-.573848-.530809c-.258232 0-.860772 .143462-.860772 1.075965c0 .90381 .746002 1.535043 1.778928 1.535043c1.305504 0 2.711431-.989888 3.05574-2.352776l1.692851-6.757058z"/>
&lt;path id="g0-88" d="m6.814443-5.824555l-1.348542-3.141817c.186501-.344309 .616886-.401693 .789041-.41604c.086077 0 .243885-.014346 .243885-.258232c0-.157808-.129116-.157808-.215193-.157808c-.243885 0-.530809 .028692-.774695 .028692h-.832079c-.875118 0-1.506351-.028692-1.520697-.028692c-.11477 0-.258232 0-.258232 .272578c0 .143462 .129116 .143462 .315616 .143462c.832079 0 .889464 .143462 1.032926 .487771l1.707197 3.988242l-3.113124 3.328317c-.516463 .559502-1.133349 1.104657-2.194968 1.162042c-.172154 .014346-.286924 .014346-.286924 .272578c0 .043039 .014346 .143462 .172154 .143462c.200847 0 .41604-.028692 .616886-.028692h.674271c.459078 0 .961195 .028692 1.405927 .028692c.100423 0 .272578 0 .272578-.258232c0-.143462-.100423-.157808-.186501-.157808c-.286924-.028692-.473424-.186501-.473424-.41604c0-.243885 .172154-.41604 .588194-.846426l1.276811-1.391581c.315616-.329963 1.075965-1.162042 1.391581-1.477658l1.506351 3.529164c.014346 .028692 .071731 .172154 .071731 .186501c0 .129116-.315616 .387347-.774695 .41604c-.086077 0-.243885 .014346-.243885 .272578c0 .143462 .143462 .143462 .215193 .143462c.243885 0 .530809-.028692 .774695-.028692h1.578082c.258232 0 .530809 .028692 .774695 .028692c.100423 0 .258232 0 .258232-.272578c0-.143462-.143462-.143462-.272578-.143462c-.860772-.014346-.889464-.086077-1.133349-.616886l-1.893698-4.447321l1.821967-1.951083c.143462-.143462 .473424-.502117 .60254-.645579c.616886-.645579 1.190734-1.233773 2.352776-1.305504c.143462-.014346 .286924-.014346 .286924-.258232c0-.157808-.129116-.157808-.186501-.157808c-.200847 0-.41604 .028692-.616886 .028692h-.659925c-.459078 0-.961195-.028692-1.405927-.028692c-.100423 0-.272578 0-.272578 .258232c0 .143462 .100423 .157808 .186501 .157808c.229539 .028692 .473424 .143462 .473424 .41604l-.014346 .028692c-.014346 .100423-.043039 .243885-.200847 .41604l-2.510584 2.697085z"/>
&lt;path id="g0-89" d="m8.435563-8.206024l.329963-.329963c.631233-.645579 1.162042-.803387 1.664159-.846426c.157808-.014346 .286924-.028692 .286924-.272578c0-.143462-.143462-.143462-.172154-.143462c-.172154 0-.358655 .028692-.530809 .028692h-.588194c-.41604 0-.860772-.028692-1.262465-.028692c-.100423 0-.258232 0-.258232 .272578c0 .129116 .143462 .143462 .186501 .143462c.430386 .028692 .430386 .243885 .430386 .329963c0 .157808-.11477 .373001-.401693 .702964l-3.414395 3.916511l-1.62112-4.361243c-.086077-.200847-.086077-.229539-.086077-.258232c0-.30127 .588194-.329963 .760348-.329963s.329963 0 .329963-.258232c0-.157808-.129116-.157808-.215193-.157808c-.243885 0-.530809 .028692-.774695 .028692h-1.592428c-.258232 0-.530809-.028692-.774695-.028692c-.100423 0-.258232 0-.258232 .272578c0 .143462 .129116 .143462 .344309 .143462c.702964 0 .832079 .129116 .961195 .459078l1.778928 4.777283c.014346 .043039 .057385 .200847 .057385 .243885s-.702964 2.869239-.746002 3.012701c-.11477 .387347-.258232 .459078-1.176388 .473424c-.243885 0-.358655 0-.358655 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.258232 0 .559502 .028692 .817733 .028692c.100423 0 .272578 0 .272578-.258232c0-.157808-.100423-.157808-.344309-.157808c-.889464 0-.889464-.100423-.889464-.258232c0-.100423 .11477-.559502 .186501-.846426l.516463-2.065852c.086077-.30127 .086077-.329963 .215193-.473424l3.600895-4.146051z"/>
&lt;path id="g0-90" d="m10.042337-9.35372c.086077-.100423 .157808-.186501 .157808-.329963c0-.100423-.014346-.11477-.344309-.11477h-5.924979c-.329963 0-.344309 .014346-.430386 .272578l-.789041 2.582315c-.043039 .143462-.043039 .172154-.043039 .200847c0 .057385 .043039 .143462 .143462 .143462c.11477 0 .143462-.057385 .200847-.243885c.530809-1.549389 1.233773-2.539277 3.500472-2.539277h2.352776l-7.861715 8.894641c-.129116 .157808-.186501 .215193-.186501 .373001c0 .11477 .071731 .11477 .344309 .11477h6.125826c.329963 0 .344309-.014346 .430386-.272578l1.004234-3.170509c.014346-.043039 .043039-.143462 .043039-.200847c0-.071731-.057385-.143462-.143462-.143462c-.11477 0-.129116 .014346-.243885 .373001c-.60254 1.850659-1.233773 2.969663-3.730011 2.969663h-2.481892l7.876061-8.908988z"/>
&lt;/defs>
&lt;g id="page1">
&lt;path d="m-71.1484 155.6211v-226.7731h226.7733v226.7731h-226.7733z" fill="none" stroke-width="1.7008" style="stroke: var(--color-fg);"/>
&lt;path d="m-65.4805 149.9531v-107.7191h107.7184v107.7191h-107.7184z" fill="none" stroke-width="1.7008" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(38.187 -127.7597)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-88"/>
&lt;/g>
&lt;path d="m-59.8125 144.2812v-45.3554h19.8438v45.3554h-19.8438z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(43.8563 -71.066)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-65"/>
&lt;/g>
&lt;path d="m-34.2969 141.4492v-56.6953h48.1878v56.6953h-48.1878z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(69.3687 -85.2395)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-66"/>
&lt;/g>
&lt;path d="m-14.457 127.2734v-79.3714h51.0269v79.3714h-51.0269z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(89.2114 -122.0904)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-67"/>
&lt;/g>
&lt;path d="m-65.4805 13.887v-79.371h79.3714v79.371h-79.3714z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(38.187 -235.4777)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-89"/>
&lt;/g>
&lt;path d="m-59.8125 8.219v-28.348h45.3555v28.348h-45.3555z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(43.8563 -190.1226)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-68"/>
&lt;/g>
&lt;path d="m-14.457-37.137v-22.679h22.6799v22.679h-22.6799z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(89.2114 -229.8084)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-69"/>
&lt;/g>
&lt;path d="m-42.8008 70.582v-113.387h99.2107v113.387h-99.2107z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(60.8646 -211.8625)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-90"/>
&lt;use x="-88.851073" y="178.762274" xlink:href="#g1-48"/>
&lt;/g>
&lt;path d="m-37.1328 64.91v-79.371h87.8747v79.371h-87.8747z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(66.5339 -184.453336)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-70"/>
&lt;/g>
&lt;path d="m22.3949 13.887v-48.188h22.679v48.188h-22.679z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-keyword);"/>
&lt;g transform="translate(126.0623 -204.296)" style="fill: var(--color-keyword);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-74"/>
&lt;/g>
&lt;path d="m64.9139 70.582v-113.387h85.043v113.387h-85.043z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(168.5825 -212.8001)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-90"/>
&lt;/g>
&lt;path d="m113.1059-.285v-36.852h31.179v36.852h-31.179z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(216.7721 -207.1309)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-71"/>
&lt;/g>
&lt;path d="m98.9299 42.234v-28.347h28.347v28.347h-28.347z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(202.5991 -156.1065)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-72"/>
&lt;/g>
&lt;path d="m70.5859-.285v-22.68h28.344v22.68h-28.344z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(174.2518 -192.95746)" style="fill: var(--color-fg);">
&lt;use x="-99.496061" y="183.968383" xlink:href="#g0-73"/>
&lt;/g>
&lt;/g>
&lt;/svg>
&lt;!-- This file was generated by dvisvgm 2.13.3 -->&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="272.409365pt" height="106.582615pt" viewBox="-72 -72 272.409365 106.582615">
&lt;defs>
&lt;path id="g2-48" d="m2.520548-4.732254c.049813-.119552 .089664-.209215 .089664-.308842c0-.288917-.259029-.52802-.56787-.52802c-.278954 0-.458281 .18929-.52802 .448319l-1.185554 4.353674c0 .019925-.039851 .129514-.039851 .139477c0 .109589 .259029 .179328 .33873 .179328c.059776 0 .069738-.029888 .129514-.159402l1.763387-4.124533z"/>
&lt;path id="g0-65" d="m2.438853-1.592428c-.502117 .846426-.989888 1.133349-1.678505 1.176388c-.157808 .014346-.272578 .014346-.272578 .272578c0 .086077 .071731 .143462 .172154 .143462c.258232 0 .90381-.028692 1.162042-.028692c.41604 0 .875118 .028692 1.276811 .028692c.086077 0 .258232 0 .258232-.272578c0-.129116-.11477-.143462-.200847-.143462c-.329963-.028692-.60254-.143462-.60254-.487771c0-.200847 .086077-.358655 .272578-.674271l1.090311-1.807621h3.65828c.014346 .129116 .014346 .243885 .028692 .373001c.043039 .373001 .215193 1.865005 .215193 2.137583c0 .430386-.731656 .459078-.961195 .459078c-.157808 0-.315616 0-.315616 .258232c0 .157808 .129116 .157808 .215193 .157808c.243885 0 .530809-.028692 .774695-.028692h.817733c.875118 0 1.506351 .028692 1.520697 .028692c.100423 0 .258232 0 .258232-.272578c0-.143462-.129116-.143462-.344309-.143462c-.789041 0-.803387-.129116-.846426-.559502l-.875118-8.952026c-.028692-.286924-.086077-.315616-.243885-.315616c-.143462 0-.229539 .028692-.358655 .243885l-5.021168 8.406871zm1.721543-2.209314l2.883585-4.820322l.487771 4.820322h-3.371356z"/>
&lt;path id="g0-66" d="m5.250708-8.82291c.129116-.530809 .186501-.559502 .746002-.559502h1.865005c1.62112 0 1.62112 1.377235 1.62112 1.506351c0 1.162042-1.162042 2.6397-3.05574 2.6397h-2.065852l.889464-3.586549zm2.424507 3.701318c1.563735-.286924 2.984009-1.377235 2.984009-2.697085c0-1.119003-.989888-1.979775-2.611008-1.979775h-4.605129c-.272578 0-.401693 0-.401693 .272578c0 .143462 .129116 .143462 .344309 .143462c.875118 0 .875118 .11477 .875118 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h4.920745c2.194968 0 3.887819-1.664159 3.887819-3.113124c0-1.176388-1.032926-1.893698-2.194968-2.008467zm-2.03716 4.705552h-1.936736c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l1.004234-4.045627h2.697085c1.692851 0 1.692851 1.578082 1.692851 1.692851c0 1.377235-1.248119 2.840547-3.027047 2.840547z"/>
&lt;path id="g0-67" d="m10.716608-9.970606c0-.129116-.100423-.129116-.129116-.129116s-.086077 0-.200847 .143462l-.989888 1.20508c-.502117-.860772-1.291158-1.348542-2.367122-1.348542c-3.098778 0-6.312326 3.141817-6.312326 6.513173c0 2.395815 1.678505 3.887819 3.773049 3.887819c1.147696 0 2.151929-.487771 2.984009-1.190734c1.248119-1.047272 1.62112-2.438853 1.62112-2.553623c0-.129116-.11477-.129116-.157808-.129116c-.129116 0-.143462 .086077-.172154 .143462c-.659925 2.238007-2.596661 3.313971-4.031281 3.313971c-1.520697 0-2.840547-.975541-2.840547-3.012701c0-.459078 .143462-2.955316 1.764582-4.834668c.789041-.918157 2.137583-1.721543 3.500472-1.721543c1.578082 0 2.281045 1.305504 2.281045 2.768816c0 .373001-.043039 .688617-.043039 .746002c0 .129116 .143462 .129116 .186501 .129116c.157808 0 .172154-.014346 .229539-.272578l.90381-3.65828z"/>
&lt;path id="g0-68" d="m2.252353-1.061618c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h4.547744c2.897932 0 5.724132-2.998355 5.724132-6.197557c0-2.065852-1.233773-3.600895-3.285279-3.600895h-4.605129c-.272578 0-.401693 0-.401693 .272578c0 .143462 .129116 .143462 .344309 .143462c.875118 0 .875118 .11477 .875118 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253zm3.027047-7.761292c.129116-.530809 .186501-.559502 .746002-.559502h1.578082c1.348542 0 2.582315 .731656 2.582315 2.711431c0 .71731-.286924 3.213548-1.678505 4.791629c-.401693 .473424-1.492004 1.463312-3.141817 1.463312h-1.635466c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l1.979775-7.9191z"/>
&lt;path id="g0-69" d="m9.970606-3.328317c.014346-.043039 .057385-.143462 .057385-.200847c0-.071731-.057385-.143462-.143462-.143462c-.057385 0-.086077 .014346-.129116 .057385c-.028692 .014346-.028692 .043039-.157808 .329963c-.846426 2.008467-1.463312 2.869239-3.758703 2.869239h-2.094545c-.200847 0-.229539 0-.315616-.014346c-.157808-.014346-.172154-.043039-.172154-.157808c0-.100423 .028692-.186501 .057385-.315616l.989888-3.95955h1.420273c1.119003 0 1.20508 .243885 1.20508 .674271c0 .143462 0 .272578-.100423 .702964c-.028692 .057385-.043039 .11477-.043039 .157808c0 .100423 .071731 .143462 .157808 .143462c.129116 0 .143462-.100423 .200847-.30127l.817733-3.328317c0-.071731-.057385-.143462-.143462-.143462c-.129116 0-.143462 .057385-.200847 .258232c-.286924 1.104657-.573848 1.420273-1.850659 1.420273h-1.362889l.889464-3.529164c.129116-.502117 .157808-.545155 .746002-.545155h2.051506c1.764582 0 2.123237 .473424 2.123237 1.563735c0 .014346 0 .41604-.057385 .889464c-.014346 .057385-.028692 .143462-.028692 .172154c0 .11477 .071731 .157808 .157808 .157808c.100423 0 .157808-.057385 .186501-.315616l.30127-2.510584c0-.043039 .028692-.186501 .028692-.215193c0-.157808-.129116-.157808-.387347-.157808h-7.000943c-.272578 0-.41604 0-.41604 .258232c0 .157808 .100423 .157808 .344309 .157808c.889464 0 .889464 .100423 .889464 .258232c0 .071731-.014346 .129116-.057385 .286924l-1.936736 7.746946c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .086077 .157808 .373001 .157808h7.20179c.315616 0 .329963-.014346 .430386-.243885l1.305504-3.084432z"/>
&lt;path id="g0-70" d="m4.26082-4.67686h1.377235c1.090311 0 1.176388 .243885 1.176388 .659925c0 .186501-.028692 .387347-.100423 .702964c-.028692 .057385-.043039 .129116-.043039 .157808c0 .100423 .057385 .157808 .157808 .157808c.11477 0 .129116-.057385 .186501-.286924l.832079-3.342664c0-.057385-.043039-.143462-.143462-.143462c-.129116 0-.143462 .057385-.200847 .30127c-.30127 1.075965-.588194 1.377235-1.836313 1.377235h-1.305504l.932503-3.715665c.129116-.502117 .157808-.545155 .746002-.545155h1.92239c1.793274 0 2.051506 .530809 2.051506 1.549389c0 .086077 0 .401693-.043039 .774695c-.014346 .057385-.043039 .243885-.043039 .30127c0 .11477 .071731 .157808 .157808 .157808c.100423 0 .157808-.057385 .186501-.315616l.30127-2.510584c0-.043039 .028692-.186501 .028692-.215193c0-.157808-.129116-.157808-.387347-.157808h-6.800097c-.272578 0-.41604 0-.41604 .258232c0 .157808 .100423 .157808 .344309 .157808c.889464 0 .889464 .100423 .889464 .258232c0 .071731-.014346 .129116-.057385 .286924l-1.936736 7.746946c-.129116 .502117-.157808 .645579-1.162042 .645579c-.272578 0-.41604 0-.41604 .258232c0 .157808 .129116 .157808 .215193 .157808c.272578 0 .559502-.028692 .832079-.028692h1.865005c.315616 0 .659925 .028692 .975541 .028692c.129116 0 .30127 0 .30127-.258232c0-.157808-.086077-.157808-.401693-.157808c-1.133349 0-1.162042-.100423-1.162042-.315616c0-.071731 .028692-.186501 .057385-.286924l.918157-3.65828z"/>
&lt;path id="g0-71" d="m10.702262-9.970606c0-.129116-.100423-.129116-.129116-.129116s-.086077 0-.200847 .143462l-.989888 1.190734c-.071731-.11477-.358655-.616886-.918157-.946849c-.616886-.387347-1.233773-.387347-1.448966-.387347c-3.070086 0-6.29798 3.127471-6.29798 6.513173c0 2.367122 1.635466 3.887819 3.787396 3.887819c1.032926 0 2.33843-.344309 3.05574-1.248119c.157808 .545155 .473424 .932503 .573848 .932503c.071731 0 .086077-.043039 .100423-.043039c.014346-.028692 .129116-.530809 .200847-.789041l.229539-.918157c.11477-.473424 .172154-.674271 .272578-1.104657c.143462-.545155 .172154-.588194 .961195-.60254c.057385 0 .229539 0 .229539-.272578c0-.143462-.143462-.143462-.186501-.143462c-.243885 0-.516463 .028692-.774695 .028692h-.774695c-.60254 0-1.233773-.028692-1.821967-.028692c-.129116 0-.30127 0-.30127 .258232c0 .143462 .11477 .143462 .11477 .157808h.358655c1.133349 0 1.133349 .11477 1.133349 .329963c0 .014346-.272578 1.463312-.545155 1.893698c-.545155 .803387-1.678505 1.133349-2.52493 1.133349c-1.104657 0-2.897932-.573848-2.897932-3.05574c0-.961195 .344309-3.156163 1.73589-4.777283c.90381-1.032926 2.238007-1.73589 3.500472-1.73589c1.692851 0 2.295391 1.448966 2.295391 2.768816c0 .229539-.057385 .545155-.057385 .746002c0 .129116 .143462 .129116 .186501 .129116c.157808 0 .172154-.014346 .229539-.272578l.90381-3.65828z"/>
&lt;path id="g0-72" d="m10.730954-8.751179c.129116-.487771 .157808-.631233 1.176388-.631233c.258232 0 .401693 0 .401693-.258232c0-.157808-.129116-.157808-.215193-.157808c-.258232 0-.559502 .028692-.832079 .028692h-1.692851c-.272578 0-.573848-.028692-.846426-.028692c-.100423 0-.272578 0-.272578 .272578c0 .143462 .100423 .143462 .373001 .143462c.860772 0 .860772 .11477 .860772 .272578c0 .028692 0 .11477-.057385 .329963l-.875118 3.471779h-4.332551l.860772-3.443087c.129116-.487771 .157808-.631233 1.176388-.631233c.258232 0 .401693 0 .401693-.258232c0-.157808-.129116-.157808-.215193-.157808c-.258232 0-.559502 .028692-.832079 .028692h-1.692851c-.272578 0-.573848-.028692-.846426-.028692c-.100423 0-.272578 0-.272578 .272578c0 .143462 .100423 .143462 .373001 .143462c.860772 0 .860772 .11477 .860772 .272578c0 .028692 0 .11477-.057385 .329963l-1.936736 7.718253c-.129116 .502117-.157808 .645579-1.147696 .645579c-.329963 0-.430386 0-.430386 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.272578 0 .573848 .028692 .846426 .028692c.11477 0 .272578 0 .272578-.272578c0-.143462-.129116-.143462-.344309-.143462c-.875118 0-.875118-.11477-.875118-.258232c0-.014346 0-.11477 .028692-.229539l.989888-3.988242h4.346897c-.243885 .946849-.975541 3.945204-1.004234 4.031281c-.157808 .430386-.387347 .430386-1.233773 .444732c-.172154 0-.30127 0-.30127 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.272578 0 .573848 .028692 .846426 .028692c.11477 0 .272578 0 .272578-.272578c0-.143462-.129116-.143462-.344309-.143462c-.875118 0-.875118-.11477-.875118-.258232c0-.014346 0-.11477 .028692-.229539l1.965429-7.847369z"/>
&lt;path id="g0-73" d="m5.2794-8.736833c.129116-.502117 .157808-.645579 1.20508-.645579c.315616 0 .430386 0 .430386-.272578c0-.143462-.157808-.143462-.200847-.143462c-.258232 0-.573848 .028692-.832079 .028692h-1.764582c-.286924 0-.616886-.028692-.90381-.028692c-.11477 0-.272578 0-.272578 .272578c0 .143462 .11477 .143462 .401693 .143462c.889464 0 .889464 .11477 .889464 .272578c0 .100423-.028692 .186501-.057385 .315616l-1.936736 7.732599c-.129116 .502117-.157808 .645579-1.20508 .645579c-.315616 0-.444732 0-.444732 .272578c0 .143462 .143462 .143462 .215193 .143462c.258232 0 .573848-.028692 .832079-.028692h1.764582c.286924 0 .60254 .028692 .889464 .028692c.11477 0 .286924 0 .286924-.258232c0-.157808-.086077-.157808-.401693-.157808c-.889464 0-.889464-.11477-.889464-.286924c0-.028692 0-.100423 .057385-.329963l1.936736-7.703907z"/>
&lt;path id="g0-74" d="m7.660868-8.808564c.11477-.430386 .143462-.573848 .846426-.573848c.229539 0 .373001 0 .373001-.258232c0-.157808-.129116-.157808-.186501-.157808c-.243885 0-.516463 .028692-.774695 .028692h-.789041c-.60254 0-1.233773-.028692-1.836313-.028692c-.129116 0-.30127 0-.30127 .258232c0 .143462 .11477 .143462 .11477 .157808h.358655c1.147696 0 1.147696 .11477 1.147696 .329963c0 .014346 0 .11477-.057385 .344309l-1.649813 6.556211c-.373001 1.463312-1.334196 2.166276-2.022814 2.166276c-.487771 0-1.176388-.229539-1.348542-.989888c.057385 .014346 .129116 .028692 .186501 .028692c.473424 0 .846426-.41604 .846426-.832079c0-.229539-.143462-.530809-.573848-.530809c-.258232 0-.860772 .143462-.860772 1.075965c0 .90381 .746002 1.535043 1.778928 1.535043c1.305504 0 2.711431-.989888 3.05574-2.352776l1.692851-6.757058z"/>
&lt;path id="g0-88" d="m6.814443-5.824555l-1.348542-3.141817c.186501-.344309 .616886-.401693 .789041-.41604c.086077 0 .243885-.014346 .243885-.258232c0-.157808-.129116-.157808-.215193-.157808c-.243885 0-.530809 .028692-.774695 .028692h-.832079c-.875118 0-1.506351-.028692-1.520697-.028692c-.11477 0-.258232 0-.258232 .272578c0 .143462 .129116 .143462 .315616 .143462c.832079 0 .889464 .143462 1.032926 .487771l1.707197 3.988242l-3.113124 3.328317c-.516463 .559502-1.133349 1.104657-2.194968 1.162042c-.172154 .014346-.286924 .014346-.286924 .272578c0 .043039 .014346 .143462 .172154 .143462c.200847 0 .41604-.028692 .616886-.028692h.674271c.459078 0 .961195 .028692 1.405927 .028692c.100423 0 .272578 0 .272578-.258232c0-.143462-.100423-.157808-.186501-.157808c-.286924-.028692-.473424-.186501-.473424-.41604c0-.243885 .172154-.41604 .588194-.846426l1.276811-1.391581c.315616-.329963 1.075965-1.162042 1.391581-1.477658l1.506351 3.529164c.014346 .028692 .071731 .172154 .071731 .186501c0 .129116-.315616 .387347-.774695 .41604c-.086077 0-.243885 .014346-.243885 .272578c0 .143462 .143462 .143462 .215193 .143462c.243885 0 .530809-.028692 .774695-.028692h1.578082c.258232 0 .530809 .028692 .774695 .028692c.100423 0 .258232 0 .258232-.272578c0-.143462-.143462-.143462-.272578-.143462c-.860772-.014346-.889464-.086077-1.133349-.616886l-1.893698-4.447321l1.821967-1.951083c.143462-.143462 .473424-.502117 .60254-.645579c.616886-.645579 1.190734-1.233773 2.352776-1.305504c.143462-.014346 .286924-.014346 .286924-.258232c0-.157808-.129116-.157808-.186501-.157808c-.200847 0-.41604 .028692-.616886 .028692h-.659925c-.459078 0-.961195-.028692-1.405927-.028692c-.100423 0-.272578 0-.272578 .258232c0 .143462 .100423 .157808 .186501 .157808c.229539 .028692 .473424 .143462 .473424 .41604l-.014346 .028692c-.014346 .100423-.043039 .243885-.200847 .41604l-2.510584 2.697085z"/>
&lt;path id="g0-89" d="m8.435563-8.206024l.329963-.329963c.631233-.645579 1.162042-.803387 1.664159-.846426c.157808-.014346 .286924-.028692 .286924-.272578c0-.143462-.143462-.143462-.172154-.143462c-.172154 0-.358655 .028692-.530809 .028692h-.588194c-.41604 0-.860772-.028692-1.262465-.028692c-.100423 0-.258232 0-.258232 .272578c0 .129116 .143462 .143462 .186501 .143462c.430386 .028692 .430386 .243885 .430386 .329963c0 .157808-.11477 .373001-.401693 .702964l-3.414395 3.916511l-1.62112-4.361243c-.086077-.200847-.086077-.229539-.086077-.258232c0-.30127 .588194-.329963 .760348-.329963s.329963 0 .329963-.258232c0-.157808-.129116-.157808-.215193-.157808c-.243885 0-.530809 .028692-.774695 .028692h-1.592428c-.258232 0-.530809-.028692-.774695-.028692c-.100423 0-.258232 0-.258232 .272578c0 .143462 .129116 .143462 .344309 .143462c.702964 0 .832079 .129116 .961195 .459078l1.778928 4.777283c.014346 .043039 .057385 .200847 .057385 .243885s-.702964 2.869239-.746002 3.012701c-.11477 .387347-.258232 .459078-1.176388 .473424c-.243885 0-.358655 0-.358655 .272578c0 .143462 .157808 .143462 .200847 .143462c.258232 0 .559502-.028692 .832079-.028692h1.692851c.258232 0 .559502 .028692 .817733 .028692c.100423 0 .272578 0 .272578-.258232c0-.157808-.100423-.157808-.344309-.157808c-.889464 0-.889464-.100423-.889464-.258232c0-.100423 .11477-.559502 .186501-.846426l.516463-2.065852c.086077-.30127 .086077-.329963 .215193-.473424l3.600895-4.146051z"/>
&lt;path id="g0-90" d="m10.042337-9.35372c.086077-.100423 .157808-.186501 .157808-.329963c0-.100423-.014346-.11477-.344309-.11477h-5.924979c-.329963 0-.344309 .014346-.430386 .272578l-.789041 2.582315c-.043039 .143462-.043039 .172154-.043039 .200847c0 .057385 .043039 .143462 .143462 .143462c.11477 0 .143462-.057385 .200847-.243885c.530809-1.549389 1.233773-2.539277 3.500472-2.539277h2.352776l-7.861715 8.894641c-.129116 .157808-.186501 .215193-.186501 .373001c0 .11477 .071731 .11477 .344309 .11477h6.125826c.329963 0 .344309-.014346 .430386-.272578l1.004234-3.170509c.014346-.043039 .043039-.143462 .043039-.200847c0-.071731-.057385-.143462-.143462-.143462c-.11477 0-.129116 .014346-.243885 .373001c-.60254 1.850659-1.233773 2.969663-3.730011 2.969663h-2.481892l7.876061-8.908988z"/>
&lt;path id="g1-111" d="m6.584904-3.070086c0-1.850659-1.405927-3.328317-3.070086-3.328317c-1.721543 0-3.084432 1.520697-3.084432 3.328317c0 1.836313 1.43462 3.213548 3.070086 3.213548c1.692851 0 3.084432-1.405927 3.084432-3.213548zm-3.070086 2.897932c-.530809 0-1.176388-.229539-1.592428-.932503c-.387347-.645579-.401693-1.492004-.401693-2.094545c0-.545155 0-1.420273 .444732-2.065852c.401693-.616886 1.032926-.846426 1.535043-.846426c.559502 0 1.162042 .258232 1.549389 .817733c.444732 .659925 .444732 1.563735 .444732 2.094545c0 .502117 0 1.391581-.373001 2.065852c-.401693 .688617-1.061618 .961195-1.606774 .961195z"/>
&lt;path id="g1-114" d="m2.395815-3.342664c0-1.391581 .573848-2.697085 1.678505-2.697085c.11477 0 .143462 0 .200847 .014346c-.11477 .057385-.344309 .143462-.344309 .530809c0 .41604 .329963 .573848 .559502 .573848c.286924 0 .573848-.186501 .573848-.573848c0-.430386-.387347-.832079-1.004234-.832079c-1.219427 0-1.635466 1.31985-1.721543 1.592428h-.014346v-1.592428l-1.92239 .157808v.41604c.975541 0 1.090311 .100423 1.090311 .803387v3.887819c0 .645579-.157808 .645579-1.090311 .645579v.41604c.401693-.028692 1.190734-.028692 1.62112-.028692c.387347 0 1.405927 0 1.73589 .028692v-.41604h-.286924c-1.047272 0-1.075965-.157808-1.075965-.674271v-2.252353z"/>
&lt;path id="g1-116" d="m2.410161-5.767171h2.022814v-.41604h-2.022814v-2.6397h-.315616c-.014346 1.348542-.530809 2.725777-1.836313 2.768816v.286924h1.219427v3.988242c0 1.592428 1.061618 1.92239 1.821967 1.92239c.90381 0 1.377235-.889464 1.377235-1.92239v-.817733h-.315616v.789041c0 1.032926-.41604 1.635466-.975541 1.635466c-.975541 0-.975541-1.334196-.975541-1.578082v-4.016935z"/>
&lt;/defs>
&lt;g id="page1">
&lt;path d="m54.586-51.312h32.004v-19.84h-32.004z" fill="none" stroke-width="1.7008" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(412.5205 -279.056)" style="fill: var(--color-fg);">
&lt;use x="-354.614106" y="222.236073" xlink:href="#g1-114"/>
&lt;use x="-349.151317" y="222.236073" xlink:href="#g1-111"/>
&lt;use x="-341.737548" y="222.236073" xlink:href="#g1-111"/>
&lt;use x="-334.713962" y="222.236073" xlink:href="#g1-116"/>
&lt;/g>
&lt;path d="m-45.633-8.789h19.84v-19.844h-19.84z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(312.5085 -236.0462)" style="fill: var(--color-fg);">
&lt;use x="-354.614106" y="222.236073" xlink:href="#g0-88"/>
&lt;/g>
&lt;path d="m53.734-54.496l-78.675 31.476" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m-71.145 33.73h19.84v-19.843h-19.84z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(288.1242 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-354.614106" y="222.236073" xlink:href="#g0-65"/>
&lt;/g>
&lt;path d="m-42.176-7.941l-12.59 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m-45.633 33.73h19.84v-19.843h-19.84z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(313.2038 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-354.614106" y="222.236073" xlink:href="#g0-66"/>
&lt;/g>
&lt;path d="m-35.711-7.941v20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m-20.121 33.73h19.844v-19.843h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(338.8735 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-354.614106" y="222.236073" xlink:href="#g0-67"/>
&lt;/g>
&lt;path d="m-29.25-7.941l12.59 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m25.234-8.789h19.84v-19.844h-19.84z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(384.1327 -236.0462)" style="fill: var(--color-fg);">
&lt;use x="-354.614106" y="222.236073" xlink:href="#g0-89"/>
&lt;/g>
&lt;path d="m61.613-50.461l-17.484 20.977" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m12.477 33.73h19.843v-19.843h-19.843z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(370.9859 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-354.614106" y="222.236073" xlink:href="#g0-68"/>
&lt;/g>
&lt;path d="m31.922-7.941l-6.293 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m37.988 33.73h19.844v-19.843h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(396.905 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-354.614106" y="222.236073" xlink:href="#g0-69"/>
&lt;/g>
&lt;path d="m38.387-7.941l6.293 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m96.102-8.789h19.839v-19.844h-19.839z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(455.313 -236.0462)" style="fill: var(--color-fg);">
&lt;use x="-354.614106" y="222.236073" xlink:href="#g0-90"/>
&lt;/g>
&lt;path d="m79.563-50.461l17.484 20.977" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m70.59 33.73h19.84v-19.843h-19.84z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(429.5834 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-354.614106" y="222.236073" xlink:href="#g0-71"/>
&lt;/g>
&lt;path d="m99.559-7.941l-12.59 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m96.102 33.73h19.839v-19.843h-19.839z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(454.2621 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-354.614106" y="222.236073" xlink:href="#g0-72"/>
&lt;/g>
&lt;path d="m106.023-7.941v20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m121.613 33.73h19.844v-19.843h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(482.486 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-354.614106" y="222.236073" xlink:href="#g0-73"/>
&lt;/g>
&lt;path d="m112.484-7.941l12.59 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m166.625-8.789h20.527v-19.844h-20.527z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(524.561 -235.5774)" style="fill: var(--color-fg);">
&lt;use x="-354.614106" y="222.236073" xlink:href="#g0-90"/>
&lt;use x="-343.969118" y="217.029964" xlink:href="#g2-48"/>
&lt;/g>
&lt;path d="m87.441-54.5l78.336 31.344" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m154.211 33.73h19.844v-19.843h-19.844z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;g transform="translate(513.224 -193.526)" style="fill: var(--color-fg);">
&lt;use x="-354.614106" y="222.236073" xlink:href="#g0-70"/>
&lt;/g>
&lt;path d="m173.656-7.941l-6.293 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-fg);"/>
&lt;path d="m179.723 33.73h19.843v-19.843h-19.843z" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-keyword);"/>
&lt;g transform="translate(539.713 -193.526)" style="fill: var(--color-keyword);">
&lt;use x="-354.614106" y="222.236073" xlink:href="#g0-74"/>
&lt;/g>
&lt;path d="m180.121-7.941l6.293 20.976" fill="none" stroke-width="1.7008" stroke-miterlimit="10" style="stroke: var(--color-keyword);"/>
&lt;/g>
&lt;/svg>
&lt;/div>
&lt;p>Visually, it&amp;rsquo;s obvious that partitioning &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo stretchy="false">{&lt;/mo>&lt;mi>F&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>G&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>H&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>I&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>J&lt;/mi>&lt;mo stretchy="false">}&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\{F,G,H,I,J\}&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mopen">{&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.13889em;">F&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal">G&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.08125em;">H&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.07847em;">I&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.09618em;">J&lt;/span>&lt;span class="mclose">}&lt;/span>&lt;/span>&lt;/span>&lt;/span> into &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo stretchy="false">{&lt;/mo>&lt;mi>G&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>H&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>I&lt;/mi>&lt;mo stretchy="false">}&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\{G,H,I\}&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mopen">{&lt;/span>&lt;span class="mord mathnormal">G&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.08125em;">H&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.07847em;">I&lt;/span>&lt;span class="mclose">}&lt;/span>&lt;/span>&lt;/span>&lt;/span> and &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo stretchy="false">{&lt;/mo>&lt;mi>F&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>J&lt;/mi>&lt;mo stretchy="false">}&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\{F,J\}&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mopen">{&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.13889em;">F&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.09618em;">J&lt;/span>&lt;span class="mclose">}&lt;/span>&lt;/span>&lt;/span>&lt;/span> is a &amp;ldquo;good&amp;rdquo; split. A good split should minimize the probability that some arbitrary future query rectangle &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>γ&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">\gamma&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.625em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.05556em;">γ&lt;/span>&lt;/span>&lt;/span>&lt;/span> overlaps both. A heuristic algorithm tries to achieve this by minimizing the combined area of the two resulting rectangles. (There are actually multiple variations that can be used for this heuristic, I will go into the details &lt;a href="#partitioning-for-node-splitting">later&lt;/a>.)&lt;/p>
&lt;h2 id="deletion">Deletion&lt;/h2>
&lt;p>Deletion is conceptually easy after we have insertion. Delete the item, and if its parent has too few items, remove it as well. (And do this recursively all the way up the tree.)&lt;/p>
&lt;p>Now we have a well-formed tree, but unfortunately we also removed a bunch of unrelated items.&lt;/p>
&lt;p>The solution is to simply reinsert all of them using the insertion algorithm we already have. That&amp;rsquo;s it.&lt;/p>
&lt;h2 id="complexity">Complexity&lt;/h2>
&lt;p>Finally, just how fast are R-tree operations? Unfortunately we can&amp;rsquo;t say anything better than &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>O&lt;/mi>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>n&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">O(n)&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.02778em;">O&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;span class="mclose">)&lt;/span>&lt;/span>&lt;/span>&lt;/span> (&lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>n&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">n&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;/span>&lt;/span>&lt;/span> being the number of items) for the worst case complexity (for any R-tree operation).&lt;/p>
&lt;p>I have seen claims of &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>O&lt;/mi>&lt;mo stretchy="false">(&lt;/mo>&lt;msub>&lt;mrow>&lt;mi>log&lt;/mi>&lt;mo>⁡&lt;/mo>&lt;/mrow>&lt;mi>M&lt;/mi>&lt;/msub>&lt;mi>n&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">O(\log_M{n})&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.02778em;">O&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mop">&lt;span class="mop">lo&lt;span style="margin-right:0.01389em;">g&lt;/span>&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t vlist-t2">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.2342em;">&lt;span style="top:-2.4559em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mathnormal mtight" style="margin-right:0.10903em;">M&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="vlist-s">​&lt;/span>&lt;/span>&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.2441em;">&lt;span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord">&lt;span class="mord mathnormal">n&lt;/span>&lt;/span>&lt;span class="mclose">)&lt;/span>&lt;/span>&lt;/span>&lt;/span> &lt;em>average&lt;/em> complexity for search, which does intuitively make sense if you assume that your data is uniformly distributed, and on average the search only continues down on a single path at each level.&lt;/p>
&lt;p>Unfortunately, I haven&amp;rsquo;t seen any rigorous derivations of an average case complexity.&lt;/p>
&lt;h2 id="specification">Specification&lt;/h2>
&lt;p>We are going to write an R-tree implementation in Coq, and prove it functionally correct. But, what does it mean for an implementation to be &lt;em>correct&lt;/em>?&lt;/p>
&lt;p>Correctness can only be established in relation to a &lt;em>specification&lt;/em>, so we will have to come up with one. Fortunately in our case the specification is quite straightforward. (Well, straightforward compared to the proof at least. This exact specification would apply to any other spatial data structure as well.)&lt;/p>
&lt;h3 id="informal-specification">Informal specification&lt;/h3>
&lt;p>In this section I will lay out the specification without making everything perfectly rigorous, while in the next section I will properly formalize everything in Coq.&lt;/p>
&lt;p>Let&amp;rsquo;s define bounding boxes to be hyperrectangles in &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>d&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">d&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6944em;">&lt;/span>&lt;span class="mord mathnormal">d&lt;/span>&lt;/span>&lt;/span>&lt;/span> dimensional Eucledian space, with intersection and all geometric concepts having their usual meanings. (Note that while we develop the specification here for arbitrary &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>d&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">d&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6944em;">&lt;/span>&lt;span class="mord mathnormal">d&lt;/span>&lt;/span>&lt;/span>&lt;/span>, my implementation later will be specialized to &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>d&lt;/mi>&lt;mo>=&lt;/mo>&lt;mn>2&lt;/mn>&lt;/mrow>&lt;annotation encoding="application/x-tex">d=2&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6944em;">&lt;/span>&lt;span class="mord mathnormal">d&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6444em;">&lt;/span>&lt;span class="mord">2&lt;/span>&lt;/span>&lt;/span>&lt;/span>.)&lt;/p>
&lt;p>We are going to denote the empty tree with &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>ε&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">\varepsilon&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">ε&lt;/span>&lt;/span>&lt;/span>&lt;/span>, and the multiset of all items contained in a tree &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>t&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">t&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6151em;">&lt;/span>&lt;span class="mord mathnormal">t&lt;/span>&lt;/span>&lt;/span>&lt;/span> with &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>ι&lt;/mi>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>t&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\iota(t)&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord mathnormal">ι&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">t&lt;/span>&lt;span class="mclose">)&lt;/span>&lt;/span>&lt;/span>&lt;/span>. (Multiset because an item is allowed to be inserted multiple times.) We define three operations (functions) on our trees:&lt;/p>
&lt;ul>
&lt;li>&lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi mathvariant="normal">insert&lt;/mi>&lt;mo>⁡&lt;/mo>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>t&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>i&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\operatorname{insert}(t, i)&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mop">&lt;span class="mord mathrm">insert&lt;/span>&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">t&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal">i&lt;/span>&lt;span class="mclose">)&lt;/span>&lt;/span>&lt;/span>&lt;/span> denotes the tree &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>t&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">t&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6151em;">&lt;/span>&lt;span class="mord mathnormal">t&lt;/span>&lt;/span>&lt;/span>&lt;/span> with the additional item &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>i&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">i&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6595em;">&lt;/span>&lt;span class="mord mathnormal">i&lt;/span>&lt;/span>&lt;/span>&lt;/span> inserted.&lt;/li>
&lt;li>&lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi mathvariant="normal">search&lt;/mi>&lt;mo>⁡&lt;/mo>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>t&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>q&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\operatorname{search}(t, q)&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mop">&lt;span class="mord mathrm">search&lt;/span>&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">t&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.03588em;">q&lt;/span>&lt;span class="mclose">)&lt;/span>&lt;/span>&lt;/span>&lt;/span> denotes the multiset of items in the tree that intersect the bounding box &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>q&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">q&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.625em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.03588em;">q&lt;/span>&lt;/span>&lt;/span>&lt;/span>.&lt;/li>
&lt;li>&lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi mathvariant="normal">delete&lt;/mi>&lt;mo>⁡&lt;/mo>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>t&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>q&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>f&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\operatorname{delete}(t, q, f)&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mop">&lt;span class="mord mathrm">delete&lt;/span>&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">t&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.03588em;">q&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.10764em;">f&lt;/span>&lt;span class="mclose">)&lt;/span>&lt;/span>&lt;/span>&lt;/span> denotes the tree &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>t&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">t&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6151em;">&lt;/span>&lt;span class="mord mathnormal">t&lt;/span>&lt;/span>&lt;/span>&lt;/span> with the items removed that intersect &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>q&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">q&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.625em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.03588em;">q&lt;/span>&lt;/span>&lt;/span>&lt;/span>, but do not satisfy the predicate &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>f&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">f&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.8889em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.10764em;">f&lt;/span>&lt;/span>&lt;/span>&lt;/span>. (This is the most general form of deletion that can efficiently be implemented on R-trees. Simpler variants (like only deleting a single item) can be trivially defined using this general form.)&lt;/li>
&lt;/ul>
&lt;p>First let&amp;rsquo;s state the trivial specification of the empty tree: &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>ι&lt;/mi>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>ε&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;mo>=&lt;/mo>&lt;mi mathvariant="normal">∅&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">\iota(\varepsilon) = \empty&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord mathnormal">ι&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">ε&lt;/span>&lt;span class="mclose">)&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.8056em;vertical-align:-0.0556em;">&lt;/span>&lt;span class="mord">∅&lt;/span>&lt;/span>&lt;/span>&lt;/span>. We are saying that the empty tree has no items.&lt;/p>
&lt;p>Next up, insertion: &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>ι&lt;/mi>&lt;mo stretchy="false">(&lt;/mo>&lt;mi mathvariant="normal">insert&lt;/mi>&lt;mo>⁡&lt;/mo>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>t&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>i&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;mo stretchy="false">)&lt;/mo>&lt;mo>=&lt;/mo>&lt;mo stretchy="false">{&lt;/mo>&lt;mi>i&lt;/mi>&lt;mo stretchy="false">}&lt;/mo>&lt;mo>+&lt;/mo>&lt;mi>ι&lt;/mi>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>t&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\iota(\operatorname{insert}(t, i)) = \{i\} + \iota(t)&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord mathnormal">ι&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mop">&lt;span class="mord mathrm">insert&lt;/span>&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">t&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal">i&lt;/span>&lt;span class="mclose">))&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mopen">{&lt;/span>&lt;span class="mord mathnormal">i&lt;/span>&lt;span class="mclose">}&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">+&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord mathnormal">ι&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">t&lt;/span>&lt;span class="mclose">)&lt;/span>&lt;/span>&lt;/span>&lt;/span>. The items in the tree with &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>i&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">i&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6595em;">&lt;/span>&lt;span class="mord mathnormal">i&lt;/span>&lt;/span>&lt;/span>&lt;/span> inserted are exactly the items of the original tree plus &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>i&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">i&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6595em;">&lt;/span>&lt;span class="mord mathnormal">i&lt;/span>&lt;/span>&lt;/span>&lt;/span>. (&lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo>+&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">+&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6667em;vertical-align:-0.0833em;">&lt;/span>&lt;span class="mord">+&lt;/span>&lt;/span>&lt;/span>&lt;/span> instead of &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo>∪&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\cup&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.5556em;">&lt;/span>&lt;span class="mord">∪&lt;/span>&lt;/span>&lt;/span>&lt;/span> is important here, since we are dealing with multisets.)&lt;/p>
&lt;p>Next, let&amp;rsquo;s specify search: &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi mathvariant="normal">search&lt;/mi>&lt;mo>⁡&lt;/mo>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>t&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>q&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;mo>=&lt;/mo>&lt;mo stretchy="false">{&lt;/mo>&lt;mi>i&lt;/mi>&lt;mo>∈&lt;/mo>&lt;mi>ι&lt;/mi>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>t&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;mo>∣&lt;/mo>&lt;mi>q&lt;/mi>&lt;mo>∩&lt;/mo>&lt;mi>i&lt;/mi>&lt;mo mathvariant="normal">≠&lt;/mo>&lt;mi mathvariant="normal">∅&lt;/mi>&lt;mo stretchy="false">}&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\operatorname{search}(t, q) = \{ i \in \iota(t) \mid q \cap i \neq \empty \}&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mop">&lt;span class="mord mathrm">search&lt;/span>&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">t&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.03588em;">q&lt;/span>&lt;span class="mclose">)&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mopen">{&lt;/span>&lt;span class="mord mathnormal">i&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">∈&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord mathnormal">ι&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">t&lt;/span>&lt;span class="mclose">)&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">∣&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.75em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.03588em;">q&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">∩&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.8889em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal">i&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">&lt;span class="mrel">&lt;span class="mord vbox">&lt;span class="thinbox">&lt;span class="rlap">&lt;span class="strut" style="height:0.8889em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="inner">&lt;span class="mord">&lt;span class="mrel">&lt;/span>&lt;/span>&lt;/span>&lt;span class="fix">&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord">∅&lt;/span>&lt;span class="mclose">}&lt;/span>&lt;/span>&lt;/span>&lt;/span>. Searching with a bounding box &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>q&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">q&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.625em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.03588em;">q&lt;/span>&lt;/span>&lt;/span>&lt;/span> means returning all items that overlap with this box.&lt;/p>
&lt;p>Finally, deletion: &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>ι&lt;/mi>&lt;mo stretchy="false">(&lt;/mo>&lt;mi mathvariant="normal">delete&lt;/mi>&lt;mo>⁡&lt;/mo>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>t&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>q&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>f&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;mo stretchy="false">)&lt;/mo>&lt;mo>=&lt;/mo>&lt;mo stretchy="false">{&lt;/mo>&lt;mi>i&lt;/mi>&lt;mo>∈&lt;/mo>&lt;mi>ι&lt;/mi>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>t&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;mo>∣&lt;/mo>&lt;mi>q&lt;/mi>&lt;mo>∩&lt;/mo>&lt;mi>i&lt;/mi>&lt;mo>=&lt;/mo>&lt;mi mathvariant="normal">∅&lt;/mi>&lt;mo>∨&lt;/mo>&lt;mi>f&lt;/mi>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>i&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;mo stretchy="false">}&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\iota(\operatorname{delete}(t, q, f)) = \{ i \in \iota(t) \mid q \cap i = \empty \lor f(i) \}&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord mathnormal">ι&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mop">&lt;span class="mord mathrm">delete&lt;/span>&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">t&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.03588em;">q&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.10764em;">f&lt;/span>&lt;span class="mclose">))&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mopen">{&lt;/span>&lt;span class="mord mathnormal">i&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">∈&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord mathnormal">ι&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">t&lt;/span>&lt;span class="mclose">)&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">∣&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.75em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.03588em;">q&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">∩&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6595em;">&lt;/span>&lt;span class="mord mathnormal">i&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.8056em;vertical-align:-0.0556em;">&lt;/span>&lt;span class="mord">∅&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">∨&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.10764em;">f&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">i&lt;/span>&lt;span class="mclose">)}&lt;/span>&lt;/span>&lt;/span>&lt;/span>. We define deletion as a kind of filtering: we keep items that are either completely outside of &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>q&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">q&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.625em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.03588em;">q&lt;/span>&lt;/span>&lt;/span>&lt;/span>, or which satisfy &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>f&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">f&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.8889em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.10764em;">f&lt;/span>&lt;/span>&lt;/span>&lt;/span>.&lt;/p>
&lt;h3 id="formal-specification-in-coq">Formal specification in Coq&lt;/h3>
&lt;p>Multisets would be somewhat tricky to represent in Coq, so I will just use plain lists instead. Duplicate items are now represented simply by including them in the list multiple times.&lt;/p>
&lt;p>Regular equality between lists would give wrong results though, since the items can be ordered differently. Instead, we will use the concept of permutations. Two lists are permutations of each other iff the multisets they represent are equal. (More plainly, if you can reorder the items of a list to get the other one, that means they have the same items.)&lt;/p>
&lt;p>The Coq standard library already includes a the permutation relation, so we will just use it. For convenience, let&amp;rsquo;s denote the proposition that two lists &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>a&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">a&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">a&lt;/span>&lt;/span>&lt;/span>&lt;/span> and &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>b&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">b&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6944em;">&lt;/span>&lt;span class="mord mathnormal">b&lt;/span>&lt;/span>&lt;/span>&lt;/span> are permutations of each other with &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>a&lt;/mi>&lt;mo>∼&lt;/mo>&lt;mi>b&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">a \sim b&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">a&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">∼&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6944em;">&lt;/span>&lt;span class="mord mathnormal">b&lt;/span>&lt;/span>&lt;/span>&lt;/span>.&lt;/p>
&lt;p>Let&amp;rsquo;s also tell Coq about this notation (you don&amp;rsquo;t need to understand the exact details of this definition, it just works as you would expect):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Notation&lt;/span> &lt;span class="s2">&amp;#34;a ~ b&amp;#34;&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">Permutation&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">at&lt;/span> &lt;span class="n">level&lt;/span> &lt;span class="mi">70&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">no&lt;/span> &lt;span class="n">associativity&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The Coq standard library defines list concatenation as &lt;code>++&lt;/code>. &lt;code>negb&lt;/code> stands for boolean negation, &lt;code>||&lt;/code> for disjunction. &lt;code>bbox&lt;/code> is the type of AABBs, and &lt;code>bbox_intersect&lt;/code> is a function determining whether two bounding boxes intersect. &lt;code>filter&lt;/code> is the usual filtering function from functional programming languages.&lt;/p>
&lt;p>Here is the whole specification. I will break it down step-by-step afterwards:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Context&lt;/span> &lt;span class="o">{&lt;/span>&lt;span class="n">I&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">Type&lt;/span>&lt;span class="o">}&lt;/span> &lt;span class="o">{&lt;/span>&lt;span class="n">item_bbox&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">I&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">bbox&lt;/span>&lt;span class="o">}.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Class&lt;/span> &lt;span class="n">Container&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">T&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">Type&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">items&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">I&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">empty&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">T&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">insert&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">I&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">T&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">search&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">bbox&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">I&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">delete&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">bbox&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">I&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="kt">bool&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">T&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">empty_correct&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">items&lt;/span> &lt;span class="n">empty&lt;/span> &lt;span class="o">~&lt;/span> &lt;span class="bp">[]&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">insert_correct&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="k">forall&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">items&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">insert&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">~&lt;/span> &lt;span class="o">[&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="o">++&lt;/span> &lt;span class="n">items&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">search_correct&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="k">forall&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="n">q&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">search&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="o">~&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">filter&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="k">fun&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">bbox_intersect&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">item_bbox&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">))&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">items&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">delete_correct&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="k">forall&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">items&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">delete&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">~&lt;/span> &lt;span class="n">filter&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="k">fun&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">negb&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">bbox_intersect&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">item_bbox&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">))&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="n">f&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">items&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>First we declare that there is some type &lt;code>I&lt;/code> (the type of items), and a projection &lt;code>item_bbox&lt;/code> that tells us the bounding box of any item.&lt;/p>
&lt;p>The &lt;code>Container&lt;/code> interface&lt;sup id="fnref:1">&lt;a href="#fn:1" role="doc-noteref">1&lt;/a>&lt;span class="footnote-tooltip">&lt;code>Container&lt;/code> is actually a &lt;a href="https://coq.inria.fr/refman/addendum/type-classes.html">typeclass&lt;/a>, a feature popularized by Haskell. In Coq they are mostly equivalent to record types, which are just syntax sugar for inductive types.&lt;/span>&lt;/sup> then consists of the following entries:&lt;/p>
&lt;ul>
&lt;li>&lt;code>T&lt;/code>, the type of trees.&lt;/li>
&lt;li>&lt;code>items&lt;/code>, the function listing the items in a tree.&lt;/li>
&lt;li>&lt;code>empty&lt;/code>, the empty tree.&lt;/li>
&lt;li>&lt;code>insert&lt;/code>, &lt;code>search&lt;/code>, and &lt;code>delete&lt;/code>, our three operations on trees.&lt;/li>
&lt;li>&lt;code>empty_correct&lt;/code>, &lt;code>insert_correct&lt;/code>, &lt;code>search_correct&lt;/code>, and &lt;code>delete_correct&lt;/code>, the proofs of the four correctness propositions.&lt;/li>
&lt;/ul>
&lt;p>The goal of the rest of this article is to provide an implementation of &lt;code>Container&lt;/code>.&lt;/p>
&lt;h1 id="techniques">Techniques&lt;/h1>
&lt;p>This section introduces some general techniques I use in this project.&lt;/p>
&lt;h2 id="extraction">Extraction&lt;/h2>
&lt;p>The transpilation of a Coq program into some other non-dependently typed functional programming language is called &lt;em>extraction&lt;/em>. The best supported extraction target is OCaml, so I will be focusing on that. (Note that extraction is not needed for the proofs themselves, but it is needed to run the verified implementations in a reasonable manner.)&lt;/p>
&lt;p>The reason it&amp;rsquo;s called extraction is because we are erasing a lot of type information, and importantly all proofs.&lt;sup id="fnref:2">&lt;a href="#fn:2" role="doc-noteref">2&lt;/a>&lt;span class="footnote-tooltip">While in theory there is no clear delineation between proofs and programs, in any reasonable Coq development all proofs will be in the &lt;code>Prop&lt;/code> sort. Extraction erases everything in &lt;code>Prop&lt;/code>.&lt;/span>&lt;/sup>&lt;/p>
&lt;p>Let&amp;rsquo;s look at this simple example first:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Require&lt;/span> &lt;span class="n">Coq&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extraction&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ExtrOcamlBasic&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">double_list&lt;/span> &lt;span class="o">{&lt;/span>&lt;span class="n">A&lt;/span>&lt;span class="o">}&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">l&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">A&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">++&lt;/span> &lt;span class="n">l&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">Recursive&lt;/span> &lt;span class="n">Extraction&lt;/span> &lt;span class="n">double_list&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The first line tells Coq to configure common options for OCaml extraction. (E.g. to map common types, like &lt;code>list&lt;/code>, to their native OCaml equivalents.) The word &lt;code>Recursive&lt;/code> in the last line tells Coq to extract not just &lt;code>double_list&lt;/code>, but also anything that it depends on. We get this as the result of the extraction:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-ocaml" data-lang="ocaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c">(** val app : &amp;#39;a1 list -&amp;gt; &amp;#39;a1 list -&amp;gt; &amp;#39;a1 list **)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">let&lt;/span> &lt;span class="k">rec&lt;/span> &lt;span class="n">app&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">match&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="bp">[]&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">m&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="n">l1&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">app&lt;/span> &lt;span class="n">l1&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">(** val double_list : &amp;#39;a1 list -&amp;gt; &amp;#39;a1 list **)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">let&lt;/span> &lt;span class="n">double_list&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">app&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="n">l&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This is mostly what we expected. &lt;code>app&lt;/code> is also extracted beside &lt;code>double_list&lt;/code>, since it depends on it.&lt;/p>
&lt;h3 id="erasing-proofs">Erasing proofs&lt;/h3>
&lt;p>Let&amp;rsquo;s take this implementation of the list head function:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">hd&lt;/span> &lt;span class="o">{&lt;/span>&lt;span class="n">A&lt;/span>&lt;span class="o">}&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">l&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">A&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">{&lt;/span>&lt;span class="n">prf&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">length&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="o">}&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">match&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">length&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="bp">[]&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="k">fun&lt;/span> &lt;span class="n">prf&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">ltac&lt;/span>&lt;span class="o">:(&lt;/span>&lt;span class="k">simpl&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="n">prf&lt;/span>&lt;span class="o">;&lt;/span> &lt;span class="n">lia&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">h&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="k">fun&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">h&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span> &lt;span class="n">prf&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>It receives a proof that the list is non-empty, and with this it can prove the empty-list case impossible. Coq&amp;rsquo;s extraction does a wonderful job with this function:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-ocaml" data-lang="ocaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c">(** val hd : &amp;#39;a1 list -&amp;gt; &amp;#39;a1 **)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">let&lt;/span> &lt;span class="n">hd&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">function&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">|&lt;/span> &lt;span class="bp">[]&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="k">assert&lt;/span> &lt;span class="bp">false&lt;/span> &lt;span class="c">(* absurd case *)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">|&lt;/span> &lt;span class="n">h&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">h&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>All of the complicated proof manipulation is erased, and the impossible case is marked with an &lt;code>assert false&lt;/code>.&lt;/p>
&lt;p>The main takeaway you should have here is that proof manipulation in Coq has no runtime performance impact, since all proofs are erased. And as long you trust the extractor, the proofs still ensure the correctness of the extracted program.&lt;/p>
&lt;h3 id="dependent-types">Dependent types&lt;/h3>
&lt;p>Now you might be thinking that sure, proofs can be erased, but Coq is dependently typed, while OCaml is not, what happens when we try to extract a dependently typed function? Here is an example (you are going to have to wait until the next section for an explanation of what &lt;code>Z&lt;/code> is and how it extracts to a literal &lt;code>1&lt;/code>):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">good_luck_with_this_ocaml&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">b&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">bool&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="k">then&lt;/span> &lt;span class="n">Z&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="kt">bool&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:=&lt;/span> &lt;span class="k">match&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="k">with&lt;/span> &lt;span class="bp">true&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="bp">false&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="bp">false&lt;/span> &lt;span class="k">end&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And here is what it extracts to:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-ocaml" data-lang="ocaml">&lt;span class="line">&lt;span class="cl">&lt;span class="k">type&lt;/span> &lt;span class="o">__&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nn">Obj&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">t&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">(** val good_luck_with_this_ocaml : bool -&amp;gt; __ **)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">let&lt;/span> &lt;span class="n">good_luck_with_this_ocaml&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">function&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">|&lt;/span> &lt;span class="bp">true&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nn">Obj&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">magic&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">|&lt;/span> &lt;span class="bp">false&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nn">Obj&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">magic&lt;/span> &lt;span class="bp">false&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>Obj.magic&lt;/code> is OCaml&amp;rsquo;s name for an unsafe cast between two arbitrary types. Unlike in Java or other languages, there is no runtime type information in OCaml, so a bad unsafe cast leads to memory corruption. For this reason, its use is very much discouraged. But, in this instance, since Coq&amp;rsquo;s typechecker (the kernel) already checked the types, we can be pretty sure that these &lt;code>Obj.magic&lt;/code> usages are correct.&lt;/p>
&lt;p>In fact, the extractor could just use &lt;code>Obj.magic&lt;/code> everywhere and ignore OCaml&amp;rsquo;s type system alltogether. Extracting to an untyped functional programming language like Scheme is actually much easier than to OCaml: just erase &lt;strong>all&lt;/strong> of the types, and that&amp;rsquo;s it. In this case we are just using Scheme as a convenient implementation of &lt;a href="https://en.wikipedia.org/wiki/Lambda_calculus">lambda calculus&lt;/a>.&lt;/p>
&lt;p>Extracting the above function to Scheme yields no weird types, since there are no static types in Scheme:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-scheme" data-lang="scheme">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="k">define &lt;/span>&lt;span class="nv">good_luck_with_this_ocaml&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="k">lambda &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">b&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nf">match&lt;/span> &lt;span class="nv">b&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">((&lt;/span>&lt;span class="nf">True&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">`&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">Zpos&lt;/span> &lt;span class="o">,`&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">XH&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">((&lt;/span>&lt;span class="nf">False&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">`&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">False&lt;/span>&lt;span class="p">)))))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The extractor actually goes to great lengths to come up with some reasonable OCaml translation of the Coq types, and it only falls back to &lt;code>Obj.magic&lt;/code> when absolutely necessary. You can read more about the extraction mechanism &lt;a href="https://coq.inria.fr/refman/addendum/extraction.html">in the Coq reference manual&lt;/a> and in &lt;span class="hugo-cite-intext" itemprop="citation">&lt;span class="tooltip-trigger">&lt;a href="#cite:3">[3]&lt;/a>&lt;span class="tooltip">P. Letouzey, &lt;span>“A New Extraction for Coq,”&lt;/span> in &lt;em>Types for Proofs and Programs&lt;/em>, G. Goos, J. Hartmanis, J. Van Leeuwen, H. Geuvers, and F. Wiedijk, Eds., Berlin, Heidelberg: Springer Berlin Heidelberg, 2003, pp. 200–219. doi: &lt;a href="https://doi.org/10.1007/3-540-39185-1_12">10.1007/3-540-39185-1_12&lt;/a>.&lt;/span>&lt;/span>&lt;/span>.&lt;/p>
&lt;h3 id="arithmetic">Arithmetic&lt;/h3>
&lt;p>Arithmetic by default does not play very well with extraction. Let&amp;rsquo;s take this example:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">double&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">nat&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This &lt;code>double&lt;/code> function gets extracted to this OCaml code:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-ocaml" data-lang="ocaml">&lt;span class="line">&lt;span class="cl">&lt;span class="k">type&lt;/span> &lt;span class="n">nat&lt;/span> &lt;span class="o">=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">|&lt;/span> &lt;span class="nc">O&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">|&lt;/span> &lt;span class="nc">S&lt;/span> &lt;span class="k">of&lt;/span> &lt;span class="n">nat&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">module&lt;/span> &lt;span class="nc">Nat&lt;/span> &lt;span class="o">=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">struct&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">(** val add : nat -&amp;gt; nat -&amp;gt; nat **)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">let&lt;/span> &lt;span class="k">rec&lt;/span> &lt;span class="n">add&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">match&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="nc">O&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">m&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="nc">S&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nc">S&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">add&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">(** val mul : nat -&amp;gt; nat -&amp;gt; nat **)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">let&lt;/span> &lt;span class="k">rec&lt;/span> &lt;span class="n">mul&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">match&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="nc">O&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nc">O&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="nc">S&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">add&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">mul&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">(** val double : nat -&amp;gt; nat **)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">let&lt;/span> &lt;span class="n">double&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nn">Nat&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">mul&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="nc">S&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="nc">S&lt;/span> &lt;span class="nc">O&lt;/span>&lt;span class="o">))&lt;/span> &lt;span class="n">a&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This is not&amp;hellip; great. &lt;code>nat&lt;/code> is good when proving mathematical theorems because of its conceptual simplicity, but storing a number &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>n&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">n&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;/span>&lt;/span>&lt;/span> using &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>O&lt;/mi>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>n&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">O(n)&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.02778em;">O&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;span class="mclose">)&lt;/span>&lt;/span>&lt;/span>&lt;/span> storage is pretty bad. What&amp;rsquo;s wrong with OCaml&amp;rsquo;s built in integers and arithmetic operators? Why can&amp;rsquo;t we just extract &lt;code>double&lt;/code> simply to &lt;code>let double a = 2 * a&lt;/code> in OCaml?&lt;/p>
&lt;p>The issue is that that such an extraction would technically be incorrect. OCaml&amp;rsquo;s integers are 63 bit, and can&amp;rsquo;t represent all integers. In everyday programming practice we usually just ignore such limits, as they are rarely exceeded.&lt;/p>
&lt;p>A solution to the aforementioned problem is to use &lt;code>Z&lt;/code> instead of &lt;code>nat&lt;/code> for arithmetic. I will let the comments from the standard library explain how &lt;code>Z&lt;/code> works:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="c">(** [positive] is a datatype representing the strictly positive integers
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"> in a binary way. Starting from 1 (represented by [xH]), one can
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"> add a new least significant digit via [xO] (digit 0) or [xI] (digit 1).
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"> Numbers in [positive] will also be denoted using a decimal notation;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"> e.g. [6%positive] will abbreviate [xO (xI xH)] *)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Inductive&lt;/span> &lt;span class="n">positive&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kn">Set&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">xI&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">positive&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">positive&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">xO&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">positive&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">positive&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">xH&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">positive&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">(** [Z] is a datatype representing the integers in a binary way.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"> An integer is either zero or a strictly positive number
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"> (coded as a [positive]) or a strictly negative number
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"> (whose opposite is stored as a [positive] value).
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"> Numbers in [Z] will also be denoted using a decimal notation;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"> e.g. [(-6)%Z] will abbreviate [Zneg (xO (xI xH))] *)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Inductive&lt;/span> &lt;span class="n">Z&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kn">Set&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">Z0&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">Z&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">Zpos&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">positive&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">Z&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">Zneg&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">positive&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">Z&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>I won&amp;rsquo;t show the extraction results using &lt;code>Z&lt;/code> as it would be even longer, but with &lt;code>Z&lt;/code> we at least don&amp;rsquo;t lose asymptotic complexity with arithmetic.&lt;/p>
&lt;p>&lt;code>Z&lt;/code> is still quite inefficient though, as we are storing &lt;strong>each bit of a number as a heap object&lt;/strong>.&lt;/p>
&lt;p>For some applications where arithmetic is not critical for performance, this can be worth it in exchange for the correctness guarantees. (E.g. &lt;a href="https://github.com/AbsInt/CompCert">CompCert&lt;/a> does this.)&lt;/p>
&lt;p>If you want to go further and step into dangerous territory, you can tell Coq to extract &lt;code>Z&lt;/code> to OCaml&amp;rsquo;s native integers. This:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Require&lt;/span> &lt;span class="kn">Import&lt;/span> &lt;span class="n">Coq&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extraction&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ExtrOcamlZInt&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">double&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">Z&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now translates into this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-ocaml" data-lang="ocaml">&lt;span class="line">&lt;span class="cl">&lt;span class="k">module&lt;/span> &lt;span class="nc">Z&lt;/span> &lt;span class="o">=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">struct&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">(** val mul : int -&amp;gt; int -&amp;gt; int **)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">let&lt;/span> &lt;span class="n">mul&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">(&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">(** val double : int -&amp;gt; int **)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">let&lt;/span> &lt;span class="n">double&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nn">Z&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">mul&lt;/span> &lt;span class="o">((&lt;/span>&lt;span class="k">fun&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="n">a&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Close enough, the OCaml compiler can optimize this to achieve glorious full native performance.&lt;sup id="fnref:3">&lt;a href="#fn:3" role="doc-noteref">3&lt;/a>&lt;span class="footnote-tooltip">Well, the thing is&amp;hellip; OCaml actually has 6&lt;strong>3&lt;/strong> bit integers, because it uses the lowest bit for tagging. And unfortunately this &lt;a href="https://blog.janestreet.com/what-is-gained-and-lost-with-63-bit-integers/">does affect performance&lt;/a>.&lt;/span>&lt;/sup> In return, we lose correctness, as overflow now becomes possible.&lt;/p>
&lt;p>(For completeness I would also like to mention that Coq does have &lt;a href="https://coq.inria.fr/refman/language/core/primitive.html#primitive-integers">built-in support for 63 bit integers&lt;/a>, which are in fact safe to directly extract to OCaml integers. With this you are stepping into the territory of modular arithmetic though, which can complicate some proofs.)&lt;/p>
&lt;h3 id="transpiling-to-javascript">Transpiling to JavaScript&lt;/h3>
&lt;p>Chaining together the OCaml extraction process with an OCaml to JavaScript transpiler like &lt;a href="https://github.com/ocsigen/js_of_ocaml">js_of_ocaml&lt;/a> or &lt;a href="https://github.com/melange-re/melange">melange&lt;/a> works surprisingly well to get Coq code running in the browser. js_of_ocaml is more mature, and focuses more on producing code with correct behavior, while melange focuses on producing readable JavaScript, that is as close to the original OCaml code as possible. For this reason, I will be using melange&amp;rsquo;s output in the following few examples.&lt;/p>
&lt;p>Taking our previous &lt;code>good_luck_with_this_ocaml&lt;/code> example, and transpiling the extracted OCaml with melange, we obtain perfectly legible JavaScript:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-js" data-lang="js">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">function&lt;/span> &lt;span class="nx">good_luck_with_this_ocaml&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">param&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nx">param&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The main reason I wanted to show some JavaScript output is to demonstrate why tail-recursion is useful. Here is an example tail-recursive function to sum a list of numbers:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Fixpoint&lt;/span> &lt;span class="n">sum&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">l&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">Z&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">acc&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">Z&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">match&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="bp">[]&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">acc&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">h&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="n">l&amp;#39;&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">sum&lt;/span> &lt;span class="n">l&amp;#39;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">acc&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">h&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And here is the JavaScript it translates to:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-js" data-lang="js">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">function&lt;/span> &lt;span class="nx">sum&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">_l&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">_acc&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">var&lt;/span> &lt;span class="nx">acc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">_acc&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">var&lt;/span> &lt;span class="nx">l&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">_l&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="nx">l&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nx">acc&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">_acc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">acc&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="nx">l&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">hd&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">_l&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">l&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">tl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">continue&lt;/span> &lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The variable names are a bit ugly, but most importantly, it got translated into a loop, without any potentially slow (or stack overflowing) recursive function calls.&lt;/p>
&lt;h2 id="the-sig-type">The &lt;code>sig&lt;/code> type&lt;/h2>
&lt;p>In this section we are going to take a look at the &lt;code>sig&lt;/code> type, which can be used for adding pre- and postconditions to functions.&lt;/p>
&lt;p>Let&amp;rsquo;s look at the definition of the &lt;code>sig&lt;/code> (which stands for &lt;em>sigma&lt;/em>) type from the standard library:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Inductive&lt;/span> &lt;span class="n">sig&lt;/span> &lt;span class="o">{&lt;/span>&lt;span class="n">A&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">Type&lt;/span>&lt;span class="o">}&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">P&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">A&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="kt">Prop&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">Type&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">exist&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">A&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">(_&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">P&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">sig&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This is a special kind of pair, where the first item is a value of some type &lt;code>A&lt;/code>, while the second member is a proof of some predicate &lt;code>P&lt;/code> defined on &lt;code>A&lt;/code>. Basically, this lets us package together some value, and a proof about it.&lt;/p>
&lt;p>Let&amp;rsquo;s look at an example:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">five_gt_zero&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="mi">5&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="n">lia&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="kn">Qed&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">a_positive_number&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">sig&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="k">fun&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">exist&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="mi">5&lt;/span> &lt;span class="n">five_gt_zero&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>sig (fun n =&amp;gt; n &amp;gt; 0)&lt;/code> is the type of pairs of a number, and a proof that this number is greater than zero. If we don&amp;rsquo;t want to be too pedantic with the language, we can simply say that &lt;code>sig (fun n =&amp;gt; n &amp;gt; 0)&lt;/code> is the type of positive numbers. (For this reason &lt;code>sig&lt;/code> is also called a &lt;em>subset&lt;/em> type.)&lt;/p>
&lt;p>The standard library also defines a notation for &lt;code>sig&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Notation&lt;/span> &lt;span class="s2">&amp;#34;{ x : A | P }&amp;#34;&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">sig&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">A&lt;/span>&lt;span class="o">:=&lt;/span>&lt;span class="n">A&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="k">fun&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="o">)).&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This is inspired by the set builder notation, as the &lt;code>sig&lt;/code> type is similar to sets defined in this way. &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo stretchy="false">{&lt;/mo>&lt;mi>n&lt;/mi>&lt;mo>∈&lt;/mo>&lt;mi mathvariant="double-struck">N&lt;/mi>&lt;mo>∣&lt;/mo>&lt;mi>n&lt;/mi>&lt;mo>&amp;gt;&lt;/mo>&lt;mn>0&lt;/mn>&lt;mo stretchy="false">}&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\{ n \in \mathbb{N} \mid n &amp;gt; 0 \}&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mopen">{&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">∈&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord mathbb">N&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">∣&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.5782em;vertical-align:-0.0391em;">&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">&amp;gt;&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord">0&lt;/span>&lt;span class="mclose">}&lt;/span>&lt;/span>&lt;/span>&lt;/span> in set theory and &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo stretchy="false">{&lt;/mo>&lt;mi>n&lt;/mi>&lt;mo>:&lt;/mo>&lt;mrow>&lt;mi mathvariant="monospace">n&lt;/mi>&lt;mi mathvariant="monospace">a&lt;/mi>&lt;mi mathvariant="monospace">t&lt;/mi>&lt;/mrow>&lt;mo>∣&lt;/mo>&lt;mi>n&lt;/mi>&lt;mo>&amp;gt;&lt;/mo>&lt;mn>0&lt;/mn>&lt;mo stretchy="false">}&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\{ n : \mathtt{nat} \mid n &amp;gt; 0 \}&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mopen">{&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">:&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord">&lt;span class="mord mathtt">nat&lt;/span>&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">∣&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.5782em;vertical-align:-0.0391em;">&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">&amp;gt;&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord">0&lt;/span>&lt;span class="mclose">}&lt;/span>&lt;/span>&lt;/span>&lt;/span> in Coq&amp;rsquo;s type theory basically represent the same idea: one is the &lt;em>set&lt;/em> of positive numbers, while the other is the &lt;em>type&lt;/em> of positive numbers.&lt;/p>
&lt;p>The way we use &lt;code>sig&lt;/code> for specifying functions is by taking in or returning &lt;code>sig&lt;/code> types. A &lt;code>sig&lt;/code> argument is basically a precondition, while a returned &lt;code>sig&lt;/code> is like a postcondition. You are going to see such uses of &lt;code>sig&lt;/code> in &lt;a href="#list-utility-functions">this&lt;/a> section.&lt;/p>
&lt;h2 id="coqs-program-attribute">Coq&amp;rsquo;s &lt;code>#[program]&lt;/code> attribute&lt;/h2>
&lt;p>The &lt;code>#[program]&lt;/code>&lt;sup id="fnref:4">&lt;a href="#fn:4" role="doc-noteref">4&lt;/a>&lt;span class="footnote-tooltip">Note that you will more often see the legacy &lt;code>Program&lt;/code> form used elsewhere, but for the sake of consistency I will be using the attribute form &lt;code>#[program]&lt;/code>.&lt;/span>&lt;/sup> attribute is a little weird, it provides some loosely related additions to Coq&amp;rsquo;s term language. I use it extensively in this project, so I wanted to introduce it briefly. What does it do exactly? From the &lt;a href="https://coq.inria.fr/refman/addendum/program.html">reference manual&lt;/a>:&lt;/p>
&lt;blockquote>
&lt;p>The goal of &lt;code>#[program]&lt;/code> is to program as in a regular functional programming language whilst using as rich a specification as desired and proving that the code meets the specification using the whole Coq proof apparatus.&lt;/p>
&lt;/blockquote>
&lt;p>To this end, it enriches Coq&amp;rsquo;s term language with a couple new features:&lt;/p>
&lt;ul>
&lt;li>Equality hypotheses are automatically injected into match expressions. (So e.g. in &lt;code>match n with 0 =&amp;gt; ... | _ =&amp;gt; ... end&lt;/code> the first branch will have a proof of &lt;code>n = 0&lt;/code> in its context.)&lt;/li>
&lt;li>Any value of &lt;code>T&lt;/code> and &lt;code>{ x : T | P }&lt;/code> can be used interchangeably. This is very useful when writing functions with rich specifications: we can write our function (mostly) like in a regular programming language, and &lt;code>#[program]&lt;/code> will generate any necessary proof obligations needed for the &lt;code>sig&lt;/code> types.&lt;/li>
&lt;li>Fixpoints can automatically be transformed to use a measure (or any well-founded relation) for termination checking with a simple annotation. (See &lt;a href="#proving-termination-manually">this&lt;/a> section for an example.)&lt;/li>
&lt;li>Filling of holes is automatically attempted using a predefined &amp;ldquo;obligation tactic&amp;rdquo;, and a proof obligation is only generated if this tactic fails.&lt;/li>
&lt;/ul>
&lt;p>&lt;code>#[program]&lt;/code> is not a magic bullet, but it still helps a lot when working with rich specifications, and I am using it for most non-trivial functions in my R-tree implementation.&lt;/p>
&lt;h2 id="termination">Termination&lt;/h2>
&lt;p>In Coq, all functions have to terminate. If non-terminating functions were allowed, proving &lt;code>False&lt;/code> would be trivial:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Fixpoint&lt;/span> &lt;span class="n">proof_of_false&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">n&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">nat&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">False&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:=&lt;/span> &lt;span class="n">proof_of_false&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">n&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>When trying to check the above in Coq, we get an error message:&lt;/p>
&lt;pre tabindex="0">&lt;code>Error: Recursive definition of proof_of_false is ill-formed.
In environment
proof_of_false : nat -&amp;gt; False
n : nat
Recursive call to proof_of_false has principal argument equal to
&amp;#34;(n + 1)%nat&amp;#34; instead of a subterm of &amp;#34;n&amp;#34;.
Recursive definition is: &amp;#34;fun n : nat =&amp;gt; proof_of_false (n + 1)%nat&amp;#34;.
&lt;/code>&lt;/pre>&lt;p>On the other hand, this (terminating) function is correctly accepted:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Fixpoint&lt;/span> &lt;span class="n">fib&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">n&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">nat&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">match&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">S&lt;/span> &lt;span class="n">n&amp;#39;&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">match&lt;/span> &lt;span class="n">n&amp;#39;&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">S&lt;/span> &lt;span class="n">n&amp;#39;&amp;#39;&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">fib&lt;/span> &lt;span class="n">n&amp;#39;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">fib&lt;/span> &lt;span class="n">n&amp;#39;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>So given that the halting problem is undecidable and all, how does Coq magically know which functions terminate?&lt;/p>
&lt;p>It doesn&amp;rsquo;t. It only accepts a small subset of terminating functions, whose termination can be proven using a simple algorithm. The above definition of &lt;code>fib&lt;/code> is already a bit contrived to get it accepted by Coq&amp;rsquo;s termination checker.&lt;/p>
&lt;p>Coq uses something called &lt;em>structural recursion&lt;/em>. All recursive functions need to have one of their arguments designated as the &lt;em>decreasing argument&lt;/em>. (Most of the time Coq automatically guesses which argument is decreasing, so we don&amp;rsquo;t have to specify it.)&lt;/p>
&lt;p>It then checks whether in each recursive call, the decreasing argument gets &lt;em>structurally smaller&lt;/em>. According to the Coq manual &amp;ldquo;the definition of being structurally smaller is a bit technical&amp;rdquo;, but you are welcome to &lt;a href="https://coq.inria.fr/refman/language/core/inductive.html#fixpoint-definitions">dive into it&lt;/a> if you are interested in the details. Intuitively, it means that the decreasing argument is always contained in (a subterm of) the previous value of the decreasing argument.&lt;/p>
&lt;p>This is easy to see in the &lt;code>fib&lt;/code> example above: both &lt;code>n'&lt;/code> and &lt;code>n''&lt;/code> are obtained from &lt;code>n&lt;/code> by pattern matching on it.&lt;/p>
&lt;p>Now let&amp;rsquo;s examine why the straightforward way to write &lt;code>fib&lt;/code> doesn&amp;rsquo;t get accepted by Coq:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Fixpoint&lt;/span> &lt;span class="n">fib&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">n&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">nat&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">match&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">fib&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">n&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">fib&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">n&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>n - 1&lt;/code> and &lt;code>n - 2&lt;/code> are &lt;strong>not&lt;/strong> structurally smaller than &lt;code>n&lt;/code>, as far as Coq&amp;rsquo;s simple termination checking algorithm is concerned.&lt;/p>
&lt;p>Unfortunately, a lot of useful recursive functions cannot be written in a structurally recursive form. I will discuss a solution in the next section.&lt;/p>
&lt;h3 id="proving-termination-manually">Proving termination manually&lt;/h3>
&lt;p>A commonly used technique for going beyond structural recursion is using &lt;a href="https://en.wikipedia.org/wiki/Well-founded_relation">&lt;em>well-founded relations&lt;/em>&lt;/a>.&lt;/p>
&lt;p>A relation &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo>≺&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\prec&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.5782em;vertical-align:-0.0391em;">&lt;/span>&lt;span class="mrel">≺&lt;/span>&lt;/span>&lt;/span>&lt;/span> is well-founded if it contains no infinite sequence of elements &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;msub>&lt;mi>x&lt;/mi>&lt;mn>0&lt;/mn>&lt;/msub>&lt;mo separator="true">,&lt;/mo>&lt;msub>&lt;mi>x&lt;/mi>&lt;mn>1&lt;/mn>&lt;/msub>&lt;mo separator="true">,&lt;/mo>&lt;msub>&lt;mi>x&lt;/mi>&lt;mn>2&lt;/mn>&lt;/msub>&lt;mo separator="true">,&lt;/mo>&lt;mo>…&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">x_0, x_1, x_2, \ldots&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.625em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord">&lt;span class="mord mathnormal">x&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t vlist-t2">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.3011em;">&lt;span style="top:-2.55em;margin-left:0em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">0&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="vlist-s">​&lt;/span>&lt;/span>&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.15em;">&lt;span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord">&lt;span class="mord mathnormal">x&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t vlist-t2">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.3011em;">&lt;span style="top:-2.55em;margin-left:0em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">1&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="vlist-s">​&lt;/span>&lt;/span>&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.15em;">&lt;span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord">&lt;span class="mord mathnormal">x&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t vlist-t2">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.3011em;">&lt;span style="top:-2.55em;margin-left:0em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">2&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="vlist-s">​&lt;/span>&lt;/span>&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.15em;">&lt;span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="minner">…&lt;/span>&lt;/span>&lt;/span>&lt;/span> such that &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi mathvariant="normal">∀&lt;/mi>&lt;mi>n&lt;/mi>&lt;mo>∈&lt;/mo>&lt;mi mathvariant="double-struck">N&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;msub>&lt;mi>x&lt;/mi>&lt;mrow>&lt;mi>n&lt;/mi>&lt;mo>+&lt;/mo>&lt;mn>1&lt;/mn>&lt;/mrow>&lt;/msub>&lt;mo>≺&lt;/mo>&lt;msub>&lt;mi>x&lt;/mi>&lt;mi>n&lt;/mi>&lt;/msub>&lt;/mrow>&lt;annotation encoding="application/x-tex">\forall n \in \mathbb{N}, x_{n+1} \prec x_n&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.7335em;vertical-align:-0.0391em;">&lt;/span>&lt;span class="mord">∀&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">∈&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.8972em;vertical-align:-0.2083em;">&lt;/span>&lt;span class="mord mathbb">N&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord">&lt;span class="mord mathnormal">x&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t vlist-t2">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.3011em;">&lt;span style="top:-2.55em;margin-left:0em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">&lt;span class="mord mathnormal mtight">n&lt;/span>&lt;span class="mbin mtight">+&lt;/span>&lt;span class="mord mtight">1&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="vlist-s">​&lt;/span>&lt;/span>&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.2083em;">&lt;span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">≺&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.5806em;vertical-align:-0.15em;">&lt;/span>&lt;span class="mord">&lt;span class="mord mathnormal">x&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t vlist-t2">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.1514em;">&lt;span style="top:-2.55em;margin-left:0em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mathnormal mtight">n&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="vlist-s">​&lt;/span>&lt;/span>&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.15em;">&lt;span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>.&lt;/p>
&lt;p>Intuitively, this means that the relation behaves like &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo>&amp;lt;&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">&amp;lt;&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.5782em;vertical-align:-0.0391em;">&lt;/span>&lt;span class="mrel">&amp;lt;&lt;/span>&lt;/span>&lt;/span>&lt;/span> behaves on the natural numbers: you can&amp;rsquo;t have an infinite sequence of decreasing numbers. Eventually, you are going to hit a minimal element (&lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mn>0&lt;/mn>&lt;/mrow>&lt;annotation encoding="application/x-tex">0&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6444em;">&lt;/span>&lt;span class="mord">0&lt;/span>&lt;/span>&lt;/span>&lt;/span> in the case of &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi mathvariant="double-struck">N&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">\mathbb{N}&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6889em;">&lt;/span>&lt;span class="mord mathbb">N&lt;/span>&lt;/span>&lt;/span>&lt;/span>). (And indeed, &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo>&amp;lt;&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">&amp;lt;&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.5782em;vertical-align:-0.0391em;">&lt;/span>&lt;span class="mrel">&amp;lt;&lt;/span>&lt;/span>&lt;/span>&lt;/span> is well-founded.)&lt;/p>
&lt;p>If you don&amp;rsquo;t quite get well-foundedness yet, don&amp;rsquo;t worry: natural numbers are all I am going to use in the next example. Just &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi mathvariant="double-struck">N&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">\mathbb{N}&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6889em;">&lt;/span>&lt;span class="mord mathbb">N&lt;/span>&lt;/span>&lt;/span>&lt;/span> equipped with &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo>&amp;lt;&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">&amp;lt;&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.5782em;vertical-align:-0.0391em;">&lt;/span>&lt;span class="mrel">&amp;lt;&lt;/span>&lt;/span>&lt;/span>&lt;/span> already gives rise to a very powerful primitive for proving termination: if I can &lt;em>measure&lt;/em> the arguments of a recursive function with a natural number, all it takes to prove termination is proving that the measure decreases with every recursive call. (A &amp;ldquo;measure&amp;rdquo; in this case simply means any function that outputs a natural number.)&lt;/p>
&lt;p>We will skip over all the stuff about proving relations well-founded in Coq, and how this actually lets us make Coq accept our functions as terminating. (Spoiler: it&amp;rsquo;s still structural recursion, but now it&amp;rsquo;s structural recursion on &lt;em>well-foundedness proofs&lt;/em>. I recommend &lt;span class="hugo-cite-intext" itemprop="citation">&lt;span class="tooltip-trigger">&lt;a href="#cite:4">[4]&lt;/a>&lt;span class="tooltip">A. Chlipala, &lt;em>Certified programming with dependent types: A pragmatic introduction to the Coq proof assistant&lt;/em>. Cambridge, MA: The MIT Press, 2013. Available: &lt;a href="http://adam.chlipala.net/cpdt/">&lt;a href="http://adam.chlipala.net/cpdt/">http://adam.chlipala.net/cpdt/&lt;/a>&lt;/a>&lt;/span>&lt;/span>&lt;/span> as a good introduction to well-founded recursion in Coq if you would like to know more.)&lt;/p>
&lt;p>We will use Coq&amp;rsquo;s &lt;code>#[program]&lt;/code> attribute, which takes care of everything in the background and lets us use measures directly. So, let&amp;rsquo;s try again with the &amp;ldquo;straightforward&amp;rdquo; &lt;code>fib&lt;/code> definition, but now equip it with a measure:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="o">#[&lt;/span>&lt;span class="n">program&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="kn">Fixpoint&lt;/span> &lt;span class="n">fib&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">n&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">nat&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">{&lt;/span>&lt;span class="n">measure&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="o">}&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">match&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">fib&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">n&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">fib&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">n&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>In this case we don&amp;rsquo;t even have to define a separate measure function, as conveniently &lt;code>n&lt;/code> is its own measure. &lt;code>#[program]&lt;/code> leaves us with two obligations to prove. By using the &lt;code>Next Obligation&lt;/code> command, we can jump straight into proving it:&lt;/p>
&lt;pre tabindex="0">&lt;code>n : nat
fib : forall n0 : nat, n0 &amp;lt; n -&amp;gt; nat
H0 : 0 &amp;lt;&amp;gt; n
H : 1 &amp;lt;&amp;gt; n
___________________(1/1)
n - 1 &amp;lt; n
&lt;/code>&lt;/pre>&lt;p>Well this is easy, we just have to prove that &lt;code>n - 1 &amp;lt; n&lt;/code>. (And also notice how &lt;code>#[program]&lt;/code> helpfully added the hypotheses that &lt;code>n&lt;/code> is not equal to &lt;code>0&lt;/code> or &lt;code>1&lt;/code>.) &lt;code>lia&lt;/code> makes short work of this. The other obligation is exactly the same, except that we have to prove that &lt;code>n - 2 &amp;lt; n&lt;/code>. The finished proofs are very simple:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="n">Next&lt;/span> &lt;span class="n">Obligation&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="n">lia&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="kn">Qed&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">Next&lt;/span> &lt;span class="n">Obligation&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="n">lia&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="kn">Qed&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And we are done! We defined a function and proved that it&amp;rsquo;s terminating using a measure, which is a much more powerful primitive than structural recursion.&lt;/p>
&lt;h2 id="rewriting-with-permutations">Rewriting with permutations&lt;/h2>
&lt;p>In Coq, you can use equality proofs for rewriting terms. (I mean, what else would you be using them for?) Let&amp;rsquo;s say we have a proof state like this (&lt;code>a&lt;/code> &lt;code>b&lt;/code> &lt;code>c&lt;/code> cut from the context for brevity):&lt;/p>
&lt;pre tabindex="0">&lt;code>ab : a = b
bc : b = c
___________________(1/1)
a = c
&lt;/code>&lt;/pre>&lt;p>By using the &lt;code>rewrite ab&lt;/code> tactic, we can rewrite occurrences of &lt;code>a&lt;/code> to &lt;code>b&lt;/code> in the goal:&lt;/p>
&lt;pre tabindex="0">&lt;code>ab : a = b
bc : b = c
___________________(1/1)
b = c
&lt;/code>&lt;/pre>&lt;p>Now we could finish the proof either by using &lt;code>rewrite bc&lt;/code> to obtain &lt;code>c = c&lt;/code> and then appealing to &lt;code>reflexivity&lt;/code>, or just by writing &lt;code>exact bc&lt;/code> since &lt;code>b = c&lt;/code> is already a hypothesis.&lt;/p>
&lt;p>Now let&amp;rsquo;s say we have a very similar proof state, but instead of equality we have &lt;code>Permutation&lt;/code> relations:&lt;/p>
&lt;pre tabindex="0">&lt;code>ab : a ~ b
bc : b ~ c
___________________(1/1)
a ~ c
&lt;/code>&lt;/pre>&lt;p>Here we could of course just say that &lt;code>Permutation&lt;/code> is transitive by definition: &lt;code>apply (perm_trans ab bc)&lt;/code>. But curiously, we can also use &lt;code>rewrite&lt;/code> in this situation, just like in the previous example. After using &lt;code>rewrite bc&lt;/code>, we get exactly what you would expect:&lt;/p>
&lt;pre tabindex="0">&lt;code>ab : a ~ b
bc : b ~ c
___________________(1/1)
b ~ c
&lt;/code>&lt;/pre>&lt;p>So&amp;hellip; why does this work? As it turns out, &lt;code>Permutation&lt;/code> is an &lt;a href="https://en.wikipedia.org/wiki/Equivalence_relation">&lt;em>equivalence relation&lt;/em>&lt;/a>: it&amp;rsquo;s reflexive, symmetric, and transitive. A set (or in this case, a type) equipped with an equivalence relation is called a &lt;em>setoid&lt;/em> in mathematics. Coq allows extending the &lt;code>rewrite&lt;/code> tactic to work with any setoid, and not just regular equality. (The standard library already contains the relevant proofs about &lt;code>Permutation&lt;/code> being an equivalence relation, so we can use &lt;code>rewrite&lt;/code> with it.)&lt;/p>
&lt;h3 id="rewriting-with-morphisms">Rewriting with morphisms&lt;/h3>
&lt;p>Let&amp;rsquo;s say we have this proof state (where &lt;code>f&lt;/code> is some arbitrary function):&lt;/p>
&lt;pre tabindex="0">&lt;code>ab : a = b
___________________(1/1)
f a = f b
&lt;/code>&lt;/pre>&lt;p>This is again easy to prove just by using &lt;code>rewrite ab&lt;/code> to rewrite &lt;code>a&lt;/code> to &lt;code>b&lt;/code> on the left side, and then appealing to &lt;code>reflexivity&lt;/code>. Let&amp;rsquo;s try the same when we are using permutations:&lt;/p>
&lt;pre tabindex="0">&lt;code>ab : a ~ b
___________________(1/1)
f a = f b
&lt;/code>&lt;/pre>&lt;p>Issuing &lt;code>rewrite ab&lt;/code> here yields an error:&lt;/p>
&lt;pre tabindex="0">&lt;code>setoid rewrite failed: Unable to satisfy the following constraints:
UNDEFINED EVARS:
?X39==[T f a b ab |- Relation_Definitions.relation (list T)] (internal placeholder) {?r}
?X40==[T f a b ab (do_subrelation:=Morphisms.do_subrelation)
|- Morphisms.Proper (Morphisms.respectful (Permutation (A:=T)) ?r) f] (internal placeholder) {?p}
?X42==[T f a b ab |- Relation_Definitions.relation (list T)] (internal placeholder) {?r0}
?X43==[T f a b ab (do_subrelation:=Morphisms.do_subrelation)
|- Morphisms.Proper (Morphisms.respectful ?r (Morphisms.respectful ?r0 (Basics.flip Basics.impl))) eq]
(internal placeholder) {?p0}
?X44==[T f a b ab |- Morphisms.ProperProxy ?r0 (f b)] (internal placeholder) {?p1}
TYPECLASSES:?X39 ?X40 ?X42 ?X43 ?X44
SHELF:||
FUTURE GOALS STACK:?X44 ?X43 ?X42 ?X40 ?X39||
&lt;/code>&lt;/pre>&lt;p>Uh-oh. What a clear and concise error message&amp;hellip; But if we think about what we are actually trying to do, Coq is definitely right to fail here: &lt;code>f a = f b&lt;/code> is &lt;strong>not&lt;/strong> true in this case for an arbitrary &lt;code>f&lt;/code>. For example if f is a function that checks whether a list is sorted, this equality is definitely false.&lt;/p>
&lt;p>We somehow need to restrict &lt;code>f&lt;/code> to being a function that satisfies the above equality. In the language of Coq&amp;rsquo;s setoid rewriting system, this is what we need to prove about &lt;code>f&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="n">Proper&lt;/span> &lt;span class="o">((@&lt;/span>&lt;span class="n">Permutation&lt;/span> &lt;span class="n">A&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">==&amp;gt;&lt;/span> &lt;span class="n">Logic&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="n">f&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This basically means that if &lt;code>x ~ y&lt;/code>, then &lt;code>f x = f y&lt;/code> also holds. The &lt;code>==&amp;gt;&lt;/code> here denotes &amp;ldquo;morphisms that are both covariant and contravariant&amp;rdquo;. What does &amp;ldquo;morphism&amp;rdquo; mean in this context? What does &amp;ldquo;proper&amp;rdquo; mean? I am not sure exactly, but importantly they do exactly what we need them to do. You are welcome to dive into the &lt;a href="https://coq.inria.fr/refman/addendum/generalized-rewriting.html">relevant chapter of the Coq reference manual&lt;/a> if would like to know more, godspeed.&lt;/p>
&lt;p>What&amp;rsquo;s important is that with a proof of the above property in scope, the previous rewrite works now:&lt;/p>
&lt;pre tabindex="0">&lt;code>ab : a ~ b
___________________(1/1)
f a = f b
&lt;/code>&lt;/pre>&lt;p>Trying &lt;code>rewrite ab&lt;/code> here again does exactly what we wanted:&lt;/p>
&lt;pre tabindex="0">&lt;code>ab : a ~ b
___________________(1/1)
f b = f b
&lt;/code>&lt;/pre>&lt;p>If you are interested in an actual example, I will be establishing a &lt;code>Proper&lt;/code> instance for one of my functions in &lt;a href="#axis-aligned-bounding-boxes">this&lt;/a> section. To see the proof scripts utilizing permutation rewriting, you can check out the &lt;a href="https://git.sr.ht/~kuruczgy/verified-rtree/tree/for-blog/item/RTree.v">source code&lt;/a>.&lt;/p>
&lt;h2 id="proof-automation">Proof automation&lt;/h2>
&lt;p>In general, I tried to follow the advice given in Adam Chlipala&amp;rsquo;s book, Certified Programming with Dependent Types &lt;span class="hugo-cite-intext" itemprop="citation">&lt;span class="tooltip-trigger">&lt;a href="#cite:4">[4]&lt;/a>&lt;span class="tooltip">A. Chlipala, &lt;em>Certified programming with dependent types: A pragmatic introduction to the Coq proof assistant&lt;/em>. Cambridge, MA: The MIT Press, 2013. Available: &lt;a href="http://adam.chlipala.net/cpdt/">&lt;a href="http://adam.chlipala.net/cpdt/">http://adam.chlipala.net/cpdt/&lt;/a>&lt;/a>&lt;/span>&lt;/span>&lt;/span>:&lt;/p>
&lt;blockquote>
&lt;p>In this book, I have been following an unusual style, where proofs are not considered finished until they are “fully automated,” in a certain sense. Each such theorem is proved by a single tactic.&lt;/p>
&lt;/blockquote>
&lt;blockquote>
&lt;p>My position is that any ideas that standard automation can find are not very big after all, and the real big ideas should be expressed through lemmas that are added as hints.&lt;/p>
&lt;/blockquote>
&lt;p>He advocates for a style where &amp;ldquo;important&amp;rdquo; ideas are expressed as separate lemmas, while individual proofs are automated to the furthest extent possible.&lt;/p>
&lt;p>While I tried to follow this style, my Ltac skills are still only rudimentary. As such, I won&amp;rsquo;t discuss the details of any non-single-tactic proofs I made, since they probably don&amp;rsquo;t contain any important ideas, and are just a failure on my part to automate them sufficiently.&lt;/p>
&lt;p>Similarly, since I only started getting my feet wet with more advanced proof automation, my Ltac scripts are still quite messy. I am not sure that showcasing them in detail would provide anything valuable, since there are probably better ways to achieve everything I am doing here. Nonetheless, I will show two tactics here as examples for what you can do with proof automation.&lt;/p>
&lt;h3 id="reflection-for-use-with-lia">Reflection for use with &lt;code>lia&lt;/code>&lt;/h3>
&lt;p>&lt;code>lia&lt;/code> can only work with propositions and not booleans, so I made a tactic to turn boolean relations into their propositional equivalents:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Ltac&lt;/span> &lt;span class="n">tac_reflect&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">match&lt;/span> &lt;span class="n">goal&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">(** normalize equality orders *)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">H&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="bp">true&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">?&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">|-&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="k">symmetry&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="n">H&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">H&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="bp">false&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">?&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">|-&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="k">symmetry&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="n">H&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">(** reflect leb as le *)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">H&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">(?&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">&amp;lt;=?&lt;/span> &lt;span class="o">?&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">true&lt;/span> &lt;span class="o">|-&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="k">apply&lt;/span> &lt;span class="n">leb_complete&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="n">H&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">H&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">(?&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">&amp;lt;=?&lt;/span> &lt;span class="o">?&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">false&lt;/span> &lt;span class="o">|-&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="k">apply&lt;/span> &lt;span class="n">leb_iff_conv&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="n">H&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">H&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">(?&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">&amp;lt;?&lt;/span> &lt;span class="o">?&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">true&lt;/span> &lt;span class="o">|-&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="k">apply&lt;/span> &lt;span class="n">Nat&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ltb_lt&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="n">H&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">H&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">(?&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">&amp;lt;?&lt;/span> &lt;span class="o">?&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">false&lt;/span> &lt;span class="o">|-&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="k">apply&lt;/span> &lt;span class="n">Nat&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ltb_ge&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="n">H&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This tactic can for example turn &lt;code>(x &amp;lt;? y) = false&lt;/code> into &lt;code>x &amp;gt;= y&lt;/code>. &lt;code>lia&lt;/code> can only work with the second form, so this is quite useful.&lt;/p>
&lt;p>I also have lemmas for turning boolean operators into propositions:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">reflect_andb_true&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="k">forall&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">bool&lt;/span>&lt;span class="o">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">a&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">true&lt;/span> &lt;span class="o">&amp;lt;-&amp;gt;&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">true&lt;/span> &lt;span class="o">/\&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">true&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">reflect_andb_false&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="k">forall&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">bool&lt;/span>&lt;span class="o">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">a&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">false&lt;/span> &lt;span class="o">&amp;lt;-&amp;gt;&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">false&lt;/span> &lt;span class="o">\/&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">false&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>I haven&amp;rsquo;t integrated these with &lt;code>tac_reflect&lt;/code> yet though.&lt;/p>
&lt;p>(Note that reflection is a much more general technique that can be used in Coq, check out &lt;a href="https://softwarefoundations.cis.upenn.edu/current/vfa-current/Decide.html">the relevant chapter in Software Foundations&lt;/a> for an introduction. My relatively simplistic tactics were enough for this project though.)&lt;/p>
&lt;h3 id="solving-permutations">Solving permutations&lt;/h3>
&lt;p>The following tactic solves goals of the form &lt;code>_ ~ _&lt;/code>, where the two sides can be made equal just by rearranging them.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Ltac&lt;/span> &lt;span class="n">bring_to_front&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">repeat&lt;/span> &lt;span class="o">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">try&lt;/span> &lt;span class="k">rewrite&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">app_assoc&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="o">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">rewrite&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">Permutation_app_comm&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="o">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">try&lt;/span> &lt;span class="k">rewrite&lt;/span> &lt;span class="o">&amp;lt;-&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">app_assoc&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">_)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Ltac&lt;/span> &lt;span class="n">solve_permutation&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kp">solve&lt;/span> &lt;span class="o">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">repeat&lt;/span> &lt;span class="k">rewrite&lt;/span> &lt;span class="o">&amp;lt;-&lt;/span> &lt;span class="n">app_assoc&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">rewrite&lt;/span> &lt;span class="o">&amp;lt;-&lt;/span> &lt;span class="o">?&lt;/span> &lt;span class="n">Permutation_rev&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">repeat&lt;/span> &lt;span class="k">match&lt;/span> &lt;span class="n">goal&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="o">|-&lt;/span> &lt;span class="o">?&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">++&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">~&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">bring_to_front&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">apply&lt;/span> &lt;span class="n">Permutation_app_head&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="o">|-&lt;/span> &lt;span class="o">?&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">~&lt;/span> &lt;span class="o">?&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="kp">reflexivity&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>&lt;span class="o">].&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>solve_permutation&lt;/code> expects both sides to be a sequence of terms separated by the &lt;code>++&lt;/code> operator. It looks at the first term on the left hand side, and tries to find the same term and bring it to the front on the right hand side as well. &lt;code>bring_to_front&lt;/code> works by repeatedly appealing to the associativity and commutativity of &lt;code>++&lt;/code>. (&lt;code>++&lt;/code> is not commutative with respect to regular equality of course, but it is with respect to permutation.)&lt;/p>
&lt;p>If &lt;code>bring_to_front&lt;/code> succeeds, the two head terms can be removed from both sides, and the procedure is repeated again. The loop terminates when both sides are equal, and the goal can be solved by simply appealing to the reflexivity of &lt;code>~&lt;/code>.&lt;/p>
&lt;h1 id="implementation">Implementation&lt;/h1>
&lt;p>Now that you have a basic overview of all the techniques that go into developing a verification project like this, we are ready to jump into discussing the actual implementation.&lt;/p>
&lt;h2 id="axis-aligned-bounding-boxes">Axis-aligned bounding boxes&lt;/h2>
&lt;p>First, we have to develop a theory of the bounding boxes that the whole data structure is build upon.&lt;/p>
&lt;p>We define bounding boxes as follows:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">interval&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">Type&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">Z&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">Z&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">bbox&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">Type&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">interval&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">interval&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>An interval is a pair of integers, and a bounding box is simply a pair of intervals. (We could of course generalize to &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>d&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">d&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6944em;">&lt;/span>&lt;span class="mord mathnormal">d&lt;/span>&lt;/span>&lt;/span>&lt;/span> dimensions by defining a hyper-bounding box to be a vector of &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>d&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">d&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6944em;">&lt;/span>&lt;span class="mord mathnormal">d&lt;/span>&lt;/span>&lt;/span>&lt;/span> intervals, but for now I am satisfied with the &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>d&lt;/mi>&lt;mo>=&lt;/mo>&lt;mn>2&lt;/mn>&lt;/mrow>&lt;annotation encoding="application/x-tex">d=2&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6944em;">&lt;/span>&lt;span class="mord mathnormal">d&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6444em;">&lt;/span>&lt;span class="mord">2&lt;/span>&lt;/span>&lt;/span>&lt;/span> special case.)&lt;/p>
&lt;p>We define the following functions on intervals:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">interval_intersect&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">interval&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">interval&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fun&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">pair&lt;/span> &lt;span class="n">a_lo&lt;/span> &lt;span class="n">a_hi&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">pair&lt;/span> &lt;span class="n">b_lo&lt;/span> &lt;span class="n">b_hi&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">a_lo&lt;/span> &lt;span class="o">&amp;lt;=?&lt;/span> &lt;span class="n">b_hi&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">b_lo&lt;/span> &lt;span class="o">&amp;lt;=?&lt;/span> &lt;span class="n">a_hi&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">interval_inside&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">interval&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">interval&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fun&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">pair&lt;/span> &lt;span class="n">a_lo&lt;/span> &lt;span class="n">a_hi&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">pair&lt;/span> &lt;span class="n">b_lo&lt;/span> &lt;span class="n">b_hi&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">b_lo&lt;/span> &lt;span class="o">&amp;lt;=?&lt;/span> &lt;span class="n">a_lo&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">a_hi&lt;/span> &lt;span class="o">&amp;lt;=?&lt;/span> &lt;span class="n">b_hi&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">interval_mbr&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">interval&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">interval&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">interval&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fun&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">pair&lt;/span> &lt;span class="n">a_lo&lt;/span> &lt;span class="n">a_hi&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">pair&lt;/span> &lt;span class="n">b_lo&lt;/span> &lt;span class="n">b_hi&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">Z&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">min&lt;/span> &lt;span class="n">a_lo&lt;/span> &lt;span class="n">b_lo&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">Z&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">max&lt;/span> &lt;span class="n">a_hi&lt;/span> &lt;span class="n">b_hi&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">interval_measure&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">interval&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">Z&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fun&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">pair&lt;/span> &lt;span class="n">lo&lt;/span> &lt;span class="n">hi&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">hi&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">lo&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;code>interval_intersect&lt;/code>: Decides whether two intervals intersect, that is, whether for two intervals &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>a&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">a&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">a&lt;/span>&lt;/span>&lt;/span>&lt;/span> and &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>b&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">b&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6944em;">&lt;/span>&lt;span class="mord mathnormal">b&lt;/span>&lt;/span>&lt;/span>&lt;/span>, &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>a&lt;/mi>&lt;mo>∩&lt;/mo>&lt;mi>b&lt;/mi>&lt;mo mathvariant="normal">≠&lt;/mo>&lt;mi mathvariant="normal">∅&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">a \cap b \neq \empty&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.5556em;">&lt;/span>&lt;span class="mord mathnormal">a&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">∩&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.8889em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal">b&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">&lt;span class="mrel">&lt;span class="mord vbox">&lt;span class="thinbox">&lt;span class="rlap">&lt;span class="strut" style="height:0.8889em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="inner">&lt;span class="mord">&lt;span class="mrel">&lt;/span>&lt;/span>&lt;/span>&lt;span class="fix">&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.8056em;vertical-align:-0.0556em;">&lt;/span>&lt;span class="mord">∅&lt;/span>&lt;/span>&lt;/span>&lt;/span>.&lt;/li>
&lt;li>&lt;code>interval_inside&lt;/code>: Decides whether &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>a&lt;/mi>&lt;mo>⊆&lt;/mo>&lt;mi>b&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">a \sube b&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.7719em;vertical-align:-0.136em;">&lt;/span>&lt;span class="mord mathnormal">a&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">⊆&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6944em;">&lt;/span>&lt;span class="mord mathnormal">b&lt;/span>&lt;/span>&lt;/span>&lt;/span>.&lt;/li>
&lt;li>&lt;code>interval_mbr&lt;/code>: Computes the minimum bounding interval of two intervals.&lt;/li>
&lt;li>&lt;code>interval_measure&lt;/code>: Computes the length of the interval.&lt;/li>
&lt;/ul>
&lt;p>Nothing fancy going on here, you would write these functions the same way in any other programming language.
(We won&amp;rsquo;t even be proving them correct, e.g. that for any &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>a&lt;/mi>&lt;mo>=&lt;/mo>&lt;mo stretchy="false">[&lt;/mo>&lt;msub>&lt;mi>a&lt;/mi>&lt;mn>1&lt;/mn>&lt;/msub>&lt;mo separator="true">,&lt;/mo>&lt;msub>&lt;mi>a&lt;/mi>&lt;mn>2&lt;/mn>&lt;/msub>&lt;mo stretchy="false">]&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">a = [a_1, a_2]&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">a&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mopen">[&lt;/span>&lt;span class="mord">&lt;span class="mord mathnormal">a&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t vlist-t2">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.3011em;">&lt;span style="top:-2.55em;margin-left:0em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">1&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="vlist-s">​&lt;/span>&lt;/span>&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.15em;">&lt;span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord">&lt;span class="mord mathnormal">a&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t vlist-t2">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.3011em;">&lt;span style="top:-2.55em;margin-left:0em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">2&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="vlist-s">​&lt;/span>&lt;/span>&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.15em;">&lt;span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mclose">]&lt;/span>&lt;/span>&lt;/span>&lt;/span> and &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>b&lt;/mi>&lt;mo>=&lt;/mo>&lt;mo stretchy="false">[&lt;/mo>&lt;msub>&lt;mi>b&lt;/mi>&lt;mn>1&lt;/mn>&lt;/msub>&lt;mo separator="true">,&lt;/mo>&lt;msub>&lt;mi>b&lt;/mi>&lt;mn>2&lt;/mn>&lt;/msub>&lt;mo stretchy="false">]&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">b = [b_1, b_2]&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6944em;">&lt;/span>&lt;span class="mord mathnormal">b&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mopen">[&lt;/span>&lt;span class="mord">&lt;span class="mord mathnormal">b&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t vlist-t2">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.3011em;">&lt;span style="top:-2.55em;margin-left:0em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">1&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="vlist-s">​&lt;/span>&lt;/span>&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.15em;">&lt;span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord">&lt;span class="mord mathnormal">b&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t vlist-t2">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.3011em;">&lt;span style="top:-2.55em;margin-left:0em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">2&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="vlist-s">​&lt;/span>&lt;/span>&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.15em;">&lt;span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mclose">]&lt;/span>&lt;/span>&lt;/span>&lt;/span>, &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>a&lt;/mi>&lt;mo>∩&lt;/mo>&lt;mi>b&lt;/mi>&lt;mo mathvariant="normal">≠&lt;/mo>&lt;mi mathvariant="normal">∅&lt;/mi>&lt;mtext>  &lt;/mtext>&lt;mo>⟺&lt;/mo>&lt;mtext>  &lt;/mtext>&lt;msub>&lt;mi>a&lt;/mi>&lt;mn>1&lt;/mn>&lt;/msub>&lt;mo>≤&lt;/mo>&lt;msub>&lt;mi>b&lt;/mi>&lt;mn>2&lt;/mn>&lt;/msub>&lt;mo>∧&lt;/mo>&lt;msub>&lt;mi>b&lt;/mi>&lt;mn>1&lt;/mn>&lt;/msub>&lt;mo>≤&lt;/mo>&lt;msub>&lt;mi>a&lt;/mi>&lt;mn>2&lt;/mn>&lt;/msub>&lt;/mrow>&lt;annotation encoding="application/x-tex">a \cap b \neq \empty \iff a_1 \leq b_2 \land b_1 \leq a_2&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.5556em;">&lt;/span>&lt;span class="mord mathnormal">a&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">∩&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.8889em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal">b&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">&lt;span class="mrel">&lt;span class="mord vbox">&lt;span class="thinbox">&lt;span class="rlap">&lt;span class="strut" style="height:0.8889em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="inner">&lt;span class="mord">&lt;span class="mrel">&lt;/span>&lt;/span>&lt;/span>&lt;span class="fix">&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.8056em;vertical-align:-0.0556em;">&lt;/span>&lt;span class="mord">∅&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">⟺&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.786em;vertical-align:-0.15em;">&lt;/span>&lt;span class="mord">&lt;span class="mord mathnormal">a&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t vlist-t2">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.3011em;">&lt;span style="top:-2.55em;margin-left:0em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">1&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="vlist-s">​&lt;/span>&lt;/span>&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.15em;">&lt;span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">≤&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.8444em;vertical-align:-0.15em;">&lt;/span>&lt;span class="mord">&lt;span class="mord mathnormal">b&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t vlist-t2">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.3011em;">&lt;span style="top:-2.55em;margin-left:0em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">2&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="vlist-s">​&lt;/span>&lt;/span>&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.15em;">&lt;span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">∧&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.8444em;vertical-align:-0.15em;">&lt;/span>&lt;span class="mord">&lt;span class="mord mathnormal">b&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t vlist-t2">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.3011em;">&lt;span style="top:-2.55em;margin-left:0em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">1&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="vlist-s">​&lt;/span>&lt;/span>&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.15em;">&lt;span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">≤&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.5806em;vertical-align:-0.15em;">&lt;/span>&lt;span class="mord">&lt;span class="mord mathnormal">a&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t vlist-t2">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.3011em;">&lt;span style="top:-2.55em;margin-left:0em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">2&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="vlist-s">​&lt;/span>&lt;/span>&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.15em;">&lt;span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>. We will just prove a few select properties which we need.)&lt;/p>
&lt;p>Now that we have these definitions, extending them to bounding boxes is straightforward:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">bbox_intersect&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">bbox&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fun&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">pair&lt;/span> &lt;span class="n">ax&lt;/span> &lt;span class="n">ay&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">pair&lt;/span> &lt;span class="n">bx&lt;/span> &lt;span class="n">by_&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">interval_intersect&lt;/span> &lt;span class="n">ax&lt;/span> &lt;span class="n">bx&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">interval_intersect&lt;/span> &lt;span class="n">ay&lt;/span> &lt;span class="n">by_&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">bbox_inside&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">bbox&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fun&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">pair&lt;/span> &lt;span class="n">ax&lt;/span> &lt;span class="n">ay&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">pair&lt;/span> &lt;span class="n">bx&lt;/span> &lt;span class="n">by_&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">interval_inside&lt;/span> &lt;span class="n">ax&lt;/span> &lt;span class="n">bx&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">interval_inside&lt;/span> &lt;span class="n">ay&lt;/span> &lt;span class="n">by_&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">bbox_mbr&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">bbox&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">bbox&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fun&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">pair&lt;/span> &lt;span class="n">ax&lt;/span> &lt;span class="n">ay&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">pair&lt;/span> &lt;span class="n">bx&lt;/span> &lt;span class="n">by_&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">interval_mbr&lt;/span> &lt;span class="n">ax&lt;/span> &lt;span class="n">bx&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">interval_mbr&lt;/span> &lt;span class="n">ay&lt;/span> &lt;span class="n">by_&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">bbox_measure&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">Z&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fun&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">pair&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">interval_measure&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">interval_measure&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>I will be using &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo>⊆&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\sube&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.7719em;vertical-align:-0.136em;">&lt;/span>&lt;span class="mrel">⊆&lt;/span>&lt;/span>&lt;/span>&lt;/span> and &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo stretchy="false">∣&lt;/mo>&lt;mtext> &lt;/mtext>&lt;mo>⋅&lt;/mo>&lt;mtext> &lt;/mtext>&lt;mo stretchy="false">∣&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">{\lvert\,\cdot\,\rvert}&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord">&lt;span class="mopen">∣&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord">⋅&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mclose">∣&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span> to denote &lt;code>bbox_inside&lt;/code> and &lt;code>bbox_measure&lt;/code> respectively.&lt;/p>
&lt;p>Next, here are the facts that we will need about bounding boxes:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">bbox_mbr_comm&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox_mbr&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">bbox_mbr&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">bbox_mbr_assoc&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="n">c&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox_mbr&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">bbox_mbr&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="n">c&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">bbox_mbr&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">bbox_mbr&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="n">c&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">bbox_inside_refl&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox_inside&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">true&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">bbox_inside_mbr&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox_inside&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">bbox_mbr&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">true&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">bbox_mbr_monotonic&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="n">c&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox_inside&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">true&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">bbox_inside&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">bbox_mbr&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="n">c&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">true&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">bbox_inside_not_intersect&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="n">c&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox_inside&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">true&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">bbox_intersect&lt;/span> &lt;span class="n">c&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">false&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">bbox_intersect&lt;/span> &lt;span class="n">c&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">false&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;code>bbox_mbr_comm&lt;/code>, &lt;code>bbox_mbr_assoc&lt;/code>: The minimum bounding rectangle (MBR) operation is commutative and associative.&lt;/li>
&lt;li>&lt;code>bbox_inside_refl&lt;/code>: &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo>⊆&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\sube&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.7719em;vertical-align:-0.136em;">&lt;/span>&lt;span class="mrel">⊆&lt;/span>&lt;/span>&lt;/span>&lt;/span> is reflexive on bounding boxes.&lt;/li>
&lt;li>&lt;code>bbox_inside_mbr&lt;/code>: Bounding boxes are inside their MBRs.&lt;/li>
&lt;li>&lt;code>bbox_mbr_monotonic&lt;/code>: If &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>a&lt;/mi>&lt;mo>⊆&lt;/mo>&lt;mi>b&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">a \sube b&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.7719em;vertical-align:-0.136em;">&lt;/span>&lt;span class="mord mathnormal">a&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">⊆&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6944em;">&lt;/span>&lt;span class="mord mathnormal">b&lt;/span>&lt;/span>&lt;/span>&lt;/span>, and you take the MBR of &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>b&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">b&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6944em;">&lt;/span>&lt;span class="mord mathnormal">b&lt;/span>&lt;/span>&lt;/span>&lt;/span> with any other &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>c&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">c&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">c&lt;/span>&lt;/span>&lt;/span>&lt;/span>, &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>a&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">a&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">a&lt;/span>&lt;/span>&lt;/span>&lt;/span> will still be inside the resulting MBR.&lt;/li>
&lt;li>&lt;code>bbox_inside_not_intersect&lt;/code>: If &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>a&lt;/mi>&lt;mo>⊆&lt;/mo>&lt;mi>b&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">a \sube b&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.7719em;vertical-align:-0.136em;">&lt;/span>&lt;span class="mord mathnormal">a&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">⊆&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6944em;">&lt;/span>&lt;span class="mord mathnormal">b&lt;/span>&lt;/span>&lt;/span>&lt;/span>, and there is a &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>c&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">c&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">c&lt;/span>&lt;/span>&lt;/span>&lt;/span> that does not intersect &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>b&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">b&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6944em;">&lt;/span>&lt;span class="mord mathnormal">b&lt;/span>&lt;/span>&lt;/span>&lt;/span>, then it also does not intersect &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>a&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">a&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">a&lt;/span>&lt;/span>&lt;/span>&lt;/span>. This is the essential property that will let us discard branches during tree search.&lt;/li>
&lt;/ul>
&lt;p>For these particular set of theorems, I was able to put together a single proof script to completely automate all of the proofs. This script can prove all of the theorems above:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Ltac&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">intros&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">repeat&lt;/span> &lt;span class="k">match&lt;/span> &lt;span class="n">goal&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">H&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">interval&lt;/span> &lt;span class="o">|-&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="k">destruct&lt;/span> &lt;span class="n">H&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">H&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox&lt;/span> &lt;span class="o">|-&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="k">destruct&lt;/span> &lt;span class="n">H&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">simpl&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="o">*;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">repeat&lt;/span> &lt;span class="k">match&lt;/span> &lt;span class="n">goal&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="o">|-&lt;/span> &lt;span class="o">(_,&lt;/span> &lt;span class="o">_)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">(_,&lt;/span> &lt;span class="o">_)&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">f_equal&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">reflect_lia&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">lia&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The idea is to completely break up the goal into a system of linear equations and simple logical connectives. For example, for &lt;code>bbox_inside_not_intersect&lt;/code>, here is the proof state just before the final &lt;code>lia&lt;/code> tactic:&lt;/p>
&lt;pre tabindex="0">&lt;code>z9, z10, z7, z8, z5, z6, z3, z4, z1, z2, z, z0 : Z
H : (z5 &amp;lt;= z9 /\ z10 &amp;lt;= z6) /\ z3 &amp;lt;= z7 /\ z8 &amp;lt;= z4
H0 : ~ ((z1 &amp;lt;= z6 /\ z5 &amp;lt;= z2) /\ z &amp;lt;= z4 /\ z3 &amp;lt;= z0)
___________________(1/1)
~ ((z1 &amp;lt;= z10 /\ z9 &amp;lt;= z2) /\ z &amp;lt;= z8 /\ z7 &amp;lt;= z0)
&lt;/code>&lt;/pre>&lt;p>This form is already beyond the limit of easy human comprehension. (12 inequalities, 11 variables, various logical connectives interspersed.) Fortunately, a specialized automated solver like &lt;code>lia&lt;/code> shines in a situation like this, and makes quick work of the proof.&lt;/p>
&lt;p>Next, we extend the theory about minimum bounding rectangles to any list of boxes, not just two:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">mbr&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">l&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">bbox&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">match&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="bp">[]&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="o">((&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="o">),&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="o">))%&lt;/span>&lt;span class="n">Z&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">fold_left&lt;/span> &lt;span class="n">bbox_mbr&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="n">x&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The &lt;code>((0, 0), (0, 0))&lt;/code> is just a dummy value for when the list is empty. It doesn&amp;rsquo;t really matter what we put here, in the theorems where it&amp;rsquo;s necessary we will specify that the list is non-empty anyway.&lt;/p>
&lt;p>We extend the idea behind &lt;code>bbox_inside_mbr&lt;/code> to our new &lt;code>mbr&lt;/code> function as well:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">mbr_inside&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">In&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">bbox_inside&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">mbr&lt;/span> &lt;span class="n">l&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">true&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This should be quite intuitive, we are just saying that for any list of boxes, all of them are inside their minimum bounding rectangle.&lt;/p>
&lt;p>I already talked about Coq&amp;rsquo;s generalized rewriting ability, and how we can use it to rewrite with the &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo>∼&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\sim&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.3669em;">&lt;/span>&lt;span class="mrel">∼&lt;/span>&lt;/span>&lt;/span>&lt;/span> relation. We want to be able to do this rewriting in the argument of the &lt;code>mbr&lt;/code> function as well, and essentially what we have to do is prove that the result of &lt;code>mbr&lt;/code> does not depend on the order of its inputs.&lt;/p>
&lt;p>As discussed in a &lt;a href="#rewriting-with-morphisms">previous section&lt;/a> already, this is how we can express this in the language of Coq&amp;rsquo;s setoid rewriting system:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Instance&lt;/span> &lt;span class="n">Permutation_mbr&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">Proper&lt;/span> &lt;span class="o">(@&lt;/span>&lt;span class="n">Permutation&lt;/span> &lt;span class="n">bbox&lt;/span> &lt;span class="o">==&amp;gt;&lt;/span> &lt;span class="n">Logic&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="n">mbr&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The proof is quite straightforward, we are basically proving that &lt;code>mbr&lt;/code> does not depend on the order of the boxes in its argument.&lt;/p>
&lt;p>This should conclude everything we wanted to know about bounding boxes. To recap:&lt;/p>
&lt;ul>
&lt;li>We defined what bounding boxes (&lt;code>bbox&lt;/code>) are.&lt;/li>
&lt;li>Defined functions on them like intersection, containment, and the minimum bounding rectangle.&lt;/li>
&lt;li>We proved some basic theorems about these functions. We will be making heavy use of these in later proofs.&lt;/li>
&lt;/ul>
&lt;h2 id="list-utility-functions">List utility functions&lt;/h2>
&lt;p>In this section we will define a few simple functions for manipulating lists which can&amp;rsquo;t be found in the standard library. The catch is that I have a few special requirements:&lt;/p>
&lt;ul>
&lt;li>The functions should have strong specifications that we can use in later proofs.&lt;/li>
&lt;li>They should also be tail recursive for runtime efficiency.&lt;/li>
&lt;/ul>
&lt;p>This is the first time we will be defining functions together with their own specifications (as opposed to proving separate theorems about them as we did in the &lt;a href="#axis-aligned-bounding-boxes">previous section about bounding boxes&lt;/a>), using the &lt;code>sig&lt;/code> types I &lt;a href="#the-sig-type">previously introduced&lt;/a>.&lt;/p>
&lt;h3 id="removing-items-from-a-list">Removing items from a list&lt;/h3>
&lt;p>Let&amp;rsquo;s look at the definition of the &lt;code>remove_ith&lt;/code> function, which we will discuss afterwards:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="o">#[&lt;/span>&lt;span class="n">program&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="kn">Fixpoint&lt;/span> &lt;span class="n">remove_ith&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">{&lt;/span>&lt;span class="n">T&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">Type&lt;/span>&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">rev_front&lt;/span> &lt;span class="n">back&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">T&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">i&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">nat&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">length&lt;/span> &lt;span class="n">back&lt;/span> &lt;span class="o">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">{&lt;/span>&lt;span class="n">measure&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">l&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">e&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">~&lt;/span> &lt;span class="n">rev_front&lt;/span> &lt;span class="o">++&lt;/span> &lt;span class="n">back&lt;/span> &lt;span class="o">}&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">match&lt;/span> &lt;span class="n">back&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="bp">[]&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="o">_&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="n">back&amp;#39;&lt;/span>&lt;span class="o">),&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">rev_append&lt;/span> &lt;span class="n">rev_front&lt;/span> &lt;span class="n">back&amp;#39;&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="n">back&amp;#39;&lt;/span>&lt;span class="o">),&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">S&lt;/span> &lt;span class="n">i&amp;#39;&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">remove_ith&amp;#39;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="n">rev_front&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="n">back&amp;#39;&lt;/span> &lt;span class="n">i&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">#[&lt;/span>&lt;span class="n">program&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="kn">Definition&lt;/span> &lt;span class="n">remove_ith&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">{&lt;/span>&lt;span class="n">T&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">Type&lt;/span>&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">l&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">T&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">i&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">nat&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">length&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">l&amp;#39;&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="n">l&amp;#39;&lt;/span> &lt;span class="o">~&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">}&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">proj1_sig&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">remove_ith&amp;#39;&lt;/span> &lt;span class="bp">[]&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>remove_ith'&lt;/code> follows an accumulator pattern to achieve tail recursion, while &lt;code>remove_ith&lt;/code> is simply a wrapper around it with the initial accumulator values.&lt;/p>
&lt;p>The specification for &lt;code>remove_ith&lt;/code> states that it returns a pair &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>x&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;msup>&lt;mi>l&lt;/mi>&lt;mo mathvariant="normal" lspace="0em" rspace="0em">′&lt;/mo>&lt;/msup>&lt;mo stretchy="false">)&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">(x, l&amp;#x27;)&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1.0019em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">x&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord">&lt;span class="mord mathnormal" style="margin-right:0.01968em;">l&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.7519em;">&lt;span style="top:-3.063em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">&lt;span class="mord mtight">′&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mclose">)&lt;/span>&lt;/span>&lt;/span>&lt;/span> which satisfies &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>x&lt;/mi>&lt;mo>&lt;mo>:&lt;/mo>&lt;mo>:&lt;/mo>&lt;/mo>&lt;msup>&lt;mi>l&lt;/mi>&lt;mo mathvariant="normal" lspace="0em" rspace="0em">′&lt;/mo>&lt;/msup>&lt;mo>∼&lt;/mo>&lt;mi>l&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">x \mathop{::} l&amp;#x27; \sim l&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.7519em;">&lt;/span>&lt;span class="mord mathnormal">x&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mop" style="position:relative;top:-0.0347em;">::&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord">&lt;span class="mord mathnormal" style="margin-right:0.01968em;">l&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.7519em;">&lt;span style="top:-3.063em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">&lt;span class="mord mtight">′&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">∼&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.01968em;">l&lt;/span>&lt;/span>&lt;/span>&lt;/span>. As you can see, the specification is now directly embedded in the function&amp;rsquo;s type, unlike in the previous section, where the bounding box functions and the theorems about them were separate.&lt;/p>
&lt;p>Also notice how the parameter &lt;code>i : { i : nat | i &amp;lt; length l }&lt;/code> is a subset type as well. It ensures that you don&amp;rsquo;t attempt to index the list out of bounds. In other programming languages handling simple constraints like this can be tricky, and no good solution exists really:&lt;/p>
&lt;ul>
&lt;li>In an unsafe language like C you could just ignore the possibility of &lt;code>i&lt;/code> being out of bounds, trusting every caller of your function to respect this implicit invariant.&lt;/li>
&lt;li>You could check the value at runtime, and throw an exception or abort the whole program if it&amp;rsquo;s out of bounds.&lt;/li>
&lt;li>You could use an optional type like &lt;code>option A&lt;/code>, and return &lt;code>None&lt;/code> when &lt;code>i&lt;/code> is out of bounds.&lt;/li>
&lt;/ul>
&lt;p>In Coq, there is another unique way to deal with this problem. Let me repeat the relevant match expression from &lt;code>remove_ith'&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl"> &lt;span class="k">match&lt;/span> &lt;span class="n">back&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="bp">[]&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="o">_&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="n">back&amp;#39;&lt;/span>&lt;span class="o">),&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">rev_append&lt;/span> &lt;span class="n">rev_front&lt;/span> &lt;span class="n">back&amp;#39;&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="n">back&amp;#39;&lt;/span>&lt;span class="o">),&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">S&lt;/span> &lt;span class="n">i&amp;#39;&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">remove_ith&amp;#39;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="n">rev_front&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="n">back&amp;#39;&lt;/span> &lt;span class="n">i&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The first branch pattern &lt;code>[], _&lt;/code> matches when the &lt;code>back&lt;/code> list is empty. The branch is simply a single underscore, which is a placeholder to be filled later. So, how is it filled?&lt;/p>
&lt;p>In Coq, anywhere where a regular value is expected, we can also provide an impossibility proof (a proof of &lt;code>False&lt;/code>) instead.&lt;sup id="fnref:5">&lt;a href="#fn:5" role="doc-noteref">5&lt;/a>&lt;span class="footnote-tooltip">Actually this is not much of a special case at all. If we have a proof &lt;code>p&lt;/code> of &lt;code>False&lt;/code>, we can just pattern match on it like this: &lt;code>match p with end&lt;/code>. This is a weird looking pattern match, which in fact has &lt;em>zero&lt;/em> branches, since &lt;code>False&lt;/code> has zero constructors. This pattern match can give you &lt;em>any&lt;/em> value of your choosing. In Coq, &lt;em>ex falso quodlibet&lt;/em> means you can not only prove anything, you can also get a value for anything.&lt;sup>&lt;a href="#fn:6" role="doc-noteref">6&lt;/a>&lt;/sup>&lt;/span>&lt;/sup> Here, this is quite easy: &lt;code>i&lt;/code> carries a proof of &lt;code>i &amp;lt; length back&lt;/code>, which in this case reduces to &lt;code>i &amp;lt; 0&lt;/code>. &lt;code>lia&lt;/code> can readily prove that this is a contradiction. (And it is part of the automation script that &lt;code>#[program]&lt;/code> automatically applies, so the hole is automatically taken care of.)&lt;/p>
&lt;p>I also defined &lt;code>remove_pair&lt;/code>, which is similar except that it removes two items from a list. (Understanding its &lt;a href="https://git.sr.ht/~kuruczgy/verified-rtree/tree/for-blog/item/RTree.v#L347">definition&lt;/a> is an exercise left to the reader.)&lt;/p>
&lt;h3 id="finding-minimal-items-in-a-list">Finding minimal items in a list&lt;/h3>
&lt;p>We start this section by declaring some common parameters:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Context&lt;/span> &lt;span class="o">{&lt;/span>&lt;span class="n">T&lt;/span> &lt;span class="n">M&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">Type&lt;/span>&lt;span class="o">}&lt;/span> &lt;span class="o">`{&lt;/span>&lt;span class="n">Ord_M&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">Ord&lt;/span> &lt;span class="n">M&lt;/span>&lt;span class="o">}&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">measure&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">M&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>T&lt;/code> is the type of items, while &lt;code>M&lt;/code> is the type of comparable values that the &lt;code>measure&lt;/code> function (not to be confused with the measures we use for proving termination) produces from any &lt;code>T&lt;/code>. &lt;code>Ord_M&lt;/code> is an implementation of the total order for &lt;code>M&lt;/code>, which importantly provides the &lt;code>leq&lt;/code> comparator function. (We are over-generalizing here a bit, since we will only be substituting &lt;code>Z&lt;/code> for &lt;code>M&lt;/code> in later parts of the development, but this way we can ensure that we are only depending on &lt;code>Z&lt;/code> being ordered, and not on any of its other properties.)&lt;/p>
&lt;p>There is nothing fancy going on with &lt;code>get_min&lt;/code>, we tail-recursively iterate the list and select the minimal element:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="o">#[&lt;/span>&lt;span class="n">program&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="kn">Fixpoint&lt;/span> &lt;span class="n">get_min&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">i&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">nat&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">l&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">T&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">mini&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="n">mini&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">mini&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">min&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">M&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="o">_)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">nat&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">M&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">length&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">}&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">match&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="bp">[]&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">mini&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">min&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="n">l&amp;#39;&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">let&lt;/span> &lt;span class="n">mx&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">measure&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="k">in&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">leq&lt;/span> &lt;span class="n">mx&lt;/span> &lt;span class="n">min&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">get_min&amp;#39;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">S&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="n">l&amp;#39;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="n">mx&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">get_min&amp;#39;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">S&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="n">l&amp;#39;&lt;/span> &lt;span class="n">mini&lt;/span> &lt;span class="n">min&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">#[&lt;/span>&lt;span class="n">program&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="kn">Definition&lt;/span> &lt;span class="n">get_min&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">l&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">length&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="o">_)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">nat&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">M&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">length&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">}:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">match&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="bp">[]&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="o">_&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="n">l&amp;#39;&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">get_min&amp;#39;&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="n">l&amp;#39;&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">measure&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Notice how we don&amp;rsquo;t actually prove &lt;code>get_min&lt;/code> correct. In theory my implementation could be wrong and it might not return the minimal item. It turns out that we don&amp;rsquo;t actually need this for the R-tree correctness proof. (A theoretical bug existing in &lt;code>get_min&lt;/code> cannot impact overall correctness, but it could degrade performance.)&lt;/p>
&lt;p>I also needed a function to find minimal pairs of items in a list. The parameters are very similar, but now &lt;code>measure&lt;/code> takes two &lt;code>T&lt;/code>s:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Context&lt;/span> &lt;span class="o">{&lt;/span>&lt;span class="n">T&lt;/span> &lt;span class="n">M&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">Type&lt;/span>&lt;span class="o">}&lt;/span> &lt;span class="o">`{&lt;/span>&lt;span class="n">Ord_M&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">Ord&lt;/span> &lt;span class="n">M&lt;/span>&lt;span class="o">}&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">measure&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">M&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">get_min_pair&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">l&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">length&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">ia&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">ib&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="o">_)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">nat&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="kt">nat&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">M&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">ia&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">ib&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">length&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">}.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The signature of &lt;code>get_min_pair&lt;/code> is a bit more complicated since it has to handle two indices. The implementation is the straightforward quadratic brute force search.&lt;/p>
&lt;h2 id="partitioning-for-node-splitting">Partitioning (for node splitting)&lt;/h2>
&lt;p>When explaining how &lt;a href="#insertion">R-tree insertion&lt;/a> works, I glossed over what heuristic algorithm is used exactly to do the node partitioning. In this section we will cover the particular algorithm I used in detail.&lt;/p>
&lt;p>The original R-tree paper &lt;span class="hugo-cite-intext" itemprop="citation">&lt;span class="tooltip-trigger">&lt;a href="#cite:2">[2]&lt;/a>&lt;span class="tooltip">A. Guttman, &lt;span>“R-trees: A dynamic index structure for spatial searching,”&lt;/span> in &lt;em>Proceedings of the 1984 ACM SIGMOD international conference on Management of data - SIGMOD ’84&lt;/em>, Boston, Massachusetts: ACM Press, 1984, p. 47. doi: &lt;a href="https://doi.org/10.1145/602259.602266">10.1145/602259.602266&lt;/a>.&lt;/span>&lt;/span>&lt;/span> describes three different algorithms for doing node splitting:&lt;/p>
&lt;ul>
&lt;li>The &amp;ldquo;Exhaustive Algorithm&amp;rdquo;, that simply tries all possible partitionings. This algorithm is exponential in complexity, but importantly it&amp;rsquo;s exponential in &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>M&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">M&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.10903em;">M&lt;/span>&lt;/span>&lt;/span>&lt;/span>, so it can actually be a viable option when &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>M&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">M&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.10903em;">M&lt;/span>&lt;/span>&lt;/span>&lt;/span> (which is a pre-defined constant for a whole R-tree) is small.&lt;/li>
&lt;li>The &amp;ldquo;Quadratic-Cost Algorithm&amp;rdquo;, which is quadratic in &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>M&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">M&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.10903em;">M&lt;/span>&lt;/span>&lt;/span>&lt;/span>.&lt;/li>
&lt;li>The &amp;ldquo;Linear-Cost Algorithm&amp;rdquo;, which is linear in &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>M&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">M&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.10903em;">M&lt;/span>&lt;/span>&lt;/span>&lt;/span>.&lt;/li>
&lt;/ul>
&lt;p>I chose to implement the quadratic algorithm as a good middle ground. It works roughly as follows:&lt;/p>
&lt;ul>
&lt;li>Define the &amp;ldquo;dead-space&amp;rdquo; of two rectangles &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>a&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>b&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">a, b&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.8889em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal">a&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal">b&lt;/span>&lt;/span>&lt;/span>&lt;/span> to be &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo stretchy="false">∣&lt;/mo>&lt;mi mathvariant="normal">mbr&lt;/mi>&lt;mo>⁡&lt;/mo>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>a&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>b&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;mo stretchy="false">∣&lt;/mo>&lt;mo>−&lt;/mo>&lt;mo stretchy="false">∣&lt;/mo>&lt;mi>a&lt;/mi>&lt;mo stretchy="false">∣&lt;/mo>&lt;mo>−&lt;/mo>&lt;mo stretchy="false">∣&lt;/mo>&lt;mi>b&lt;/mi>&lt;mo stretchy="false">∣&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\lvert \operatorname{mbr}(a, b) \rvert - \lvert a \rvert - \lvert b \rvert&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mopen">∣&lt;/span>&lt;span class="mop">&lt;span class="mord mathrm">mbr&lt;/span>&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">a&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal">b&lt;/span>&lt;span class="mclose">)∣&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">−&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mopen">∣&lt;/span>&lt;span class="mord mathnormal">a&lt;/span>&lt;span class="mclose">∣&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">−&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mopen">∣&lt;/span>&lt;span class="mord mathnormal">b&lt;/span>&lt;span class="mclose">∣&lt;/span>&lt;/span>&lt;/span>&lt;/span>. This calculates the &amp;ldquo;wasted area&amp;rdquo; when grouping &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>a&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">a&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">a&lt;/span>&lt;/span>&lt;/span>&lt;/span> and &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>b&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">b&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6944em;">&lt;/span>&lt;span class="mord mathnormal">b&lt;/span>&lt;/span>&lt;/span>&lt;/span> together. In the first step choose two entries with the &lt;strong>largest&lt;/strong> dead-space, and make them the initial seed entries of the two groups.&lt;/li>
&lt;li>Repeatedly determine the next best entry to assign to a group, and assign it. The next best entry is the one which has the &lt;strong>largest difference in area enlargement&lt;/strong> if assigned to the two groups. (The area enlargement an entry &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>e&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">e&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">e&lt;/span>&lt;/span>&lt;/span>&lt;/span> incurs on a group &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>g&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">g&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.625em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.03588em;">g&lt;/span>&lt;/span>&lt;/span>&lt;/span> is simply &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo stretchy="false">∣&lt;/mo>&lt;mi mathvariant="normal">mbr&lt;/mi>&lt;mo>⁡&lt;/mo>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>g&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mi>e&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;mo stretchy="false">∣&lt;/mo>&lt;mo>−&lt;/mo>&lt;mo stretchy="false">∣&lt;/mo>&lt;mi>g&lt;/mi>&lt;mo stretchy="false">∣&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\lvert \operatorname{mbr}(g,e) \rvert - \lvert g \rvert&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mopen">∣&lt;/span>&lt;span class="mop">&lt;span class="mord mathrm">mbr&lt;/span>&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.03588em;">g&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal">e&lt;/span>&lt;span class="mclose">)∣&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">−&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mopen">∣&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.03588em;">g&lt;/span>&lt;span class="mclose">∣&lt;/span>&lt;/span>&lt;/span>&lt;/span>.) Assign it to the group whose bounding rectangle has to be enlarged the least to accommodate the new entry.&lt;/li>
&lt;li>If one of the groups has so few items that it needs all of the remaining entries to have at least &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>m&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">m&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">m&lt;/span>&lt;/span>&lt;/span>&lt;/span> items (as required for a well-formed R-tree), just assign all of the remaining entries to that group.&lt;/li>
&lt;/ul>
&lt;p>Picking the seeds can easily be implemented using &lt;code>get_min_pair&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="o">#[&lt;/span>&lt;span class="n">program&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="kn">Definition&lt;/span> &lt;span class="n">partition_pick_seeds&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">l&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">length&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">l&amp;#39;&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="n">l&amp;#39;&lt;/span> &lt;span class="o">~&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">}&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">let&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">mini&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="o">_)&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">get_min_pair&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="k">fun&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">dead_space&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">item_bbox&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">item_bbox&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="o">))&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="k">in&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">remove_pair&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="n">mini&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">prf&lt;/span>&lt;span class="o">:=_).&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The function for picking the next entry is not very difficult either using &lt;code>get_min&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="o">#[&lt;/span>&lt;span class="n">program&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="kn">Definition&lt;/span> &lt;span class="n">partition_pick_next&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">bbox1&lt;/span> &lt;span class="n">bbox2&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">l&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">length&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">l&amp;#39;&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">e&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="n">l&amp;#39;&lt;/span> &lt;span class="o">~&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">}&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">let&lt;/span> &lt;span class="n">neg_diff&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">let&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">item_bbox&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="k">in&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Z&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">opp&lt;/span> &lt;span class="o">$&lt;/span> &lt;span class="n">Z&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">abs&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">enlargement&lt;/span> &lt;span class="n">bbox1&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">enlargement&lt;/span> &lt;span class="n">bbox2&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="k">in&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">let&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="o">_)&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">get_min&lt;/span> &lt;span class="n">neg_diff&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="k">in&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">remove_ith&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Assembling these together is a bit involved, you can look at the source code if you are interested in the details. The final signature of our &lt;code>partition&lt;/code> function looks like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">partition&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">l&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">length&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">M&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="o">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">((&lt;/span>&lt;span class="n">la&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">mbra&lt;/span>&lt;span class="o">),&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">lb&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">mbrb&lt;/span>&lt;span class="o">))&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="kt">list&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">bbox&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="kt">list&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">bbox&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">|&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">m&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">length&lt;/span> &lt;span class="n">la&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">M&lt;/span> &lt;span class="o">/\&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">length&lt;/span> &lt;span class="n">lb&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">M&lt;/span> &lt;span class="o">/\&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">la&lt;/span> &lt;span class="o">++&lt;/span> &lt;span class="n">lb&lt;/span> &lt;span class="o">~&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">/\&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">mbra&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mbr&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">map&lt;/span> &lt;span class="n">item_bbox&lt;/span> &lt;span class="n">la&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">/\&lt;/span> &lt;span class="n">mbrb&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mbr&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">map&lt;/span> &lt;span class="n">item_bbox&lt;/span> &lt;span class="n">lb&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">}.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The postcondition says that:&lt;/p>
&lt;ul>
&lt;li>both output groups have appropriate lengths,&lt;/li>
&lt;li>the two groups together are a permutation of the input list,&lt;/li>
&lt;li>and that the returned bounding boxes do indeed correspond to the returned groups.&lt;/li>
&lt;/ul>
&lt;h2 id="the-tree-data-structure">The tree data structure&lt;/h2>
&lt;p>Now we need to define the type of trees. I initially did try to encode the needed invariants into the tree data structure itself, but I ran into issues with Coq&amp;rsquo;s &lt;a href="https://coq.inria.fr/refman/language/core/inductive.html#positivity-condition">positivity requirements&lt;/a>, so the tree data structure itself is just like what you would see in non-dependent languages:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Inductive&lt;/span> &lt;span class="n">tree&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">Type&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">Leaf&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">item&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">tree&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">Node&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">tree&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">tree&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>A leaf has items as its children, while inner nodes have other trees as their children.&lt;/p>
&lt;p>Instead of encoding the invariants directly in &lt;code>tree&lt;/code>, we will encode them as a separate inductive proposition called &lt;code>wf_tree&lt;/code> (&amp;ldquo;wf&amp;rdquo; here stands for &lt;em>well-formed&lt;/em>):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Inductive&lt;/span> &lt;span class="n">wf_tree&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">tree&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="kt">Prop&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">wf_leaf&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">b&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">l&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">p&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">length&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">M&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">pmbr&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mbr&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">map&lt;/span> &lt;span class="n">item_bbox&lt;/span> &lt;span class="n">l&lt;/span>&lt;span class="o">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">wf_tree&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">Leaf&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="n">l&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">wf_node&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">b&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">l&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">tree&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">p&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">length&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">M&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">pl&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="k">forall&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">In&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">wf_tree&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">pmbr&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mbr&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">map&lt;/span> &lt;span class="n">tree_bbox&lt;/span> &lt;span class="n">l&lt;/span>&lt;span class="o">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">wf_tree&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">Node&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="n">l&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>A leaf is well-formed if the number of its children is between the required bounds, and its bounding box is the minimum bounding rectangle of its children. Inner nodes have to satisfy the same properties, and additionally all of their children have to be well-formed as well.&lt;/p>
&lt;p>We also define a property called &lt;code>wf_root&lt;/code>, which is identical to &lt;code>wf_tree&lt;/code>, except that the lower bounds for the number of children are relaxed. (Root nodes are a bit special, since we can&amp;rsquo;t guarantee that they will have at least &lt;code>m&lt;/code> children.)&lt;/p>
&lt;p>We will often need to deal with well-formed trees, and a pattern you will be seeing is a &lt;code>tree&lt;/code> and a proof of its well-formedness packaged together into a single &lt;code>sig&lt;/code> type: &lt;code>{ t : tree | wf_tree t }&lt;/code>.&lt;/p>
&lt;p>We can now straightforwardly define &lt;code>tree_items&lt;/code> (which we denoted with &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>ι&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">\iota&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">ι&lt;/span>&lt;/span>&lt;/span>&lt;/span>):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Fixpoint&lt;/span> &lt;span class="n">tree_items&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">t&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">tree&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">match&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">Leaf&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="n">items&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">items&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">Node&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="n">nodes&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">flat_map&lt;/span> &lt;span class="n">tree_items&lt;/span> &lt;span class="n">nodes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>We also prove an intuitively true, but important lemma, namely that all items in a well-formed tree are inside its bounding box (this is just a corollary of &lt;code>pmbr&lt;/code> in &lt;code>wf_tree&lt;/code>):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">Items_inside&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">t&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">tree&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">forall&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">In&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">tree_items&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">bbox_inside&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">item_bbox&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">tree_bbox&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">true&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Lemma&lt;/span> &lt;span class="n">wf_tree_items_inside&lt;/span> &lt;span class="o">{&lt;/span>&lt;span class="n">t&lt;/span>&lt;span class="o">}&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">w&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">wf_tree&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">Items_inside&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Last but not least, we need to define a &lt;code>child_tree&lt;/code> relation, and prove that it&amp;rsquo;s well-founded (not to be confused with well-formed):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">child_tree&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">tree&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">match&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">Leaf&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">False&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">Node&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="n">nodes&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">In&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="n">nodes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">wf_child_tree&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">well_founded&lt;/span> &lt;span class="n">child_tree&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The &lt;code>child_tree&lt;/code> relation should be straightforward. &lt;code>well_founded&lt;/code> comes from Coq&amp;rsquo;s standard library: we are proving that &lt;code>child_tree&lt;/code> is a well-founded relation. (See &lt;a href="#proving-termination-manually">this previous section&lt;/a> for an explanation of well-foundedness.)&lt;/p>
&lt;p>Again we are doing a lot of work just to prove something seemingly obvious: when we only recurse on child trees, eventually we have to get to the bottom, and we can&amp;rsquo;t get into an infinite loop!&lt;/p>
&lt;h2 id="tree-operations">Tree operations&lt;/h2>
&lt;h3 id="insertion-1">Insertion&lt;/h3>
&lt;p>The core of the insert implementation looks like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="o">#[&lt;/span>&lt;span class="n">program&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="kn">Fixpoint&lt;/span> &lt;span class="n">insert&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">t&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">tree&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">wf_tree&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">i&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">{&lt;/span>&lt;span class="n">wf&lt;/span> &lt;span class="n">child_tree&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">|&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="mi">1&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">length&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">/\&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="k">forall&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">In&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">wf_tree&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">/\&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">i&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="n">tree_items&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">~&lt;/span> &lt;span class="n">flat_map&lt;/span> &lt;span class="n">tree_items&lt;/span> &lt;span class="n">l&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">}&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">match&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">Leaf&lt;/span> &lt;span class="n">mbr&lt;/span> &lt;span class="n">items&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">length&lt;/span> &lt;span class="n">items&lt;/span> &lt;span class="o">&amp;lt;?&lt;/span> &lt;span class="n">M&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">[&lt;/span>&lt;span class="n">Leaf&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">bbox_mbr&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">item_bbox&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="n">mbr&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">i&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="n">items&lt;/span>&lt;span class="o">)]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">let&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">((&lt;/span>&lt;span class="n">lx&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">mbrx&lt;/span>&lt;span class="o">),&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">ly&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">mbry&lt;/span>&lt;span class="o">))&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">partition&lt;/span> &lt;span class="n">item_bbox&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">i&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="n">items&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="k">in&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">[&lt;/span>&lt;span class="n">Leaf&lt;/span> &lt;span class="n">mbrx&lt;/span> &lt;span class="n">lx&lt;/span>&lt;span class="o">;&lt;/span> &lt;span class="n">Leaf&lt;/span> &lt;span class="n">mbry&lt;/span> &lt;span class="n">ly&lt;/span>&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">Node&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="n">nodes&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">let&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">idx&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="o">_)&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">get_min&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="k">fun&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">enlargement&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">tree_bbox&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">item_bbox&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">))&lt;/span> &lt;span class="n">nodes&lt;/span> &lt;span class="k">in&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">let&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">L&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">nodes&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">remove_ith&lt;/span> &lt;span class="n">nodes&lt;/span> &lt;span class="n">idx&lt;/span> &lt;span class="k">in&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">let&lt;/span> &lt;span class="n">nodes&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">insert&amp;#39;&lt;/span> &lt;span class="n">L&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">++&lt;/span> &lt;span class="n">nodes&lt;/span> &lt;span class="k">in&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">M&lt;/span> &lt;span class="o">&amp;lt;?&lt;/span> &lt;span class="n">length&lt;/span> &lt;span class="n">nodes&lt;/span> &lt;span class="k">then&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">let&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">((&lt;/span>&lt;span class="n">lx&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">mbrx&lt;/span>&lt;span class="o">),&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">ly&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">mbry&lt;/span>&lt;span class="o">))&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">partition&lt;/span> &lt;span class="n">tree_bbox&lt;/span> &lt;span class="n">nodes&lt;/span> &lt;span class="k">in&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">[&lt;/span>&lt;span class="n">Node&lt;/span> &lt;span class="n">mbrx&lt;/span> &lt;span class="n">lx&lt;/span>&lt;span class="o">;&lt;/span> &lt;span class="n">Node&lt;/span> &lt;span class="n">mbry&lt;/span> &lt;span class="n">ly&lt;/span>&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">[&lt;/span>&lt;span class="n">Node&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">mbr&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">map&lt;/span> &lt;span class="n">tree_bbox&lt;/span> &lt;span class="n">nodes&lt;/span>&lt;span class="o">))&lt;/span> &lt;span class="n">nodes&lt;/span>&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>We take a well-formed tree and an item to insert. We return either 1 or 2 well-formed trees, whose items are exactly the items of the original tree plus the inserted item.&lt;/p>
&lt;p>The implementation uses &lt;code>partition&lt;/code> to do the heavy lifting when splitting nodes, and is relatively straightforward. All the proofs that are returned by &lt;code>partition&lt;/code>, &lt;code>get_min&lt;/code>, and &lt;code>insert'&lt;/code> itself in the recursive case can be used to assemble the proof for the specification of &lt;code>insert'&lt;/code>.&lt;/p>
&lt;p>Finally we wrap &lt;code>insert'&lt;/code> with a separate function to handle the special cases with the root node, which will be our actual &lt;code>insert&lt;/code> implementation:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="o">#[&lt;/span>&lt;span class="n">program&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="kn">Definition&lt;/span> &lt;span class="n">insert&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">t&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">tree&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">wf_root&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">i&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="n">t&amp;#39;&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">wf_root&lt;/span> &lt;span class="n">t&amp;#39;&lt;/span> &lt;span class="o">/\&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="n">tree_items&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">~&lt;/span> &lt;span class="n">tree_items&lt;/span> &lt;span class="n">t&amp;#39;&lt;/span> &lt;span class="o">}.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This signature is actually quite simple compared to some others we have seen. It says that &lt;code>insert&lt;/code> takes a well-formed tree and an item, and it returns a well-formed tree, whose items are exactly the items of the original tree plus the new item.&lt;/p>
&lt;h3 id="search">Search&lt;/h3>
&lt;p>To search for items intersecting a query rectangle &lt;code>q&lt;/code>, we traverse the whole tree and skip any subtrees that do not intersect &lt;code>q&lt;/code>. The central lemma stating that this optimization is correct is called &lt;a href="https://git.sr.ht/~kuruczgy/verified-rtree/tree/for-blog/item/RTree.v#L1019">&lt;code>tree_item_intersect&lt;/code>&lt;/a>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Lemma&lt;/span> &lt;span class="n">tree_item_intersect&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">{&lt;/span>&lt;span class="n">q&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">Hwf&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">wf_tree&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">Hin&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">In&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">tree_items&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="kn">Hint&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox_intersect&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">tree_bbox&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">false&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox_intersect&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">item_bbox&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">false&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This lemma says that if &lt;code>q&lt;/code> does not intersect the bounding box of a tree, then it cannot intersect the bounding box of any of its items either. This fact is a simple corollary of &lt;code>wf_tree_items_inside&lt;/code> (all items of a tree are inside its bounding box) and &lt;code>bbox_inside_not_intersect&lt;/code>.&lt;/p>
&lt;p>Equipped with this lemma, we are ready to prove &lt;a href="https://git.sr.ht/~kuruczgy/verified-rtree/tree/for-blog/item/RTree.v#L1136">&lt;code>range_search&lt;/code>&lt;/a> correct:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="o">#[&lt;/span>&lt;span class="n">program&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="kn">Fixpoint&lt;/span> &lt;span class="n">range_search&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">t&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">wf_root&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">q&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">{&lt;/span>&lt;span class="n">wf&lt;/span> &lt;span class="n">child_tree&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">item&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">l&lt;/span> &lt;span class="o">~&lt;/span> &lt;span class="n">filter&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="k">fun&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">bbox_intersect&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">item_bbox&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">))&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">tree_items&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">}&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">match&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">Leaf&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="n">items&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">filter&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="k">fun&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">bbox_intersect&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">item_bbox&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">))&lt;/span> &lt;span class="n">items&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">Node&lt;/span> &lt;span class="n">mbr&lt;/span> &lt;span class="n">nodes&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">let&lt;/span> &lt;span class="n">ns&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">filter&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="k">fun&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">bbox_intersect&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">tree_bbox&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">proj1_sig&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="o">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">forall_distr&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">P&lt;/span>&lt;span class="o">:=(&lt;/span>&lt;span class="k">fun&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">In&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="n">nodes&lt;/span>&lt;span class="o">))&lt;/span> &lt;span class="n">nodes&lt;/span> &lt;span class="o">_)&lt;/span> &lt;span class="k">in&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">flat_map&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="k">fun&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">range_search&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">exist&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">proj1_sig&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">_)&lt;/span> &lt;span class="n">q&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="n">ns&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The specification is quite straightforward: &lt;code>range_search&lt;/code> returns all items of the tree that intersect &lt;code>q&lt;/code>. The implementation is quite straightforward, except for a couple extra things (&lt;code>forall_distr&lt;/code>, &lt;code>proj1_sig&lt;/code>, and &lt;code>exist&lt;/code>) needed to shuffle around the correctness proof. (The proof script following the above definition is not long either, around 20 lines.)&lt;/p>
&lt;h3 id="deletion-1">Deletion&lt;/h3>
&lt;p>I define deletion as a kind of filtering: we are filtering items intersecting a bounding box &lt;code>q&lt;/code> with a predicate &lt;code>f&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Context&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">f&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">item&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="kt">bool&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">q&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">bbox&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>For use in the specification of &lt;code>delete&lt;/code>, we define &lt;code>f'&lt;/code> to determine which items are actually kept: items either not intersecting &lt;code>q&lt;/code>, or items which satisfy &lt;code>f&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Let&lt;/span> &lt;span class="n">f&amp;#39;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">negb&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">bbox_intersect&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">item_bbox&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">))&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="n">f&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The specification of &lt;code>delete&lt;/code> is then quite straightforward:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">delete&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">t&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">wf_root&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="n">t&amp;#39;&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">wf_root&lt;/span> &lt;span class="n">t&amp;#39;&lt;/span> &lt;span class="o">/\&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">tree_items&lt;/span> &lt;span class="n">t&amp;#39;&lt;/span> &lt;span class="o">~&lt;/span> &lt;span class="n">filter&lt;/span> &lt;span class="n">f&amp;#39;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">tree_items&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">))&lt;/span> &lt;span class="o">}.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The items of the returned tree are just the items of the original tree filtered with &lt;code>f'&lt;/code>.&lt;/p>
&lt;p>To recap, deletion works by removing items that need to be removed, and also dropping any nodes that would become invalid as a result. At the end, we reinsert all items removed due to this &amp;ldquo;collateral damage&amp;rdquo;. To do this, we need a little helper function to insert a list of items into a tree:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="o">#[&lt;/span>&lt;span class="n">program&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="kn">Fixpoint&lt;/span> &lt;span class="n">insert_many&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">t&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">wf_root&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">items&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">{&lt;/span>&lt;span class="n">measure&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">length&lt;/span> &lt;span class="n">items&lt;/span>&lt;span class="o">)}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="n">t&amp;#39;&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">wf_root&lt;/span> &lt;span class="n">t&amp;#39;&lt;/span> &lt;span class="o">/\&lt;/span> &lt;span class="n">items&lt;/span> &lt;span class="o">++&lt;/span> &lt;span class="n">tree_items&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">~&lt;/span> &lt;span class="n">tree_items&lt;/span> &lt;span class="n">t&amp;#39;&lt;/span> &lt;span class="o">}&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">match&lt;/span> &lt;span class="n">items&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="bp">[]&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">t&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">::&lt;/span> &lt;span class="n">items&amp;#39;&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">insert_many&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">insert&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="n">items&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>We can&amp;rsquo;t just do &lt;code>fold_left insert items t&lt;/code> because we also need a correctness proof for &lt;code>insert_many&lt;/code>.&lt;/p>
&lt;p>The structure of the implementation is similar to that of insertion, with a tail recursive &lt;code>delete'&lt;/code> function operating on the inner nodes, and a wrapper called &lt;code>delete&lt;/code> handling special cases for the root.&lt;/p>
&lt;p>In &lt;code>delete'&lt;/code> we return an &lt;code>option { t | wf_tree t } * list tree&lt;/code> pair. We either return the updated subtree or nothing (if the whole subtree is just gone as the result of the deletion), and a list of subtrees whose items need to be reinserted at the end.&lt;/p>
&lt;p>The specification became quite verbose, so I pulled it out into a separate definition:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">delete_R&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">t&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">tree&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">option&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">wf_tree&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">}&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="kt">list&lt;/span> &lt;span class="n">tree&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="kt">Prop&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="k">fun&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">t&amp;#39;&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">match&lt;/span> &lt;span class="n">t&amp;#39;&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">None&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="bp">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">Some&lt;/span> &lt;span class="n">t&amp;#39;&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">tree_items&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">proj1_sig&lt;/span> &lt;span class="n">t&amp;#39;&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span> &lt;span class="o">++&lt;/span> &lt;span class="n">flat_map&lt;/span> &lt;span class="n">tree_items&lt;/span> &lt;span class="n">N&lt;/span> &lt;span class="o">~&lt;/span> &lt;span class="n">filter&lt;/span> &lt;span class="n">f&amp;#39;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">tree_items&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This basically says that the set of items in the returned trees (the optional one and the list that needs to be reinserted) is the same as the items in the original tree filtered with &lt;code>f'&lt;/code>.&lt;/p>
&lt;p>With &lt;code>delete_R&lt;/code>, the signature of &lt;code>delete'&lt;/code> becomes very simple:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Fixpoint&lt;/span> &lt;span class="n">delete&amp;#39;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">t&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">wf_tree&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">sig&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">delete_R&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">proj1_sig&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">)).&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>I won&amp;rsquo;t show the implementation here, it&amp;rsquo;s a mess, &lt;a href="https://git.sr.ht/~kuruczgy/verified-rtree/tree/for-blog/item/RTree.v#L1329">here is the source code&lt;/a> if you are interested.&lt;/p>
&lt;p>You can check out the final &lt;code>delete&lt;/code> implementation &lt;a href="https://git.sr.ht/~kuruczgy/verified-rtree/tree/for-blog/item/RTree.v#L1498">here&lt;/a>. It handles some special cases for the root, and at the end it uses &lt;code>insert_many&lt;/code> to reinsert the needed items.&lt;/p>
&lt;h2 id="putting-everything-together">Putting everything together&lt;/h2>
&lt;p>Believe it or not, the hard part is over! Remember the &lt;code>Container&lt;/code> interface from the &lt;a href="#formal-specification-in-coq">section on specifications&lt;/a>? All we have to do now is assemble all of our work into an implementation of this interface.&lt;/p>
&lt;p>First, let&amp;rsquo;s define some parameters:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Context&lt;/span> &lt;span class="o">{&lt;/span>&lt;span class="n">I&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">Type&lt;/span>&lt;span class="o">}&lt;/span> &lt;span class="o">{&lt;/span>&lt;span class="n">item_bbox&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">I&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">bbox&lt;/span>&lt;span class="o">}.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And some constants:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Let&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="mi">4&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Let&lt;/span> &lt;span class="n">M&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="mi">8&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Let&lt;/span> &lt;span class="n">pm1&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">ltac&lt;/span>&lt;span class="o">:(&lt;/span>&lt;span class="n">lia&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Let&lt;/span> &lt;span class="n">pm2&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">M&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">ltac&lt;/span>&lt;span class="o">:(&lt;/span>&lt;span class="n">lia&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>(We could make &lt;code>m&lt;/code> and &lt;code>M&lt;/code> parameters as well, but for the sake of simplicity I will leave them as constants for now.)&lt;/p>
&lt;p>Let&amp;rsquo;s define the type of our container to be the well-formed tree:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="o">{&lt;/span> &lt;span class="n">data&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">tree&lt;/span> &lt;span class="n">I&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">wf_root&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="n">M&lt;/span> &lt;span class="n">I&lt;/span> &lt;span class="n">item_bbox&lt;/span> &lt;span class="n">data&lt;/span> &lt;span class="o">}.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then we have to define some wrapper functions which operate on &lt;code>T&lt;/code> (this basically amounts to plugging in &lt;code>m&lt;/code> and &lt;code>M&lt;/code>, and shuffling around some proofs):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">empty&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">exist&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">empty&lt;/span> &lt;span class="n">I&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">wf_empty&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="n">M&lt;/span> &lt;span class="n">pm1&lt;/span> &lt;span class="n">pm2&lt;/span> &lt;span class="n">I&lt;/span> &lt;span class="n">item_bbox&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">insert&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">let&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">exist&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="n">data&amp;#39;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">conj&lt;/span> &lt;span class="n">wf&amp;#39;&lt;/span> &lt;span class="o">_))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:=&lt;/span> &lt;span class="n">insert&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="n">M&lt;/span> &lt;span class="n">pm1&lt;/span> &lt;span class="n">pm2&lt;/span> &lt;span class="n">I&lt;/span> &lt;span class="n">item_bbox&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="k">in&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">exist&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="n">data&amp;#39;&lt;/span> &lt;span class="n">wf&amp;#39;&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">search&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">let&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">exist&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="n">res&lt;/span> &lt;span class="o">_)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:=&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">range_search&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="n">M&lt;/span> &lt;span class="n">pm1&lt;/span> &lt;span class="n">pm2&lt;/span> &lt;span class="n">I&lt;/span> &lt;span class="n">item_bbox&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="n">q&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="k">in&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">res&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">delete&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="n">f&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">let&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">exist&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="n">data&amp;#39;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">conj&lt;/span> &lt;span class="n">wf&amp;#39;&lt;/span> &lt;span class="o">_))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:=&lt;/span> &lt;span class="n">delete&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="n">M&lt;/span> &lt;span class="n">pm1&lt;/span> &lt;span class="n">pm2&lt;/span> &lt;span class="n">I&lt;/span> &lt;span class="n">item_bbox&lt;/span> &lt;span class="n">f&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="k">in&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="n">exist&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="n">data&amp;#39;&lt;/span> &lt;span class="n">wf&amp;#39;&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, we have to prove the necessary theorems about these wrapper functions, exactly the ones that &lt;code>Container&lt;/code> expects (again, this is very easy and just amounts to plugging in the proofs that the wrapped functions already return about themselves):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Ltac&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">intros&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">unfold&lt;/span> &lt;span class="n">all_items&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">insert&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">delete&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">search&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">repeat&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="k">match&lt;/span> &lt;span class="n">goal&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="o">|-&lt;/span> &lt;span class="n">context&lt;/span>&lt;span class="o">[&lt;/span>&lt;span class="k">let&lt;/span> &lt;span class="k">&amp;#39;&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">exist&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">_)&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="o">?&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="o">_]&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="k">destruct&lt;/span> &lt;span class="n">x&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">prf&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">/\&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">|-&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="k">destruct&lt;/span> &lt;span class="n">prf&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">prf&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">~&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">|-&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="k">simpl&lt;/span>&lt;span class="o">;&lt;/span> &lt;span class="k">simpl&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="n">prf&lt;/span>&lt;span class="o">;&lt;/span> &lt;span class="n">now&lt;/span> &lt;span class="k">rewrite&lt;/span> &lt;span class="n">prf&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">empty_correct&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">all_items&lt;/span> &lt;span class="n">empty&lt;/span> &lt;span class="o">~&lt;/span> &lt;span class="bp">[]&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Proof&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="kp">reflexivity&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="kn">Qed&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">insert_correct&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="k">forall&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">all_items&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">insert&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">~&lt;/span> &lt;span class="o">[&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="o">++&lt;/span> &lt;span class="n">all_items&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Proof&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="kn">Qed&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">delete_correct&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="k">forall&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">all_items&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">delete&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">~&lt;/span> &lt;span class="n">filter&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="k">fun&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">negb&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">bbox_intersect&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">item_bbox&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">))&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="n">f&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">all_items&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Proof&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="kn">Qed&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">search_correct&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="k">forall&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="n">q&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">search&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="o">~&lt;/span> &lt;span class="n">filter&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">(&lt;/span>&lt;span class="k">fun&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">bbox_intersect&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">item_bbox&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">))&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">all_items&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Proof&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="kn">Qed&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And now we have exactly what&amp;rsquo;s needed to define an implementation of &lt;code>Container&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Instance&lt;/span> &lt;span class="n">rtree_container&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">Container&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">T&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">T&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">items&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">all_items&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">empty&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">empty&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">insert&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">insert&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">search&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">search&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">delete&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">delete&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">empty_correct&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">empty_correct&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">insert_correct&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">insert_correct&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">search_correct&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">search_correct&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">delete_correct&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">delete_correct&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And that&amp;rsquo;s it. &lt;code>rtree_container&lt;/code> is now an R-tree implementation that carries the proof of its own functional correctness with it.&lt;/p>
&lt;h1 id="benchmarks">Benchmarks&lt;/h1>
&lt;p>In a famous quote Donald Knuth once wrote:&lt;/p>
&lt;!-- Source: https://www-cs-faculty.stanford.edu/~knuth/faq.html -->
&lt;blockquote>
&lt;p>Beware of bugs in the above code; I have only proved it correct, not tried it.&lt;/p>
&lt;/blockquote>
&lt;p>So, let&amp;rsquo;s actually run the code. While performance was not the focus of this project, I still wanted to know how a program that has been directly extracted from a verified Coq implementation performed. Here are the results, comparing it to various other implementations:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>&lt;/th>
&lt;th>&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>my C implementation&lt;/td>
&lt;td>0.05 ms&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>rbush (JavaScript) &lt;span class="hugo-cite-intext" itemprop="citation">&lt;span class="tooltip-trigger">&lt;a href="#cite:5">[5]&lt;/a>&lt;span class="tooltip">V. Agafonkin, &lt;span>“RBush,”&lt;/span> &lt;em>GitHub repository&lt;/em>. Available: &lt;a href="https://github.com/mourner/rbush">&lt;a href="https://github.com/mourner/rbush">https://github.com/mourner/rbush&lt;/a>&lt;/a>&lt;/span>&lt;/span>&lt;/span>&lt;/td>
&lt;td>0.07 ms&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>brute force in C&lt;/td>
&lt;td>0.60 ms&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>my JavaScript implementation&lt;/td>
&lt;td>0.74 ms&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>brute force (JavaScript)&lt;/td>
&lt;td>1.15 ms&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>verified-rtree (OCaml)&lt;/td>
&lt;td>1.26 ms&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>verified-rtree (js_of_ocaml)&lt;/td>
&lt;td>2.65 ms&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ocaml-rtree &lt;span class="hugo-cite-intext" itemprop="citation">&lt;span class="tooltip-trigger">&lt;a href="#cite:6">[6]&lt;/a>&lt;span class="tooltip">M. Eriksen and P. Ferris, &lt;span>“Ocaml-rtree,”&lt;/span> &lt;em>GitHub repository&lt;/em>. Available: &lt;a href="https://github.com/geocaml/ocaml-rtree">&lt;a href="https://github.com/geocaml/ocaml-rtree">https://github.com/geocaml/ocaml-rtree&lt;/a>&lt;/a>&lt;/span>&lt;/span>&lt;/span>&lt;/td>
&lt;td>3.11 ms&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>brute force (OCaml)&lt;/td>
&lt;td>4.93 ms&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;div class="figcaption">
&lt;p>Querying was measured with &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>N&lt;/mi>&lt;mo>=&lt;/mo>&lt;mn>2&lt;/mn>&lt;mo>⋅&lt;/mo>&lt;mn>1&lt;/mn>&lt;msup>&lt;mn>0&lt;/mn>&lt;mn>5&lt;/mn>&lt;/msup>&lt;/mrow>&lt;annotation encoding="application/x-tex">N = 2 \cdot 10^5&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.10903em;">N&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6444em;">&lt;/span>&lt;span class="mord">2&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">⋅&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.8141em;">&lt;/span>&lt;span class="mord">1&lt;/span>&lt;span class="mord">&lt;span class="mord">0&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.8141em;">&lt;span style="top:-3.063em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">5&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span> boxes, &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>k&lt;/mi>&lt;mo>=&lt;/mo>&lt;mn>214&lt;/mn>&lt;/mrow>&lt;annotation encoding="application/x-tex">k = 214&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.03148em;">k&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6444em;">&lt;/span>&lt;span class="mord">214&lt;/span>&lt;/span>&lt;/span>&lt;/span> results from the query, and &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>M&lt;/mi>&lt;mo>=&lt;/mo>&lt;mn>8&lt;/mn>&lt;/mrow>&lt;annotation encoding="application/x-tex">M = 8&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.10903em;">M&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6444em;">&lt;/span>&lt;span class="mord">8&lt;/span>&lt;/span>&lt;/span>&lt;/span> maximum branching factor. Results are averaged over 10 runs. Both &lt;code>Z&lt;/code> and &lt;code>nat&lt;/code> were extracted to OCaml integers for performance, I talked about the caveats &lt;a href="#arithmetic">here&lt;/a>. Language implementations used: OCaml 5.1.0, Node.js 18.17.1, and GCC 12.3.0.&lt;/p>
&lt;/div>
&lt;p>My naive unoptimized C implementation is the fastest, I am only mildly surprised by this. The big surprise in this benchmark is rbush &lt;span class="hugo-cite-intext" itemprop="citation">&lt;span class="tooltip-trigger">&lt;a href="#cite:5">[5]&lt;/a>&lt;span class="tooltip">V. Agafonkin, &lt;span>“RBush,”&lt;/span> &lt;em>GitHub repository&lt;/em>. Available: &lt;a href="https://github.com/mourner/rbush">&lt;a href="https://github.com/mourner/rbush">https://github.com/mourner/rbush&lt;/a>&lt;/a>&lt;/span>&lt;/span>&lt;/span>, written in JavaScript, which is basically on par with the C implementation in terms of speed. Shout out to whoever optimized it this well.&lt;/p>
&lt;p>Next up is brute force (linear search) in C, not too surprised with this one either, it is well known that on modern CPUs simple linear algorithms which utilize cache prefetching and other hardware optimizations often outperform smarter algorithms.&lt;/p>
&lt;p>The other results seem to suggest that in general JavaScript outperforms OCaml, which is quite surprising to me. Even brute force search in JavaScript is better than anything in OCaml.&lt;/p>
&lt;p>My verified R-tree performs quite well in OCaml (it beats ocaml-rtree by a significant margin), but not so well in JavaScript (it&amp;rsquo;s outperformed by brute force search).&lt;/p>
&lt;p>The worst one is ocaml-rtree, the only one it beats is brute force search in OCaml.&lt;/p>
&lt;p>Conclusion? A lot of these results are surprising to me. If you discover something wrong with my &lt;a href="https://git.sr.ht/~kuruczgy/verified-rtree/tree/for-blog">testing setup&lt;/a>, please let me know. It would also be interesting to dig into why some implementations are performing unexpectedly badly (like my R-tree compiled to JavaScript, or ocaml-rtree), and why some (like rbush) are performing so well.&lt;/p>
&lt;p>The most important takeaway though in the context of this article is that &lt;strong>formal verification doesn&amp;rsquo;t incur performance overhead&lt;/strong>. As this benchmark demonstrates, there are R-tree implementations out there (ocaml-rtree) that are conclusively beaten by my verified implementation in terms of performance.&lt;/p>
&lt;h1 id="conclusions">Conclusions&lt;/h1>
&lt;p>On the topic of writing dependently typed programs in Coq, I have mixed feelings. When reading Adam Chlipala&amp;rsquo;s book &lt;span class="hugo-cite-intext" itemprop="citation">&lt;span class="tooltip-trigger">&lt;a href="#cite:4">[4]&lt;/a>&lt;span class="tooltip">A. Chlipala, &lt;em>Certified programming with dependent types: A pragmatic introduction to the Coq proof assistant&lt;/em>. Cambridge, MA: The MIT Press, 2013. Available: &lt;a href="http://adam.chlipala.net/cpdt/">&lt;a href="http://adam.chlipala.net/cpdt/">http://adam.chlipala.net/cpdt/&lt;/a>&lt;/a>&lt;/span>&lt;/span>&lt;/span>, I got the feeling that dependently typed programming is something that he recommends you do in Coq. I unfortunately ran into obstacles when trying to scale it beyond the simple examples showcased in the book, manually inserting convoy patterns and inline proofs everywhere is simply prohibitive. The &lt;code>#[program]&lt;/code> facility in Coq helps a bit with these issues (and I used &lt;code>#[program]&lt;/code> extensively for this project), but &lt;code>#[program]&lt;/code> has many issues and isn&amp;rsquo;t developed anymore as far as I can tell.&lt;/p>
&lt;p>I still need to get better at writing proofs in Coq, I feel like too many things were done just by trial-and-error instead of advance planning. Still, this is by far the largest proof development I have done to date, and I learned a lot during the course of this project. If you made it this far, I hope you learned something new as well, and I managed to get you interested in using formal methods for improving software correctness.&lt;/p>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>&lt;code>Container&lt;/code> is actually a &lt;a href="https://coq.inria.fr/refman/addendum/type-classes.html">typeclass&lt;/a>, a feature popularized by Haskell. In Coq they are mostly equivalent to record types, which are just syntax sugar for inductive types.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>While in theory there is no clear delineation between proofs and programs, in any reasonable Coq development all proofs will be in the &lt;code>Prop&lt;/code> sort. Extraction erases everything in &lt;code>Prop&lt;/code>.&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:3">
&lt;p>Well, the thing is&amp;hellip; OCaml actually has 6&lt;strong>3&lt;/strong> bit integers, because it uses the lowest bit for tagging. And unfortunately this &lt;a href="https://blog.janestreet.com/what-is-gained-and-lost-with-63-bit-integers/">does affect performance&lt;/a>.&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:4">
&lt;p>Note that you will more often see the legacy &lt;code>Program&lt;/code> form used elsewhere, but for the sake of consistency I will be using the attribute form &lt;code>#[program]&lt;/code>.&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:5">
&lt;p>Actually this is not much of a special case at all. If we have a proof &lt;code>p&lt;/code> of &lt;code>False&lt;/code>, we can just pattern match on it like this: &lt;code>match p with end&lt;/code>. This is a weird looking pattern match, which in fact has &lt;em>zero&lt;/em> branches, since &lt;code>False&lt;/code> has zero constructors. This pattern match can give you &lt;em>any&lt;/em> value of your choosing. In Coq, &lt;em>ex falso quodlibet&lt;/em> means you can not only prove anything, you can also get a value for anything.&lt;sup id="fnref:6">&lt;a href="#fn:6" role="doc-noteref">6&lt;/a>&lt;span class="footnote-tooltip">Actually, it is kind of a special case, since pattern matching on a type of sort &lt;code>Prop&lt;/code> to get something other than &lt;code>Prop&lt;/code> is usually not allowed. As a special case, it is allowed for types with exactly zero or one constructors.&lt;/span>&lt;/sup>&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:6">
&lt;p>Actually, it is kind of a special case, since pattern matching on a type of sort &lt;code>Prop&lt;/code> to get something other than &lt;code>Prop&lt;/code> is usually not allowed. As a special case, it is allowed for types with exactly zero or one constructors.&amp;#160;&lt;a href="#fnref:6" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div>
&lt;h1 id="bibliography">Bibliography&lt;/h1>
&lt;div class="bibliography">&lt;div id="cite:1">
&lt;div>[1]&lt;/div>
&lt;div>H. B. Curry, J. R. Hindley, and J. P. Seldin, Eds., &lt;em>To H.B. Curry: Essays on combinatory logic, lambda calculus, and formalism&lt;/em>. London&amp;#8239;; New York: Academic Press, 1980.&lt;/div>
&lt;/div>&lt;div id="cite:2">
&lt;div>[2]&lt;/div>
&lt;div>A. Guttman, &lt;span>&amp;#8220;R-trees: A dynamic index structure for spatial searching,&amp;#8221;&lt;/span> in &lt;em>Proceedings of the 1984 ACM SIGMOD international conference on Management of data - SIGMOD &amp;#8217;84&lt;/em>, Boston, Massachusetts: ACM Press, 1984, p. 47. doi: &lt;a href="https://doi.org/10.1145/602259.602266">10.1145/602259.602266&lt;/a>.&lt;/div>
&lt;/div>&lt;div id="cite:3">
&lt;div>[3]&lt;/div>
&lt;div>P. Letouzey, &lt;span>&amp;#8220;A New Extraction for Coq,&amp;#8221;&lt;/span> in &lt;em>Types for Proofs and Programs&lt;/em>, G. Goos, J. Hartmanis, J. Van Leeuwen, H. Geuvers, and F. Wiedijk, Eds., Berlin, Heidelberg: Springer Berlin Heidelberg, 2003, pp. 200&amp;#8211;219. doi: &lt;a href="https://doi.org/10.1007/3-540-39185-1_12">10.1007/3-540-39185-1_12&lt;/a>.&lt;/div>
&lt;/div>&lt;div id="cite:4">
&lt;div>[4]&lt;/div>
&lt;div>A. Chlipala, &lt;em>Certified programming with dependent types: A pragmatic introduction to the Coq proof assistant&lt;/em>. Cambridge, MA: The MIT Press, 2013. Available: &lt;a href="http://adam.chlipala.net/cpdt/">http://adam.chlipala.net/cpdt/&lt;/a>&lt;/div>
&lt;/div>&lt;div id="cite:5">
&lt;div>[5]&lt;/div>
&lt;div>V. Agafonkin, &lt;span>&amp;#8220;RBush,&amp;#8221;&lt;/span> &lt;em>GitHub repository&lt;/em>. Available: &lt;a href="https://github.com/mourner/rbush">https://github.com/mourner/rbush&lt;/a>&lt;/div>
&lt;/div>&lt;div id="cite:6">
&lt;div>[6]&lt;/div>
&lt;div>M. Eriksen and P. Ferris, &lt;span>&amp;#8220;Ocaml-rtree,&amp;#8221;&lt;/span> &lt;em>GitHub repository&lt;/em>. Available: &lt;a href="https://github.com/geocaml/ocaml-rtree">https://github.com/geocaml/ocaml-rtree&lt;/a>&lt;/div>
&lt;/div>&lt;/div></description></item><item><title>Theorem proving in Coq</title><link>https://kuruczgy.com/blog/2023/06/18/theorem-proving-in-coq/</link><pubDate>Sun, 18 Jun 2023 00:00:00 +0000</pubDate><guid>https://kuruczgy.com/blog/2023/06/18/theorem-proving-in-coq/</guid><description>&lt;h1 id="introduction">Introduction&lt;/h1>
&lt;p>Coq is a proof assistant that lets you state and prove propositions in a kind of constructive logic, the &lt;a href="https://coq.inria.fr/distrib/current/refman/language/cic.html">&lt;em>Calculus of Inductive Constructions&lt;/em>&lt;/a>. The main reason for using such a system is because proofs written in it can be efficiently machine checked.&lt;/p>
&lt;p>Coq is built around the &lt;a href="https://coq.inria.fr/refman/language/core/index.html">&lt;em>Coq kernel&lt;/em>&lt;/a>, the component responsible for checking the validity of proofs. The kernel is deliberately kept small, and carefully checked, since a bug in its implementation would mean that incorrect proofs could be accepted.&lt;/p>
&lt;p>No other part of Coq can compromise the correctness of proofs that the kernel checks. In particular, the tactics that we will use in the &lt;a href="#theorem-proving">main section&lt;/a> of this article to construct proofs are not part of the kernel.&lt;/p>
&lt;p>This is the most important concept about Coq, and worth reiterating: it doesn&amp;rsquo;t matter how we construct the proofs. We can use the built-in tactic language. We could write our own tactics. We could even ask ChatGPT to write the proofs for us. Doesn&amp;rsquo;t matter. If &lt;strong>the kernel&lt;/strong> says that a proof is correct, it&amp;rsquo;s irrelevant where it came from.&lt;/p>
&lt;p>The &lt;a href="#syntax">first section&lt;/a> in this article will go over the basic syntax of Coq. This is mostly useful to bring you up to speed if you are already familiar with other dependently typed functional languages. (I cover most of the knowledge I am building on here regarding dependent types in my &lt;a href="https://kuruczgy.com/blog/2022/10/20/introduction-to-dependent-types/">previous article&lt;/a>.)&lt;/p>
&lt;p>On the surface Coq tries to mimic regular mathematical practice with its syntax, and you can get pretty far with proving theorems in it without actually understanding the underlying type theory. Don&amp;rsquo;t expect to understand everything though, beneath the surface it relies on a system fundamentally different to &lt;a href="https://en.wikipedia.org/wiki/Zermelo%E2%80%93Fraenkel_set_theory">ZFC&lt;/a>, the set theoretic axiomatic system most of mathematics is built upon. Any non-trivial usage of Coq requires a proper understanding of its foundations.&lt;/p>
&lt;p>In the &lt;a href="#theorem-proving">theorem proving&lt;/a> section, I will go over a very basic proof step-by-step. I will not attempt to explain any proofs in detail beyond this first example though. Coq&amp;rsquo;s interactive proofs are very hard to understand without stepping through it with an IDE yourself and seeing the proof state at each step. (An IDE plugin is just a useful way to display the proof state of Coq in real time, while you are editing. Plugins exist for most popular text editors like &lt;a href="https://proofgeneral.github.io/">Emacs&lt;/a>, &lt;a href="https://github.com/whonore/Coqtail">Vim&lt;/a>, or &lt;a href="https://github.com/coq-community/vscoq">VS Code&lt;/a>. You can also use Coq&amp;rsquo;s interactive &lt;a href="https://coq.inria.fr/refman/practical-tools/coq-commands.html#interactive-use-coqtop">command line interface&lt;/a>, though it&amp;rsquo;s not very convenient. Coq also ships with its own IDE called &lt;a href="https://coq.inria.fr/refman/practical-tools/coqide.html">CoqIDE&lt;/a>, but I would recommend just going with the plugin for the editor you are already using.)&lt;/p>
&lt;p>The &lt;a href="#proof-automation">last section&lt;/a> will showcase some more advanced proofs to show how they can be heavily &amp;ldquo;automated&amp;rdquo; in Coq.&lt;/p>
&lt;p>In summary, the goal of this article is to give you a very basic overview of Coq, and hopefully get you interested in learning it for yourself. &lt;a href="#learning-resources">At the end&lt;/a> I summarize my tips for getting into and learning Coq.&lt;/p>
&lt;h1 id="syntax">Syntax&lt;/h1>
&lt;p>Global definitions can be created with the &lt;code>Definition&lt;/code> command:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">one&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">nat&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Each Coq top level command (called &amp;ldquo;The Vernacular&amp;rdquo;) is terminated with a period. (&lt;code>Definition&lt;/code> is just one of the possible commands, we will see a few others too throughout this article.)&lt;/p>
&lt;p>Functions are defined using the &lt;code>fun&lt;/code> keyword, the identity function is denoted as &lt;code>fun x =&amp;gt; x&lt;/code>.&lt;/p>
&lt;p>A convenient syntax is provided for function parameters when defining functions, making these two definitions equivalent:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">f&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">nat&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="kt">nat&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="kt">nat&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="k">fun&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="k">fun&lt;/span> &lt;span class="n">y&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">f&amp;#39;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="n">y&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">nat&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">nat&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>(Notice the use of the apostrophe in an identifier. This is allowed so that names can more closely reflect the common mathematical practice of denoting closely related things with apostrophes.)&lt;/p>
&lt;p>Coq also features very powerful type inference, we could have also written the previous definition without any type annotations at all:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">f&amp;#39;&amp;#39;&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="n">y&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Coq knows that the &lt;code>+&lt;/code> operator takes &lt;code>nat&lt;/code>s, and can infer everything from there.&lt;/p>
&lt;p>Dependent function types are denoted with the &lt;code>forall&lt;/code> keyword. (Remember that on the logical side of the Curry&amp;ndash;Howard isomorphism dependent function types mean universal quantification, hence the &amp;ldquo;forall&amp;rdquo; name.)&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">g&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="k">forall&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">T&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">Type&lt;/span>&lt;span class="o">),&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">T&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="k">fun&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="k">fun&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The above definition looks quite clunky, fortunately the simplified definition syntax works for dependent function types as well:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">g&amp;#39;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">T&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">Type&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">T&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="notations">Notations&lt;/h2>
&lt;p>Coq has a powerful extensible parser. Let&amp;rsquo;s look at the definition of &lt;code>+&lt;/code> from the standard library:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Notation&lt;/span> &lt;span class="s2">&amp;#34;x + y&amp;#34;&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">plus&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">at&lt;/span> &lt;span class="n">level&lt;/span> &lt;span class="mi">50&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="k">left&lt;/span> &lt;span class="n">associativity&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>(The actual definition is more complicated, but that doesn&amp;rsquo;t concern us right now.)&lt;/p>
&lt;p>This should be quite straightforward: we ask Coq to translate the &lt;code>x + y&lt;/code> infix notation to the &lt;code>plus x y&lt;/code> function application.&lt;/p>
&lt;p>Some additional information is provided to the parser between the second set of parentheses:&lt;/p>
&lt;ul>
&lt;li>&lt;code>left associativity&lt;/code> tells the parser that this notation should be left associative. (Does not really matter for &lt;code>+&lt;/code>, but could matter for other operators.)&lt;/li>
&lt;li>&lt;code>at level 50&lt;/code> sets the precedence level for this notation. Lower precedence levels bind more &amp;ldquo;tightly&amp;rdquo;. For instance, the &lt;code>*&lt;/code> multiplication operator has level 40, so that the expression &lt;code>a + b * c&lt;/code> parses as you would expect, and not as &lt;code>(a + b) * c&lt;/code> that would be dictated just by left associativity.&lt;/li>
&lt;/ul>
&lt;p>One thing that might surprise you is that the &lt;code>-&amp;gt;&lt;/code> function type constructor is just a notation as well:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Notation&lt;/span> &lt;span class="s2">&amp;#34;A -&amp;gt; B&amp;#34;&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="k">forall&lt;/span> &lt;span class="o">(_&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">A&lt;/span>&lt;span class="o">),&lt;/span> &lt;span class="n">B&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">at&lt;/span> &lt;span class="n">level&lt;/span> &lt;span class="mi">99&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="k">right&lt;/span> &lt;span class="n">associativity&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This should be fairly straightforward: non-dependent function types are simply a special case of dependent function types.&lt;/p>
&lt;h1 id="theorem-proving">Theorem proving&lt;/h1>
&lt;p>We will start with proving some simple tautologies, considered the &amp;ldquo;Hello World&amp;rdquo; of proof assistants.&lt;/p>
&lt;p>Let&amp;rsquo;s suppose we have two arbitrary propositions &lt;code>A&lt;/code> and &lt;code>B&lt;/code>. We can declare them in Coq with the &lt;code>Parameters&lt;/code> command:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Parameters&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">A&lt;/span> &lt;span class="n">B&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="kt">Prop&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>Prop&lt;/code> is the type of propositions in Coq. It is very similar to &lt;code>Type&lt;/code>, but there are a few subtle differences. For now just remember that we will use &lt;code>Prop&lt;/code> for propositions instead of &lt;code>Type&lt;/code>.&lt;/p>
&lt;p>The tautology we want to prove is this one:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="n">A&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">B&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">A&lt;/span> &lt;span class="o">/\&lt;/span> &lt;span class="n">B&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>/\&lt;/code> means conjunction of course, and it is defined as the &lt;code>and&lt;/code> type constructor. The proposition then says that &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>A&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">A&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal">A&lt;/span>&lt;/span>&lt;/span>&lt;/span> and &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>B&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">B&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.05017em;">B&lt;/span>&lt;/span>&lt;/span>&lt;/span> implies &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>A&lt;/mi>&lt;mo>∧&lt;/mo>&lt;mi>B&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">A \land B&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal">A&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">∧&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.05017em;">B&lt;/span>&lt;/span>&lt;/span>&lt;/span>.&lt;/p>
&lt;p>We could prove it like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Definition&lt;/span> &lt;span class="n">prove_and&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">A&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">B&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">A&lt;/span> &lt;span class="o">/\&lt;/span> &lt;span class="n">B&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">fun&lt;/span> &lt;span class="n">prf_a&lt;/span> &lt;span class="n">prf_b&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">conj&lt;/span> &lt;span class="n">prf_a&lt;/span> &lt;span class="n">prf_b&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>While this is a perfectly fine proof, directly writing out the proof term is inconvenient and quickly becomes infeasible for larger proofs. Let&amp;rsquo;s look at the &lt;em>Coq way&lt;/em> of proving things:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">prove_and&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">A&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">B&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">A&lt;/span> &lt;span class="o">/\&lt;/span> &lt;span class="n">B&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Proof&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">intros&lt;/span> &lt;span class="n">prf_a&lt;/span> &lt;span class="n">prf_b&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">split&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">-&lt;/span> &lt;span class="kp">exact&lt;/span> &lt;span class="n">prf_a&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">-&lt;/span> &lt;span class="kp">exact&lt;/span> &lt;span class="n">prf_b&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Qed&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Let&amp;rsquo;s break this down.&lt;/p>
&lt;p>&lt;code>Theorem&lt;/code> is the same as &lt;code>Definition&lt;/code>&lt;sup id="fnref:1">&lt;a href="#fn:1" role="doc-noteref">1&lt;/a>&lt;span class="footnote-tooltip">The &lt;code>Theorem&lt;/code> command also makes terms &amp;ldquo;opaque&amp;rdquo;, meaning that the definition cannot be unfolded. This is useful for proofs since once the proof is finished, we only care about its existence and not the actual proof term.&lt;/span>&lt;/sup>, except instead of providing a value straight away, Coq enters its special &amp;ldquo;interactive proof mode&amp;rdquo; to help us interactively construct one. (&lt;code>Proof.&lt;/code> is a no-op, it just helps visually separate the interactive proof script.)&lt;/p>
&lt;p>And here is where the magic of interactive proof construction comes in: using an appropriate IDE, you can see see the &amp;ldquo;proof state&amp;rdquo; while writing the proof. Just after entering &lt;code>Proof.&lt;/code>, this is what the proof state looks like:&lt;/p>
&lt;pre tabindex="0">&lt;code>1 goal
___________________(1/1)
A -&amp;gt; B -&amp;gt; A /\ B
&lt;/code>&lt;/pre>&lt;p>The goal (what needs to be proven) is shown below the line, while hypotheses are above the line. Currently there are no hypotheses, but we can introduce some with the &lt;code>intros&lt;/code> tactic. The &lt;code>intros prf_a prf_b.&lt;/code> tactic introduces the 2 hypotheses, namely the proof of &lt;code>A&lt;/code> and the proof of &lt;code>B&lt;/code>.&lt;/p>
&lt;pre tabindex="0">&lt;code>1 goal
prf_a : A
prf_b : B
___________________(1/1)
A /\ B
&lt;/code>&lt;/pre>&lt;p>The hypotheses are now shown above the line. (We named them &lt;code>prf_a&lt;/code> and &lt;code>prf_b&lt;/code> with the &lt;code>intros&lt;/code> tactic.) We have to prove &lt;code>A /\ B&lt;/code> now. We will use the &lt;code>split&lt;/code> tactic, which lets us prove the two sides of the conjunction separately. The state after &lt;code>split&lt;/code> looks like this:&lt;/p>
&lt;pre tabindex="0">&lt;code>2 goals
prf_a : A
prf_b : B
___________________(1/2)
A
___________________(2/2)
B
&lt;/code>&lt;/pre>&lt;p>Now we have two goals. Coq conveniently lets us focus goals with &amp;ldquo;bullet points&amp;rdquo;. After the first &lt;code>-&lt;/code> bullet, the proof state looks like this:&lt;/p>
&lt;pre tabindex="0">&lt;code>1 goal
prf_a : A
prf_b : B
___________________(1/1)
A
&lt;/code>&lt;/pre>&lt;p>The goal is to prove &lt;code>A&lt;/code>. At this point this is trivial, since we do have a proof of &lt;code>A&lt;/code> as a hypothesis. We can tell Coq which hypothesis we want with the &lt;code>exact&lt;/code> tactic. After &lt;code>exact prf_a.&lt;/code>, Coq will tell us this:&lt;/p>
&lt;pre tabindex="0">&lt;code>This subproof is complete, but there are some unfocused goals:
___________________(1/1)
B
&lt;/code>&lt;/pre>&lt;p>We completed one branch of the proof, but Coq tells us that to finish the whole thing we have to take care of the other branch as well. We can again go to the next goal with the &lt;code>-&lt;/code> bullet:&lt;/p>
&lt;pre tabindex="0">&lt;code>1 goal
prf_a : A
prf_b : B
___________________(1/1)
B
&lt;/code>&lt;/pre>&lt;p>The situation is very similar to the first branch. We have to prove &lt;code>B&lt;/code>, and we have it as a hypothesis, so just use it. After the &lt;code>exact prf_b.&lt;/code> tactic, Coq will show the following:&lt;/p>
&lt;pre tabindex="0">&lt;code>No more goals.
&lt;/code>&lt;/pre>&lt;p>This means that we proved everything, and now the proof is complete. Again, the whole proof looks like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">prove_and&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">A&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">B&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">A&lt;/span> &lt;span class="o">/\&lt;/span> &lt;span class="n">B&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Proof&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">intros&lt;/span> &lt;span class="n">prf_a&lt;/span> &lt;span class="n">prf_b&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">split&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">-&lt;/span> &lt;span class="kp">exact&lt;/span> &lt;span class="n">prf_a&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">-&lt;/span> &lt;span class="kp">exact&lt;/span> &lt;span class="n">prf_b&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Qed&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The &lt;code>Qed.&lt;/code> command terminates the proof, and sends the constructed proof term to the kernel to be verified.&lt;/p>
&lt;h1 id="proof-automation">Proof automation&lt;/h1>
&lt;p>Here is a proof of the commutativity of addition:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Lemma&lt;/span> &lt;span class="n">plus_n_O&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Proof&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">induction&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">-&lt;/span> &lt;span class="kp">reflexivity&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">-&lt;/span> &lt;span class="k">simpl&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="k">rewrite&lt;/span> &lt;span class="o">&amp;lt;-&lt;/span> &lt;span class="n">IHn&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="kp">reflexivity&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Qed&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Lemma&lt;/span> &lt;span class="n">plus_n_Sm&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">S&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">n&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">S&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Proof&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">induction&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">-&lt;/span> &lt;span class="kp">reflexivity&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">-&lt;/span> &lt;span class="k">simpl&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="k">rewrite&lt;/span> &lt;span class="n">IHn&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="kp">reflexivity&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Qed&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">plus_comm&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Proof&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">induction&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">-&lt;/span> &lt;span class="k">rewrite&lt;/span> &lt;span class="o">&amp;lt;-&lt;/span> &lt;span class="n">plus_n_O&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="kp">reflexivity&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">-&lt;/span> &lt;span class="k">rewrite&lt;/span> &lt;span class="o">&amp;lt;-&lt;/span> &lt;span class="n">plus_n_Sm&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="k">rewrite&lt;/span> &lt;span class="o">&amp;lt;-&lt;/span> &lt;span class="n">IHa&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="kp">reflexivity&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Qed&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>You may wonder, if it takes &lt;em>this much&lt;/em> just to prove that &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>a&lt;/mi>&lt;mo>+&lt;/mo>&lt;mi>b&lt;/mi>&lt;mo>=&lt;/mo>&lt;mi>b&lt;/mi>&lt;mo>+&lt;/mo>&lt;mi>a&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">a + b = b + a&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6667em;vertical-align:-0.0833em;">&lt;/span>&lt;span class="mord mathnormal">a&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">+&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6944em;">&lt;/span>&lt;span class="mord mathnormal">b&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.7778em;vertical-align:-0.0833em;">&lt;/span>&lt;span class="mord mathnormal">b&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">+&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">a&lt;/span>&lt;/span>&lt;/span>&lt;/span>, how much can it take to prove something actually useful?&lt;/p>
&lt;p>Here is a shorter proof of the above theorem:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Require&lt;/span> &lt;span class="kn">Import&lt;/span> &lt;span class="n">Lia&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">plus_comm&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Proof&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">lia&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Qed&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>lia&lt;/code> is a tactic for &lt;a href="https://coq.inria.fr/refman/addendum/micromega.html">linear integer arithmetic&lt;/a>. Proving &lt;code>plus_comm&lt;/code> is just a trivial case for it. (It relies on existing proofs for the properties of the standard mathematical operators.) Let&amp;rsquo;s look at a more complex case:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">binomial&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">b&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Proof&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">lia&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Qed&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This is not even completely linear, but &lt;code>lia&lt;/code> can handle some simple non-linear cases. If you still can&amp;rsquo;t quite appreciate how much heavy lifting &lt;code>lia&lt;/code> is doing here for us, let me show you my handwritten proof that just appeals to the basic properties of addition and multiplication:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">binomial&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">b&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Proof&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">rewrite&lt;/span> &lt;span class="n">mul_add_distr_r&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">rewrite&lt;/span> &lt;span class="n">mul_add_distr_l&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">rewrite&lt;/span> &lt;span class="n">mul_add_distr_l&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">rewrite&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">mul_comm&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">rewrite&lt;/span> &lt;span class="n">add_assoc&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">rewrite&lt;/span> &lt;span class="o">&amp;lt;-&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">mul_1_l&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="o">)).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">rewrite&lt;/span> &lt;span class="o">&amp;lt;-&lt;/span> &lt;span class="n">add_assoc&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">rewrite&lt;/span> &lt;span class="o">&amp;lt;-&lt;/span> &lt;span class="n">add_assoc&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">rewrite&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">add_assoc&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="mi">1&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="o">_)).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">rewrite&lt;/span> &lt;span class="o">&amp;lt;-&lt;/span> &lt;span class="n">mul_add_distr_r&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">change&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="mi">1&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="k">with&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">rewrite&lt;/span> &lt;span class="n">add_assoc&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">rewrite&lt;/span> &lt;span class="n">mul_assoc&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kp">reflexivity&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Qed&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>You probably learn to do the above multiplication in high school, but might not appreciate just how much goes into it if you rigorously write out every step.&lt;/p>
&lt;h2 id="writing-your-own-automation-tactics">Writing your own automation tactics&lt;/h2>
&lt;p>&lt;code>lia&lt;/code> is a generally useful automation tactic based on well established algorithms, implemented in OCaml&lt;sup id="fnref:2">&lt;a href="#fn:2" role="doc-noteref">2&lt;/a>&lt;span class="footnote-tooltip">Coq is written in OCaml, so the easiest way to write plugins is in OCaml.&lt;/span>&lt;/sup> for performance. You probably don&amp;rsquo;t want to start with writing your own tactics in OCaml though.&lt;/p>
&lt;p>A language called Ltac ships by default with Coq for writing tactics. (In fact, all of the interactive proofs you have seen so far were written in Ltac, they just weren&amp;rsquo;t too complex, mostly consisting of simple sequences of tactic invocations.)&lt;/p>
&lt;p>Ltac is a domain specific language that specifically evolved to be used with Coq. It is a dynamically typed, Turing-complete scripting language that features built-in backtracking for proof search. The language is not great by modern standards, it has a lot of inconsistencies stemming from its organic evolution alongside Coq. Efforts are underway to &lt;a href="https://coq.inria.fr/refman/proof-engine/ltac2.html">replace&lt;/a> it, and &lt;a href="https://plv.mpi-sws.org/mtac/">alternative&lt;/a> tactic languages exist as well. Nonetheless, Ltac is still the most widely used tactic language today for Coq, and probably the best starting point for learning proof automation.&lt;/p>
&lt;p>Let&amp;rsquo;s use some logical tautologies as examples again:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">taut1&lt;/span> &lt;span class="n">A&lt;/span> &lt;span class="n">B&lt;/span> &lt;span class="n">C&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">A&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">B&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">C&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">A&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">B&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">A&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">C&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Proof&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">intros&lt;/span> &lt;span class="n">abc&lt;/span> &lt;span class="n">ab&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">specialize&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">ab&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">specialize&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">abc&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">specialize&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">abc&lt;/span> &lt;span class="n">ab&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kp">exact&lt;/span> &lt;span class="n">abc&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Qed&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The proof is quite straightforward. Just apply hypotheses to implications until we reach &lt;code>C&lt;/code>.&lt;/p>
&lt;p>Let&amp;rsquo;s say we also need to prove a slight variant of &lt;code>taut1&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">taut2&lt;/span> &lt;span class="n">A&lt;/span> &lt;span class="n">B&lt;/span> &lt;span class="n">C&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">B&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">C&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">A&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">B&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">A&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">C&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Proof&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">intros&lt;/span> &lt;span class="n">bc&lt;/span> &lt;span class="n">ab&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">specialize&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">ab&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">specialize&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">bc&lt;/span> &lt;span class="n">ab&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kp">exact&lt;/span> &lt;span class="n">bc&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Qed&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>We can just copy-paste our previous proof script, and modify it a bit. Not too bad, right?&lt;/p>
&lt;p>Well, imagine if we had to do a 100 proofs like this. All with very slight variations. Something like this can easily happen in real-world proof developments. It&amp;rsquo;s not uncommon to encounter a lot of very similar goals (usually as a result of some combinatorial explosion) that need to be proven. We clearly need some more scalable approach.&lt;/p>
&lt;p>This is where proof automation comes in. We will implement our intuition (&amp;ldquo;just apply hypotheses to implications until we reach the goal&amp;rdquo;) in Ltac:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Ltac&lt;/span> &lt;span class="n">my_tauto&lt;/span> &lt;span class="o">:=&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">intros&lt;/span>&lt;span class="o">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">repeat&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="k">match&lt;/span> &lt;span class="n">goal&lt;/span> &lt;span class="k">with&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">?&lt;/span>&lt;span class="n">H&lt;/span> &lt;span class="o">|-&lt;/span> &lt;span class="o">?&lt;/span>&lt;span class="n">H&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="kp">exact&lt;/span> &lt;span class="n">x&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">|&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">?&lt;/span>&lt;span class="n">H&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">?&lt;/span>&lt;span class="n">H&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">|-&lt;/span> &lt;span class="o">_&lt;/span> &lt;span class="o">=&amp;gt;&lt;/span> &lt;span class="n">specialize&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">p&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">end&lt;/span>&lt;span class="o">).&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Let&amp;rsquo;s break this down. First, &lt;code>intros&lt;/code> will introduce as many hypotheses as it can. (In this case their names are auto-generated by Coq.)&lt;/p>
&lt;p>Next, we will use the very common &lt;code>repeat&lt;/code> and &lt;code>match&lt;/code> pattern. It will repeatedly choose a branch and execute it, until either the goal is solved or it can&amp;rsquo;t progress anymore.&lt;/p>
&lt;p>The heart of this script are the two match patterns. Patterns on the left side of the turnstile (&lt;code>|-&lt;/code>) match hypotheses, while the pattern on the right side matches the goal. Underscores are wildcards, while names prefixed with question marks are unification variables. (For example, the pattern &lt;code>?A&lt;/code> matches any proposition, while &lt;code>?A -&amp;gt; ?B&lt;/code> matches any implication. Any unification variables we don&amp;rsquo;t care about can just be replaced with underscores: &lt;code>_ -&amp;gt; _&lt;/code> matches implications as well, we just can&amp;rsquo;t extract the matched propositions afterwards.)&lt;/p>
&lt;p>The first branch looks for any hypothesis directly proving the goal. This is achieved by using the unification variable &lt;code>?H&lt;/code> to match the goal, and also a hypothesis. If we find such a hypothesis, we can just directly prove the goal, and we are done. (We name this hypothesis &lt;code>x&lt;/code> here. Of course the pattern can match a hypothesis with any name, and Coq will allow us to refer to the hypothesis with the name &lt;code>x&lt;/code> in this branch.)&lt;/p>
&lt;p>The second branch looks for any hypothesis proving &lt;code>?H&lt;/code>, and any implication with an antecedent &lt;code>?H&lt;/code>. (We don&amp;rsquo;t care about the goal in this case.) If it finds a pair like this, it specializes the implication to obtain its consequent as a hypothesis.&lt;/p>
&lt;p>This simple algorithm makes short work of our two previous example tautologies:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-coq" data-lang="coq">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">taut1&amp;#39;&lt;/span> &lt;span class="n">A&lt;/span> &lt;span class="n">B&lt;/span> &lt;span class="n">C&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">A&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">B&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">C&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">A&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">B&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">A&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">C&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Proof&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">my_tauto&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Qed&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Theorem&lt;/span> &lt;span class="n">taut2&amp;#39;&lt;/span> &lt;span class="n">A&lt;/span> &lt;span class="n">B&lt;/span> &lt;span class="n">C&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">B&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">C&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">A&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">B&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">A&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">C&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Proof&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">my_tauto&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">Qed&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>I hope this section was able to give you a glimpse of just how powerful proof automation can be.&lt;/p>
&lt;h1 id="learning-resources">Learning resources&lt;/h1>
&lt;p>I hope this short introduction gave you a good picture of what Coq is capable of, and maybe got you interested in learning more. Here a few resources I would recommend:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://softwarefoundations.cis.upenn.edu/lf-current/index.html">Volume 1 of Software Foundations&lt;/a>: A very good introduction to Coq, building up to quite advanced levels. I would recommend this as a starting point.&lt;/li>
&lt;li>&lt;a href="https://coq.inria.fr/refman/">Coq Reference Manual&lt;/a>: The best resource to look up a specific detail about Coq. Are you interested in the exact backtracking semantics of Ltac, or maybe learning about &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>η&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">\eta&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.625em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.03588em;">η&lt;/span>&lt;/span>&lt;/span>&lt;/span>-expansion? This is the right place.&lt;/li>
&lt;li>&lt;a href="http://adam.chlipala.net/cpdt/">Certified Programming with Dependent Types&lt;/a>: A book about dependently typed programming and advanced proof automation in Coq. It shows off some cool ideas, and I think it&amp;rsquo;s good for getting some inspiration, but it is in no way a comprehensive guide for any particular technique.&lt;/li>
&lt;/ul>
&lt;p>The &lt;a href="https://coq.inria.fr/documentation">Coq website&lt;/a> also has a long list of Coq related resources, but I have only read the ones I listed above, so I can&amp;rsquo;t vouch for the quality of any others.&lt;/p>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>The &lt;code>Theorem&lt;/code> command also makes terms &amp;ldquo;opaque&amp;rdquo;, meaning that the definition cannot be unfolded. This is useful for proofs since once the proof is finished, we only care about its existence and not the actual proof term.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>Coq is written in OCaml, so the easiest way to write plugins is in OCaml.&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>Introduction to dependent types and the Curry-Howard isomorphism</title><link>https://kuruczgy.com/blog/2022/10/20/introduction-to-dependent-types/</link><pubDate>Thu, 20 Oct 2022 00:00:00 +0000</pubDate><guid>https://kuruczgy.com/blog/2022/10/20/introduction-to-dependent-types/</guid><description>&lt;p>This article is meant to be a quick introduction to dependently typed programming, and theorem proving through the Curry&amp;ndash;Howard isomorphism.&lt;/p>
&lt;p>I assume basic knowledge of programming in statically typed imperative languages, as well as familiarity with some basic concepts from first order classical logic (quantifiers, implication, conjunction, disjunction). I will be using Idris for the examples, but I will explain the syntax and all necessary functional programming concept as we go. Still, this article covers a lot of material in a short amount of text. Take a break if you need space to process the new concepts, and use the table of contents to navigate.&lt;/p>
&lt;p>Note that often an explanation for a new code sample is only offered afterwards, so make sure to read on. Sometimes it takes multiple paragraphs just to explain every aspect of a single example.&lt;/p>
&lt;div>
&lt;h2>Table Of Contents&lt;/h2>
&lt;nav id="TableOfContents">
&lt;ol>
&lt;li>&lt;a href="#motivating-examples">Motivating examples&lt;/a>&lt;/li>
&lt;li>&lt;a href="#pure-functional-programming">Pure functional programming&lt;/a>&lt;/li>
&lt;li>&lt;a href="#first-class-types">First class types&lt;/a>&lt;/li>
&lt;li>&lt;a href="#inductive-types">Inductive types&lt;/a>
&lt;ol>
&lt;li>&lt;a href="#algebraic-data-types">Algebraic data types&lt;/a>&lt;/li>
&lt;li>&lt;a href="#parameterized-and-recursive-types">Parameterized and recursive types&lt;/a>&lt;/li>
&lt;li>&lt;a href="#type-indices">Type indices&lt;/a>&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;a href="#programming-with-dependent-types">Programming with dependent types&lt;/a>&lt;/li>
&lt;li>&lt;a href="#the-curry--howard-correspondence">The Curry&amp;ndash;Howard correspondence&lt;/a>&lt;/li>
&lt;li>&lt;a href="#conclusion">Conclusion&lt;/a>&lt;/li>
&lt;/ol>
&lt;/nav>
&lt;/div>
&lt;h1 id="motivating-examples">Motivating examples&lt;/h1>
&lt;p>Let&amp;rsquo;s look at a regular function in C++.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">id&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This is one of the simplest functions imaginable, the identity function:&lt;/p>
&lt;p>&lt;span class="katex-display">&lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML" display="block">&lt;semantics>&lt;mrow>&lt;mrow>&lt;mi mathvariant="normal">i&lt;/mi>&lt;mi mathvariant="normal">d&lt;/mi>&lt;/mrow>&lt;mo>:&lt;/mo>&lt;mrow>&lt;mi mathvariant="monospace">i&lt;/mi>&lt;mi mathvariant="monospace">n&lt;/mi>&lt;mi mathvariant="monospace">t&lt;/mi>&lt;/mrow>&lt;mo>→&lt;/mo>&lt;mrow>&lt;mi mathvariant="monospace">i&lt;/mi>&lt;mi mathvariant="monospace">n&lt;/mi>&lt;mi mathvariant="monospace">t&lt;/mi>&lt;/mrow>&lt;mspace linebreak="newline">&lt;/mspace>&lt;mrow>&lt;mi mathvariant="normal">i&lt;/mi>&lt;mi mathvariant="normal">d&lt;/mi>&lt;/mrow>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>x&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;mo>=&lt;/mo>&lt;mi>x&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">
\mathrm{id} : \mathtt{int} \to \mathtt{int} \\
\mathrm{id}(x) = x
&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6944em;">&lt;/span>&lt;span class="mord">&lt;span class="mord mathrm">id&lt;/span>&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">:&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6111em;">&lt;/span>&lt;span class="mord">&lt;span class="mord mathtt">int&lt;/span>&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">→&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6111em;">&lt;/span>&lt;span class="mord">&lt;span class="mord mathtt">int&lt;/span>&lt;/span>&lt;/span>&lt;span class="mspace newline">&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord">&lt;span class="mord mathrm">id&lt;/span>&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">x&lt;/span>&lt;span class="mclose">)&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">x&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/p>
&lt;p>The domain and codomain of this function is fixed. If we wanted an identity function for any other imaginable type out there, we would have to redefine it for that type.&lt;/p>
&lt;p>In C++, we have templates to address this issue.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">template&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="k">typename&lt;/span> &lt;span class="n">T&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">T&lt;/span> &lt;span class="n">id&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">T&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This is what is usually called a polymorphic identity function. When calling &lt;code>id&lt;/code>, you have to supply two arguments: a type for the parameter &lt;code>T&lt;/code>, and a value of type &lt;code>T&lt;/code> for the parameter &lt;code>x&lt;/code>. The two parameters are quite different though: one is a type, and the other is a value. They are also clearly separated when calling the function:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="n">id&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">id&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">char&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sc">&amp;#39;x&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Okay, so even though the syntax is a bit awkward, we can take types as arguments. Next, what about returning them?&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">template&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="k">typename&lt;/span> &lt;span class="n">A&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">typename&lt;/span> &lt;span class="n">B&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">struct&lt;/span> &lt;span class="nc">pair&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">A&lt;/span> &lt;span class="n">fst&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">B&lt;/span> &lt;span class="n">snd&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If you squint at this hard enough, it is actually a function taking two type arguments, and returning the type of pairs constructed from them. Again, I am deliberately using a language where it is awkward to express these type level concepts.&lt;/p>
&lt;p>Next, what about a function that takes a value, and returns a type? Here is an attempt:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">template&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">bool&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">using&lt;/span> &lt;span class="n">f&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kt">char&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">template&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="nb">true&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">using&lt;/span> &lt;span class="n">f&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kt">double&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>f&amp;lt;false&amp;gt;&lt;/code> returns &lt;code>char&lt;/code>, and &lt;code>f&amp;lt;true&amp;gt;&lt;/code> returns &lt;code>double&lt;/code>. This is almost what we are looking for, but something is not quite right. The issue with this example is that &lt;code>b&lt;/code> is not truly a value, it can only be a compile time constant. In particular, you can&amp;rsquo;t do this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">auto&lt;/span> &lt;span class="nf">g&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">bool&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">?&lt;/span> &lt;span class="mf">1.0&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="sc">&amp;#39;x&amp;#39;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Let&amp;rsquo;s examine what this function is trying to do. It takes a boolean, and depending on its value it either returns a &lt;code>char&lt;/code> or a &lt;code>double&lt;/code>. Such a function is called &lt;em>dependently typed&lt;/em>, since its return type depends on the actual value supplied to it. The obvious issue here is that &lt;code>b&lt;/code> might only be known at runtime (it could be input from the user for instance), so it&amp;rsquo;s impossible to know the type of this function at compile time. Allowing something like this would clearly break &lt;em>static&lt;/em> typing, right?&lt;/p>
&lt;h1 id="pure-functional-programming">Pure functional programming&lt;/h1>
&lt;p>For the rest of this article I will be using Idris, but the ideas should be applicable for any dependently typed functional language.&lt;/p>
&lt;p>So, how do functional programming languages differ from the more common &lt;em>imperative&lt;/em> languages? The most important difference is that functions are much more like mathematical functions. That is:&lt;/p>
&lt;ol>
&lt;li>They have exactly one input and one output.&lt;/li>
&lt;li>They can&amp;rsquo;t have side effects. When you &amp;ldquo;call&amp;rdquo; &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>sin&lt;/mi>&lt;mo>⁡&lt;/mo>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>x&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\sin(x)&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mop">sin&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">x&lt;/span>&lt;span class="mclose">)&lt;/span>&lt;/span>&lt;/span>&lt;/span> in mathematics, it can&amp;rsquo;t mutate global variables, or affect anything else.&lt;/li>
&lt;/ol>
&lt;p>The notation &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>f&lt;/mi>&lt;mo>:&lt;/mo>&lt;mi>A&lt;/mi>&lt;mo>→&lt;/mo>&lt;mi>B&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">f : A \to B&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.8889em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.10764em;">f&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">:&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal">A&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">→&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.05017em;">B&lt;/span>&lt;/span>&lt;/span>&lt;/span> is used in mathematics to denote a function with domain &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>A&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">A&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal">A&lt;/span>&lt;/span>&lt;/span>&lt;/span> and codomain &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>B&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">B&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.05017em;">B&lt;/span>&lt;/span>&lt;/span>&lt;/span>. The same notation is used in Idris, but unlike in regular set theory, the domain and codomain are &lt;em>types&lt;/em> instead of sets.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">f&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="kt">A&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kt">B&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Here is how you would define the function &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>f&lt;/mi>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>x&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;mo>=&lt;/mo>&lt;mi>x&lt;/mi>&lt;mo>+&lt;/mo>&lt;mn>1&lt;/mn>&lt;/mrow>&lt;annotation encoding="application/x-tex">f(x) = x + 1&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.10764em;">f&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">x&lt;/span>&lt;span class="mclose">)&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6667em;vertical-align:-0.0833em;">&lt;/span>&lt;span class="mord mathnormal">x&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">+&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6444em;">&lt;/span>&lt;span class="mord">1&lt;/span>&lt;/span>&lt;/span>&lt;/span> in Idris:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">f&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="kt">Int&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kt">Int&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">f x &lt;span class="ow">=&lt;/span> x &lt;span class="ow">+&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Note the lack of parenthesis. As functional languages are all about functions, the notation around them is simplified as much as possible. Function application also omits parenthesis, so &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>f&lt;/mi>&lt;mo stretchy="false">(&lt;/mo>&lt;mn>1&lt;/mn>&lt;mo stretchy="false">)&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">f(1)&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.10764em;">f&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord">1&lt;/span>&lt;span class="mclose">)&lt;/span>&lt;/span>&lt;/span>&lt;/span> would simply be written as &lt;code>f 1&lt;/code>.&lt;/p>
&lt;p>A very important concept in functional programming is that functions are first class values. (&lt;em>First class&lt;/em> in this context means that functions are like any other value, they can be received and returned by functions.) The above definition is just syntactic sugar for defining &lt;code>f&lt;/code> as the anonymous function value &lt;code>\x =&amp;gt; x + 1&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">f&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="kt">Int&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kt">Int&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">f &lt;span class="ow">=&lt;/span> &lt;span class="ow">\&lt;/span>x &lt;span class="ow">=&amp;gt;&lt;/span> x &lt;span class="ow">+&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>In mathematics we don&amp;rsquo;t usually define functions over functions, but in functional programming this is perfectly normal:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">plus&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="kt">Int&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="ow">(&lt;/span>&lt;span class="kt">Int&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kt">Int&lt;/span>&lt;span class="ow">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">plus &lt;span class="ow">=&lt;/span> &lt;span class="ow">\&lt;/span>x &lt;span class="ow">=&amp;gt;&lt;/span> &lt;span class="ow">(\&lt;/span>y &lt;span class="ow">=&amp;gt;&lt;/span> x &lt;span class="ow">+&lt;/span> y&lt;span class="ow">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>In this example, we return a function from a function. This technique is called &lt;em>currying&lt;/em>, and it is the most common way to define multi argument functions. The terse application syntax makes using such functions natural: &lt;code>plus 1 2&lt;/code>. The meaning of this is to apply &lt;code>1&lt;/code> to the &lt;code>plus&lt;/code> function, then apply &lt;code>2&lt;/code> to the function returned by &lt;code>plus 1&lt;/code>.&lt;/p>
&lt;p>Syntactic sugar also allows us to simplify the definition of &lt;code>plus&lt;/code>. We can remove the parenthesis from the type as well, since the &lt;code>-&amp;gt;&lt;/code> type constructor is right associative:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">plus&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="kt">Int&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kt">Int&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kt">Int&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">plus x y &lt;span class="ow">=&lt;/span> x &lt;span class="ow">+&lt;/span> y
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>One thing you might have glossed over so far is that I haven&amp;rsquo;t actually described what &lt;code>x + y&lt;/code> means. It just seems natural, everybody knows what addition is, right?&lt;/p>
&lt;p>In fact, in Idris, operators are just regular functions.&lt;sup id="fnref:1">&lt;a href="#fn:1" role="doc-noteref">1&lt;/a>&lt;span class="footnote-tooltip">There are some exceptions, notably &lt;code>-&amp;gt;&lt;/code> is built in.&lt;/span>&lt;/sup> &lt;code>x + y&lt;/code> is syntactic sugar for &lt;code>(+) x y&lt;/code>. Just remember this for now, later we will be defining some of our own infix operators as well.&lt;/p>
&lt;p>At this point you may wonder how any actually useful programming gets done in a pure language. Let&amp;rsquo;s say, how do you print something? That certainly counts as a side effect.&lt;/p>
&lt;p>Various techniques can be used to emulate imperative constructs while preserving functional purity, but this topic is not really relevant to this article, so I won&amp;rsquo;t go into any details. Look for any decent Haskell introductory material if you are interested in learning more.&lt;/p>
&lt;h1 id="first-class-types">First class types&lt;/h1>
&lt;p>So functions are first class. A much more unique feature of Idris is that &lt;em>types&lt;/em> are also first class. You can manipulate types just like you would any other values.&lt;/p>
&lt;p>Despite this, static typechecking is fully retained. The details on how such dependently typed programs can be typechecked and compiled are somewhat complicated, but they are well studied, and &lt;a href="https://bentnib.org/quantitative-type-theory.pdf">backed by solid formal mathematics&lt;/a>. Let&amp;rsquo;s set aside our worries about the implementation for now, and explore what first class types can do. First consider our familiar identity function over &lt;code>Int&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">id&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="kt">Int&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kt">Int&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">id x &lt;span class="ow">=&lt;/span> x
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>We can extend it to be polymorphic by taking another parameter of type &lt;code>Type&lt;/code>, which is the &lt;em>type of types&lt;/em>:&lt;sup id="fnref:2">&lt;a href="#fn:2" role="doc-noteref">2&lt;/a>&lt;span class="footnote-tooltip">And if you are perhaps wondering what is the type of &lt;code>Type&lt;/code>, &lt;a href="https://cs.stackexchange.com/questions/13285/universes-in-dependent-type-theory">you are in for a ride&lt;/a>. Fortunately though most of the time you can just ignore the complicated theory and pretend that &lt;code>Type : Type&lt;/code>.&lt;/span>&lt;/sup>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">id&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="ow">(&lt;/span>a &lt;span class="ow">:&lt;/span> &lt;span class="kt">Type&lt;/span>&lt;span class="ow">)&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> a &lt;span class="ow">-&amp;gt;&lt;/span> a
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">id &lt;span class="kr">_&lt;/span> x &lt;span class="ow">=&lt;/span> x
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>An interesting new piece of syntax here is that we can name parameters in the function type. (In general, any time you see a colon, it means that the thing on its left hand side has the type on its right hand side.) Naming &lt;code>a&lt;/code> is necessary since we want to refer to it in the rest of the type. This new &lt;code>id&lt;/code> function has two parameters, but we don&amp;rsquo;t need to use the type parameter in the body, so we can write &lt;code>_&lt;/code> to just ignore it.&lt;/p>
&lt;p>With this new definition, &lt;code>id Int&lt;/code> would be equivalent to our previous &lt;code>id&lt;/code> definition. We can of course now use this new definition with any other type as well:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">id &lt;span class="kt">Int&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">id &lt;span class="kt">Char&lt;/span> &lt;span class="sc">&amp;#39;x&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Notice how the types are just regular arguments, not distinguished in any special way.&lt;/p>
&lt;p>The above example is good for introducing the concept of first class types, but writing out the types every time we use &lt;code>id&lt;/code> would be a bit verbose. In Idris we can mark some parameters as &lt;em>implicit&lt;/em>, and they will be inferred at the call site instead of having to be explicitly provided:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">id&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="ow">{&lt;/span>a &lt;span class="ow">:&lt;/span> &lt;span class="kt">Type&lt;/span>&lt;span class="ow">}&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> a &lt;span class="ow">-&amp;gt;&lt;/span> a
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">id x &lt;span class="ow">=&lt;/span> x
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>With this definition we can just write &lt;code>id 1&lt;/code> and &lt;code>id 'x'&lt;/code>, and Idris will figure out what &lt;code>a&lt;/code> should be.&lt;/p>
&lt;p>We can go even one step further. This definition is equivalent to the previous one:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">id&lt;/span> &lt;span class="ow">:&lt;/span> a &lt;span class="ow">-&amp;gt;&lt;/span> a
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">id x &lt;span class="ow">=&lt;/span> x
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Since using implicit parameters is so common, Idris provides special syntactic sugar for them. In particular, any lowercase names in types will automatically get turned into implicit parameters.&lt;/p>
&lt;p>We ended the &lt;a href="#motivating-examples">motivating examples&lt;/a> section with attempting to write a function that returned different types based on the value of the input. Let&amp;rsquo;s now write such a function in Idris:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">g&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="ow">(&lt;/span>b &lt;span class="ow">:&lt;/span> &lt;span class="kt">Bool&lt;/span>&lt;span class="ow">)&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kr">if&lt;/span> b &lt;span class="kr">then&lt;/span> &lt;span class="kt">Double&lt;/span> &lt;span class="kr">else&lt;/span> &lt;span class="kt">Char&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">g b &lt;span class="ow">=&lt;/span> &lt;span class="kr">if&lt;/span> b &lt;span class="kr">then&lt;/span> &lt;span class="mf">1.0&lt;/span> &lt;span class="kr">else&lt;/span> &lt;span class="sc">&amp;#39;x&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Notice how the same &lt;code>if&lt;/code> construct is used at the type and the value level: types are first class, and there isn&amp;rsquo;t really any difference between types and values anymore.&lt;/p>
&lt;p>Of course we could have easily written such a function in any dynamically typed language. The novel thing here is that the Idris typechecker is perfectly on board with the above definition, and will ensure that any usage of &lt;code>g&lt;/code> is correct: the type of &lt;code>g True&lt;/code> is &lt;code>Double&lt;/code>, and the type of &lt;code>g False&lt;/code> is &lt;code>Char&lt;/code>.&lt;/p>
&lt;p>One final piece of syntax I want to introduce before we move on is pattern matching definitions. We also could have written &lt;code>g&lt;/code> like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">g&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="ow">(&lt;/span>b &lt;span class="ow">:&lt;/span> &lt;span class="kt">Bool&lt;/span>&lt;span class="ow">)&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kr">if&lt;/span> b &lt;span class="kr">then&lt;/span> &lt;span class="kt">Double&lt;/span> &lt;span class="kr">else&lt;/span> &lt;span class="kt">Char&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">g &lt;span class="kt">True&lt;/span> &lt;span class="ow">=&lt;/span> &lt;span class="mf">1.0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">g &lt;span class="kt">False&lt;/span> &lt;span class="ow">=&lt;/span> &lt;span class="sc">&amp;#39;x&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>We can pattern match on any inductive type in such a manner. So&amp;hellip; what are inductive types exactly?&lt;/p>
&lt;h1 id="inductive-types">Inductive types&lt;/h1>
&lt;p>The only method we have seen so far for constructing types was &lt;code>-&amp;gt;&lt;/code>, the function type constructor. Idris also supports inductive type definitions, a very powerful mechanism for creating our own types.&lt;/p>
&lt;h2 id="algebraic-data-types">Algebraic data types&lt;/h2>
&lt;p>Let&amp;rsquo;s start with a subset of inductive types commonly referred to as algebraic data types. It turns out that &lt;code>Bool&lt;/code> is not built into Idris, but defined as an algebraic data type:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">data&lt;/span> &lt;span class="kt">Bool&lt;/span> &lt;span class="ow">=&lt;/span> &lt;span class="kt">False&lt;/span> &lt;span class="ow">|&lt;/span> &lt;span class="kt">True&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The names don&amp;rsquo;t matter, we could also define our own special isomorphic variant of &lt;code>Bool&lt;/code> if we wanted to:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">data&lt;/span> &lt;span class="kt">Light&lt;/span> &lt;span class="ow">=&lt;/span> &lt;span class="kt">Off&lt;/span> &lt;span class="ow">|&lt;/span> &lt;span class="kt">On&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Next, let&amp;rsquo;s extend this type a bit:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">data&lt;/span> &lt;span class="kt">Color&lt;/span> &lt;span class="ow">=&lt;/span> &lt;span class="kt">Red&lt;/span> &lt;span class="ow">|&lt;/span> &lt;span class="kt">Green&lt;/span> &lt;span class="ow">|&lt;/span> &lt;span class="kt">Blue&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">data&lt;/span> &lt;span class="kt">Light&lt;/span> &lt;span class="ow">=&lt;/span> &lt;span class="kt">Off&lt;/span> &lt;span class="ow">|&lt;/span> &lt;span class="kt">On&lt;/span> &lt;span class="kt">Color&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>Color&lt;/code> is straightforward, it has 3 possible values instead of 2. This new &lt;code>Light&lt;/code> type is also similar to the previous one, but we are attaching some extra data to the &lt;code>On&lt;/code> state, namely its color. There are 4 possible values of this type: &lt;code>Off&lt;/code>, &lt;code>On Red&lt;/code>, &lt;code>On Green&lt;/code>, and &lt;code>On Blue&lt;/code>. &lt;code>On&lt;/code> is called a &lt;em>data constructor&lt;/em>, and it takes a single argument of type &lt;code>Color&lt;/code> to &lt;em>construct&lt;/em> a value of the type &lt;code>Light&lt;/code>. (&lt;code>Off&lt;/code> is also called a constructor, it just takes no arguments.)&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">data&lt;/span> &lt;span class="kt">Intensity&lt;/span> &lt;span class="ow">=&lt;/span> &lt;span class="kt">Low&lt;/span> &lt;span class="ow">|&lt;/span> &lt;span class="kt">High&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">data&lt;/span> &lt;span class="kt">Light&lt;/span> &lt;span class="ow">=&lt;/span> &lt;span class="kt">On&lt;/span> &lt;span class="kt">Color&lt;/span> &lt;span class="kt">Intensity&lt;/span> &lt;span class="ow">|&lt;/span> &lt;span class="kt">Off&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Here I added another parameter to the &lt;code>On&lt;/code> constructor. This &lt;code>Light&lt;/code> type has 7 possible values, and this is how we can calculate that:&lt;/p>
&lt;p>&lt;span class="katex-display">&lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML" display="block">&lt;semantics>&lt;mrow>&lt;munder>&lt;munder>&lt;mrow>&lt;mover>&lt;mover>&lt;mn>3&lt;/mn>&lt;mo stretchy="true">⏞&lt;/mo>&lt;/mover>&lt;mrow>&lt;mi mathvariant="monospace">C&lt;/mi>&lt;mi mathvariant="monospace">o&lt;/mi>&lt;mi mathvariant="monospace">l&lt;/mi>&lt;mi mathvariant="monospace">o&lt;/mi>&lt;mi mathvariant="monospace">r&lt;/mi>&lt;/mrow>&lt;/mover>&lt;mo>×&lt;/mo>&lt;mover>&lt;mover>&lt;mn>2&lt;/mn>&lt;mo stretchy="true">⏞&lt;/mo>&lt;/mover>&lt;mrow>&lt;mi mathvariant="monospace">I&lt;/mi>&lt;mi mathvariant="monospace">n&lt;/mi>&lt;mi mathvariant="monospace">t&lt;/mi>&lt;mi mathvariant="monospace">e&lt;/mi>&lt;mi mathvariant="monospace">n&lt;/mi>&lt;mi mathvariant="monospace">s&lt;/mi>&lt;mi mathvariant="monospace">i&lt;/mi>&lt;mi mathvariant="monospace">t&lt;/mi>&lt;mi mathvariant="monospace">y&lt;/mi>&lt;/mrow>&lt;/mover>&lt;/mrow>&lt;mo stretchy="true">⏟&lt;/mo>&lt;/munder>&lt;mrow>&lt;mi mathvariant="monospace">O&lt;/mi>&lt;mi mathvariant="monospace">n&lt;/mi>&lt;/mrow>&lt;/munder>&lt;mo>+&lt;/mo>&lt;munder>&lt;munder>&lt;mn>1&lt;/mn>&lt;mo stretchy="true">⏟&lt;/mo>&lt;/munder>&lt;mrow>&lt;mi mathvariant="monospace">O&lt;/mi>&lt;mi mathvariant="monospace">f&lt;/mi>&lt;mi mathvariant="monospace">f&lt;/mi>&lt;/mrow>&lt;/munder>&lt;mo>=&lt;/mo>&lt;mn>7&lt;/mn>&lt;/mrow>&lt;annotation encoding="application/x-tex">
\underbrace{\overbrace{3}^{\mathtt{Color}} \times \overbrace{2}^{\mathtt{Intensity}}}_{\mathtt{On}} + \underbrace{1}_{\mathtt{Off}} = 7
&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:3.4349em;vertical-align:-1.3591em;">&lt;/span>&lt;span class="mord munder">&lt;span class="vlist-t vlist-t2">&lt;span class="vlist-r">&lt;span class="vlist" style="height:2.0758em;">&lt;span style="top:-2.7167em;">&lt;span class="pstrut" style="height:4.0758em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">&lt;span class="mord mtight">&lt;span class="mord mathtt mtight">On&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span style="top:-4.0758em;">&lt;span class="pstrut" style="height:4.0758em;">&lt;/span>&lt;span class="mord munder">&lt;span class="vlist-t vlist-t2">&lt;span class="vlist-r">&lt;span class="vlist" style="height:2.0758em;">&lt;span class="svg-align" style="top:-3.3444em;">&lt;span class="pstrut" style="height:4.0758em;">&lt;/span>&lt;span class="stretchy" style="height:0.548em;min-width:1.6em;">&lt;span class="brace-left" style="height:0.548em;">&lt;svg xmlns="http://www.w3.org/2000/svg" width='400em' height='0.548em' viewBox='0 0 400000 548' preserveAspectRatio='xMinYMin slice'>&lt;path d='M0 6l6-6h17c12.688 0 19.313.3 20 1 4 4 7.313 8.3 10 13
35.313 51.3 80.813 93.8 136.5 127.5 55.688 33.7 117.188 55.8 184.5 66.5.688
0 2 .3 4 1 18.688 2.7 76 4.3 172 5h399450v120H429l-6-1c-124.688-8-235-61.7
-331-161C60.687 138.7 32.312 99.3 7 54L0 41V6z'/>&lt;/svg>&lt;/span>&lt;span class="brace-center" style="height:0.548em;">&lt;svg xmlns="http://www.w3.org/2000/svg" width='400em' height='0.548em' viewBox='0 0 400000 548' preserveAspectRatio='xMidYMin slice'>&lt;path d='M199572 214
c100.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14
53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3
11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0
-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z'/>&lt;/svg>&lt;/span>&lt;span class="brace-right" style="height:0.548em;">&lt;svg xmlns="http://www.w3.org/2000/svg" width='400em' height='0.548em' viewBox='0 0 400000 548' preserveAspectRatio='xMaxYMin slice'>&lt;path d='M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3
28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237
-174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z'/>&lt;/svg>&lt;/span>&lt;/span>&lt;/span>&lt;span style="top:-4.0758em;">&lt;span class="pstrut" style="height:4.0758em;">&lt;/span>&lt;span class="mord">&lt;span class="mord mover">&lt;span class="vlist-t">&lt;span class="vlist-r">&lt;span class="vlist" style="height:1.9202em;">&lt;span style="top:-3.2924em;">&lt;span class="pstrut" style="height:3.2924em;">&lt;/span>&lt;span class="mord mover">&lt;span class="vlist-t">&lt;span class="vlist-r">&lt;span class="vlist" style="height:1.2924em;">&lt;span style="top:-3em;">&lt;span class="pstrut" style="height:3em;">&lt;/span>&lt;span class="mord">&lt;span class="mord">3&lt;/span>&lt;/span>&lt;/span>&lt;span class="svg-align" style="top:-3.7444em;">&lt;span class="pstrut" style="height:3em;">&lt;/span>&lt;span class="stretchy" style="height:0.548em;min-width:1.6em;">&lt;span class="brace-left" style="height:0.548em;">&lt;svg xmlns="http://www.w3.org/2000/svg" width='400em' height='0.548em' viewBox='0 0 400000 548' preserveAspectRatio='xMinYMin slice'>&lt;path d='M6 548l-6-6v-35l6-11c56-104 135.3-181.3 238-232 57.3-28.7 117
-45 179-50h399577v120H403c-43.3 7-81 15-113 26-100.7 33-179.7 91-237 174-2.7
5-6 9-10 13-.7 1-7.3 1-20 1H6z'/>&lt;/svg>&lt;/span>&lt;span class="brace-center" style="height:0.548em;">&lt;svg xmlns="http://www.w3.org/2000/svg" width='400em' height='0.548em' viewBox='0 0 400000 548' preserveAspectRatio='xMidYMin slice'>&lt;path d='M200428 334
c-100.7-8.3-195.3-44-280-108-55.3-42-101.7-93-139-153l-9-14c-2.7 4-5.7 8.7-9 14
-53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7
311.7-78.3 403-201 6-8 9.7-12 11-12 .7-.7 6.7-1 18-1s17.3.3 18 1c1.3 0 5 4 11
12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z'/>&lt;/svg>&lt;/span>&lt;span class="brace-right" style="height:0.548em;">&lt;svg xmlns="http://www.w3.org/2000/svg" width='400em' height='0.548em' viewBox='0 0 400000 548' preserveAspectRatio='xMaxYMin slice'>&lt;path d='M400000 542l
-6 6h-17c-12.7 0-19.3-.3-20-1-4-4-7.3-8.3-10-13-35.3-51.3-80.8-93.8-136.5-127.5
s-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1
c124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z'/>&lt;/svg>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span style="top:-4.7849em;">&lt;span class="pstrut" style="height:3.2924em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">&lt;span class="mord mtight">&lt;span class="mord mathtt mtight">Color&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">×&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mord mover">&lt;span class="vlist-t">&lt;span class="vlist-r">&lt;span class="vlist" style="height:2.0758em;">&lt;span style="top:-3.2924em;">&lt;span class="pstrut" style="height:3.2924em;">&lt;/span>&lt;span class="mord mover">&lt;span class="vlist-t">&lt;span class="vlist-r">&lt;span class="vlist" style="height:1.2924em;">&lt;span style="top:-3em;">&lt;span class="pstrut" style="height:3em;">&lt;/span>&lt;span class="mord">&lt;span class="mord">2&lt;/span>&lt;/span>&lt;/span>&lt;span class="svg-align" style="top:-3.7444em;">&lt;span class="pstrut" style="height:3em;">&lt;/span>&lt;span class="stretchy" style="height:0.548em;min-width:1.6em;">&lt;span class="brace-left" style="height:0.548em;">&lt;svg xmlns="http://www.w3.org/2000/svg" width='400em' height='0.548em' viewBox='0 0 400000 548' preserveAspectRatio='xMinYMin slice'>&lt;path d='M6 548l-6-6v-35l6-11c56-104 135.3-181.3 238-232 57.3-28.7 117
-45 179-50h399577v120H403c-43.3 7-81 15-113 26-100.7 33-179.7 91-237 174-2.7
5-6 9-10 13-.7 1-7.3 1-20 1H6z'/>&lt;/svg>&lt;/span>&lt;span class="brace-center" style="height:0.548em;">&lt;svg xmlns="http://www.w3.org/2000/svg" width='400em' height='0.548em' viewBox='0 0 400000 548' preserveAspectRatio='xMidYMin slice'>&lt;path d='M200428 334
c-100.7-8.3-195.3-44-280-108-55.3-42-101.7-93-139-153l-9-14c-2.7 4-5.7 8.7-9 14
-53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7
311.7-78.3 403-201 6-8 9.7-12 11-12 .7-.7 6.7-1 18-1s17.3.3 18 1c1.3 0 5 4 11
12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z'/>&lt;/svg>&lt;/span>&lt;span class="brace-right" style="height:0.548em;">&lt;svg xmlns="http://www.w3.org/2000/svg" width='400em' height='0.548em' viewBox='0 0 400000 548' preserveAspectRatio='xMaxYMin slice'>&lt;path d='M400000 542l
-6 6h-17c-12.7 0-19.3-.3-20-1-4-4-7.3-8.3-10-13-35.3-51.3-80.8-93.8-136.5-127.5
s-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1
c124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z'/>&lt;/svg>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span style="top:-4.9404em;">&lt;span class="pstrut" style="height:3.2924em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">&lt;span class="mord mtight">&lt;span class="mord mathtt mtight">Intensity&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="vlist-s">​&lt;/span>&lt;/span>&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.7313em;">&lt;span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="vlist-s">​&lt;/span>&lt;/span>&lt;span class="vlist-r">&lt;span class="vlist" style="height:1.3591em;">&lt;span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">+&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1.9202em;vertical-align:-1.2758em;">&lt;/span>&lt;span class="mord munder">&lt;span class="vlist-t vlist-t2">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.6444em;">&lt;span style="top:-1.7242em;">&lt;span class="pstrut" style="height:3em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">&lt;span class="mord mtight">&lt;span class="mord mathtt mtight">Off&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span style="top:-3em;">&lt;span class="pstrut" style="height:3em;">&lt;/span>&lt;span class="mord munder">&lt;span class="vlist-t vlist-t2">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.6444em;">&lt;span class="svg-align" style="top:-2.352em;">&lt;span class="pstrut" style="height:3em;">&lt;/span>&lt;span class="stretchy" style="height:0.548em;min-width:1.6em;">&lt;span class="brace-left" style="height:0.548em;">&lt;svg xmlns="http://www.w3.org/2000/svg" width='400em' height='0.548em' viewBox='0 0 400000 548' preserveAspectRatio='xMinYMin slice'>&lt;path d='M0 6l6-6h17c12.688 0 19.313.3 20 1 4 4 7.313 8.3 10 13
35.313 51.3 80.813 93.8 136.5 127.5 55.688 33.7 117.188 55.8 184.5 66.5.688
0 2 .3 4 1 18.688 2.7 76 4.3 172 5h399450v120H429l-6-1c-124.688-8-235-61.7
-331-161C60.687 138.7 32.312 99.3 7 54L0 41V6z'/>&lt;/svg>&lt;/span>&lt;span class="brace-center" style="height:0.548em;">&lt;svg xmlns="http://www.w3.org/2000/svg" width='400em' height='0.548em' viewBox='0 0 400000 548' preserveAspectRatio='xMidYMin slice'>&lt;path d='M199572 214
c100.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14
53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3
11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0
-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z'/>&lt;/svg>&lt;/span>&lt;span class="brace-right" style="height:0.548em;">&lt;svg xmlns="http://www.w3.org/2000/svg" width='400em' height='0.548em' viewBox='0 0 400000 548' preserveAspectRatio='xMaxYMin slice'>&lt;path d='M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3
28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237
-174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z'/>&lt;/svg>&lt;/span>&lt;/span>&lt;/span>&lt;span style="top:-3em;">&lt;span class="pstrut" style="height:3em;">&lt;/span>&lt;span class="mord">&lt;span class="mord">1&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="vlist-s">​&lt;/span>&lt;/span>&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.648em;">&lt;span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="vlist-s">​&lt;/span>&lt;/span>&lt;span class="vlist-r">&lt;span class="vlist" style="height:1.2758em;">&lt;span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">=&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6444em;">&lt;/span>&lt;span class="mord">7&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/p>
&lt;p>At this point the reason for calling these algebraic data types should become apparent. The number of values is the sum of the number of values for each constructor, and the number of values for each constructor is the product of the number of values of each of its parameter. (You will often see types with these properties called &lt;em>sum&lt;/em> types and &lt;em>product&lt;/em> types respectively.)&lt;/p>
&lt;h2 id="parameterized-and-recursive-types">Parameterized and recursive types&lt;/h2>
&lt;p>Parameterized types are supported as well:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">data&lt;/span> &lt;span class="kt">Prod&lt;/span> a b &lt;span class="ow">=&lt;/span> &lt;span class="kt">Pair&lt;/span> a b
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">data&lt;/span> &lt;span class="kt">Sum&lt;/span> a b &lt;span class="ow">=&lt;/span> &lt;span class="kt">Left&lt;/span> a &lt;span class="ow">|&lt;/span> &lt;span class="kt">Right&lt;/span> b
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Here we can see the concept of algebraic data types distilled into the notion of sums and products. &lt;code>Prod&lt;/code> is not the type of pairs by itself, it is a &lt;em>type constructor&lt;/em> taking two parameters: &lt;code>Prod Bool Bool&lt;/code> is the type of &lt;code>Pair True False&lt;/code>, and &lt;code>Prod Int Char&lt;/code> is the type of &lt;code>Pair 1 'x'&lt;/code>.&lt;/p>
&lt;p>Note that I am glossing over a technical detail here, which is that we also have to supply the type arguments to the data constructors, but Idris automatically makes these parameters implicit. &lt;!--The last example could also be written as `Pair {a=Int, b=Char} 1 'x'` by providing these arguments explicitly.-->&lt;/p>
&lt;p>For the next example, you need to be familiar with how the Peano axioms define natural numbers:&lt;/p>
&lt;ol>
&lt;li>&lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mn>0&lt;/mn>&lt;/mrow>&lt;annotation encoding="application/x-tex">0&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6444em;">&lt;/span>&lt;span class="mord">0&lt;/span>&lt;/span>&lt;/span>&lt;/span> is a natural number.&lt;/li>
&lt;li>For any natural number &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>n&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">n&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;/span>&lt;/span>&lt;/span>, &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>S&lt;/mi>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>n&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">S(n)&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.05764em;">S&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;span class="mclose">)&lt;/span>&lt;/span>&lt;/span>&lt;/span> is also a natural number.&lt;/li>
&lt;/ol>
&lt;p>&lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>S&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">S&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6833em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.05764em;">S&lt;/span>&lt;/span>&lt;/span>&lt;/span> is called the &lt;em>successor&lt;/em> function. &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>S&lt;/mi>&lt;mo stretchy="false">(&lt;/mo>&lt;mn>0&lt;/mn>&lt;mo stretchy="false">)&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">S(0)&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.05764em;">S&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord">0&lt;/span>&lt;span class="mclose">)&lt;/span>&lt;/span>&lt;/span>&lt;/span> is 1, &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>S&lt;/mi>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>S&lt;/mi>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>S&lt;/mi>&lt;mo stretchy="false">(&lt;/mo>&lt;mn>0&lt;/mn>&lt;mo stretchy="false">)&lt;/mo>&lt;mo stretchy="false">)&lt;/mo>&lt;mo stretchy="false">)&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">S(S(S(0)))&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.05764em;">S&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.05764em;">S&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.05764em;">S&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord">0&lt;/span>&lt;span class="mclose">)))&lt;/span>&lt;/span>&lt;/span>&lt;/span> is 3, and so on.&lt;/p>
&lt;p>We can encode natural numbers with a &lt;em>recursively&lt;/em> defined type:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">data&lt;/span> &lt;span class="kt">Nat&lt;/span> &lt;span class="ow">=&lt;/span> &lt;span class="kt">Z&lt;/span> &lt;span class="ow">|&lt;/span> &lt;span class="kt">S&lt;/span> &lt;span class="kt">Nat&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Zero is represented as &lt;code>Z&lt;/code>, one as &lt;code>S Z&lt;/code>, three as &lt;code>S S S Z&lt;/code>, just like in the Peano axioms. Idris in fact provides syntactic sugar for the built in &lt;code>Nat&lt;/code> type, so that instead of &lt;code>S S S Z&lt;/code> we can simply write &lt;code>3&lt;/code>.&lt;/p>
&lt;p>At this point it&amp;rsquo;s important to note that &lt;code>Nat&lt;/code> should not be confused with &lt;code>Int&lt;/code>, even though the numeric notation can be used for both. &lt;code>Nat&lt;/code> is the type of natural numbers &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi mathvariant="double-struck">N&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">\mathbb{N}&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6889em;">&lt;/span>&lt;span class="mord mathbb">N&lt;/span>&lt;/span>&lt;/span>&lt;/span>, its cardinality is &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;msub>&lt;mi mathvariant="normal">ℵ&lt;/mi>&lt;mn>0&lt;/mn>&lt;/msub>&lt;/mrow>&lt;annotation encoding="application/x-tex">\aleph_0&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.8444em;vertical-align:-0.15em;">&lt;/span>&lt;span class="mord">&lt;span class="mord">ℵ&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t vlist-t2">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.3011em;">&lt;span style="top:-2.55em;margin-left:0em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">0&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="vlist-s">​&lt;/span>&lt;/span>&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.15em;">&lt;span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>. &lt;code>Int&lt;/code> is the type of machine integers, usually &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo stretchy="false">[&lt;/mo>&lt;mo>−&lt;/mo>&lt;msup>&lt;mn>2&lt;/mn>&lt;mn>63&lt;/mn>&lt;/msup>&lt;mo separator="true">,&lt;/mo>&lt;msup>&lt;mn>2&lt;/mn>&lt;mn>63&lt;/mn>&lt;/msup>&lt;mo>−&lt;/mo>&lt;mn>1&lt;/mn>&lt;mo stretchy="false">]&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">[-2^{63}, 2^{63} - 1]&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1.0641em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mopen">[&lt;/span>&lt;span class="mord">−&lt;/span>&lt;span class="mord">&lt;span class="mord">2&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.8141em;">&lt;span style="top:-3.063em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">&lt;span class="mord mtight">63&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord">&lt;span class="mord">2&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.8141em;">&lt;span style="top:-3.063em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">&lt;span class="mord mtight">63&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">−&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord">1&lt;/span>&lt;span class="mclose">]&lt;/span>&lt;/span>&lt;/span>&lt;/span>, with cardinality &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;msup>&lt;mn>2&lt;/mn>&lt;mn>64&lt;/mn>&lt;/msup>&lt;/mrow>&lt;annotation encoding="application/x-tex">2^{64}&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.8141em;">&lt;/span>&lt;span class="mord">&lt;span class="mord">2&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.8141em;">&lt;span style="top:-3.063em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">&lt;span class="mord mtight">64&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>.&lt;/p>
&lt;p>Also I would suggest not really thinking about cardinalities for anything beyond simple algebraic types. Infinities in set theory are quite complicated, for instance the cardinality of &lt;code>Nat -&amp;gt; Nat&lt;/code> should be &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;msubsup>&lt;mi mathvariant="normal">ℵ&lt;/mi>&lt;mn>0&lt;/mn>&lt;msub>&lt;mi mathvariant="normal">ℵ&lt;/mi>&lt;mn>0&lt;/mn>&lt;/msub>&lt;/msubsup>&lt;/mrow>&lt;annotation encoding="application/x-tex">\aleph_0^{\aleph_0}&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1.1973em;vertical-align:-0.2663em;">&lt;/span>&lt;span class="mord">&lt;span class="mord">ℵ&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t vlist-t2">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.931em;">&lt;span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">0&lt;/span>&lt;/span>&lt;/span>&lt;span style="top:-3.1449em;margin-right:0.05em;">&lt;span class="pstrut" style="height:2.7em;">&lt;/span>&lt;span class="sizing reset-size6 size3 mtight">&lt;span class="mord mtight">&lt;span class="mord mtight">&lt;span class="mord mtight">ℵ&lt;/span>&lt;span class="msupsub">&lt;span class="vlist-t vlist-t2">&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.3173em;">&lt;span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;">&lt;span class="pstrut" style="height:2.5em;">&lt;/span>&lt;span class="sizing reset-size3 size1 mtight">&lt;span class="mord mtight">0&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="vlist-s">​&lt;/span>&lt;/span>&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.143em;">&lt;span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;span class="vlist-s">​&lt;/span>&lt;/span>&lt;span class="vlist-r">&lt;span class="vlist" style="height:0.2663em;">&lt;span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>. You can run into issues if you define types as sets in regular set theory, so just remember that types are not sets, they are defined by a completely separate system of axioms.&lt;/p>
&lt;p>With that said, let&amp;rsquo;s get back to exploring inductive types. In this next example, we combine type parameters and recursion to define lists:&lt;sup id="fnref:3">&lt;a href="#fn:3" role="doc-noteref">3&lt;/a>&lt;span class="footnote-tooltip">I have no idea why the list constructors are named &lt;code>Nil&lt;/code> and &lt;code>Cons&lt;/code>, but everyone names them like this. Just roll with it.&lt;/span>&lt;/sup>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">data&lt;/span> &lt;span class="kt">List&lt;/span> a &lt;span class="ow">=&lt;/span> &lt;span class="kt">Nil&lt;/span> &lt;span class="ow">|&lt;/span> &lt;span class="kt">Cons&lt;/span> a &lt;span class="ow">(&lt;/span>&lt;span class="kt">List&lt;/span> a&lt;span class="ow">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>List Int&lt;/code> is the type of the lists of integers. &lt;code>Nil&lt;/code> is the empty list, &lt;code>Cons 1 Nil&lt;/code> is a list with one element, &lt;code>Cons 1 (Cons 2 (Cons 3 Nil))&lt;/code> is a three element list containing 1, 2, and 3. (And again syntactic sugar comes to the rescue, the list notation &lt;code>[1, 2, 3]&lt;/code> expands to constructors of the built in &lt;code>List&lt;/code> type.)&lt;/p>
&lt;h2 id="type-indices">Type indices&lt;/h2>
&lt;p>The syntax we have been using so far to define types is actually just the abbreviated syntax. The more verbose way to define &lt;code>List&lt;/code> would be the following:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">data&lt;/span> &lt;span class="kt">List&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="kt">Type&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kt">Type&lt;/span> &lt;span class="kr">where&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">Nil&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="kt">List&lt;/span> a
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">Cons&lt;/span> &lt;span class="ow">:&lt;/span> a &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kt">List&lt;/span> a &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kt">List&lt;/span> a
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Here you can see the type of the type and data constructors fully written out. (Note that there is nothing special about the type parameter &lt;code>a&lt;/code> here, it gets automatically inserted as an implicit parameter just like it would be when defining a function.)&lt;/p>
&lt;p>When we write &lt;code>List Int&lt;/code> it really is just a function application. When we write &lt;code>Nil&lt;/code> the type parameter &lt;code>a&lt;/code> is automatically inferred from the context. (Note that type and data constructors are &lt;em>not&lt;/em> functions, but their types are the same, and they can be used in the exact same ways. The special thing about data constructors is that they can be deconstructed in pattern matching definitions.)&lt;/p>
&lt;p>A question that arises is whether we have to parameterize the type constructor the same way in each data constructor? Inductive types in fact do allow for such heterogeneity. In this case these are usually called type indices instead of parameters, and the whole definition an &lt;em>indexed type family&lt;/em>.&lt;sup id="fnref:4">&lt;a href="#fn:4" role="doc-noteref">4&lt;/a>&lt;span class="footnote-tooltip">I don&amp;rsquo;t think Idris actually distinguishes type parameters and indices, but some languages like Coq do.&lt;/span>&lt;/sup>&lt;/p>
&lt;p>With all that said, let&amp;rsquo;s consider the ubiquitous example when introducing type indices, the length indexed list. It is called &lt;code>Vect&lt;/code> to differentiate it from the regular &lt;code>List&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">data&lt;/span> &lt;span class="kt">Vect&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="kt">Nat&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kt">Type&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kt">Type&lt;/span> &lt;span class="kr">where&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">Nil&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="kt">Vect&lt;/span> &lt;span class="mi">0&lt;/span> a
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">Cons&lt;/span> &lt;span class="ow">:&lt;/span> a &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kt">Vect&lt;/span> n a &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kt">Vect&lt;/span> &lt;span class="ow">(&lt;/span>n &lt;span class="ow">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="ow">)&lt;/span> a
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Let&amp;rsquo;s unpack this definition. The &lt;code>Vect&lt;/code> type constructor has two parameters: a &lt;code>Nat&lt;/code> that represents its length, and the type of the contained elements. So for instance &lt;code>Vect 3 Int&lt;/code> is the type of 3 element &lt;code>Int&lt;/code> vectors.&lt;/p>
&lt;p>Let&amp;rsquo;s look at the constructors. &lt;code>Nil&lt;/code> is quite straightforward: it says that the empty vector has length &lt;code>0&lt;/code>.&lt;/p>
&lt;p>The magic mostly happens in the &lt;code>Cons&lt;/code> constructor: it says that for any &lt;code>Vect n a&lt;/code>, when you add one element, it will have length &lt;code>Vect (n + 1) a&lt;/code>. (Note that both &lt;code>a&lt;/code> and &lt;code>n&lt;/code> are still just implicit parameters of &lt;code>Cons&lt;/code>, even if the syntax makes it seem like they come out of thin air.)&lt;/p>
&lt;p>So, how can such a type be used? We will look at an example in the next section.&lt;/p>
&lt;h1 id="programming-with-dependent-types">Programming with dependent types&lt;/h1>
&lt;p>Indexed types allow for a level of expressiveness not seen outside dependently typed languages.&lt;/p>
&lt;p>Consider the &lt;code>head&lt;/code> function that returns the first item of a list:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">head&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="kt">List&lt;/span> a &lt;span class="ow">-&amp;gt;&lt;/span> a
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">head &lt;span class="ow">(&lt;/span>&lt;span class="kt">Cons&lt;/span> h &lt;span class="kr">_&lt;/span>&lt;span class="ow">)&lt;/span> &lt;span class="ow">=&lt;/span> h
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">head &lt;span class="kt">Nil&lt;/span> &lt;span class="ow">=&lt;/span> &lt;span class="ow">?&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The &lt;code>Cons&lt;/code> case is straightforward, but what should we do when the list is empty? In other languages, we would throw an exception, return a null value, or maybe an option type. Unfortunately none of these are very good solutions, and they make it harder to reason about our programs. What we would really want is a function that&amp;rsquo;s guaranteed to receive a non-empty list:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">head&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="kt">Vect&lt;/span> &lt;span class="ow">(&lt;/span>n &lt;span class="ow">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="ow">)&lt;/span> a &lt;span class="ow">-&amp;gt;&lt;/span> a
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">head &lt;span class="ow">(&lt;/span>&lt;span class="kt">Cons&lt;/span> x &lt;span class="kr">_&lt;/span>&lt;span class="ow">)&lt;/span> &lt;span class="ow">=&lt;/span> x
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">head &lt;span class="kt">Nil&lt;/span> &lt;span class="kr">impossible&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>In this example, we take a &lt;code>Vect&lt;/code> with length &lt;code>n + 1&lt;/code> as the argument. This guarantees, at the type level, that it is not empty: &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi mathvariant="normal">∀&lt;/mi>&lt;mi>n&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mtext> &lt;/mtext>&lt;mi>n&lt;/mi>&lt;mo>+&lt;/mo>&lt;mn>1&lt;/mn>&lt;mo>&amp;gt;&lt;/mo>&lt;mn>0&lt;/mn>&lt;/mrow>&lt;annotation encoding="application/x-tex">\forall n,\ n + 1 \gt 0&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.8889em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord">∀&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace"> &lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">+&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6835em;vertical-align:-0.0391em;">&lt;/span>&lt;span class="mord">1&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">&amp;gt;&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6444em;">&lt;/span>&lt;span class="mord">0&lt;/span>&lt;/span>&lt;/span>&lt;/span>. So, what do we write in the &lt;code>Nil&lt;/code> case? We now know that it&amp;rsquo;s impossible. Idris can in fact handle this for us: by using the &lt;code>impossible&lt;/code> keyword, Idris will go ahead and prove for itself that no &lt;code>n&lt;/code> exists for which &lt;code>n + 1 = 0&lt;/code>. (In more complicated cases we might have to provide our custom proof that a certain case is impossible.)&lt;/p>
&lt;p>Except&amp;hellip; there is a slight error. Idris won&amp;rsquo;t accept the above definition, and gives us a cryptic error message:&lt;/p>
&lt;pre tabindex="0">&lt;code>While processing left hand side of head. Can&amp;#39;t solve constraint between: ?n [no locals in scope] and ?_ [no locals in scope].
&lt;/code>&lt;/pre>&lt;p>Can you tell what&amp;rsquo;s the error based on this? Me neither. I think Idris is trying to be too smart for its own good here by attempting to unify some terms when pattern matching, and failing.&lt;/p>
&lt;p>The fix is relatively simple in this case. Change occurrences of &lt;code>n + 1&lt;/code> to the more &amp;ldquo;natural&amp;rdquo; &lt;code>S n&lt;/code>. While Idris tries to handle unification automatically, it can still fail even in simple cases like this. This is not Idris&amp;rsquo; fault: unification is undecidable in general, and no algorithm can exist that covers every case. In this case, Idris can&amp;rsquo;t figure out by itself that &lt;code>n + 1&lt;/code> and &lt;code>S n&lt;/code> are the same.&lt;/p>
&lt;p>The main issue with dependently typed programming I have experienced so far is that you often can&amp;rsquo;t just write the code you would without strong types. The above failure is a contrived example, but issues like this also occur in practice in cases where you can&amp;rsquo;t just solve the issue with such simple tweaks.&lt;/p>
&lt;p>Often you have to add explicit rewriting annotations, or even large hand written proofs to your code. This is not really surprising though: as you can express very complex properties with dependent types, a type checker that wouldn&amp;rsquo;t need annotations would essentially be a completely automatic theorem prover.&lt;/p>
&lt;p>Using dependent types sparingly to enforce some key properties of your program can work amazingly. (The Idris compiler itself, written in Idris, does exactly this, and is able to encode some important guarantees in the types.) What definitely won&amp;rsquo;t work is putting any property you can think of indiscriminately in the types, and expecting to be able to program normally.&lt;/p>
&lt;h1 id="the-curry--howard-correspondence">The Curry&amp;ndash;Howard correspondence&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">data&lt;/span> &lt;span class="kt">And&lt;/span> a b &lt;span class="ow">=&lt;/span> &lt;span class="kt">Conj&lt;/span> a b
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nf">modus_ponens&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="kt">And&lt;/span> p &lt;span class="ow">(&lt;/span>p &lt;span class="ow">-&amp;gt;&lt;/span> q&lt;span class="ow">)&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> q
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">modus_ponens &lt;span class="ow">(&lt;/span>&lt;span class="kt">Conj&lt;/span> prf impl&lt;span class="ow">)&lt;/span> &lt;span class="ow">=&lt;/span> impl prf
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Look at the type of the suggestively named &lt;code>modus_ponens&lt;/code>. It is supposed to mean &lt;span class="katex-display">&lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML" display="block">&lt;semantics>&lt;mrow>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>p&lt;/mi>&lt;mtext> &lt;/mtext>&lt;mo>∧&lt;/mo>&lt;mtext> &lt;/mtext>&lt;mo stretchy="false">(&lt;/mo>&lt;mi>p&lt;/mi>&lt;mo>→&lt;/mo>&lt;mi>q&lt;/mi>&lt;mo stretchy="false">)&lt;/mo>&lt;mo stretchy="false">)&lt;/mo>&lt;mo>→&lt;/mo>&lt;mi>q&lt;/mi>&lt;mtext>,&lt;/mtext>&lt;/mrow>&lt;annotation encoding="application/x-tex">(p\ \wedge\ (p \rightarrow q)) \rightarrow q\text{,}&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">p&lt;/span>&lt;span class="mspace"> &lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">∧&lt;/span>&lt;span class="mspace"> &lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mopen">(&lt;/span>&lt;span class="mord mathnormal">p&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">→&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:1em;vertical-align:-0.25em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.03588em;">q&lt;/span>&lt;span class="mclose">))&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">→&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.625em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.03588em;">q&lt;/span>&lt;span class="mord text">&lt;span class="mord">,&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span>&lt;/span> that is, the proposition that if &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>p&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">p&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.625em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal">p&lt;/span>&lt;/span>&lt;/span>&lt;/span> is true, and &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>p&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">p&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.625em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal">p&lt;/span>&lt;/span>&lt;/span>&lt;/span> implies &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>q&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">q&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.625em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.03588em;">q&lt;/span>&lt;/span>&lt;/span>&lt;/span>, then &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>q&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">q&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.625em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord mathnormal" style="margin-right:0.03588em;">q&lt;/span>&lt;/span>&lt;/span>&lt;/span> is true.&lt;/p>
&lt;p>So&amp;hellip; what am I talking about here? &lt;code>And&lt;/code> is an inductive type, &lt;code>modus_ponens&lt;/code> is just a function, &lt;code>p&lt;/code> and &lt;code>q&lt;/code> are types. What does this all have to do with logic?&lt;/p>
&lt;p>As it turns out, quite a lot actually. In fact, the famous Curry&amp;ndash;Howard isomorphism states a strong equivalence between programs and mathematical proofs. In this view, types are propositions, and programs are proofs.&lt;sup id="fnref:5">&lt;a href="#fn:5" role="doc-noteref">5&lt;/a>&lt;span class="footnote-tooltip">Note however that we won&amp;rsquo;t get a classical logic here, but rather a kind of constructive logic, but we can ignore this technical detail for now.&lt;/span>&lt;/sup>&lt;/p>
&lt;p>An important thing to note here is that this logical correspondence only applies to &lt;em>terminating&lt;/em> programs. If you had an infinitely recursive function, the whole system would break down, and you would be able to prove any propositions.&lt;sup id="fnref:6">&lt;a href="#fn:6" role="doc-noteref">6&lt;/a>&lt;span class="footnote-tooltip">Idris does not verify this by default, you have to provide the &lt;code>%default total&lt;/code> directive to tell it to only accept functions for which it can prove termination. This built in checking works well for most cases.&lt;/span>&lt;/sup>&lt;/p>
&lt;p>So, let&amp;rsquo;s go through the computational features we have learned about so far, and uncover their hidden logical meaning. (By the end, the meaning of the &lt;code>modus_ponens&lt;/code> proof above should also become clear.)&lt;/p>
&lt;p>First, as I already said, types correspond to propositions. &lt;code>p&lt;/code>, &lt;code>q&lt;/code>, &lt;code>p -&amp;gt; q&lt;/code>, and &lt;code>And p (p -&amp;gt; q) -&amp;gt; q&lt;/code> are all types, and can be interpreted as propositions as well. In turn, a value of a type corresponds to a proof of the proposition.&lt;/p>
&lt;p>As a very simple example, let&amp;rsquo;s prove the proposition &lt;code>And a b&lt;/code>. This is possible if we have a proof of &lt;code>a&lt;/code> and a proof of &lt;code>b&lt;/code>. Let&amp;rsquo;s create a function taking these proofs:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">prove_and&lt;/span> &lt;span class="ow">:&lt;/span> a &lt;span class="ow">-&amp;gt;&lt;/span> b &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kt">And&lt;/span> a b
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">prove_and prf_a prf_b &lt;span class="ow">=&lt;/span> &lt;span class="kt">Conj&lt;/span> prf_a prf_b
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Once we have both of them, the proof of &lt;code>And a b&lt;/code> can be simply constructed using the &lt;code>Conj&lt;/code> data constructor we defined previously.&lt;/p>
&lt;p>Actually, remember our &lt;code>Prod&lt;/code> and &lt;code>Sum&lt;/code> types from the previous section?&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">data&lt;/span> &lt;span class="kt">Prod&lt;/span> a b &lt;span class="ow">=&lt;/span> &lt;span class="kt">Pair&lt;/span> a b
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">data&lt;/span> &lt;span class="kt">Sum&lt;/span> a b &lt;span class="ow">=&lt;/span> &lt;span class="kt">Left&lt;/span> a &lt;span class="ow">|&lt;/span> &lt;span class="kt">Right&lt;/span> b
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Our definition of &lt;code>And&lt;/code> is exactly the same as &lt;code>Prod&lt;/code>! Looking at it this way, a proof of a conjunction is really just a pair of proofs.&lt;/p>
&lt;p>The logical meaning of &lt;code>Sum&lt;/code> should also be obvious: it corresponds to disjunction. A proof of either &lt;code>a&lt;/code> or &lt;code>b&lt;/code> is enough to prove &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>a&lt;/mi>&lt;mo>∨&lt;/mo>&lt;mi>b&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">a \vee b&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.5556em;">&lt;/span>&lt;span class="mord mathnormal">a&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">∨&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6944em;">&lt;/span>&lt;span class="mord mathnormal">b&lt;/span>&lt;/span>&lt;/span>&lt;/span>.&lt;/p>
&lt;p>Next, as you might have already noticed, function types correspond to implications. Our &lt;code>modus_ponens&lt;/code> proof above is actually superfluous, as modus ponens corresponds directly to function application: if you have &lt;code>prf_p : p&lt;/code> and &lt;code>prf_pq : p -&amp;gt; q&lt;/code>, then a proof of &lt;code>q&lt;/code> is simply &lt;code>prf_pq prf_p&lt;/code>.&lt;/p>
&lt;p>As it turns out, inductive types can be used to encode many complex mathematical relations. Let&amp;rsquo;s take a look at our definition of the less than or equal to relation (note that &lt;code>S&lt;/code> and &lt;code>Z&lt;/code> are the constructors of the &lt;code>Nat&lt;/code> type we &lt;a href="#parameterized-and-recursive-types">discussed previously&lt;/a>):&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">data&lt;/span> &lt;span class="ow">(&amp;lt;=)&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="kt">Nat&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kt">Nat&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kt">Type&lt;/span> &lt;span class="kr">where&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">LeN&lt;/span> &lt;span class="ow">:&lt;/span> n &lt;span class="ow">&amp;lt;=&lt;/span> n
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">LeS&lt;/span> &lt;span class="ow">:&lt;/span> n &lt;span class="ow">&amp;lt;=&lt;/span> m &lt;span class="ow">-&amp;gt;&lt;/span> n &lt;span class="ow">&amp;lt;=&lt;/span> &lt;span class="kt">S&lt;/span> m
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Notice how we are defining the &lt;code>&amp;lt;=&lt;/code> infix operator to be an inductive type. &lt;code>LeN&lt;/code> defines the base case saying that &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi mathvariant="normal">∀&lt;/mi>&lt;mi>n&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mtext> &lt;/mtext>&lt;mi>n&lt;/mi>&lt;mo>≤&lt;/mo>&lt;mi>n&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">\forall n,\ n \leq n&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.8889em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord">∀&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace"> &lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">≤&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;/span>&lt;/span>&lt;/span>. &lt;code>LeS&lt;/code> defines that given a proof of &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>n&lt;/mi>&lt;mo>≤&lt;/mo>&lt;mi>m&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">n \leq m&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.7719em;vertical-align:-0.136em;">&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">≤&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">m&lt;/span>&lt;/span>&lt;/span>&lt;/span>, &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>n&lt;/mi>&lt;mo>≤&lt;/mo>&lt;mi>m&lt;/mi>&lt;mo>+&lt;/mo>&lt;mn>1&lt;/mn>&lt;/mrow>&lt;annotation encoding="application/x-tex">n \leq m + 1&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.7719em;vertical-align:-0.136em;">&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">≤&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6667em;vertical-align:-0.0833em;">&lt;/span>&lt;span class="mord mathnormal">m&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">+&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6444em;">&lt;/span>&lt;span class="mord">1&lt;/span>&lt;/span>&lt;/span>&lt;/span> is also true. These two rules are sufficient to define the &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo>≤&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\leq&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.7719em;vertical-align:-0.136em;">&lt;/span>&lt;span class="mrel">≤&lt;/span>&lt;/span>&lt;/span>&lt;/span> relation.&lt;/p>
&lt;p>Let&amp;rsquo;s now state the proposition that &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi mathvariant="normal">∀&lt;/mi>&lt;mi>n&lt;/mi>&lt;mo separator="true">,&lt;/mo>&lt;mtext> &lt;/mtext>&lt;mn>0&lt;/mn>&lt;mo>≤&lt;/mo>&lt;mi>n&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">\forall n,\ 0 \leq n&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.8889em;vertical-align:-0.1944em;">&lt;/span>&lt;span class="mord">∀&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;span class="mpunct">,&lt;/span>&lt;span class="mspace"> &lt;/span>&lt;span class="mspace" style="margin-right:0.1667em;">&lt;/span>&lt;span class="mord">0&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">≤&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;/span>&lt;/span>&lt;/span>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">all_geq_z&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="ow">(&lt;/span>n &lt;span class="ow">:&lt;/span> &lt;span class="kt">Nat&lt;/span>&lt;span class="ow">)&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kt">Z&lt;/span> &lt;span class="ow">&amp;lt;=&lt;/span> n
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Notice that this is not a regular function type, but a &lt;em>dependent&lt;/em> function type. Dependent function types correspond exactly to universal quantification.&lt;/p>
&lt;p>Let&amp;rsquo;s now prove this proposition. The case where &lt;code>n&lt;/code> is zero is quite simple, &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mn>0&lt;/mn>&lt;mo>≤&lt;/mo>&lt;mn>0&lt;/mn>&lt;/mrow>&lt;annotation encoding="application/x-tex">0 \leq 0&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.7804em;vertical-align:-0.136em;">&lt;/span>&lt;span class="mord">0&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;span class="mrel">≤&lt;/span>&lt;span class="mspace" style="margin-right:0.2778em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6444em;">&lt;/span>&lt;span class="mord">0&lt;/span>&lt;/span>&lt;/span>&lt;/span> by definition.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">all_geq_z &lt;span class="kt">Z&lt;/span> &lt;span class="ow">=&lt;/span> &lt;span class="kt">LeN&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>In the case where &lt;code>n&lt;/code> is nonzero, we want to somehow construct a chain of &lt;code>LeS&lt;/code> applications until we get down to zero. We can do this quite easily with a recursive function call:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">all_geq_z &lt;span class="ow">(&lt;/span>&lt;span class="kt">S&lt;/span> n&lt;span class="ow">)&lt;/span> &lt;span class="ow">=&lt;/span> &lt;span class="kt">LeS&lt;/span> &lt;span class="ow">(&lt;/span>all_geq_z n&lt;span class="ow">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>What we just did is a &lt;em>proof by induction&lt;/em>. We first proved our proposition for zero, then for any &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>n&lt;/mi>&lt;mo>+&lt;/mo>&lt;mn>1&lt;/mn>&lt;/mrow>&lt;annotation encoding="application/x-tex">n + 1&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.6667em;vertical-align:-0.0833em;">&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;span class="mbin">+&lt;/span>&lt;span class="mspace" style="margin-right:0.2222em;">&lt;/span>&lt;/span>&lt;span class="base">&lt;span class="strut" style="height:0.6444em;">&lt;/span>&lt;span class="mord">1&lt;/span>&lt;/span>&lt;/span>&lt;/span> by using the proof for &lt;span class="katex">&lt;span class="katex-mathml">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>n&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">n&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>&lt;span class="katex-html" aria-hidden="true">&lt;span class="base">&lt;span class="strut" style="height:0.4306em;">&lt;/span>&lt;span class="mord mathnormal">n&lt;/span>&lt;/span>&lt;/span>&lt;/span>.&lt;/p>
&lt;p>As our final example, let&amp;rsquo;s define equality:&lt;sup id="fnref:7">&lt;a href="#fn:7" role="doc-noteref">7&lt;/a>&lt;span class="footnote-tooltip">In reality Idris doesn&amp;rsquo;t accept this definition because equality is already defined by the standard library, and &lt;code>=&lt;/code> is a reserved symbol.&lt;/span>&lt;/sup>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">data&lt;/span> &lt;span class="ow">(=)&lt;/span> &lt;span class="ow">:&lt;/span> a &lt;span class="ow">-&amp;gt;&lt;/span> a &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kt">Type&lt;/span> &lt;span class="kr">where&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">Refl&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="ow">(&lt;/span>x &lt;span class="ow">:&lt;/span> a&lt;span class="ow">)&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> x &lt;span class="ow">=&lt;/span> x
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The above definition might seem a bit strange at first though.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">eq3&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="mi">3&lt;/span> &lt;span class="ow">=&lt;/span> &lt;span class="mi">3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">eq3 &lt;span class="ow">=&lt;/span> &lt;span class="kt">Refl&lt;/span> &lt;span class="mi">3&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Our equality works well for reflexive cases, but how could we ever prove two things equal that are not literally the same?&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">eq_2_1_plus_1&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="ow">=&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="ow">+&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">eq_2_1_plus_1 &lt;span class="ow">=&lt;/span> &lt;span class="kt">Refl&lt;/span> &lt;span class="mi">2&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Turns out Idris is perfectly content with this proof. So what&amp;rsquo;s going on? Can Idris just magically prove things equal?&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">plus_z&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="ow">(&lt;/span>n &lt;span class="ow">:&lt;/span> &lt;span class="kt">Nat&lt;/span>&lt;span class="ow">)&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> n &lt;span class="ow">+&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="ow">=&lt;/span> n
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">plus_z n &lt;span class="ow">=&lt;/span> &lt;span class="kt">Refl&lt;/span> n
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This proof won&amp;rsquo;t be accepted:&lt;/p>
&lt;pre tabindex="0">&lt;code>Can&amp;#39;t solve constraint between: n and plus n 0.
&lt;/code>&lt;/pre>&lt;p>What the typechecker actually is doing is called &lt;em>reduction&lt;/em>. The &lt;code>+&lt;/code> operator is just defined as the &lt;code>plus&lt;/code> function. When faced with &lt;code>1 + 1&lt;/code>, Idris will apply the &lt;code>plus&lt;/code> function and arrive at the answer &lt;code>2&lt;/code>. On the other hand, it can&amp;rsquo;t reduce &lt;code>n + 0&lt;/code> since it doesn&amp;rsquo;t know anything about &lt;code>n&lt;/code> yet.&lt;/p>
&lt;p>Let me now show what it actually takes to prove &lt;code>plus_z&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-idris" data-lang="idris">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">replace&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="ow">(&lt;/span>p &lt;span class="ow">:&lt;/span> a &lt;span class="ow">-&amp;gt;&lt;/span> &lt;span class="kt">Type&lt;/span>&lt;span class="ow">)&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> x &lt;span class="ow">=&lt;/span> y &lt;span class="ow">-&amp;gt;&lt;/span> p x &lt;span class="ow">-&amp;gt;&lt;/span> p y
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">replace &lt;span class="kr">_&lt;/span> &lt;span class="ow">(&lt;/span>&lt;span class="kt">Refl&lt;/span> &lt;span class="kr">_&lt;/span>&lt;span class="ow">)&lt;/span> prf &lt;span class="ow">=&lt;/span> prf
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nf">plus_z&lt;/span> &lt;span class="ow">:&lt;/span> &lt;span class="ow">(&lt;/span>n &lt;span class="ow">:&lt;/span> &lt;span class="kt">Nat&lt;/span>&lt;span class="ow">)&lt;/span> &lt;span class="ow">-&amp;gt;&lt;/span> n &lt;span class="ow">+&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="ow">=&lt;/span> n
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">plus_z &lt;span class="mi">0&lt;/span> &lt;span class="ow">=&lt;/span> &lt;span class="kt">Refl&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">plus_z &lt;span class="ow">(&lt;/span>&lt;span class="kt">S&lt;/span> n&lt;span class="ow">)&lt;/span> &lt;span class="ow">=&lt;/span> replace &lt;span class="ow">(\&lt;/span>x &lt;span class="ow">=&amp;gt;&lt;/span> &lt;span class="kt">S&lt;/span> &lt;span class="ow">(&lt;/span>n &lt;span class="ow">+&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="ow">)&lt;/span> &lt;span class="ow">=&lt;/span> &lt;span class="kt">S&lt;/span> x&lt;span class="ow">)&lt;/span> &lt;span class="ow">(&lt;/span>plus_z n&lt;span class="ow">)&lt;/span> &lt;span class="ow">(&lt;/span>&lt;span class="kt">Refl&lt;/span> &lt;span class="ow">(&lt;/span>&lt;span class="kt">S&lt;/span> &lt;span class="ow">(&lt;/span>n &lt;span class="ow">+&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="ow">)))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>That&amp;rsquo;s quite a mouthful, so let&amp;rsquo;s go through it step by step.&lt;/p>
&lt;p>Let&amp;rsquo;s look at the definition of &lt;code>replace&lt;/code>. It might not look too complex, but it&amp;rsquo;s actually a very powerful tool: it can replace arbitrary terms with each other as long as you have an equality proof between them. Suddenly our definition of equality becomes an immensely powerful tool for manipulating propositions, and we no longer have to rely just on reduction to unify terms for us. (Something similar called &lt;code>rewrite&lt;/code> is actually built into Idris that can deduce &lt;code>p&lt;/code> automatically, but I am deliberately showing here how it could be defined by hand.)&lt;/p>
&lt;p>Using &lt;code>replace&lt;/code>, we can prove &lt;code>plus_z&lt;/code> by induction:&lt;/p>
&lt;ul>
&lt;li>The &lt;code>0&lt;/code> case is trivial.&lt;/li>
&lt;li>In the &lt;code>S n&lt;/code> case, we have to prove that &lt;code>S n + 0 = S n&lt;/code>
&lt;ul>
&lt;li>Idris&amp;rsquo; reduction can still partially help us here: it reduces the above term to &lt;code>S (n + 0) = S n&lt;/code>, by the definition of &lt;code>plus&lt;/code>.&lt;/li>
&lt;li>We can trivially obtain a proof of &lt;code>S (n + 0) = S (n + 0)&lt;/code>, this is what &lt;code>Refl (S (n + 0))&lt;/code> stands for.&lt;/li>
&lt;li>We have &lt;code>plus_z n&lt;/code> as a proof of &lt;code>n + 0 = n&lt;/code>. We can use this to rewrite the right hand side of the above equality, and obtain &lt;code>S (n + 0) = S n&lt;/code>, which is exactly what we wanted to prove.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h1 id="conclusion">Conclusion&lt;/h1>
&lt;p>We went over a lot here, building up from just introducing functional programming to writing mechanized proofs using dependent types. I really just went over the basics here, but these are the foundations modern type theory based proof assistants are built on. (Writing proofs like this by hand is not really practical though. Coq for example has a whole separate language just for automating the creation of proofs like these, so that most of the time you don&amp;rsquo;t even have to think about the details of what&amp;rsquo;s going on under the hood.)&lt;/p>
&lt;p>If this topic has caught your interest, here is a list of resources I would recommend:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://softwarefoundations.cis.upenn.edu/">Software Foundations&lt;/a>: A very good introduction to Coq, building up to quite advanced levels.&lt;/li>
&lt;li>&lt;a href="http://adam.chlipala.net/cpdt/">Certified Programming with Dependent Types&lt;/a>: A book about dependently typed programming and advanced proof automation in Coq.&lt;/li>
&lt;li>&lt;a href="https://github.com/stefan-hoeck/idris2-tutorial">Functional Programming in Idris 2&lt;/a>: A comprehensive introduction if you are interested in Idris specifically. (Idris does not have anything like Coq&amp;rsquo;s advanced proof automation capabilities though, it is more suited as a practical dependently typed programming language.)&lt;/li>
&lt;/ul>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>There are some exceptions, notably &lt;code>-&amp;gt;&lt;/code> is built in.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>And if you are perhaps wondering what is the type of &lt;code>Type&lt;/code>, &lt;a href="https://cs.stackexchange.com/questions/13285/universes-in-dependent-type-theory">you are in for a ride&lt;/a>. Fortunately though most of the time you can just ignore the complicated theory and pretend that &lt;code>Type : Type&lt;/code>.&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:3">
&lt;p>I have no idea why the list constructors are named &lt;code>Nil&lt;/code> and &lt;code>Cons&lt;/code>, but everyone names them like this. Just roll with it.&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:4">
&lt;p>I don&amp;rsquo;t think Idris actually distinguishes type parameters and indices, but some languages like Coq do.&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:5">
&lt;p>Note however that we won&amp;rsquo;t get a classical logic here, but rather a kind of constructive logic, but we can ignore this technical detail for now.&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:6">
&lt;p>Idris does not verify this by default, you have to provide the &lt;code>%default total&lt;/code> directive to tell it to only accept functions for which it can prove termination. This built in checking works well for most cases.&amp;#160;&lt;a href="#fnref:6" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:7">
&lt;p>In reality Idris doesn&amp;rsquo;t accept this definition because equality is already defined by the standard library, and &lt;code>=&lt;/code> is a reserved symbol.&amp;#160;&lt;a href="#fnref:7" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>My first impressions with OCaml</title><link>https://kuruczgy.com/blog/2022/03/12/my-first-impressions-with-ocaml/</link><pubDate>Sat, 12 Mar 2022 00:00:00 +0000</pubDate><guid>https://kuruczgy.com/blog/2022/03/12/my-first-impressions-with-ocaml/</guid><description>&lt;p>I currently am on a quest to find a generally useful functional language that I could experiment with on various projects.&lt;/p>
&lt;p>While this article specifically is about OCaml, I have plans for trying out other languages as well, so first I will talk in general about my criteria for evaluating functional languages.&lt;/p>
&lt;h1 id="how-am-i-evaluating-functional-languages">How am I evaluating functional languages&lt;/h1>
&lt;p>I don&amp;rsquo;t consider this list to be complete in any way, and expect it to be refined and extended as I learn more and try out new languages. Also, a large part of this can be applied to any software platform in general, not just functional programming languages.&lt;/p>
&lt;h2 id="tooling">Tooling&lt;/h2>
&lt;p>In general, a single tool for a purpose that&amp;rsquo;s &amp;ldquo;blessed&amp;rdquo; and endorsed by the ecosystem (or is at least a de facto standard) is a plus. Fragmentation of the ecosystem doesn&amp;rsquo;t really seems useful in this context.&lt;/p>
&lt;h3 id="build-system">Build system&lt;/h3>
&lt;p>Incremental compilation and good performance in general are nice to have. The build system also shouldn&amp;rsquo;t be overly difficult to learn and use.&lt;/p>
&lt;h3 id="formatter">Formatter&lt;/h3>
&lt;p>Ever since I tried &lt;a href="https://prettier.io">&lt;code>prettier&lt;/code>&lt;/a> I have been hooked on the idea of not having to care at all about the formatting of my source code. I think having such a formatter is even more useful for functional languages, as deeply nested expressions can be especially tricky to format by hand.&lt;/p>
&lt;h3 id="editor-support">Editor support&lt;/h3>
&lt;p>Type systems can be used to provide all kinds of useful editor features like smarter syntax highlighting, type annotations/queries, and context aware autocompletion. All of these are a plus for me.&lt;/p>
&lt;h2 id="runtime-environment">Runtime environment&lt;/h2>
&lt;p>One feature I would value quite much that might sound surprising at first is the ability to target JavaScript/WASM. As it stands right now, the web is by far the largest and most commonly available software platform, despite all of its shortcomings. Being able to deploy my code onto it can be quite valuable.&lt;/p>
&lt;p>For server use I don&amp;rsquo;t have any requirements, as with today&amp;rsquo;s container technology you can deploy pretty much anything anywhere.&lt;/p>
&lt;h2 id="learnability">Learnability&lt;/h2>
&lt;p>This criterion might even sound too obvious written out like this, but I want the language to be learnable with a reasonable amount of effort. By this I don&amp;rsquo;t mean that the language shouldn&amp;rsquo;t be complex, but there should be some resource, or collection of resources, that can give you a comprehensive understanding of the whole language.&lt;/p>
&lt;p>Having a language specification is of course the best, but I am willing to compromise with a collection of other resources as well, as long as that&amp;rsquo;s a reasonable substitute for a specification. (For example, if I have a specific question about how some part of the language works, there should be a way to get an answer to that with a reasonable amount of effort.)&lt;/p>
&lt;h2 id="functional-purity">Functional purity&lt;/h2>
&lt;p>While purity is certainly useful, you eventually do have to interface with the real world, and have some side effects in one way or another.&lt;/p>
&lt;p class="light-img">&lt;img src="https://kuruczgy.com/img/haskell.png
" alt="" title="xkcd.com/1312">&lt;/p>
&lt;p>I already use pure function as a generally useful tool in basically any language, and never felt the need for the language to enforce that. Nevertheless, my impression is that the methods for describing side effects in pure languages are quite mature too, and I wouldn&amp;rsquo;t mind using such a language either.&lt;/p>
&lt;h2 id="type-system">Type system&lt;/h2>
&lt;p>I would like a statically typed language. Not that I take any issue with dynamic typing, but I already have my default go-to language for that (Python), and various alternatives as well (JavaScript, Lua, even any kind of LISP).&lt;/p>
&lt;p>The issue is that beyond a certain level of complexity, you are bound to make mistakes in a dynamic language, and a type system can effectively alleviate large classes of them. While I agree that static typing can also be a source of mental overhead, and it&amp;rsquo;s sometimes more convenient to just program without strong types, I want the option to ask the compiler for help with checking my work whenever I feel like I need it. I am just a human after all, and bound to eventually make mistakes.&lt;/p>
&lt;p>I am open to trying various type systems, though some features I probably want are algebraic data types, and some method of generalizing over types. But stronger features like higher kinded types, or even dependent types are a plus too.&lt;/p>
&lt;h1 id="my-first-impressions-with-ocaml">My first impressions with OCaml&lt;/h1>
&lt;p>So with all that said, I will give you my first impressions of OCaml.&lt;/p>
&lt;p>It has a pretty mature community, a long history, and there are large companies (Facebook&lt;sup id="fnref:1">&lt;a href="#fn:1" role="doc-noteref">1&lt;/a>&lt;span class="footnote-tooltip">Yes it&amp;rsquo;s &amp;ldquo;Meta&amp;rdquo; I know&amp;hellip;&lt;/span>&lt;/sup> for instance) using it and helping with the development of the ecosystem.&lt;/p>
&lt;p>The package management seems quite good, &lt;code>opam&lt;/code> is the de facto standard package manager. I really like that the &lt;code>opam&lt;/code> repository is curated, and the compiler developers actually use it as a giant test suite for the compiler. Submitting a package requires a pull request in &lt;a href="https://github.com/ocaml/opam-repository">&lt;code>opam-repository&lt;/code>&lt;/a>, so this way every package publication is reviewed. The compiler, package manager, package repository, and the build system all live under the same &lt;a href="https://github.com/ocaml">GitHub organization&lt;/a>.&lt;/p>
&lt;p>The formatter, &lt;a href="https://github.com/ocaml-ppx/ocamlformat">&lt;code>ocamlformat&lt;/code>&lt;/a>, is a relatively new addition to the ecosystem, but it seems to work very well, I haven&amp;rsquo;t had any problems with it.&lt;/p>
&lt;p>The editor support seems good as well. I only tried the plugin for VS Code for ease of installation, but I assume that it would work well with any LSP capable editor.&lt;/p>
&lt;p>As for actually running your programs, OCaml compiles natively to most mainstream processor architectures. There are also multiple solutions for compiling it to JavaScript, namely &lt;a href="https://github.com/ocsigen/js_of_ocaml">&lt;code>js_of_ocaml&lt;/code>&lt;/a> and &lt;a href="https://rescript-lang.org/">ReScript&lt;/a>. While &lt;code>js_of_ocaml&lt;/code> is intended for OCaml developers to compile their code to JavaScript, and integrates with the ecosystem, ReScript is targeted more at JavaScript developers seeking better type safety, and actually comes with an alternative JavaScript-like syntax for OCaml, but still has support for the regular syntax. (Note that actually &lt;code>js_of_ocaml&lt;/code> also supports the ReScript syntax.) The ReScript syntax can be useful for using React as it supports JSX.&lt;/p>
&lt;p>While I read from multiple sources that the language was lacking good learning materials, I had very good experience with the &lt;a href="https://dev.realworldocaml.org/">Real World OCaml&lt;/a> book. There is a sort of language reference &lt;a href="https://ocaml.org/manual/language.html">available&lt;/a> as well, but the exact type checking and inference rules seem to be scattered in various research papers and university course notes. Nevertheless, because of the academic background, I have confidence in the soundness of the type system.&lt;/p>
&lt;p>The language is not pure, you can have side effects, mutable values, and global variables. The language makes it explicit which values are mutable, but not which functions do and do not have side effects.&lt;/p>
&lt;p>The type system is okay, you get amazing type inference, GADTs&lt;sup id="fnref:2">&lt;a href="#fn:2" role="doc-noteref">2&lt;/a>&lt;span class="footnote-tooltip">&lt;a href="https://en.wikipedia.org/wiki/Generalized_algebraic_data_type">Generalized algebraic data types&lt;/a>&lt;/span>&lt;/sup>, but no higher kinded types (though you can supposedly emulate them with modules). The module system is powerful, but also pretty weird, there is a distinction between &lt;em>first-class&lt;/em> and non-&lt;em>first-class&lt;/em> modules, with explicit conversions between them, an artifact of first-class modules having been added later into the language. One annoying thing is that the language calls parameterized modules &lt;em>functors&lt;/em>, which don&amp;rsquo;t really have anything to do with actual functors&lt;sup id="fnref:3">&lt;a href="#fn:3" role="doc-noteref">3&lt;/a>&lt;span class="footnote-tooltip">I of course mean &lt;a href="https://en.wikipedia.org/wiki/Functor">functors&lt;/a> from category theory. For some reason programming languages really like naming random things functors, C++ and Prolog are also guilty of this.&lt;/span>&lt;/sup>.&lt;/p>
&lt;p>Metaprogramming is done with the so-called &lt;em>ppx&lt;/em> system, which can apply arbitrary AST level transformations to the source code. This sounds quite powerful, but the system is used for some core functionality like generating comparison functions and pretty printers, and it actually has some pretty major flaws.&lt;/p>
&lt;p>First of all, the AST is apparently not very stable between compiler versions, and in practice ppx derivers have to be updated with each compiler version. The barrier to entry to writing them is also very high, requiring understanding of some compiler internals. I also had issues with composing extension nodes (using one inside of another), which is again pretty annoying given that they provide some core functionality.&lt;/p>
&lt;p>There supposedly is a &lt;a href="https://ocaml.org/manual/debugger.html">debugger&lt;/a> for the language, but I could not get it working based on the official docs.&lt;/p>
&lt;p>By far the largest issue I have with the language so far is the difficulty of debugging. It&amp;rsquo;s hard to insert random print statements to inspect arbitrary values, since there is no default pretty printer for values. Setting them up is non-trivial, given that the ppx derivers are non-recursive, so you have to annotate each type definition separately. The issue is exacerbated by the standard library&amp;rsquo;s (well actually there are multiple standard libraries, I was using &lt;code>base&lt;/code>) lack of pretty printing definitions. All of these issues together make printf debugging needlessly difficult.&lt;/p>
&lt;p>In summary, my largest complaints with the language are lack of good debugging methods, and lack of higher kinded types. But as there does not seem to be a fundamental obstacle to solving either of these (as I said earlier, higher kinded types can in theory be emulated with modules), I might consider revisiting OCaml sometime in the future.&lt;/p>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>Yes it&amp;rsquo;s &amp;ldquo;Meta&amp;rdquo; I know&amp;hellip;&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>&lt;a href="https://en.wikipedia.org/wiki/Generalized_algebraic_data_type">Generalized algebraic data types&lt;/a>&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:3">
&lt;p>I of course mean &lt;a href="https://en.wikipedia.org/wiki/Functor">functors&lt;/a> from category theory. For some reason programming languages really like naming random things functors, C++ and Prolog are also guilty of this.&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item></channel></rss>