<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <updated>2026-06-17T00:00:00-00:00</updated>
  <title>Posts</title>
  <id>https://patrick.sirref.org/posts/</id>
  <link rel="alternate" href="https://patrick.sirref.org/posts/" />
  <link rel="self" href="https://patrick.sirref.org/posts/atom.xml" />
  <entry>
    <title>A Shell is Born</title>
    <published>2026-06-17T00:00:00-00:00</published>
    <updated>2026-06-17T00:00:00-00:00</updated>
    <author>
      <name>https://patrick.sirref.org/Patrick Ferris/</name>
      <uri>https://patrick.sirref.org/Patrick%20Ferris/</uri>
    </author>
    <link rel="alternate" type="text/html" href="https://patrick.sirref.org/a-shell-is-born/" />
    <id>https://patrick.sirref.org/a-shell-is-born/</id>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p xmlns:html="http://www.w3.org/1999/xhtml"><a href="https://patrick.sirref.org/merry/">Merry</a> passed a milestone this week after installing the following packages <code>vim fakeroot fakechroot debootstrap</code> and successfully performing a <a href="https://wiki.debian.org/fakechroot">fakechroot debootstrap</a>.</p>
        <p xmlns:html="http://www.w3.org/1999/xhtml">To me, this signals that <a href="https://patrick.sirref.org/merry/">Merry</a> is closer than ever to being an <em>actual</em> POSIX-ish shell. This is exciting because we now have a completely customisable, OCaml implementation of a shell that can run a significant number of existing shell scripts in the world. Let the hacking commence!</p>
        <section>
          <header>
            <h2>Installation</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">You can install the binary, <code>msh</code>, today:</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="sh-source">opam pin git+https://git.sirref.org/merry
</span>
              <span class="sh-support-function-builtin">eval</span>
              <span class="sh-source"> </span>
              <span class="sh-punctuation-definition-string-begin"><![CDATA[$(]]></span>
              <span class="sh-string-interpolated-dollar">opam env</span>
              <span class="sh-punctuation-definition-string-end"><![CDATA[)]]></span>
              <span class="sh-source">
</span>
              <span class="sh-source">msh
</span>
            </code>
          </pre>
        </section>
        <section>
          <header>
            <h2>What's next?</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">There are a few avenues to try next. In the short-term, more testing of the shell is probably worthwhile. In particular, trying to boot an Alpine Linux image with <code>msh</code> as the default shell would be good.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Integrating the various components of <a href="https://patrick.sirref.org/shelter/">Shelter</a> is also on the list. A time-travelling POSIX shell is within reach; the actual semantics still need to be ironed out.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">I know for certain that some shell options and built-ins will be the first issues to arise going forward.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">As a fun experiment, <a href="https://patrick.sirref.org/anilmadhavapeddy/">Anil</a>'s vibecoded <a href="https://tangled.org/anil.recoil.org/ocaml-bbox">OCaml busybox translation</a> could be plumbed into <code>msh</code>. This would allow a very versatile, but <em>zero-forking</em> shell! Throw in an in-memory Eio filesystem into the mix and the whole thing becomes in-memory... <a href="https://mirage.io/"><code>mirageSH</code></a>.</p>
        </section>
        <section>
          <header>
            <h2>Weeknotes</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Below are a collection of weeknotes for <a href="https://patrick.sirref.org/merry/">Merry</a>.</p>
        </section>
      </div>
    </content>
  </entry>
  <entry>
    <title>Vibecoding Etiquette</title>
    <published>2026-03-09T00:00:00-00:00</published>
    <updated>2026-03-09T00:00:00-00:00</updated>
    <author>
      <name>https://patrick.sirref.org/Patrick Ferris/</name>
      <uri>https://patrick.sirref.org/Patrick%20Ferris/</uri>
    </author>
    <link rel="alternate" type="text/html" href="https://patrick.sirref.org/vibecoding-etiquette/" />
    <id>https://patrick.sirref.org/vibecoding-etiquette/</id>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p xmlns:html="http://www.w3.org/1999/xhtml">I am yet to jump head-first into using LLM-based tools like Claude Code or even ChatGPT to help with my programming in any serious way. After using some "free"-tier tools to try to better understand some tricky eBPF problems and to make sense of the semantics of POSIX shells, I was left unimpressed and ultimately felt my time was wasted.</p>
        <p xmlns:html="http://www.w3.org/1999/xhtml">I feel unwilling to send my money to the corporations behind these tools. This is for a variety of reasons including the deeply worrying relationship with the US Department of War (I struggle to find the meaningful difference between <a href="https://www.anthropic.com/news/where-stand-department-war">"opertational planning" vs. "operational decision-making" given the leaders of the US DoW</a>), environmental concerns, exploitation of human labour and a fast-and-loose approach to copyright laws. All of which leaves the entire industry very unattractive to me.</p>
        <p xmlns:html="http://www.w3.org/1999/xhtml">Everybody can draw their line where they want, and I am, in good faith, trying to find where mine should be.</p>
        <p xmlns:html="http://www.w3.org/1999/xhtml">Unfortunately, my own decision to not use these tools is not completely in my control. What do I do about pull requests to open-source libraries I maintain that include agentic code? I am, after all, participating in the idea of open-source and inclusive collaboration. Agentic code also comes in many flavours, from blatant LLM-generated pull requests to heavily edited, human-in-the-loop contributions.</p>
        <p xmlns:html="http://www.w3.org/1999/xhtml">An immediate first step for me is to develop some policy for contributions to projects I maintain regarding code where LLMs have had a hand. This can help set expectations for contributors. <a href="https://github.com/ocaml-multicore/eio/blob/main/HACKING.md#ai-generated-code">Eio's "AI-generated Code"</a> subsection is succinct and prohibits contributions that <em>solely</em> use AI.</p>
        <blockquote xmlns:html="http://www.w3.org/1999/xhtml">
          <p>It obfuscates how you think. Purely AI-generated code tells us little about how you think and the problems you might be having. This makes it harder to provide good feedback on PRs and issues.</p>
          <p>It is often more work to review. Particularly for the OCaml ecosystem and libraries like Eio, it seems that these tools are not very good and generate a lot of believable code that is in actual fact completely wrong. PR comments and the code submitted with them can say completely different things.</p>
          <p>It is a grey area for licensing. Models like ChatGPT have been trained on lots of code with different licenses and has been known to simply copy code as an answer to a prompt. We would like to avoid this headache as best we can.</p>
        </blockquote>
        <p xmlns:html="http://www.w3.org/1999/xhtml">Additionally, I plead to other developers to <em>own</em> their use of these tools. Please, make Claude a co-author of the commits where Claude has generated <em>any</em> code at the very least. This is the bare minimum. I have strong feelings about the etiquette of sending AI summarised information or LLM-generated code to other people, but before any of that, the decent thing is to remove any uncertainty in the receiving party's mind of how the information they are receiving came to be. In this way, I appreciate the <a href="https://github.com/ocaml/ocaml/blob/trunk/AI.md">OCaml compiler's AI notice</a> which includes:</p>
        <blockquote xmlns:html="http://www.w3.org/1999/xhtml">
          <p>If a significant portion of your code, PR description, review comments or messages has been AI-generated, this must be disclosed, stating which tool was used and for what. Reviewing AI-produced code can require a different approach from human-written code. You should have an acknowledgement anyway even if another human contributor did some of the work.</p>
        </blockquote>
      </div>
    </content>
  </entry>
  <entry>
    <title>ICFP 2025</title>
    <published>2025-10-24T00:00:00-00:00</published>
    <updated>2025-10-24T00:00:00-00:00</updated>
    <author>
      <name>https://patrick.sirref.org/Patrick Ferris/</name>
      <uri>https://patrick.sirref.org/Patrick%20Ferris/</uri>
    </author>
    <link rel="alternate" type="text/html" href="https://patrick.sirref.org/icfp-2025/" />
    <id>https://patrick.sirref.org/icfp-2025/</id>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p xmlns:html="http://www.w3.org/1999/xhtml">Two weeks ago I was fortunate enough to attend the <a href="https://icfp25.sigplan.org/">International Conference on Functional Programming</a> in Singapore. My first time in Asia and my second time at the conference, what follows are some thoughts and presentations I enjoyed whilst I was there.</p>
        <p xmlns:html="http://www.w3.org/1999/xhtml">I must thank my office mate (and friend!) <a href="https://ryan.freumh.org/">Ryan Gibb</a> for his camaraderie and sage advice: "the best track is <em>hallway</em> track". Not to mention all of his <a href="https://ryan.freumh.org/photos.html">photos</a> too. Thanks Ryan!</p>
        <div xmlns:html="http://www.w3.org/1999/xhtml" style="text-align: center">
  <img class="inner-img" src="/bafkrmid2d6u3qdufa6m5gogavtwm6uqksaicozrc5s2unrtzjtth3hpvey.jpeg" alt="Description follows image." />
</div>
        <p xmlns:html="http://www.w3.org/1999/xhtml">From right to left, top to bottom: <a href="https://patrick.sirref.org/anil%20madhavapeddy/">Anil Madhavapeddy</a>, <a href="https://patrick.sirref.org/sadiq%20jaffer/">Sadiq Jaffer</a>, <a href="https://patrick.sirref.org/patrick%20ferris/">Patrick Ferris</a>, <a href="https://patrick.sirref.org/ryan%20gibb/">Ryan Gibb</a> and <a href="https://patrick.sirref.org/roy%20ang/">Roy Ang</a>.</p>
        <section>
          <header>
            <h2>Random Hacking</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Below are just some of the pieces of random hacking I got up to whilst in Singapore.</p>
          <section>
            <header>
              <h3>OxCaml and Uring</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">Jane Street were a big presence at ICFP 2025, carting along with them a shiny new OCaml compiler: <a href="https://oxcaml.org/">OxCaml</a>. If have been <a href="https://patrick.sirref.org/try-oxcaml/">playing around with OxCaml recently</a> but nothing outside toplevels in Javascript. Until now!</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">After talking to <a href="https://patrick.sirref.org/dra27/">David</a>, I spent some time converting a small corner of the <a href="https://github.com/ocaml-multicore/ocaml-uring">ocaml-uring</a> library to use a part of <a href="https://patrick.sirref.org/oxcaml/">OxCaml</a>. In particular making the following change:</p>
            <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
              <code>
                <span class="ocaml-source">  </span>
                <span class="ocaml-keyword-other">module</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-language-capital-identifier">Heap</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other">struct</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">    </span>
                <span class="ocaml-keyword-other">type</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">ptr</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-support-type">int32</span>
                <span class="ocaml-keyword-other">#</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">    </span>
                <span class="ocaml-comment-block"><![CDATA[(*]]></span>
                <span class="ocaml-comment-block"> ... </span>
                <span class="ocaml-comment-block"><![CDATA[*)]]></span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">  </span>
                <span class="ocaml-keyword-other">end</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">  </span>
                <span class="ocaml-keyword-other">type</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">cqe</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[{]]></span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">    </span>
                <span class="ocaml-source">user_data_id</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-language-capital-identifier">Heap</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
                <span class="ocaml-source">ptr</span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">    </span>
                <span class="ocaml-source">res</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-support-type">int32</span>
                <span class="ocaml-keyword-other">#</span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">  </span>
                <span class="ocaml-source"><![CDATA[}]]></span>
                <span class="ocaml-source">
</span>
              </code>
            </pre>
            <p xmlns:html="http://www.w3.org/1999/xhtml">The idea being that a completion queue entry (a notification that some operation has completed) could be fully represented using 64 bits (two 32-bit, <a href="https://oxcaml.org/documentation/unboxed-types/01-intro/">unboxed values</a>). You can <a href="https://github.com/ocaml-multicore/ocaml-uring/compare/main...patricoferris:ocaml-uring:oxcaml?expand=1">see how this impacted the library</a>! I'm not certain about this change (and I'm sure I did it wrong) but it was nice to realise <a href="https://patrick.sirref.org/oxcaml/">OxCaml</a> gives you this kind of control. However, I am worried about the ergonomics of manipulating values like <code>int32#</code> and the temptation to case it into an <code>int</code> (presumably losing a good portion of the value of having an unboxed value in the first place).</p>
          </section>
          <section>
            <header>
              <h3>Bibtex Parser</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">On the flight over to Singapore, I started to write a post for this website. Some readers may remember that I use <a href="https://patrick.sirref.org/forester/">forester</a> after a preprocessing step via <a href="https://patrick.sirref.org/graft/">graft</a> to build this site. Part of that preprocessing consumes bibtex files and outputs forester trees. For the initial <a href="https://patrick.sirref.org/graft/">graft</a> release I used the excellent <a href="https://github.com/Octachron/talaria_bibtex">Talaria Bibtex</a> library. Unfortunately, it presented a pretty confusing API that, whilst nicely typed, felt a little cumbersome to use. Additionally, it was too specific in what it would accept as valid Bibtex. I wanted something that was a little more straight-forward to use (if a little fast-and-loose when it comes to types...). And so I built <a href="https://patrick.sirref.org/bib/">bib</a>.</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">This was my first real attempt at using the <a href="https://ocaml.org/p/bytesrw">Bytesrw</a> library. I was happy with the results, although I did have to copy a substantial amount of code from <a href="https://ocaml.org/p/jsont">other bytesrw-compatible libraries</a>. I'd be happy to shift to this <code>bytes</code>-first world if it wasn't for the ever-present-in-my-mind issue of relocatable values in the OCaml heap!</p>
          </section>
          <section>
            <header>
              <h3>Geocaml Libraries</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">There has been some excellent <a href="https://patrick.sirref.org/outreachy/">outreachy</a> work happening on the <a href="https://github.com/geocaml/ocaml-tiff">geocaml/ocaml-tiff</a> library which is a potential Outreachy internship project for December 2025. More on this in a future post.</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">On the way back (and a little during the conference), I spent some time building an OCaml counterpart to <a href="https://github.com/ucam-eo/geotessera/">geotessera</a>, a library for working with <a href="https://patrick.sirref.org/tessera2025/">Tessera</a>. The library is not ready for people to use directly, but I was working on various constituent parts including:</p>
            <ul xmlns:html="http://www.w3.org/1999/xhtml">
              <li>
                <p><a href="https://github.com/geocaml/ocaml-proj">Modern OCaml bindings to PROJ</a> (a coordinate reference system projection library)</p>
              </li>
              <li>
                <p>
                  <a href="https://github.com/geocaml/ocaml-wkt">Further work on a WKT library for OCaml</a>
                </p>
              </li>
              <li>
                <p>Coming soon... ocaml-geotessera</p>
              </li>
            </ul>
          </section>
        </section>
        <section>
          <header>
            <h2>Talks</h2>
          </header>
          <section>
            <header>
              <h3>Hazel of OCaml at TyDe</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">The <em>type-driven development</em> (TyDe) workshop was held on the first day of ICFP at the <a href="https://www.comp.nus.edu.sg/">NUS School of Computing</a>. I find the workshop name to be a little misleading, but perhaps this comes from my engineering background. The talks focused a lot on type <em>theory</em>, presenting the formal mathematics of interesting type systems with less focus on <em>why</em> it might be useful to have such an exotic type system... but then again, that was the nature of the entire conference.</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">I presented a talk on <a href="https://patrick.sirref.org/hazel-of-ocaml/">hazel_of_ocaml</a>. The <a href="https://patrick.sirref.org/var/tyde2025.pdf">slides are here</a>, along with the <a href="https://patrick.sirref.org/var/tyde2025-ea.pdf">extended abstract</a>. My talk ended up focusing a lot on the pedagogical benefits of having a type system that helped explain the most important thing a type system does... catch type errors! This work represents a small piece of work inside <a href="https://maxcarroll0.github.io/">Max Carroll's</a> excellent <a href="https://patrick.sirref.org/part-ii-hazel/">part II</a> project, which he presented at the <a href="https://maxcarroll0.github.io/papers/workshops/HATRA-decomposable-type-highlighting/">HATRA workshop</a>: <em>Decomposable Type Highlighting for Bidirectional Type and Cast Systems</em>.</p>
          </section>
          <section>
            <header>
              <h3>Scientific Programming at PROPL</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">I think it is important to be honest whenever you get a talk accepted that you otherwise feel should not have been. My talk "<em>about scientific programming what we talk about when we talk</em>" is one such talk. The <a href="https://patrick.sirref.org/var/propl2025.pdf">slides are here</a>. The talk itself was nothing to write home about, but I think there were a few nice ideas that came out of it and the conversations I had with fellow PROPL attenders.</p>
            <section>
              <header>
                <h4>TMF Data Discrepancies Redux</h4>
              </header>
              <p xmlns:html="http://www.w3.org/1999/xhtml">On the eve of my talk, I decided to re-run some analysis I did a few years ago on the <a href="https://forobs.jrc.ec.europa.eu/TMF/data#downloads">tropical moist forest dataset</a>, knowing that since then a few more years had become available. After fighting with some bit-rot in the Google Earth Engine script I had used, the new results were not very uplifting.</p>
              <table xmlns:html="http://www.w3.org/1999/xhtml">
    <tbody>
    <tr>
    <td><strong>Land Use Class</strong></td>
    <td><strong>Percent Change</strong></td>
    </tr>
    <tr>
    <td>Undisturbed</td>
    <td> -2.9</td>
    </tr>
    <tr>
    <td>Degraded</td>
    <td> -5.5</td>
    </tr>
    <tr style="background: yellow">
    <td>Deforested</td>
    <td> 8.6</td>
    </tr>
    <tr>
    <td>Regrowth</td>
    <td> 0.5</td>
    </tr>
    <tr>
    <td>Water</td>
    <td> 0.0</td>
    </tr>
    <tr>
    <td>Other</td>
    <td>-0.6</td>
    </tr>
    </tbody>
</table>
              <p xmlns:html="http://www.w3.org/1999/xhtml">The data in the table corresponds to the land use class values in Indonesia in the year 2008. The analysis computed the difference across each of the classes between the dataset released in 2021 and the dataset released in 2024. Most notably, the amount of deforested land has gone up by <em>8.6</em> percent!</p>
              <p xmlns:html="http://www.w3.org/1999/xhtml">As a somewhat tangential, though related, aside, I had the pleasure of talking to <a href="https://cs.nyu.edu/~shw8119/">Sam Westrick</a>, <a href="https://forthoney.github.io/">Seong-Heon Jung</a> and <a href="https://svishnus.github.io/">Sundara Vishnu Satish</a> of the <a href="https://nyu-parcour.github.io/">ParCour</a> research group. They were telling me about <a href="https://github.com/mpllang/mpl">MaPLe</a>, a programming language from the MLs built for parallelism. We discussed some ideas of using real-world, geospatial algorithms as benchmarks for MaPLe. <a href="https://patrick.sirref.org/mdales/">Michael</a>, if you got this far remind me to chat to you about this!</p>
            </section>
            <section>
              <header>
                <h4>Shelter Reactions</h4>
              </header>
              <p xmlns:html="http://www.w3.org/1999/xhtml">At the end of my talk, I briefly mentioned <a href="https://patrick.sirref.org/shelter/">shelter</a>. By far, this was the topic I got the most engagement on post-talk. During the conference, this was also true when people asked what I was working on. The tag line "a shell with <em>undo</em>" seemed to capture the attention of most people.</p>
              <p xmlns:html="http://www.w3.org/1999/xhtml">I'm feeling a renewed sense of interest in my own work thanks to that, even if the "research" contributions are not very apparent. However, I also had a good discussion with <a href="https://kcsrk.info/">KC</a> about the underlying <a href="https://patrick.sirref.org/mrdt/">MRDT</a> in <a href="https://patrick.sirref.org/shelter/">Shelter</a> and how we might think about collaborating in the future on MRDT-related work.</p>
              <p xmlns:html="http://www.w3.org/1999/xhtml">Related to that, I managed to spend the evening in <a href="https://www.openstreetmap.org/relation/18195609#map=16/1.28090/103.84222">Chinatown</a> with <a href="https://dynamicaspects.org/research/">Roly Perera</a>. Roly's work has focused on <a href="https://f.luid.org/">Fluid</a>, a transparency-based programming language that allows authors to reveal their computation to their user. Excitingly, Roly presented a <a href="https://conf.researchr.org/details/icfp-splash-2025/propl-2025-papers/10/Authoring-Tools-for-Transparent-Climate-Reporting">new text-based part of the language</a> at PROPL. Our work is in the same universe, loosely orbiting some notion of reproducibility and explainability, but quite different in engineering work and how users might actually interact with our systems. I thoroughly enjoyed talking about solutions or research ideas that <em>preserve</em> existing workflows. Roly was great at pulling that out of the current work I have been doing.</p>
            </section>
          </section>
        </section>
        <section>
          <header>
            <h2>Other Talks and Highlights</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">I was a part of, often in a very small way, some other talks that were presented at ICFP including</p>
          <ul xmlns:html="http://www.w3.org/1999/xhtml">
            <li>
              <p><a href="https://www.youtube.com/watch?v=j84ocjlj1JA&amp;amp%3Bt=12880s">Functional Networking for Docker</a>, I encourage you to read <a href="https://patrick.sirref.org/anilmadhavapeddy/">Anil's</a> <a href="https://anil.recoil.org/notes/icfp25-ocaml5-js-docker#functional-networking-at-docker">notes on the topic</a>. It is also worth mentioning <a href="https://patrick.sirref.org/anilmadhavapeddy/">Anil's</a> <a href="https://anil.recoil.org/notes/icfp25-post-posix">post-posix talk</a> (not unrelated to my Uring musings above).</p>
            </li>
            <li>
              <p><a href="https://patrick.sirref.org/mdales/">Michael</a> gave an excellent, <em>very live</em>, talk about <a href="https://conf.researchr.org/details/icfp-splash-2025/propl-2025-papers/6/Yirgacheffe-a-declarative-approach-to-geospatial-data">Yirgacheffe</a> at PROPL which I thoroughly enjoyed. I'm also excited about his recent developments which I'm sure you can clue into <a href="https://digitalflapjack.com/weeknotes/">over on his blog</a>.</p>
            </li>
          </ul>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Below is a non-exhaustive list of talks I enjoyed whilst at the conference. Some relevant, most of them not!</p>
          <ul xmlns:html="http://www.w3.org/1999/xhtml">
            <li>
              <p>By far, one of the best talks was <a href="https://icfp25.sigplan.org/details/icfp-2025-papers/13/Polynomial-Time-Program-Equivalence-for-Machine-Knitting">Polynomial-time Program Equivalence for Machine Knitting</a>. I think the talk really nailed the "here's the idea, the details are in the paper"-presenting style as they described an "...algorithm that canonicalizes the algebraic representations of the topological semantics of machine knitting programs".</p>
            </li>
            <li>
              <p>I attended most of the <a href="https://conf.researchr.org/details/icfp-splash-2025/icfp-splash-2025-tutorials/5/A-guided-tour-through-Oxidized-OCaml">OxCaml tutorial</a> presented by the incredibly friendly <a href="https://gavinleroy.com/">Gavin Gray</a>.</p>
            </li>
            <li>
              <p><a href="https://patrick.sirref.org/ryangibb/">Ryan</a>'s talk <a href="https://conf.researchr.org/details/icfp-splash-2025/propl-2025-papers/13/Spatial-Programming-for-Environmental-Monitoring">Spatial Programming for Environmental Monitoring</a> at PROPL was excellent.</p>
            </li>
          </ul>
          <p xmlns:html="http://www.w3.org/1999/xhtml">There's plenty more to talk about, and I'm sure my future posts will reference other parts of my experience at ICFP 2025. Thanks for reading, and if anybody is interested in any aspects of this do reach out!</p>
        </section>
      </div>
    </content>
  </entry>
  <entry>
    <title>Irmin Retrospective</title>
    <published>2025-08-07T00:00:00-00:00</published>
    <updated>2025-08-07T00:00:00-00:00</updated>
    <author>
      <name>https://patrick.sirref.org/Patrick Ferris/</name>
      <uri>https://patrick.sirref.org/Patrick%20Ferris/</uri>
    </author>
    <link rel="alternate" type="text/html" href="https://patrick.sirref.org/irmin-retro/" />
    <id>https://patrick.sirref.org/irmin-retro/</id>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p xmlns:html="http://www.w3.org/1999/xhtml"><a href="https://patrick.sirref.org/irmin/">Irmin</a> is an OCaml library for building <em>branchable</em> and <em>mergeable</em> data stores. The data is <em>mergeable</em> in the sense of <a href="https://patrick.sirref.org/kcrsk-mrdts-2022/">mergeable replicated data types</a>.</p>
        <p xmlns:html="http://www.w3.org/1999/xhtml">I have been using Irmin for over five years to build different kinds of interesting data stores including:</p>
        <ul xmlns:html="http://www.w3.org/1999/xhtml">
          <li>
            <p>A <a href="https://github.com/patricoferris/omditor">simple markdown-based note-taking web application</a>.</p>
          </li>
          <li>
            <p>A <a href="https://github.com/carboncredits/retirement-db">content-addressed database</a>.</p>
          </li>
          <li>
            <p>Mentoring an intern who <a href="https://tarides.com/blog/2022-08-02-irmin-in-the-browser/">worked on Irmin in the browser</a>.</p>
          </li>
          <li>
            <p>Most recently, an <a href="https://patrick.sirref.org/shelter/">Irmin-backed shell session manager</a>.</p>
          </li>
        </ul>
        <p xmlns:html="http://www.w3.org/1999/xhtml">I was asked to provide some feedback recently on <a href="https://patrick.sirref.org/irmin/">Irmin</a>, so I thought writing a little retrospective here would be a good way to do that. The remit for the retrospective was about improving <a href="https://patrick.sirref.org/irmin/">Irmin</a>, so the content is focussed on pain points and areas of improvement.</p>
        <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
          <code>
            <span class="ocaml-comment-block"><![CDATA[(*]]></span>
            <span class="ocaml-comment-block"> An in-memory Irmin store </span>
            <span class="ocaml-comment-block"><![CDATA[*)]]></span>
            <span class="ocaml-source">
</span>
            <span class="ocaml-keyword-other">module</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-constant-language-capital-identifier">Store</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-keyword-operator">=</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-constant-language-capital-identifier">Irmin_mem</span>
            <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
            <span class="ocaml-constant-language-capital-identifier">KV</span>
            <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
            <span class="ocaml-constant-language-capital-identifier">Make</span>
            <span class="ocaml-source"><![CDATA[(]]></span>
            <span class="ocaml-constant-language-capital-identifier">Irmin</span>
            <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
            <span class="ocaml-constant-language-capital-identifier">Contents</span>
            <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
            <span class="ocaml-constant-language-capital-identifier">String</span>
            <span class="ocaml-source"><![CDATA[)]]></span>
            <span class="ocaml-source">
</span>
          </code>
        </pre>
        <section>
          <header>
            <h2>What is Irmin?</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml"><a href="https://patrick.sirref.org/irmin/">Irmin</a>, at its simplest, is a key-value database. Users associate keys with values and can query and update these bindings.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Additionally, this database supports versioning. This means independent snapshots of the database can coexist and users can switch between them and update them without fear of interfering with other versions.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Different versions of the database can be combined by <em>merging</em>. When you set up your instance of an <a href="https://patrick.sirref.org/irmin/">Irmin</a> database, you also provide it with a <a href="https://patrick.sirref.org/kcrsk-mrdts-2022/">merge function</a>.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-mdx-hash">#</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other">#</span>
              <span class="ocaml-keyword-other">show_type</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Irmin</span>
              <span class="ocaml-source">.</span>
              <span class="ocaml-constant-language-capital-identifier">Merge</span>
              <span class="ocaml-source">.</span>
              <span class="ocaml-source">f</span>
              <span class="ocaml-source">;;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-other">type</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other">nonrec</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-storage-type">'a</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">f</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">    </span>
              <span class="ocaml-source">old</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-storage-type">'a</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Irmin</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">Merge</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">promise</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">    </span>
              <span class="ocaml-storage-type">'a</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-storage-type">'a</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-storage-type">'a</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Irmin</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">Merge</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">conflict</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">result</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Lwt</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">t</span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
        </section>
        <section>
          <header>
            <h2>Design and API</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml"><a href="https://patrick.sirref.org/irmin/">Irmin</a>'s API is very git-inspired. There is a large overlap of shared vocabulary and concepts: <em>repositories</em>, <em>branches</em>, <em>commits</em>, <em>heads</em> etc.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Probably the most confusing aspect of this is the notion of a <code>Store</code>. When I was describing <a href="https://patrick.sirref.org/irmin/">Irmin</a> above, I used the term <em>database</em> to help distinguish between some of these concepts. In Irmin's documentation, it is used for multiple related (but different) concepts. In "<a href="https://irmin.org/tutorial/getting-started/#creating-a-store">Creating a Store</a>" stores refer to the entire database, whereas in the <a href="https://patrick.sirref.org/irmin/">Irmin</a> API docs we have that:</p>
          <blockquote xmlns:html="http://www.w3.org/1999/xhtml">
            <p>There are two kinds of store in Irmin: the ones based on persistent named branches and the ones based temporary detached heads.</p>
          </blockquote>
          <p xmlns:html="http://www.w3.org/1999/xhtml">For <a href="https://patrick.sirref.org/irmin/">Irmin</a> library users, a <code>Store.t</code> can be thought of as a checkout of the database at a particular revision. This may be from a branch or a specific commit.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-mdx-hash">#</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Store</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">of_branch</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-operator">-</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Store</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">repo</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-support-type">string</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Store</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">t</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Lwt</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">t</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">&lt;</span>
              <span class="ocaml-keyword-other">fun</span>
              <span class="ocaml-keyword-operator">&gt;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-mdx-hash">#</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Store</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">of_commit</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-operator">-</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Store</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">commit</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Store</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">t</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Lwt</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">t</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">&lt;</span>
              <span class="ocaml-keyword-other">fun</span>
              <span class="ocaml-keyword-operator">&gt;</span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">The overloading of the term is confusing. I think it leaves users unsure about what other people might mean when they say "store". Being careful with these terms, and the contexts in which they are used, would help avoid this confusion.</p>
          <section>
            <header>
              <h3>Module and Functor Soup</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">Undoubtedly for a majority of use-cases and users, <a href="https://patrick.sirref.org/irmin/">Irmin</a> is over-functorised. Nearly every module requires that you must apply some functor to access any useful code. In general, a user will have to interact with the <a href="https://mirage.github.io/irmin/irmin/Irmin/module-type-S/Schema/index.html"><code>Schema</code> module</a> when describing the types they want to instantiate their store with.</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">To counteract this, Irmin has plenty of <code>KV</code> modules that provide a <code>Make</code> functor that only requires a user to provide a suitable <em>content</em> module for their store (i.e. something that provides a type, a runtime representation of that type and a merge function).</p>
            <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
              <code>
                <span class="ocaml-mdx-hash">#</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other">#</span>
                <span class="ocaml-keyword-other">show_module</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-language-capital-identifier">Irmin_mem</span>
                <span class="ocaml-source">.</span>
                <span class="ocaml-constant-language-capital-identifier">KV</span>
                <span class="ocaml-source">;;</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-keyword-other">module</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-language-capital-identifier">KV</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">  </span>
                <span class="ocaml-keyword-other">sig</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">    </span>
                <span class="ocaml-keyword">type</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-entity-name-function-binding">endpoint</span>
                <span class="ocaml-source"> = unit
</span>
                <span class="ocaml-source">    </span>
                <span class="ocaml-keyword">type</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-entity-name-function-binding">metadata</span>
                <span class="ocaml-source"> = unit
</span>
                <span class="ocaml-source">    </span>
                <span class="ocaml-keyword">type</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-entity-name-function-binding">hash</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">    </span>
                <span class="ocaml-keyword">type</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-entity-name-function-binding">info</span>
                <span class="ocaml-source"> = Store.info
</span>
                <span class="ocaml-source">    </span>
                <span class="ocaml-keyword">type</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[('h, _)]]></span>
                <span class="ocaml-entity-name-function-binding">contents_key</span>
                <span class="ocaml-source"> = 'h
</span>
                <span class="ocaml-source">    </span>
                <span class="ocaml-keyword">type</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">'h </span>
                <span class="ocaml-entity-name-function-binding">node_key</span>
                <span class="ocaml-source"> = 'h
</span>
                <span class="ocaml-source">    </span>
                <span class="ocaml-keyword">type</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">'h </span>
                <span class="ocaml-entity-name-function-binding">commit_key</span>
                <span class="ocaml-source"> = 'h
</span>
                <span class="ocaml-source">    </span>
                <span class="ocaml-keyword-other-ocaml">module</span>
                <span class="ocaml-source"><![CDATA[ Make : (C : Irmin__.Contents.S) ->]]></span>
                <span class="ocaml-keyword-other-ocaml">sig</span>
                <span class="ocaml-source"> ... </span>
                <span class="ocaml-keyword-other">end</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">  </span>
                <span class="ocaml-keyword-other">end</span>
                <span class="ocaml-source">
</span>
              </code>
            </pre>
            <p xmlns:html="http://www.w3.org/1999/xhtml">I think it is fair to say the documentation is hard to follow as it is a module and functor soup. For example, looking at <code>irmin.3.11.0</code>, starting at <a href="https://ocaml.org/p/irmin/latest/doc/index.html">the toplevel documentation page</a> our path to finding this paricular module and functor is as follows:</p>
            <ol xmlns:html="http://www.w3.org/1999/xhtml">
              <li>
                <p>We jump into <a href="https://ocaml.org/p/irmin/latest/doc/irmin.mem/Irmin_mem/index.html"><code>Irmin_mem</code></a> from the nicely written landing page.</p>
              </li>
              <li>
                <p>We scroll down to find <a href="https://ocaml.org/p/irmin/latest/doc/irmin.mem/Irmin_mem/index.html#module-KV">the KV module</a>.</p>
              </li>
              <li>
                <p>We now make sense of the module's signature by following the <a href="https://ocaml.org/p/irmin/latest/doc/irmin/Irmin/module-type-KV_maker/index.html">KV_maker link</a>.</p>
              </li>
              <li>
                <p>We see a <code>Make (C : Contents.S) : sig ... end</code> at the end of the module, and <a href="https://ocaml.org/p/irmin/latest/doc/irmin/Irmin/module-type-KV_maker/Make/index.html#module-Schema">we navigate through that</a>.</p>
              </li>
              <li>
                <p>Finally we have come to our journey's end, and find the <a href="https://ocaml.org/p/irmin/latest/doc/irmin/Irmin/module-type-KV_maker/Make/index.html#module-Schema">schema module</a> with type constraints like <code>type Branch.t = string</code>.</p>
              </li>
            </ol>
            <p xmlns:html="http://www.w3.org/1999/xhtml">There is a big assumption there that you know what the <code>Schema</code> module is telling you and how it relates to your "store".</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">There is a counter-argument here, in that Irmin is incredibly flexible in terms of what you can use as types for your keys, branches, hashes etc. I was quite easily able to produce <a href="https://github.com/patricoferris/ocaml-cid/blob/main/test/irmin_cid.ml">Irmin stores that use CIDs (self-describing content identifiers)</a> for example.</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">I think there is a middle ground. For Irmin to be usable it needs to reduce the complexity of the API. The complexity is due to, in large part, over-functorisation. If the functors cannot be removed then perhaps better documentation or more <a href="https://ocaml.org/p/irmin-containers/latest/doc/irmin-containers/Irmin_containers/index.html">introductory libraries like irmin-containers</a> would be helpful. Perhaps a <em>standalone</em> library that acts as an interface to Irmin stores would be helpful. I find myself time and again implementing <a href="https://github.com/fn06/shelter/blob/main/src/lib/store.ml">something like that</a>.</p>
          </section>
          <section>
            <header>
              <h3>Backends Galore</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">Irmin has plenty of backends including <a href="https://ocaml.org/p/irmin-git/latest">a git-compatible one</a>, <a href="https://ocaml.org/p/irmin-mirage/latest">a MirageOS backend</a>, <a href="https://ocaml.org/p/irmin-indexeddb/latest">an in-browser IndexedDB backend</a> and even a <a href="https://github.com/andreas/irmin-fdb">FoundationDB backend</a>.</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml"><a href="https://patrick.sirref.org/irmin/">Irmin</a> needs to have fewer, better tested backends. Of course, some of these are likely driven by funding and use-case specific details. However, I think by focusing on a few key backends and striving for solid performance but also strong consitency guarantees, <a href="https://patrick.sirref.org/irmin/">Irmin</a> would become a more viable candidate for potential users. I also believe the browser backend plays a key part to making this work in order to facilate <a href="https://lofi.so/">local-first applications</a>.</p>
          </section>
          <section>
            <header>
              <h3>Syncing Remote Stores</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">The <a href="https://ocaml.org/p/irmin/3.11.0/doc/irmin/Irmin/Sync/index.html">synchronisation mechanisms in Irmin</a> are powerful, but often the API is very confusing. For example, with the git-compatible Unix backend, nested deep in the documentation is the function required to create a <a href="https://ocaml.org/p/irmin-git/latest/doc/irmin-git.unix/Irmin_git_unix/Maker/Make/index.html#val-remote">remote endpoint</a>. Once they have found this function, using it is not easy as it requires them to learn about the <a href="https://ocaml.org/p/mimic/latest"><code>Mimic.ctx</code></a>, which is an abstraction of the networking stack!</p>
          </section>
          <section>
            <header>
              <h3>Do Fewer Things and Do Them Well</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">Irmin is simultaneously a database that supports: content-addressing, merging, key-value lookup, branches, transactions, complete OS portability etc. I think, in short, it tries to do too many things and comes up short on some of them in ways that really matter.</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">When building the <a href="https://github.com/carboncredits/retirement-db">content-addressed database</a> I needed strong guarantees about some atomic actions to perform on the underlying store. For example, <a href="https://github.com/mirage/irmin/issues/2073">setting the value and accessing the commit associated with it</a> which was not possible with the API at that time in an atomic way. This kind of missing functionality is probably only understood after users stumble across it, but it also makes the library feel less focused and ready for production use-cases.</p>
          </section>
        </section>
        <section>
          <header>
            <h2>Documentation</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">It will probably come as no surprise that one of the main limitations of using <a href="https://patrick.sirref.org/irmin/">Irmin</a> is the lack of documentation and tutorials. This is a particular pain point as the API is not very straightforward.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">A while back, I started an <a href="https://patricoferris.github.io/irmin-book/">Irmin book</a> intending to help document the kinds of things real-world users would need in order to use <a href="https://patrick.sirref.org/irmin/">Irmin</a> in earnest. For example: ways to <a href="https://patricoferris.github.io/irmin-book/contents/versioned-data.html">deal with type migrations</a> or <a href="https://patricoferris.github.io/irmin-book/arch/runtime-types.html">primers on runtime types</a>. I still believe this sort of work would be invaluable, but there is a large cost to completing it, and it is not clear if there is enough interest in the project to warrant such an effort.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">The <a href="https://irmin.org/tutorial/introduction/">tutorials on the irmin website</a> are still good starting points for most new users. But they quickly lack the depth for real-world scenarios.</p>
        </section>
        <section>
          <header>
            <h2>Feature Wishlist</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">What follows are additional ideas for improving <a href="https://patrick.sirref.org/irmin/">Irmin</a>.</p>
          <section>
            <header>
              <h3>Heterogeneous Stores</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[For all of [Irmin]'s abstraction and functorisation, there is a very clear]]> missing feature for lots of first-time users of the library: you can only store values of a single type.</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">This leads to a few common workarounds:</p>
            <ul xmlns:html="http://www.w3.org/1999/xhtml">
              <li>
                <p>Storing a serealised version of your values, essentially escaping the type-system and implementing a form of dynamic typing.</p>
              </li>
              <li>
                <p>Growing your value to hold lots of different types via some large variant type.</p>
              </li>
            </ul>
            <p xmlns:html="http://www.w3.org/1999/xhtml">Both of these options are feasible and have been used in practice. However, they are workarounds. A long time ago <a href="https://craigfe.io/">CraigFe</a> created an <a href="https://github.com/mirage/irmin/issues/909">RFC for heterogeneous stores</a>, which I think about a lot. The main idea is to augment <a href="https://patrick.sirref.org/irmin/">Irmin</a> paths (keys) to be GADTs that carry type information about the kinds of values they access (similar to <a href="https://ocaml.org/p/hmap">heterogeneuous variants of other data structures</a>). Something like this alongside a simplified API would make Irmin more appealing as a library for persistent data storage.</p>
          </section>
          <section>
            <header>
              <h3>Real-world Retrospectives</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">This echos some thoughts from the <em>Documentation</em> section. There are some very real-world <a href="https://patrick.sirref.org/irmin/">Irmin</a> use-cases out there. For example, for a long time (I'm not sure if this is still the case) parts of the <a href="https://ocaml.org/p/tezos-context/latest#dependencies">Tezos blockchain were using Irmin</a> which uses the <a href="https://ocaml.org/p/irmin-pack/latest">irmin-pack</a> backend. Does this make irmin-pack the best tested backend and perhaps should be the default backend for new users? Or is it hyper-specific to the Tezos use case? There are <a href="https://tarides.com/blog/2020-09-01-introducing-irmin-pack/">blogs on tarides.com about the irmin-pack backend</a>, but they might be outdated and should not be the first place to find advice on which Irmin backend to use.</p>
          </section>
          <section>
            <header>
              <h3>Active Development and Engagement</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">As far as I know, <a href="https://patrick.sirref.org/irmin/">Irmin</a> was at the forefront of technologies that have come to be described as <a href="https://lofi.so/">local-first</a>. There is a growing interest in this area (particularly as it acts as a counter-argument to an increasingly online, centralised model). I highly recommend reading <a href="https://patrick.sirref.org/ink%20&amp;%20switch's%20essay%20on%20the%20matter/">Ink &amp; Switch's essay on the matter</a>. And it would be great to see more research via <a href="https://patrick.sirref.org/irmin/">Irmin</a> at things like <a href="https://lu.ma/localfirstswunconf-stlouis">the lofi unconference</a> and the <a href="https://2023.splashcon.org/home/plf-2023">PLF workshop at SPLASH 2023</a>!</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">Thank you for reading! And thank you to all the <a href="https://patrick.sirref.org/irmin/">Irmin</a> contributors. I hope this might be useful in the future for building the next-generation <a href="https://patrick.sirref.org/irmin/">Irmin</a>!</p>
          </section>
        </section>
      </div>
    </content>
  </entry>
  <entry>
    <title>Slipshow x x-ocaml</title>
    <published>2025-07-23T00:00:00-00:00</published>
    <updated>2025-07-23T00:00:00-00:00</updated>
    <link rel="alternate" type="text/html" href="https://patrick.sirref.org/slipshow-x-xocaml/" />
    <id>https://patrick.sirref.org/slipshow-x-xocaml/</id>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p xmlns:html="http://www.w3.org/1999/xhtml">A short, explanatory post about combining two very fun pieces of work in OCaml.</p>
        <p xmlns:html="http://www.w3.org/1999/xhtml"><a href="https://github.com/panglesd">Paul-Elliot</a> has been building <a href="https://github.com/panglesd/slipshow">Slipshow</a> for some time now where slides are <em>slips</em> and your presentations run vertically. More recently, <a href="https://patrick.sirref.org/artw/">Arthur</a> has built <a href="https://github.com/art-w/x-ocaml">x-ocaml</a>, a web component library for executable OCaml cells embedded into OCaml.</p>
        <p xmlns:html="http://www.w3.org/1999/xhtml">Using <a href="https://github.com/patricoferris/xocmd">xocmd</a>, a small tool I built for translating markdown codeblocks to x-ocaml components, your Slipshow's can now be <em>executable</em>!</p>
        <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[xocmd learn-effects.md | slipshow compile - > learn-effects.html]]></pre>
        <p xmlns:html="http://www.w3.org/1999/xhtml">
    Take a look at 
    <a href="https://patrick.sirref.org/bafkrmictvc3ap2ah37cbcdoo6rsl7vxqu6srogmgzx6iml45bq7zz5weo4.html">an example</a>!
    (or the 
    <a href="https://patrick.sirref.org/bafkrmib3jugpkznxcftqjvhbbtfqgx4oz2m32p5xloh4nxia3lhxy2momq.md">source markdown</a>).
</p>
        <p xmlns:html="http://www.w3.org/1999/xhtml">I really like this light-weight approach to building interactive presentations for explaining things in OCaml (e.g. over running a jupyter notebook server).</p>
      </div>
    </content>
  </entry>
  <entry>
    <title>Quarterly OCaml Q2</title>
    <published>2025-07-18T00:00:00-00:00</published>
    <updated>2025-07-18T00:00:00-00:00</updated>
    <author>
      <name>https://patrick.sirref.org/Patrick Ferris/</name>
      <uri>https://patrick.sirref.org/Patrick%20Ferris/</uri>
    </author>
    <link rel="alternate" type="text/html" href="https://patrick.sirref.org/ocaml-quarterly-q2/" />
    <id>https://patrick.sirref.org/ocaml-quarterly-q2/</id>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p xmlns:html="http://www.w3.org/1999/xhtml">Thanks to <a href="https://patrick.sirref.org/tarides/">Tarides</a> sponsorship, I get to work on open-source OCaml. This quarterly is a companion to my <a href="https://patrick.sirref.org/weeklies/">weeklies</a>, summarising the last three months of development, peppered with ideas and thoughts about OCaml, its community and its future.</p>
        <section>
          <header>
            <h2>What I wanted to work on?</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">There were two main things I hoped to <em>continue</em> working on: <strong>ppxlib</strong> and <strong>outreachy</strong>. These are projects that I was previously working on, and in the case of Outreachy I have now been involved for many years.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">In addition to this, all of my <a href="https://patrick.sirref.org/part-ii-2024/">Part II</a> projects this year used OCaml in some regard. In general, I want to see more adoption of OCaml. Over the years this has taken many forms including <a href="https://ocaml-explore.netlify.app/">my initial work on developing workflows for OCaml that just turned five years old</a>. This directly fed into the rebranding and rethinking of <a href="https://ocaml.org/">ocaml.org</a> itself.</p>
        </section>
        <section>
          <header>
            <h2>What I worked on?</h2>
          </header>
          <section>
            <header>
              <h3>Ppxlib</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml"><a href="https://patrick.sirref.org/ppxlib/">Ppxlib</a> is the de facto standard library for building OCaml preprocessors. At the time of writing, <code>opam list --depends-on=ppxlib</code> informs me that there are 267 reverse dependencies. <a href="https://www.janestreet.com/">Janestreet</a> is a heavy user of ppxes and has <a href="https://github.com/orgs/janestreet/repositories?language=&amp;amp%3Bq=ppx&amp;amp%3Bsort=&amp;amp%3Btype=all">authored many</a>.</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">One of the main accomplishments this quarter was <a href="https://patrick.sirref.org/ppxlib-5-2/">bumping the internal AST to 5.2</a>. This allows ppx authors to use new OCaml language features in their ppxes. In bumping the AST, we knowingly broke compatability for pretty much every single reverse dependency. As best we can, we have been sending patches to ppx libraries and helping users migrate to the latest <a href="https://patrick.sirref.org/ppxlib/">ppxlib</a>.</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">There is an interesting dicussion to had about the nature of open-source, and its interaction with industrial monorepos and community tended package repositories. Package ecosystems thrive whenever there is a dedicated community creating, maintaining and publishing packages. The idea is that the published world should be healthy. The publishing medium can act as natural limiting factor in the churn of breaking changes (in the case of OCaml this is via <a href="https://github.com/ocaml/opam-repository/">PRs to the opam-repository</a>). This, I have come to notice, reacts poorly to changes coming from internally consistent monorepos where introducing breaking changes is easily fixed by applying patches there and then. Whatsmore, OCaml is often stated as an incredibly safe language to perform large refactorings thanks to its type system.</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml"><a href="https://patrick.sirref.org/ppxlib/">Ppxlib</a> sits awkwardly in the space of possible breaking changes. Tied to OCaml's parsetree, impacts of changes there ripple down to <a href="https://patrick.sirref.org/ppxlib/">ppxlib</a>. The compiler itself can remain internally consistent, and is protected as it need only parse source code. <a href="https://patrick.sirref.org/ppxlib/">Ppxlib</a>, on the other hand, exposes the parsetree to users and thus any changes to the parsetree will likely be felt by ppx authors. Since I started working on <a href="https://patrick.sirref.org/ppxlib/">ppxlib</a>, it feels as though the number of syntax changes has gone up (primarily from Janestreet work). Unless we make changes to how we provide support for these, maintainers of <a href="https://patrick.sirref.org/ppxlib/">ppxlib</a> will forever be stuck doing busy work! Thankfully, <a href="https://patrick.sirref.org/nathanreb/">Nathan</a> <a href="https://patrick.sirref.org/ocaml-weekly-2025-w29/">has thoughts on how to improve this</a>.</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">There are a slew of other features I have added to <a href="https://patrick.sirref.org/ppxlib/">ppxlib</a> including:</p>
            <ul xmlns:html="http://www.w3.org/1999/xhtml">
              <li>
                <p>Support for deriving from classes.</p>
              </li>
              <li>
                <p>Support for deriving from module bindings and signatures.</p>
              </li>
              <li>
                <p>Fixing compiler and ppxlib dummy locations.</p>
              </li>
              <li>
                <p>Bumping to 5.3.</p>
              </li>
              <li>
                <p>Migrations for 5.4.</p>
              </li>
            </ul>
          </section>
          <section>
            <header>
              <h3>Outreachy</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">Our two projects this year, one on <a href="https://github.com/claudiusFX/claudius">claudius</a> and one on <a href="https://github.com/ocaml/dune">dune</a>, are going extremely well. At the time of writing, we just had <a href="https://patrick.sirref.org/ocaml-weekly-2025-w29/">a mid-internship call to catch up</a>, and I was blown away by the progress each intern has made. Unfortunately, <a href="https://patrick.sirref.org/outreachy/">Outreachy</a> is struggling with funding and the next round is perhaps not going to happen. This is a real shame and I am hoping that it will not be the case.</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">Outreachy has been a wonderful source of new, committed OCaml developers. If you haven't already, do peruse the <a href="https://ocaml.org/outreachy">webpage on OCaml.org</a> to see past internships or <a href="https://watch.ocaml.org/c/outreachy_ocaml/videos">watch the demo day presentations</a>. For the mentors involved, I believe it has also been a rewarding experience (though at times a challenging one). We are always looking for new mentors and project ideas, please <a href="https://patrick.sirref.org/patrickferris/">do reach out to me</a> if you are interested.</p>
          </section>
          <section>
            <header>
              <h3>Hazel</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">OCaml's feature set allows it to shine at writing programming languages (and things of that ilk: compilers, interpretters, static analysis tools). <a href="https://patrick.sirref.org/hazel/">Hazel</a> is a research programming language with typed holes written completely in OCaml (via the <a href="https://reasonml.github.io/">reason dialect</a>).</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">Relating this back to the original intent of my work, to improve OCaml adoption, I believe this also means keeping existing users happy. In the last quarter I developed a compiler from <a href="https://patrick.sirref.org/hazel_of_ocaml/">OCaml to Hazel</a>. Whilst new features are still being added to <a href="https://patrick.sirref.org/hazel/">Hazel</a>, I hope this could serve as a tool to help develop test-suites and standard library functions using existing OCaml solutions. In a student's work (<a href="https://patrick.sirref.org/part-ii-hazel/">Typed Debugging for Hazel</a>), we used this tool to build a corpus of ill-typed <a href="https://patrick.sirref.org/hazel/">Hazel</a> programs to great effect.</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">OCaml should continue to be a world-class programming language for building other programming languages. I hope to upstream some of this work to <a href="https://patrick.sirref.org/hazel/">Hazel</a> and provide some low effort maintenance to help keep their compiler in good shape.</p>
          </section>
          <section>
            <header>
              <h3>Systems Programming in OCaml</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">In a cross-over with my own research, I have been developing many tools related to systems programming in OCaml including:</p>
            <ul xmlns:html="http://www.w3.org/1999/xhtml">
              <li>
                <p>An eBPF-based <a href="https://patrick.sirref.org/open-trace/"><code>open</code> syscall tracing tool</a>.</p>
              </li>
              <li>
                <p>A library in OCaml for <a href="https://github.com/quantifyearth/void">spawning void processes</a>.</p>
              </li>
              <li>
                <p>A <a href="https://patrick.sirref.org/shelter/">shell session manager</a> that uses <a href="https://irmin.org/">Irmin</a> to manage sessions. It is nice to see a new push to <a href="https://github.com/mirage/irmin/pull/2149">finally land the direct-style Irmin PR</a>!</p>
              </li>
            </ul>
            <p xmlns:html="http://www.w3.org/1999/xhtml">This work is means to develop the underlying libraries that support it. For example, I have opened a few PRs to <a href="https://github.com/ocaml-multicore/eio">Eio</a> to add new "fork actions" to the spawn API. I also investigated the feasibility of changing the underlying mechanisms in <a href="https://patrick.sirref.org/eio/">Eio</a> to use <a href="https://github.com/ocaml-multicore/picos">Picos</a>. In the future, I think this could be important avoid further splitting the OCaml ecosystem.</p>
            <section>
              <header>
                <h4>OxCaml</h4>
              </header>
              <p xmlns:html="http://www.w3.org/1999/xhtml">I dabbled a little with <a href="https://oxcaml.org/">OxCaml</a> and build <a href="https://patrick.sirref.org/try-oxcaml/">try-oxcaml</a> to let people take it for a spin without having to perform opam repository gymnastics. It turned into a lot of work to track down some pretty inane bugs (type definitions differeing between js_of_ocaml and the OxCaml compiler, resulting in different Javascript runtime representations...).</p>
              <p xmlns:html="http://www.w3.org/1999/xhtml">This unblocked a few of my colleagues to get OxCaml working on tools like <a href="https://jon.recoil.org/notebooks/foundations/foundations1.html">odoc_notebooks</a> and <a href="https://github.com/art-w/x-ocaml">x-ocaml</a>.</p>
            </section>
          </section>
          <section>
            <header>
              <h3>Forester</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">A good proportion of my work this quarter has been focused on how to present the very work that I am doing. <a href="https://patrick.sirref.org/jonmsterling/">Jon Sterling</a> has been developing a tool for scientific thought called <a href="https://patrick.sirref.org/forester/">Forester</a> which seemed like a possible candidate for writing and sharing my work.</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">Porting my existing blog posts and website content from markdown to Forester's LaTeX-inspired syntax didn't seem like an option. In particular, many of my posts made use of additional markdown-based tools (like <a href="https://github.com/realworldocaml/mdx">ocaml-mdx</a>).</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">This lead to the development of <a href="https://patrick.sirref.org/graft/">Graft</a>: a preprocessor for Forester forests, converting markdown and bibtex to trees.</p>
          </section>
        </section>
        <section>
          <header>
            <h2>What's next?</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">So, I worked on most of what I wanted to work on and then some! Going forward I hope to keep maintaining <a href="https://patrick.sirref.org/ppxlib/">ppxlib</a> in some capacity and coordinating the OCaml community's <a href="https://patrick.sirref.org/outreachy/">Outreachy</a> efforts.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">I hope to continue my small experiments (e.g. converting Eio to Picos). My own research makes heavy use of Irmin, and I would be interested to help with that too. More recently, a new library has been released for working with numerical data in OCaml called <a href="https://github.com/raven-ml/">Raven</a>: I am interested to use this library in <a href="https://patrick.sirref.org/geocaml/">Geocaml</a>, a suite of geospatial tools written in OCaml that I maintain.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">I feel conflicted about the <a href="https://patrick.sirref.org/oxcaml/">OxCaml</a> efforts. I admit, I am not fully aware of the full benefits of the features, but I worry about some proliferation of modes that make the type system in OCaml unbearable to use. On top of this, with my <a href="https://patrick.sirref.org/ppxlib/">ppxlib</a> hat on, I worry about the impact of changing the compiler so frequently, placing strain on an already small community. That being said, by releasing <a href="https://patrick.sirref.org/oxcaml/">OxCaml</a> separately I do believe running it as an experimental set of packages will help understand the tool better. But I would not be building anything I intend to maintain or research with right now as that ecosystem is far too volatile.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Finally, over the past two years I have done a lot of teaching. From <a href="https://patrick.sirref.org/part-ii/">Part II projects</a> to <a href="https://patrick.sirref.org/focs/">supervisions</a>. Going into next (academic) year, I intend to reduce my in-person teaching to focus on my research. However, I am interested in producing more materials for learning, maybe some of this in OCaml, perhaps something similar to <a href="https://beautifulracket.com/">Beautiful Racket</a>. I have tried in the past to do these sorts of things, for example <a href="https://patricoferris.github.io/irmin-book/">The Irmin Book</a>.</p>
        </section>
        <section>
          <header>
            <h2>Thank you</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Thank you for reading this wrap up! And thank you again to <a href="https://patrick.sirref.org/tarides/">Tarides</a> for letting me work so freely on things that I think are good for the OCaml community.</p>
        </section>
      </div>
    </content>
  </entry>
  <entry>
    <title>Opentrace</title>
    <published>2025-05-19T00:00:00-00:00</published>
    <updated>2025-05-19T00:00:00-00:00</updated>
    <author>
      <name>https://patrick.sirref.org/Patrick Ferris/</name>
      <uri>https://patrick.sirref.org/Patrick%20Ferris/</uri>
    </author>
    <link rel="alternate" type="text/html" href="https://patrick.sirref.org/open-trace/" />
    <id>https://patrick.sirref.org/open-trace/</id>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p xmlns:html="http://www.w3.org/1999/xhtml">Thanks to <a href="https://github.com/koonwen/">Koonwen's</a> excellent <a href="https://github.com/koonwen/ocaml-libbpf">libbpf bindings in OCaml</a>, I have been building a little tool called <code>opentrace</code> to make it easier to track an executable's inputs and outputs.</p>
        <p xmlns:html="http://www.w3.org/1999/xhtml">This work was inspired my <a href="https://patrick.sirref.org/mdales/">Michael's</a> self-proclaimed "gross hack": <a href="https://github.com/quantifyearth/pyshark">pyshark</a>. Whilst pyshark achieves its goals by injecting code into commonly used python objects and methods, <a href="https://patrick.sirref.org/opentrace/">opentrace</a> uses <a href="https://ebpf.io/">eBPF</a>. By using a lower-level API (hooks in the kernel), <a href="https://patrick.sirref.org/opentrace/">opentrace</a> can remain programming language agnostic. However, less information is none about the user's intent compared to something like pyshark.</p>
        <section>
          <header>
            <h2>Monitoring the System</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml"><a href="https://patrick.sirref.org/opentrace/">opentrace</a> has an <code>all</code> command that will trace the entire system.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[$ sudo opentrace all --flags=O_WRONLY
pid,cgid,comm,kind,flags,mode,filename,return
16324,4417,".nheko-wrapped",openat,577,438,"/home/patrick/.cache/nheko/nheko/curl_alt_svc_cache.txt",47
16324,4417,".nheko-wrapped",openat,193,33188,"/home/patrick/.cache/nheko/nheko/cr3ZUHqBErIOe3PlwJ1SuU8zFKKxL12VzrRoHYMH.tmp",47
16324,4417,".nheko-wrapped",openat,577,438,"/home/patrick/.cache/nheko/nheko/curl_alt_svc_cache.txt",47
16324,4417,".nheko-wrapped",openat,193,33188,"/home/patrick/.cache/nheko/nheko/QfZTdZSuC56NdcDQ3aMxJc3BhMhAj8PmtYW1zFDP.tmp",47
2530,4235,"systemd",openat,524865,438,"/sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/app.slice/gammastep.service/cgroup.subtree_control",41
2530,4235,"systemd",openat,524545,0,"/sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/app.slice/gammastep.service/memory.min",41
2530,4235,"systemd",openat,524545,0,"/sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/app.slice/gammastep.service/memory.low",41
2530,4235,"systemd",openat,524545,0,"/sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/app.slice/gammastep.service/memory.high",41
2530,4235,"systemd",openat,524545,0,"/sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/app.slice/gammastep.service/memory.max",41]]></pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">The <code>--flags=O_WRONLY</code> argument filters the events where the <code>O_WRONLY</code> flag was set in the call to <code>open</code>.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">We also get the name of the current executable linked to the task (<code>comm</code>). The <code>-wrapped</code> is an artefact of using Nix.</p>
        </section>
        <section>
          <header>
            <h2>Tracing an Executable</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">The primary use case for this tool is to inspect what files your program might be reading and writing.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[$ sudo opentrace exec --format=json --flags=O_CREAT -- opam list
$ cat trace.json | jq ".[] | .fname"
"/home/patrick/.opam/cshell/.opam-switch/packages/cache"
"/home/patrick/.opam/log/log-118747-29da3d.out"
"/home/patrick/.opam/log/log-118747-29da3d.err"
"/home/patrick/.opam/log/log-118747-29da3d.env"
"/home/patrick/.opam/log/log-118747-29da3d.info"]]></pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">The "flags" argument can specify a small boolean formula for checking the open flags of a particular event with <code>|</code> (or), <code>&amp;</code> (and), and <code>~</code> (not). Parentheses can be used for precedence.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[$ sudo opentrace exec --flags="O_WRONLY|O_RDONLY" -- ocaml --version]]></pre>
        </section>
        <section>
          <header>
            <h2>Spawning Subprocesses</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">One feature <a href="https://patrick.sirref.org/opentrace/">opentrace</a> needs (in this proof-of-concept phase) is the ability to also trace subprocesses.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml"><a href="https://patrick.sirref.org/opentrace/">opentrace</a> is primarily an eBPF program that is loaded into the kernel and communicates with an OCaml program. Events are communicated via a ring buffer and most of the post-processing happens in OCaml. To capture subprocesses, <a href="https://patrick.sirref.org/opentrace/">opentrace</a> creates a new control group (cgroup) and places the new process into that group. This gives <a href="https://patrick.sirref.org/opentrace/">opentrace</a> a new identifier to track, namely the cgroup.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">So consider the following program.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-keyword-other">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-unit"><![CDATA[()]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-constant-language-capital-identifier">Eio_posix</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">run</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">@@</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other">fun</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">env</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-constant-language-capital-identifier">Eio</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">Path</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source">save</span>
              <span class="ocaml-source"> ~</span>
              <span class="ocaml-source">create</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-polymorphic-variant">`Or_truncate</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-numeric-octal-integer">0o664</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source">env</span>
              <span class="ocaml-keyword-other">#</span>
              <span class="ocaml-source">fs</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">/</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">hello.txt</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">hello</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-constant-language-capital-identifier">Eio</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">Process</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">run</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">env</span>
              <span class="ocaml-keyword-other">#</span>
              <span class="ocaml-source">process_mgr</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">    </span>
              <span class="ocaml-source"><![CDATA[[]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">/bin/bash</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">-c</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">echo 'heya' &gt; heya.txt</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[]]]></span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">It first creates a file using direct calls to functions like <code>openat</code>. Then it spawns a process which creates a new file called <code>heya.txt</code>. This happens in a separate process. However, with the <code>--cgroups</code> flag we can capture both interactions with the operating system.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[$ sudo opentrace exec --cgroups --flags="O_CREAT|O_TRUNC" ./main.exe
pid,cgid,comm,kind,flags,mode,filename,return
153187,530807,"main.exe",openat,526914,436,"hello.txt",5
153192,530807,"bash",openat,577,438,"heya.txt",3]]></pre>
          <section>
            <header>
              <h3>Eio's Process API</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">I have used the <code>Eio_unix</code> <a href="https://ocaml.org/p/eio/latest/doc/Eio_unix/Process/index.html">fork action process API</a> to be able to extend what happens in the child process. Loading most eBPF programs into the kernel requires special privileges hence the need for <code>sudo</code>. When a user requests for a particular program to be executed and traced, <a href="https://patrick.sirref.org/opentrace/">opentrace</a> spawns a process via the Eio Process API. <a href="https://patrick.sirref.org/opentrace/">Opentrace</a> defines a few new so-called "fork actions", little fragments of C code that are run after the call to <code>fork</code> (<code>clone</code>). Most likely this ends with a call to <code>execve</code>, but other calls are possible for example <code>setuid</code> allowing <a href="https://patrick.sirref.org/opentrace/">opentrace</a> to change the user of the child process so it does not run as <code>root</code>. Similarly, this is where (if used) we create the cgroup and place the process into that group.</p>
          </section>
        </section>
        <section>
          <header>
            <h2>Limitations: Io_uring</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Whilst testing <code>opentrace</code> against some of the tools I use nearly daily, I noticed some events were being missed. I tried tracing <a href="https://patrick.sirref.org/forester/">forester</a>, and only the initial read of <code>forest.toml</code> was logged. It dawned on me that the reason for this was that <a href="https://patrick.sirref.org/forester/">forester</a> (via <a href="https://patrick.sirref.org/eio/">eio</a>) was using <a href="https://patrick.sirref.org/io_uring/">io_uring</a> to perform most of the IO. Most attempts to open files were bypassing the open system calls, and instead they were being performed by the kernel after reading a submission request for an <code>openat2</code>-style call!</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">This is not news to seasoned, Linux systems programmers. Io_uring <a href="https://blog.0x74696d.com/posts/iouring-and-seccomp/">bypasses <code>SECCOMP</code> filters</a> for exactly the same reasons.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[$ sudo opentrace exec -- forester build
$ cat trace.csv
pid,cgid,comm,kind,flags,mode,filename,return
155007,535570,"forester",openat,524288,0,"forest.toml",5
155007,535570,"forester",Uring,2621440,0,"",0
155021,535570,"cp",openat,131072,0,"/home/patrick/documents/forest/theme/favicon-32x32.png",4
155007,535570,"forester",Uring,2686976,0,"",0
155007,535570,"iou-wrk-155007",Uring,557634,420,"",0
155007,535570,"iou-wrk-155007",Uring,557634,420,"",0
155007,535570,"iou-wrk-155007",Uring,557634,420,"",0]]></pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">It is interesting to note two things here:</p>
          <ol xmlns:html="http://www.w3.org/1999/xhtml">
            <li>
              <p>We can tell that <a href="https://patrick.sirref.org/forester/">forester</a> reads the configuration file probably using something like <code>In_channel</code> in OCaml (<a href="https://git.sr.ht/~jonsterling/ocaml-forester/tree/7f275290e211db2590b0d715d8fb47fc1de36550/item/lib/frontend/Config.ml#L22">it does</a>).</p>
            </li>
            <li>
              <p>It appears that Uring is performing IO in both worker threads and directly.</p>
            </li>
          </ol>
          <p xmlns:html="http://www.w3.org/1999/xhtml">The file paths are empty at the moment as I cannot find a clean way to trace openat submission requests into Uring without it sometimes going very wrong. I have tried quite a few methods (e.g. tracing <code>do_filp_open</code>) and at the moment I am tracing <code>io_openat2</code>, but this seems quite brittle, and often the filename is completely garbled, so I do not set it. If anyone has any ideas to trace Io_uring more reliably, I am all ears!</p>
        </section>
      </div>
    </content>
  </entry>
  <entry>
    <title>Try OxCaml</title>
    <published>2025-05-09T00:00:00-00:00</published>
    <updated>2025-05-09T00:00:00-00:00</updated>
    <author>
      <name>https://patrick.sirref.org/Patrick Ferris/</name>
      <uri>https://patrick.sirref.org/Patrick%20Ferris/</uri>
    </author>
    <link rel="alternate" type="text/html" href="https://patrick.sirref.org/try-oxcaml/" />
    <id>https://patrick.sirref.org/try-oxcaml/</id>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p xmlns:html="http://www.w3.org/1999/xhtml">This week, I have been trying out Janestreet's <a href="https://blog.janestreet.com/oxidizing-ocaml-locality/">Oxidised OCaml</a> (see their <a href="https://patrick.sirref.org/oxcaml-2024/">ICFP paper</a>). This adds a system of <em>modes</em> to OCaml for expressing things like locality.</p>
        <blockquote xmlns:html="http://www.w3.org/1999/xhtml">
          <p>...we’re introducing a system of modes, which track properties like the locality and uniqueness of OCaml values. Modes allow the compiler to emit better, lower-allocation code, empower users to write safer APIs, and with the advent of multicore, statically guarantee data race freedom—all in a lightweight way that only affects those in need.</p>
        </blockquote>
        <p xmlns:html="http://www.w3.org/1999/xhtml">For example, you might say:</p>
        <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
          <code>
            <span class="ocaml-keyword">let</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-entity-name-function-binding">is_empty</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-source"><![CDATA[(]]></span>
            <span class="ocaml-source">s</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-support-type">string</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-keyword-operator">@@</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-source">local</span>
            <span class="ocaml-source"><![CDATA[)]]></span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-keyword-operator">=</span>
            <span class="ocaml-source">
</span>
            <span class="ocaml-source">  </span>
            <span class="ocaml-constant-language-capital-identifier">String</span>
            <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
            <span class="ocaml-source">length</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-source">s</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-keyword-operator">=</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-constant-numeric-decimal-integer">0</span>
            <span class="ocaml-source">
</span>
          </code>
        </pre>
        <p xmlns:html="http://www.w3.org/1999/xhtml">To get a feel for how this changes the language, you can follow their <a href="https://github.com/janestreet/opam-repository/tree/with-extensions">instructions on their custom opam-repository</a>. Alternatively, you can <a href="https://patrick.sirref.org/oxcaml">give it a go in your browser</a>! This is a full toplevel running with <code>Base</code> installed (which has plenty of OxCaml annotations on Stdlib-like functions).</p>
        <p xmlns:html="http://www.w3.org/1999/xhtml">Happy OxCamling!</p>
      </div>
    </content>
  </entry>
  <entry>
    <title>A Transpiler from OCaml to Hazel</title>
    <published>2025-05-02T00:00:00-00:00</published>
    <updated>2025-05-02T00:00:00-00:00</updated>
    <author>
      <name>https://patrick.sirref.org/Patrick Ferris/</name>
      <uri>https://patrick.sirref.org/Patrick%20Ferris/</uri>
    </author>
    <link rel="alternate" type="text/html" href="https://patrick.sirref.org/hazel-of-ocaml/" />
    <id>https://patrick.sirref.org/hazel-of-ocaml/</id>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p xmlns:html="http://www.w3.org/1999/xhtml">Over the past few months, I have been piecing together a transpiler from <a href="https://patrick.sirref.org/hazel/">Hazel</a> to OCaml. This is, in part, to help one of my third-year undergraduate students who is working on <a href="https://patrick.sirref.org/part-ii-hazel/">type error debugging in Hazel</a>.</p>
        <section>
          <header>
            <h2>Typed Holes</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml"><a href="https://patrick.sirref.org/hazel/">Hazel</a> is a <a href="https://patrick.sirref.org/omar-hazel-2017/">functional programming language with typed holes</a>. Holes are pieces of your program that have not yet been filled in. Holes can appear anywhere in your program both as expression or types. Hazel can still evaluate your program in the presence of holes.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">To get a flavour of Hazel, take a regular map function for lists.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[let map = fun f -> fun xs -> case xs
  | [] => []
  | x :: xs => f (x) :: map(f)(xs) 
end in
map(fun x -> ?)([1, 2, 3])]]></pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">The question mark (<code>?</code>) is a hole. The program evaluates to the following expression of type <code><![CDATA[[?]]]></code> (for people more familiar with OCaml types <code>? list</code>).</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[[ ?, ?, ? ]]]></pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Hazel supports <a href="https://patrick.sirref.org/zhao-typeerror-2024/">local type inference</a> but nothing involving unification variables. For example, a simple <code>add_one</code> function in <a href="https://patrick.sirref.org/hazel/">Hazel</a> (<code>fun x -&gt; x + 1</code>) has type <code>? -&gt; Int</code>.</p>
        </section>
        <section>
          <header>
            <h2>From OCaml to Hazel</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">The ability to transpile OCaml programs to Hazel programs is motivated by one simple thought: there are more OCaml programs than there are Hazel programs. This could help bootstrap projects by alleviating the need to rewrite boilerplate code (e.g. URI parsing or standard library functions for strings).</p>
          <section>
            <header>
              <h3>A Transformation of Syntax</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">Hazel markets itself as an "Elm/ML-like functional programming language". From the previous example of <code>map</code>, it should be apparent just how close to OCaml the language is.</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">It turns out that a majority of the transpiler is a <em>transformation of syntax</em>. Take a simple ADT for an arithmetic programming language.</p>
            <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
              <code>
                <span class="ocaml-keyword-other">type</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">expr</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">  </span>
                <span class="ocaml-keyword-other">|</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-language-capital-identifier">Float</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other">of</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-support-type">float</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">  </span>
                <span class="ocaml-keyword-other">|</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-language-capital-identifier">Add</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other">of</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">expr</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">*</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">expr</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">  </span>
                <span class="ocaml-keyword-other">|</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-language-capital-identifier">Sub</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other">of</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">expr</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">*</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">expr</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">  </span>
                <span class="ocaml-keyword-other">|</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-language-capital-identifier">Mul</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other">of</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">expr</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">*</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">expr</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">  </span>
                <span class="ocaml-keyword-other">|</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-language-capital-identifier">Div</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other">of</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">expr</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">*</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">expr</span>
                <span class="ocaml-source">
</span>
              </code>
            </pre>
            <p xmlns:html="http://www.w3.org/1999/xhtml">And when we run <a href="https://patrick.sirref.org/hazel_of_ocaml/">hazel_of_ocaml</a> over this OCaml type declaration.</p>
            <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[type expr =
  + Float(Float)
  + Add((expr, expr))
  + Sub((expr, expr))
  + Mul((expr, expr))
  + Div((expr, expr))
 in ?]]></pre>
            <p xmlns:html="http://www.w3.org/1999/xhtml">Not much has changed expect some syntax. <a href="https://patrick.sirref.org/hazel/">Hazel</a> does not have a notion of top-level expression so <a href="https://patrick.sirref.org/hazel_of_ocaml/">hazel_of_ocaml</a> wraps the program into one set of value bindings. For the most part, Hazel acts as a subset of the pure, functional part of OCaml. At the time of writing, this subset is fairly limited with no support for modules or labelled records out of the box (there are plenty of development branches with these features).</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">If we try out the same <code>map</code> function but written in OCaml and transpiled to Hazel we get.</p>
            <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
              <code>
                <span class="ocaml-keyword">let</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword">rec </span>
                <span class="ocaml-entity-name-function-binding">map</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">f</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other">function</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">  </span>
                <span class="ocaml-keyword-other">|</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-language-list"><![CDATA[[]]]></span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">-&gt;</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-language-list"><![CDATA[[]]]></span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">  </span>
                <span class="ocaml-keyword-other">|</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">x</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">xs</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">-&gt;</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">f</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">x</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">map</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">f</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">xs</span>
                <span class="ocaml-source">
</span>
              </code>
            </pre>
            <p xmlns:html="http://www.w3.org/1999/xhtml">Which becomes the following hazel program.</p>
            <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[let map = fun f -> fun x1 -> case x1
  | [] => []
  | x :: xs => f(x) :: map(f)(xs)
end in ?]]></pre>
            <p xmlns:html="http://www.w3.org/1999/xhtml">We could have a field day discussing the syntax of OCaml and Hazel (parentheses for function arguments, well-scoped cases for pattern-matching, a different arrow for pattern-matching etc.). What would be more interesting is taking a look at how to handle polymorphism in Hazel.</p>
          </section>
          <section>
            <header>
              <h3>Explicit Polymorphism</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">Hazel has <em>explicit polymorphism</em>. So far, we have not seen it as we have let the types have holes in them. The <code>map</code> function in OCaml has the following type.</p>
            <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
              <code>
                <span class="ocaml-keyword-other">val</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">map</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
                <span class="ocaml-source"> 
</span>
                <span class="ocaml-source">  </span>
                <span class="ocaml-source"><![CDATA[(]]></span>
                <span class="ocaml-storage-type">'a</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">-&gt;</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-storage-type">'b</span>
                <span class="ocaml-source"><![CDATA[)]]></span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">-&gt;</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-storage-type">'a</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">list</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">-&gt;</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-storage-type">'b</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">list</span>
                <span class="ocaml-source">
</span>
              </code>
            </pre>
            <p xmlns:html="http://www.w3.org/1999/xhtml">We must remind ourselves (by reading <a href="https://www.craigfe.io/posts/polymorphic-type-constraints">Craig's excellent blogpost on the matter</a>) that in OCaml</p>
            <blockquote xmlns:html="http://www.w3.org/1999/xhtml">
              <p>... type variables in signatures are implicitly universally-quantified</p>
            </blockquote>
            <p xmlns:html="http://www.w3.org/1999/xhtml">So in reality, we have that <code>map</code> has the following type.</p>
            <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[val map : ∀ a b. (a ->  b) -> a list -> b list]]></pre>
            <p xmlns:html="http://www.w3.org/1999/xhtml">In Hazel, we have to explicitly type our <code>map</code> function to be polymorphic. Not only does this mean the type annotation requires universally quantified type variables, but we must also perform type application wherever we choose to apply the <code>map</code> function (whether that be recursively or somewhere later in our program).</p>
            <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[let map : forall a -> forall b -> (a -> b) -> [a] -> [b] =
  typfun a -> typfun b -> fun f -> fun xs -> case xs
    | [] => []
    | x :: xs => f (x) :: map@<a>@<b>(f)(xs) 
end in
map@<Int>@<Int>(fun x -> ?)([1, 2, 3])]]></pre>
            <p xmlns:html="http://www.w3.org/1999/xhtml"><code>forall</code> introduces a universally quantified type variable into our type annotation, and <code>typfun</code> introduces it into the function itself (à la System F). Type application requires <code>@&lt;T&gt;</code> where <code>T</code> is some type. This allows hazel to quite easily support higher rank polymorphism, but we will not worry too much about that.</p>
          </section>
          <section>
            <header>
              <h3>Propagating OCaml Types into Hazel</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">Most often, OCaml users interact with <em>prenex</em> polymorphism (rank-1) where the universal quantifiers are at the front of the type. <a href="https://ocaml.org/manual/5.2/polymorphism.html#s:higher-rank-poly">OCaml does support quantifiers inside certain types like records</a>.</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">What this means for the transpiler is that we can <strong>reuse OCaml's type inference</strong> to safely instantiate the correct type annotations and type applications in Hazel! To do this, <code>hazel_of_ocaml</code> uses <a href="https://ocaml.github.io/merlin/">Merlin</a> to inspect the type of the function in either a value binding or at the point of a function application.</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">Take a simple, polymorphic <code>length</code> function.</p>
            <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
              <code>
                <span class="ocaml-keyword">let</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword">rec </span>
                <span class="ocaml-entity-name-function-binding">length</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other">function</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other">|</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-language-list"><![CDATA[[]]]></span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">-&gt;</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-integer">0</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other">|</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-language">_</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">xs</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">-&gt;</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-integer">1</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">+</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">length</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">xs</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-keyword">let</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-entity-name-function-binding">int_len</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">length</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[[]]></span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-integer">1</span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-integer">2</span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-integer">3</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[]]]></span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-keyword">let</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-entity-name-function-binding">str_len</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">length</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[[]]></span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-string-quoted-double">"</span>
                <span class="ocaml-string-quoted-double">only</span>
                <span class="ocaml-string-quoted-double">"</span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-string-quoted-double">"</span>
                <span class="ocaml-string-quoted-double">two</span>
                <span class="ocaml-string-quoted-double">"</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[]]]></span>
                <span class="ocaml-source">
</span>
              </code>
            </pre>
            <p xmlns:html="http://www.w3.org/1999/xhtml">When we run this through <code>hazel_of_ocaml</code> with the <code>-type</code> flag we get.</p>
            <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[let length : forall a -> [a] -> Int = typfun a -> fun x1 -> case x1
  | [] => 0
  | _ :: xs => 1 + length@<a>(xs)
end in
let int_len : Int = length@<Int>(1 :: 2 :: [3]) in
let str_len : Int = length@<String>("only" :: ["two"])
in ?]]></pre>
            <p xmlns:html="http://www.w3.org/1999/xhtml"><code>hazel_of_ocaml</code> has correctly instantiated the type for <code>length</code> inside the recursive function and then in each case with the integer list and the string list.</p>
          </section>
        </section>
        <section>
          <header>
            <h2>A Corpus of Hazel Programs</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">The impetus for this work was to derive a corpus of ill-typed Hazel programs. Luckily, such a corpus exists for OCaml! <a href="https://patrick.sirref.org/ocaml-corpus/">Seidel et al.</a> created a corpus of OCaml programs from their undergraduate students at UC San Diego. <a href="https://github.com/patricoferris/hazel-corpus">Some of these programs have been transpiled to Hazel</a>.</p>
        </section>
        <section>
          <header>
            <h2>Future Work</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml"><a href="https://patrick.sirref.org/hazel/">Hazel</a> is a fun, research programming language. Potential third-year students may find it interesting to take this work further. For example, how would this look in terms of a module system? From a purely engineering perspective, plenty of work would be needed to convert a multi-library OCaml project to Hazel (e.g. handling the <code>cmi</code> files).</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Another line of research would be to have Hazel target one of the intermediate representations in OCaml which would give Hazel a fully functioning compiler to "native" code?</p>
        </section>
      </div>
    </content>
  </entry>
  <entry>
    <title>Defunctorising VPNKit</title>
    <published>2025-02-28T00:00:00-00:00</published>
    <updated>2025-02-28T00:00:00-00:00</updated>
    <link rel="alternate" type="text/html" href="https://patrick.sirref.org/vpnkit-upgrade/" />
    <id>https://patrick.sirref.org/vpnkit-upgrade/</id>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p xmlns:html="http://www.w3.org/1999/xhtml"><a href="https://patrick.sirref.org/vpnkit/">VPNKit</a> is a core part of the Docker for Mac/Windows stack. It is tasked with translating network activity from the host to the Linux container.</p>
        <p xmlns:html="http://www.w3.org/1999/xhtml">This short post discusses some of the recent changes to MirageOS and how they impact <a href="https://patrick.sirref.org/vpnkit/">VPNKit</a>.</p>
        <section>
          <header>
            <h2>Dune Virtual Libraries</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Dune, for quite some time, has supported <em>virtual libraries</em>. This allows library authors to define a signature without an implementation (similar to OCaml's <code>module type S = struct ... end</code>). The package is something other dune libraries can build against, still without choosing a particular implementation of the interface. An application author can make the decision about which implementation they would like to build into their program.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">This feature has been quite widely used in OCaml. For example, the <a href="https://github.com/mirage/digestif">excellent <code>digestif</code> library</a> of hashing algorithms provides both C and OCaml implementations individually packaged into <code>digestif.c</code> and <code>digestif.ocaml</code> respectively. Consider developing a browser application that needs some hashing algorithm (e.g. <a href="https://github.com/patricoferris/omditor">Irmin in the browser</a>). We can explicitly use the OCaml backend for digestif which <a href="https://github.com/ocsigen/js_of_ocaml">js_of_ocaml</a> will happily compile for us.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">There are two distinct limitations to this approach.</p>
          <ol xmlns:html="http://www.w3.org/1999/xhtml">
            <li>
              <p>Applications can only link <em>exactly one</em> implementation.</p>
            </li>
            <li>
              <p>Implementations cannot expose additional functionality easily (see <a href="https://github.com/ocaml/dune/issues/5997">dune#5597</a>).</p>
            </li>
          </ol>
        </section>
        <section>
          <header>
            <h2>Functors in MirageOS</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml"><a href="https://mirage.io/">MirageOS</a> is a framework for building unikernels in OCaml. It relies heavily on OCaml's functors to abstract implementation from interface. The mirage tool will then select appropriate instantiations of these functors depending on the backend that is targeted (e.g. <code>unix</code>, <code>hvt</code> etc.)</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Recently, <a href="https://github.com/mirage/mirage-skeleton/pull/407/">there has been a push</a> to use <a href="https://patrick.sirref.org/dune-virt-libs/">dune virtual libraries</a> instead.</p>
        </section>
        <section>
          <header>
            <h2>VPNKit's Fake Clock &amp; Time</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">We need to be able to overcome the limitation that implementations cannot expose additional functionality very easily using dune virtual libraries. As it stands, we need to make Mirage's virtual libraries unwrapped (i.e. set <code>(wrapped false)</code>). This allows implementers to expose additional modules alongside the implementation of the virtual library.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">For VPNkit, we need this to port some of the DNS forwarding tests which use a fake clock and sleep module. Previously, they could be provided directly as functor arguments to the various DNS modules e.g.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">R</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-constant-language-capital-identifier">Dns_forward</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">Resolver</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">Make</span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Proto_client</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Fake</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">Time</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Fake</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">Clock</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">In this new world of <a href="https://patrick.sirref.org/dune-virt-libs/">dune virtual libraries</a>, our <code>Resolver</code> is significantly more simple.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">R</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Dns_forward</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">Resolver</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">Make</span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Proto_client</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">The flexibility of time and clock implementation has been pushed to a build-time decision in a dune file. This means that in order to provide the same fake clock and time we will need to create a private dune library that (a) implements the respective signatures of the virtual libraries and (b) provides the extended interface to allow the test suite to modify the internals of the implementations.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">The first thing I had to do was make the <code>mirage-mtime</code> and <code>mirage-sleep</code> virtual libraries unwrapped. This allowed me to make a new private dune library called <code>fake_time</code> with <em>two</em> public modules: the normal interface required by <code>mirage-mtime</code> and another module called <code>Fake_time_state</code> containing:</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">timeofday</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">ref</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-numeric-decimal-integer">0L</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">c</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Lwt_condition</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">create</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-unit"><![CDATA[()]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">advance</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">nsecs</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-source">timeofday</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Int64</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">add</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">!</span>
              <span class="ocaml-source">timeofday</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">nsecs</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-constant-language-capital-identifier">Lwt_condition</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">broadcast</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">c</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-unit"><![CDATA[()]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">reset</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-unit"><![CDATA[()]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-source">timeofday</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-numeric-decimal-integer">0L</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-constant-language-capital-identifier">Lwt_condition</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">broadcast</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">c</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-unit"><![CDATA[()]]></span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">I did the same for <code>fake_sleep</code> which depended on the state from the <code>fake_time</code> library (something a normal library wouldn't).</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Once I had the implementations for the virtual libraries in place, all that remained was to tell the executable (in this case the test suite) to select these new implementations instead of the defaults. Whereas before, all the tests could live in the same test suite, now they had to be split into those that needed the fake implementation and those that did not. This is another slight limitation of this virtual library approach. You can only link one implementation at a time to an executable (or test). Thus, the dune rules for running the <code>dns_forward</code> test suite became:</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="dune-comment-line">; Uses the default  implementations provided by virtual libraries</span>
              <span class="dune-source">
</span>
              <span class="dune-meta-stanza"><![CDATA[(]]></span>
              <span class="dune-meta-class-stanza">executable</span>
              <span class="dune-meta-stanza">
</span>
              <span class="dune-meta-stanza"> </span>
              <span class="dune-meta-stanza-library-field"><![CDATA[(]]></span>
              <span class="dune-keyword-other">name</span>
              <span class="dune-meta-stanza-library-field"> </span>
              <span class="dune-meta-atom">test</span>
              <span class="dune-meta-stanza-library-field"><![CDATA[)]]></span>
              <span class="dune-meta-stanza">
</span>
              <span class="dune-meta-stanza"> </span>
              <span class="dune-meta-stanza-lib-or-exec-buildable"><![CDATA[(]]></span>
              <span class="dune-keyword-other">libraries</span>
              <span class="dune-meta-stanza-lib-or-exec-buildable"> </span>
              <span class="dune-meta-atom">dns_forward</span>
              <span class="dune-meta-stanza-lib-or-exec-buildable"> </span>
              <span class="dune-meta-atom">alcotest</span>
              <span class="dune-meta-stanza-lib-or-exec-buildable"><![CDATA[)]]></span>
              <span class="dune-meta-stanza"><![CDATA[)]]></span>
              <span class="dune-source">
</span>
              <span class="dune-source">
</span>
              <span class="dune-comment-line">; Override the defaults and select the private fake libraries</span>
              <span class="dune-source">
</span>
              <span class="dune-meta-stanza"><![CDATA[(]]></span>
              <span class="dune-meta-class-stanza">executable</span>
              <span class="dune-meta-stanza">
</span>
              <span class="dune-meta-stanza">  </span>
              <span class="dune-meta-stanza-library-field"><![CDATA[(]]></span>
              <span class="dune-keyword-other">name</span>
              <span class="dune-meta-stanza-library-field"> </span>
              <span class="dune-meta-atom">test_fake</span>
              <span class="dune-meta-stanza-library-field"><![CDATA[)]]></span>
              <span class="dune-meta-stanza">
</span>
              <span class="dune-meta-stanza">  </span>
              <span class="dune-meta-stanza-lib-or-exec-buildable"><![CDATA[(]]></span>
              <span class="dune-keyword-other">libraries</span>
              <span class="dune-meta-stanza-lib-or-exec-buildable"> </span>
              <span class="dune-meta-atom">dns_forward</span>
              <span class="dune-meta-stanza-lib-or-exec-buildable"> </span>
              <span class="dune-meta-atom">alcotest</span>
              <span class="dune-meta-stanza-lib-or-exec-buildable"> </span>
              <span class="dune-meta-atom">fake_sleep</span>
              <span class="dune-meta-stanza-lib-or-exec-buildable"> </span>
              <span class="dune-meta-atom">fake_time</span>
              <span class="dune-meta-stanza-lib-or-exec-buildable"><![CDATA[)]]></span>
              <span class="dune-meta-stanza"><![CDATA[)]]></span>
              <span class="dune-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">With all of this machinery in place, I could now update <code>test_fake</code> to use the new modules that would provide the custom functionality for the clock and time implementations.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-comment-block"><![CDATA[(*]]></span>
              <span class="ocaml-comment-block"> The bad server should be marked offline and no-one will wait for it </span>
              <span class="ocaml-comment-block"><![CDATA[*)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-constant-language-capital-identifier">Fake_time_state</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">reset</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-unit"><![CDATA[()]]></span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-comment-block"><![CDATA[(*]]></span>
              <span class="ocaml-comment-block"> avoid the timeouts winning the race with the actual result </span>
              <span class="ocaml-comment-block"><![CDATA[*)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-constant-language-capital-identifier">Fake_time_state</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">advance</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Duration</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source">of_ms</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-numeric-decimal-integer">500</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source"> 
</span>
            </code>
          </pre>
        </section>
        <section>
          <header>
            <h2>Conclusion</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">The switch to <a href="https://patrick.sirref.org/dune-virt-libs/">dune virtual libraries</a> seems to be a good one. A majority of applications only require a single clock or time implementation. However, it has become harder to inject custom implementations of various resources into your MirageOS-based applications.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">The <a href="https://github.com/moby/vpnkit/pull/646">pull request to upgrade VPNKit is open</a>.</p>
        </section>
      </div>
    </content>
  </entry>
  <entry>
    <title>Bumping Ppxlib's AST to 5.2</title>
    <published>2025-02-18T00:00:00-00:00</published>
    <updated>2025-02-18T00:00:00-00:00</updated>
    <link rel="alternate" type="text/html" href="https://patrick.sirref.org/ppxlib-5-2/" />
    <id>https://patrick.sirref.org/ppxlib-5-2/</id>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p xmlns:html="http://www.w3.org/1999/xhtml"><a href="https://patrick.sirref.org/ppxlib/">Ppxlib</a> is a libary for building OCaml preprocessors. Users can generate OCaml code <em>from</em> OCaml code (derivers) or replace parts of OCaml code with other OCaml code (rewriters).</p>
        <p xmlns:html="http://www.w3.org/1999/xhtml">At the core of <a href="https://patrick.sirref.org/ppxlib/">ppxlib</a> is the OCaml parsetree; a data structure in the compiler that represents OCaml source code. <a href="https://patrick.sirref.org/ppxlib/">Ppxlib</a> makes a distinction between the source parsetree (based on the version of the OCaml compiler you are using) and <a href="https://patrick.sirref.org/ppxlib/">ppxlib</a>'s parsetree (a copy of <em>some</em> parsetree from the compiler).</p>
        <p xmlns:html="http://www.w3.org/1999/xhtml">In <a href="https://discuss.ocaml.org/t/ann-ppxlib-0-36-0">ppxlib.0.36.0</a>, the internal AST was bumped from the AST of OCaml 4.14.0, to the AST of OCaml 5.2.0. This post discusses some of the internal mechanisms that allows ppxlib to support multiple compilers and how this bump broke a lot of backwards compatibility.</p>
        <section>
          <header>
            <h2>Manual Migrations in Ppxlib</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">It is possible to perform migrations between parsetrees manually using the <code>ppxlib.ast</code> package.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-keyword-other">open</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Ppxlib</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-other">open</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Ast_builder</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">Make</span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-other">struct</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">loc</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Location</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">none</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other">end</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">pp_expr</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Format</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">printf</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-constant-character-printf"><![CDATA[%a]]></span>
              <span class="ocaml-constant-character-printf"><![CDATA[%!]]></span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Pp_ast</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source">expression</span>
              <span class="ocaml-source"> ?</span>
              <span class="ocaml-source">config</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-constant-language-capital-identifier">None</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">loc</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Location</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">none</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">str</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">txt</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[{]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">txt</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">loc</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[}]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">To_408</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> 
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-constant-language-capital-identifier">Ppxlib_ast</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">Convert</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Ppxlib_ast</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">Js</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Ppxlib_ast__</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">Versions</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">OCaml_408</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">The <code>Ppxlib_ast.Js</code> module is <a href="https://patrick.sirref.org/ppxlib/">ppxlib</a>'s AST (since <code>ppxlib.0.36.0</code> OCaml 5.2.0). We can use functions provided by the <code>Convert</code> functor to copy parts of the AST from one version to another. Usually there is very little difference between the versioned parsetrees.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">func</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">arg</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">body</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-source">pexp_fun</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Nolabel</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">None</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source">ppat_var</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source">str</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">arg</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">body</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">add_expr</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">func</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">x</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source">func</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">y</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source">eapply</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source">evar</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">Int.add</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[[]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">evar</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">x</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">evar</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">y</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[]]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">The above excerpt of OCaml code produces an expression in the language. More accurately, a function that has two arguments. If we print the simplified AST we can see that the arguments are stored together in a list.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-mdx-hash">#</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">pp_expr</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">add_expr</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source"> 
</span>
              <span class="ocaml-constant-language-capital-identifier">Pexp_function</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[[]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[{]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">pparam_loc</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">__loc</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">      </span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">pparam_desc</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Pparam_val</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Nolabel</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">None</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Ppat_var</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">x</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">      </span>
              <span class="ocaml-source"><![CDATA[}]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">    </span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[{]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">pparam_loc</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">__loc</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">      </span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">pparam_desc</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Pparam_val</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Nolabel</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">None</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Ppat_var</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">y</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">      </span>
              <span class="ocaml-source"><![CDATA[}]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">    </span>
              <span class="ocaml-source"><![CDATA[]]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">None</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Pfunction_body</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">      </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Pexp_apply</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">         </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Pexp_ident</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Ldot</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Lident</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">Int</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">add</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">         </span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[[]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Nolabel</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Pexp_ident</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Lident</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">x</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">           </span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Nolabel</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Pexp_ident</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Lident</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">y</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">           </span>
              <span class="ocaml-source"><![CDATA[]]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">         </span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-operator">-</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-support-type">unit</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-unit"><![CDATA[()]]></span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">This is a relatively new feature of the parsetree, if we migrate the expression down to <code>4.08</code> we see it is represented differently. The output is a little too verbose to be readable, and there's no good way to show the AST, so you will just have to take my word.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">expr_408</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">To_408</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">copy_expression</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">add_expr</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
        </section>
        <section>
          <header>
            <h2>Function Arity in the OCaml Parsetree</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">OCaml 5.2 introduced a new way to represent functions. Before 5.2, all functions were represented with single arity. Functions with multiple arguments would return functions as their body. For example:</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">add</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">x</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">y</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">x</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">+</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">y</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">A two-argument <code>add</code> function would be represented in the parsetree as <code>fun x -&gt; fun y -&gt; x + y</code>. Using the nodes from the parsetree (with some details removed) it would be <code>Pexp_fun (x, Pexp_fun (y, Pexp_apply ...))</code>.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Now, since OCaml 5.2, functions can be expressed with their syntactic arity intact. The function <code>add</code> would look something like <code><![CDATA[Pexp_function ([ x; y ], Pfunction_body (Pexp_apply ...))]]></code>. Both arguments are stored as a list.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">The constructor <code>Pexp_function</code> was not a new addition to the parsetree. It used to represent pattern-matching expressions like <code>function A -&gt; 1</code>. This can now be expressed as a function body of <code>Pfunction_cases</code>.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Whilst these additions and modifications to the parsetree are arguably a better design, it has caused chaos in terms of <a href="https://patrick.sirref.org/ppxlib/">ppxlib</a>'s reverse dependencies!</p>
        </section>
        <section>
          <header>
            <h2>Coalescing Function Arguments</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">In <a href="https://patrick.sirref.org/ppxlib/">ppxlib</a> <code>0.36.0</code>, functions from <code>Ast_builder</code> will help ppx authors produce maximum arity functions. However, functions from <code>Ast_helper</code> will not do this.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">ast_helper_func</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">arg</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">body</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-constant-language-capital-identifier">Ast_helper</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">Exp</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">fun_</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Nolabel</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">None</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source">ppat_var</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source">str</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">arg</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">body</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">ast_helper_expr</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">ast_helper_func</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">x</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source">ast_helper_func</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">y</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source">eapply</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source">evar</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">Int.equal</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[[]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">evar</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">x</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">evar</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">y</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[]]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Here we recreate our helper function to create function expressions using <code>Ast_helper.Exp.fun_</code> instead. We can now show the difference between the <code>expr</code> expression and the <code>ast_helper_expr</code> expression.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-mdx-hash">#</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">pp_expr</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">add_expr</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-constant-language-capital-identifier">Pexp_function</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[[]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[{]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">pparam_loc</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">__loc</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">      </span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">pparam_desc</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Pparam_val</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Nolabel</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">None</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Ppat_var</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">x</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">      </span>
              <span class="ocaml-source"><![CDATA[}]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">    </span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[{]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">pparam_loc</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">__loc</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">      </span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">pparam_desc</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Pparam_val</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Nolabel</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">None</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Ppat_var</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">y</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">      </span>
              <span class="ocaml-source"><![CDATA[}]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">    </span>
              <span class="ocaml-source"><![CDATA[]]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">None</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Pfunction_body</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">      </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Pexp_apply</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">         </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Pexp_ident</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Ldot</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Lident</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">Int</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">add</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">         </span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[[]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Nolabel</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Pexp_ident</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Lident</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">x</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">           </span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Nolabel</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Pexp_ident</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Lident</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">y</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">           </span>
              <span class="ocaml-source"><![CDATA[]]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">         </span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-operator">-</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-support-type">unit</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-unit"><![CDATA[()]]></span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Above, we see a function expression with arity <em>two</em>. Below, we see nested function expressions each with arity <em>one</em>.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-mdx-hash">#</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">pp_expr</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">ast_helper_expr</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-constant-language-capital-identifier">Pexp_function</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[[]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[{]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">pparam_loc</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">__loc</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">      </span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">pparam_desc</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Pparam_val</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Nolabel</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">None</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Ppat_var</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">x</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">      </span>
              <span class="ocaml-source"><![CDATA[}]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">    </span>
              <span class="ocaml-source"><![CDATA[]]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">None</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Pfunction_body</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">      </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Pexp_function</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">         </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[[]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[{]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">pparam_loc</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">__loc</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">             </span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">pparam_desc</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Pparam_val</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Nolabel</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">None</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Ppat_var</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">y</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">             </span>
              <span class="ocaml-source"><![CDATA[}]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">           </span>
              <span class="ocaml-source"><![CDATA[]]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">         </span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">None</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">         </span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Pfunction_body</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">             </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Pexp_apply</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">                </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Pexp_ident</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Ldot</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Lident</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">Int</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">equal</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">                </span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[[]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Nolabel</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Pexp_ident</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Lident</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">x</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">                  </span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Nolabel</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Pexp_ident</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Lident</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">y</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">                  </span>
              <span class="ocaml-source"><![CDATA[]]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">                </span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">         </span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-operator">-</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-support-type">unit</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-unit"><![CDATA[()]]></span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
        </section>
        <section>
          <header>
            <h2>Ramifications for Ppxlib Users</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Many, many, <em>many</em> ppxes broke after migrating the <a href="https://patrick.sirref.org/ppxlib/">ppxlib</a> AST to 5.2. Mostly, this is due to pattern-matching. Downstream users of <a href="https://patrick.sirref.org/ppxlib/">ppxlib</a> frequently pattern-match directly against the parsetree. However, nodes such as <code>Pexp_fun</code> no longer exist and <code>Pexp_function</code> has completely different constructor arguments!</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Patching all the ppxes has been quite difficult. Most ppxes only deal with single arguments at a time (e.g. <code>Pexp_fun x</code>) but now they must handle zero or more arguments at a time. (In the zero case, this will always correspond to a pattern-matching <code>function</code>).</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Here is a non-exhaustive list of some of the ppxes that have been patched. It may useful for other ppx authors who wish to upgrade to <code>ppxlib.0.36.0</code>:</p>
          <ul xmlns:html="http://www.w3.org/1999/xhtml">
            <li>
              <p>
                <a href="https://github.com/patricoferris/ppx_deriving_yaml/pull/58">https://github.com/patricoferris/ppx_deriving_yaml/pull/58</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://github.com/mirage/ocaml-rpc/pull/181">https://github.com/mirage/ocaml-rpc/pull/181</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://gitlab.com/o-labs/ppx_deriving_jsoo/-/merge_requests/1">https://gitlab.com/o-labs/ppx_deriving_jsoo/-/merge_requests/1</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://github.com/ocaml-community/sedlex/pull/160">https://github.com/ocaml-community/sedlex/pull/160</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://github.com/ocaml-sys/config.ml/pull/22">https://github.com/ocaml-sys/config.ml/pull/22</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://github.com/vogler/ppx_distr_guards/pull/2">https://github.com/vogler/ppx_distr_guards/pull/2</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://github.com/ocaml-gospel/gospel/pull/424">https://github.com/ocaml-gospel/gospel/pull/424</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://github.com/teamwalnut/graphql-ppx/pull/299">https://github.com/teamwalnut/graphql-ppx/pull/299</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://github.com/ocsigen/lwt/pull/1033">https://github.com/ocsigen/lwt/pull/1033</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://gitlab.com/gopiandcode/ppx-inline-alcotest/-/merge_requests/3">https://gitlab.com/gopiandcode/ppx-inline-alcotest/-/merge_requests/3</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://github.com/dariusf/ppx_interact/pull/3">https://github.com/dariusf/ppx_interact/pull/3</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://github.com/ocaml-ppx/ppx_deriving_yojson/pull/160">https://github.com/ocaml-ppx/ppx_deriving_yojson/pull/160</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://github.com/lpcic/elpi/pull/276">https://github.com/LPCIC/elpi/pull/276</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://github.com/mirage/repr/pull/110">https://github.com/mirage/repr/pull/110</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://github.com/programingisthefuture/ppx_default/pull/3">https://github.com/ProgramingIsTheFuture/ppx_default/pull/3</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://github.com/codinuum/vlt/pull/3">https://github.com/codinuum/vlt/pull/3</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://github.com/sim642/ppx_deriving_hash/pull/6">https://github.com/sim642/ppx_deriving_hash/pull/6</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://github.com/ocsigen/tyxml/pull/340">https://github.com/ocsigen/tyxml/pull/340</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://github.com/sim642/ppx_viewpattern/pull/2">https://github.com/sim642/ppx_viewpattern/pull/2</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://github.com/little-arhat/ppx_jsobject_conv/pull/11">https://github.com/little-arhat/ppx_jsobject_conv/pull/11</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://github.com/robur-coop/lun/pull/1">https://github.com/robur-coop/lun/pull/1</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://gitlab.com/o-labs/ppx_deriving_encoding/-/merge_requests/4">https://gitlab.com/o-labs/ppx_deriving_encoding/-/merge_requests/4</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://github.com/francoisthire/bam/pull/12">https://github.com/francoisthire/bam/pull/12</a>
              </p>
            </li>
            <li>
              <p>
                <a href="https://github.com/xguerin/bitstring/pull/36">https://github.com/xguerin/bitstring/pull/36</a>
              </p>
            </li>
          </ul>
          <p xmlns:html="http://www.w3.org/1999/xhtml">This release has emphasised the tension between using pattern-matching on algebraic datatypes and wanting to reduce downstream breakages (e.g. using abstract datatypes). This <a href="https://www.cambridge.org/core/journals/journal-of-functional-programming/article/pattern-matching-with-abstract-data-types1/04DD26A0E6CA3A1E87E0E6AE8BC02EED">tension is not new</a>.</p>
        </section>
        <section>
          <header>
            <h2>The Future of Ppxlib</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml"><a href="https://patrick.sirref.org/ppxlib/">Ppxlib</a> is not going anywhere anytime soon. We have committed to trying to keep the internal AST up to date with the latest OCaml release. In fact, there is already a PR for <a href="https://github.com/ocaml-ppx/ppxlib/pull/558">the 5.3 bump</a>!</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">There have been many discussions about simplifying this process, but so far the time and effort to build a <a href="https://patrick.sirref.org/ppxlib/">ppxlib</a> that will result in fewer breakages is too high (see <a href="https://github.com/ocaml-ppx/ppx">an attempt using views</a>).</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Thank you to Tarides and Jane Street for funding my time to work on this release and all the chaos it has caused.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Happy preprocessing!</p>
        </section>
      </div>
    </content>
  </entry>
  <entry>
    <title>Reviving OCaml R-Tree</title>
    <published>2023-08-09T00:00:00-00:00</published>
    <updated>2023-08-09T00:00:00-00:00</updated>
    <author>
      <name>https://patrick.sirref.org/Patrick Ferris/</name>
      <uri>https://patrick.sirref.org/Patrick%20Ferris/</uri>
    </author>
    <link rel="alternate" type="text/html" href="https://patrick.sirref.org/ocaml-rtree/" />
    <id>https://patrick.sirref.org/ocaml-rtree/</id>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p xmlns:html="http://www.w3.org/1999/xhtml">Antonin Guttman <a href="http://www-db.deis.unibo.it/courses/SI-LS/papers/Gut84.pdf">first proposed R-Trees in 1984</a>.</p>
        <blockquote xmlns:html="http://www.w3.org/1999/xhtml">
          <p>In order to handle spatial data efficiently, as required in computer aided design and geo-data applications, a database system needs an index mechanism that will help it retrieve data items quickly according to their spatial locations...</p>
        </blockquote>
        <p xmlns:html="http://www.w3.org/1999/xhtml">There are lots of excellent resources for understanding more about R-Trees and all of the wonderful variations there of (e.g. <a href="http://www.cs.ucr.edu/~ravi/CS236Papers/rstar.pdf">R*-trees</a>). This <a href="https://www.bartoszsypytkowski.com/r-tree/">blog post</a> seems to be the most popular introduction.</p>
        <section>
          <header>
            <h2>An OCaml Rtree Implementation</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">In the <a href="https://www.cst.cam.ac.uk/research/eeg">Energy and Environment Group</a> we are working on various geospatial tools, one of which is written in OCaml and needed a geospatial index to speedup spatial queries over a dataset. Searching Github revealed <a href="https://github.com/mariusae/ocaml-rtree">an implementation in pure OCaml</a>. After reaching out to the author, they were more than happy for their work to be maintained in the <a href="https://github.com/geocaml">Geocaml organisation</a>, updated to the latest OCaml tools and <a href="https://github.com/ocaml/opam-repository/pull/24227">hopefully released on opam</a>.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">The <a href="https://github.com/geocaml/ocaml-rtree/commit/073d79ad34de15f0671f2faafb24b1edc5c2d8c7">dunification</a> went smoothly whilst fast-forwarding 15 OCaml compiler versions with no changes or problems (just dune unused variable warnings).</p>
        </section>
        <section>
          <header>
            <h2>OCaml Rtree Examples</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">An R-Tree in OCaml is created from an envelope (the kind of bounding box) and a value (for storing in the tree). The value depends on the envelope as you have to provide a function to calculate an envelope from a value. Here is one way we might define a line using the provided two-dimensional <code>Rectangle</code> envelope.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Line</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other">struct</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-keyword-other">type</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">t</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">    </span>
              <span class="ocaml-source"><![CDATA[{]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">p0</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-support-type">float</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">*</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-support-type">float</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">p1</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-support-type">float</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">*</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-support-type">float</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[}]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">t</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">    </span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword">open</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Repr</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other">in</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">    </span>
              <span class="ocaml-source">record</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">line</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-other">fun</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">p0</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">p1</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[{]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">p0</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">p1</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[}]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">    </span>
              <span class="ocaml-keyword-operator">|+</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">field</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">p0</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source">pair</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-support-type">float</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-support-type">float</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-other">fun</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">t</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">t</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">p0</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">    </span>
              <span class="ocaml-keyword-operator">|+</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">field</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">p1</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source">pair</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-support-type">float</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-support-type">float</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-other">fun</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">t</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">t</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">p1</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">    </span>
              <span class="ocaml-keyword-operator">|&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">sealr</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-keyword-other">type</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">envelope</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Rtree</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">Rectangle</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">t</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">envelope</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[{]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">p0</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source">x1</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">y1</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">p1</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source">x2</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">y2</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[}]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">    </span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">x0</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Float</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">min</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">x1</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">x2</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other">in</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">    </span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">x1</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Float</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">max</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">x1</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">x2</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other">in</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">    </span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">y0</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Float</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">min</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">y1</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">y2</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other">in</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">    </span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">y1</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Float</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">max</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">y1</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">y2</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other">in</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">    </span>
              <span class="ocaml-constant-language-capital-identifier">Rtree</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">Rectangle</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">v</span>
              <span class="ocaml-source"> ~</span>
              <span class="ocaml-source">x0</span>
              <span class="ocaml-source"> ~</span>
              <span class="ocaml-source">y0</span>
              <span class="ocaml-source"> ~</span>
              <span class="ocaml-source">x1</span>
              <span class="ocaml-source"> ~</span>
              <span class="ocaml-source">y1</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-other">end</span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">In addition to the <code>envelope</code> function, we also need to provide a runtime representation using <code>Repr</code>. In the example, we've constructed it by hand but I recommend using <a href="https://ocaml.org/p/ppx_repr/latest">ppx_repr</a> to derive it for you. From here we can create our index.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">R</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Rtree</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">Make</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Rtree</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">Rectangle</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Line</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <section>
            <header>
              <h3>Inserting Values</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">There are two ways to insert values into the index -- either by inserting them one-by-one or by bulk loading them. The latter is the recommended approach where possible as the resulting layout of the R-Tree is much better.</p>
            <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
              <code>
                <span class="ocaml-mdx-hash">#</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword">let</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-entity-name-function-binding">r</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">    </span>
                <span class="ocaml-keyword">let</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-entity-name-function-binding">i</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-language-capital-identifier">R</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
                <span class="ocaml-source">empty</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-integer">4</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other">in</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">    </span>
                <span class="ocaml-constant-language-capital-identifier">R</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
                <span class="ocaml-source">insert</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">i</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-language-capital-identifier">Line</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
                <span class="ocaml-source"><![CDATA[{]]></span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">p0</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[(]]></span>
                <span class="ocaml-constant-numeric-decimal-float">1.</span>
                <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-float">1.</span>
                <span class="ocaml-source"><![CDATA[)]]></span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">p1</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[(]]></span>
                <span class="ocaml-constant-numeric-decimal-float">2.</span>
                <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-float">2.</span>
                <span class="ocaml-source"><![CDATA[)]]></span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[}]]></span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-keyword-other">val</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">r</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-language-capital-identifier">R</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
                <span class="ocaml-source">t</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">&lt;</span>
                <span class="ocaml-source">abstr</span>
                <span class="ocaml-keyword-operator">&gt;</span>
                <span class="ocaml-source">
</span>
              </code>
            </pre>
            <p xmlns:html="http://www.w3.org/1999/xhtml">As you might expect, bulk loading takes a list of values instead.</p>
            <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
              <code>
                <span class="ocaml-mdx-hash">#</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword">let</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-entity-name-function-binding">r</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">    </span>
                <span class="ocaml-keyword">let</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-entity-name-function-binding">lines</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">        </span>
                <span class="ocaml-constant-language-capital-identifier">Line</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
                <span class="ocaml-source"><![CDATA[[]]></span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">        </span>
                <span class="ocaml-source"><![CDATA[{]]></span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">p0</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[(]]></span>
                <span class="ocaml-constant-numeric-decimal-float">0.</span>
                <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-float">0.</span>
                <span class="ocaml-source"><![CDATA[)]]></span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">p1</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[(]]></span>
                <span class="ocaml-constant-numeric-decimal-float">1.</span>
                <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-float">1.</span>
                <span class="ocaml-source"><![CDATA[)]]></span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[}]]></span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">        </span>
                <span class="ocaml-source"><![CDATA[{]]></span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">p0</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[(]]></span>
                <span class="ocaml-constant-numeric-decimal-float">1.</span>
                <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-float">1.</span>
                <span class="ocaml-source"><![CDATA[)]]></span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">p1</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[(]]></span>
                <span class="ocaml-constant-numeric-decimal-float">2.</span>
                <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-float">2.</span>
                <span class="ocaml-source"><![CDATA[)]]></span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[}]]></span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">        </span>
                <span class="ocaml-source"><![CDATA[{]]></span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">p0</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[(]]></span>
                <span class="ocaml-constant-numeric-decimal-float">2.</span>
                <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-float">2.</span>
                <span class="ocaml-source"><![CDATA[)]]></span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">p1</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[(]]></span>
                <span class="ocaml-constant-numeric-decimal-float">3.</span>
                <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-float">3.</span>
                <span class="ocaml-source"><![CDATA[)]]></span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[}]]></span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">        </span>
                <span class="ocaml-source"><![CDATA[{]]></span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">p0</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[(]]></span>
                <span class="ocaml-constant-numeric-decimal-float">3.</span>
                <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-float">3.</span>
                <span class="ocaml-source"><![CDATA[)]]></span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">p1</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[(]]></span>
                <span class="ocaml-constant-numeric-decimal-float">4.</span>
                <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-float">4.</span>
                <span class="ocaml-source"><![CDATA[)]]></span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[}]]></span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">        </span>
                <span class="ocaml-source"><![CDATA[]]]></span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">    </span>
                <span class="ocaml-keyword-other">in</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source">    </span>
                <span class="ocaml-constant-language-capital-identifier">R</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
                <span class="ocaml-source">load</span>
                <span class="ocaml-source"> ~</span>
                <span class="ocaml-source">max_node_load</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
                <span class="ocaml-constant-numeric-decimal-integer">4</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">lines</span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-keyword-other">val</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">r</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-language-capital-identifier">R</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
                <span class="ocaml-source">t</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">&lt;</span>
                <span class="ocaml-source">abstr</span>
                <span class="ocaml-keyword-operator">&gt;</span>
                <span class="ocaml-source">
</span>
              </code>
            </pre>
          </section>
          <section>
            <header>
              <h3>Spatial Queries</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">The lines we loaded into the last index are really just four segments of the line <code>y = x</code>. Let's spatially query for the first two segments.</p>
            <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
              <code>
                <span class="ocaml-mdx-hash">#</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-language-capital-identifier">R</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
                <span class="ocaml-source">find</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">r</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[(]]></span>
                <span class="ocaml-constant-language-capital-identifier">Rtree</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
                <span class="ocaml-constant-language-capital-identifier">Rectangle</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
                <span class="ocaml-source">v</span>
                <span class="ocaml-source"> ~</span>
                <span class="ocaml-source">x0</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
                <span class="ocaml-constant-numeric-decimal-float">0.</span>
                <span class="ocaml-source"> ~</span>
                <span class="ocaml-source">y0</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
                <span class="ocaml-constant-numeric-decimal-float">0.</span>
                <span class="ocaml-source"> ~</span>
                <span class="ocaml-source">x1</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
                <span class="ocaml-constant-numeric-decimal-float">2.</span>
                <span class="ocaml-source"> ~</span>
                <span class="ocaml-source">y1</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
                <span class="ocaml-constant-numeric-decimal-float">2.</span>
                <span class="ocaml-source"><![CDATA[)]]></span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-keyword-operator">-</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-language-capital-identifier">Line</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
                <span class="ocaml-source">t</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">list</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source"><![CDATA[[]]></span>
                <span class="ocaml-source"><![CDATA[{]]></span>
                <span class="ocaml-constant-language-capital-identifier">Line</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
                <span class="ocaml-source">p0</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[(]]></span>
                <span class="ocaml-constant-numeric-decimal-float">0.</span>
                <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-float">0.</span>
                <span class="ocaml-source"><![CDATA[)]]></span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">p1</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[(]]></span>
                <span class="ocaml-constant-numeric-decimal-float">1.</span>
                <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-float">1.</span>
                <span class="ocaml-source"><![CDATA[)]]></span>
                <span class="ocaml-source"><![CDATA[}]]></span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[{]]></span>
                <span class="ocaml-constant-language-capital-identifier">Line</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
                <span class="ocaml-source">p0</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[(]]></span>
                <span class="ocaml-constant-numeric-decimal-float">1.</span>
                <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-float">1.</span>
                <span class="ocaml-source"><![CDATA[)]]></span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">p1</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[(]]></span>
                <span class="ocaml-constant-numeric-decimal-float">2.</span>
                <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-float">2.</span>
                <span class="ocaml-source"><![CDATA[)]]></span>
                <span class="ocaml-source"><![CDATA[}]]></span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source">
</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[{]]></span>
                <span class="ocaml-constant-language-capital-identifier">Line</span>
                <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
                <span class="ocaml-source">p0</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[(]]></span>
                <span class="ocaml-constant-numeric-decimal-float">2.</span>
                <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-float">2.</span>
                <span class="ocaml-source"><![CDATA[)]]></span>
                <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source">p1</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-keyword-operator">=</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-source"><![CDATA[(]]></span>
                <span class="ocaml-constant-numeric-decimal-float">3.</span>
                <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
                <span class="ocaml-source"> </span>
                <span class="ocaml-constant-numeric-decimal-float">3.</span>
                <span class="ocaml-source"><![CDATA[)]]></span>
                <span class="ocaml-source"><![CDATA[}]]></span>
                <span class="ocaml-source"><![CDATA[]]]></span>
                <span class="ocaml-source">
</span>
              </code>
            </pre>
            <p xmlns:html="http://www.w3.org/1999/xhtml">You can see the query actually returned the first three, that's because all bound checks are inclusive.</p>
          </section>
        </section>
        <p xmlns:html="http://www.w3.org/1999/xhtml">The <a href="https://github.com/geocaml/ocaml-rtree/blob/d0a789b8eb6c594ed8c0f9c9a6c4b5cd7c734a03/test/image.ml#L95-L106">source repository includes a fairly simple example of rendering an R-Tree</a> using <a href="https://github.com/dbuenzli/vg">Vg</a>. This can be done outside of the repository using the <code>tree</code> representation.</p>
        <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
          <code>
            <span class="ocaml-mdx-hash">#</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-keyword-other">#</span>
            <span class="ocaml-keyword-other">show</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-constant-language-capital-identifier">R</span>
            <span class="ocaml-source">.</span>
            <span class="ocaml-source">tree</span>
            <span class="ocaml-source">;;</span>
            <span class="ocaml-source">
</span>
            <span class="ocaml-keyword-other">val</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-source">tree</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-constant-language-capital-identifier">R</span>
            <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
            <span class="ocaml-source">t</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-keyword-operator">-&gt;</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-constant-language-capital-identifier">R</span>
            <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
            <span class="ocaml-source">tree</span>
            <span class="ocaml-source">
</span>
            <span class="ocaml-keyword-other">type</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-keyword-other">nonrec</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-source">tree</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-keyword-operator">=</span>
            <span class="ocaml-source">
</span>
            <span class="ocaml-source">  </span>
            <span class="ocaml-constant-language-capital-identifier">R</span>
            <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
            <span class="ocaml-source">tree</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-keyword-operator">=</span>
            <span class="ocaml-source">
</span>
            <span class="ocaml-source">    </span>
            <span class="ocaml-constant-language-capital-identifier">Node</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-keyword-other">of</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-source"><![CDATA[(]]></span>
            <span class="ocaml-constant-language-capital-identifier">Line</span>
            <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
            <span class="ocaml-source">envelope</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-keyword-operator">*</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-constant-language-capital-identifier">R</span>
            <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
            <span class="ocaml-source">tree</span>
            <span class="ocaml-source"><![CDATA[)]]></span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-source">list</span>
            <span class="ocaml-source">
</span>
            <span class="ocaml-source">  </span>
            <span class="ocaml-keyword-other">|</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-constant-language-capital-identifier">Leaf</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-keyword-other">of</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-source"><![CDATA[(]]></span>
            <span class="ocaml-constant-language-capital-identifier">Line</span>
            <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
            <span class="ocaml-source">envelope</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-keyword-operator">*</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-constant-language-capital-identifier">Line</span>
            <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
            <span class="ocaml-source">t</span>
            <span class="ocaml-source"><![CDATA[)]]></span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-source">list</span>
            <span class="ocaml-source">
</span>
            <span class="ocaml-source">  </span>
            <span class="ocaml-keyword-other">|</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-constant-language-capital-identifier">Empty</span>
            <span class="ocaml-source">
</span>
          </code>
        </pre>
        <p xmlns:html="http://www.w3.org/1999/xhtml">Here is an example rendering from the repository showing some random lines and the envelopes of the R-tree.</p>
        <p xmlns:html="http://www.w3.org/1999/xhtml" style="text-align:center">
    <img src="./rtree.svg" />
</p>
      </div>
    </content>
  </entry>
  <entry>
    <title>Modular Explicits in OCaml</title>
    <author>
      <name>https://patrick.sirref.org/Patrick Ferris/</name>
      <uri>https://patrick.sirref.org/Patrick%20Ferris/</uri>
    </author>
    <link rel="alternate" type="text/html" href="https://patrick.sirref.org/modular-explicits/" />
    <id>https://patrick.sirref.org/modular-explicits/</id>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p xmlns:html="http://www.w3.org/1999/xhtml">Abstraction, in OCaml, often refers to hiding a particular type's implementation using a <em>signature</em>. For example:</p>
        <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
          <code>
            <span class="ocaml-keyword-other">module</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-constant-language-capital-identifier">S</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-keyword-other">sig</span>
            <span class="ocaml-source">
</span>
            <span class="ocaml-source">  </span>
            <span class="ocaml-keyword">type</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-entity-name-function-binding">t</span>
            <span class="ocaml-source">
</span>
            <span class="ocaml-source">  </span>
            <span class="ocaml-keyword">val</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-entity-name-function-binding">add</span>
            <span class="ocaml-source"> : t -&gt; t -&gt; t
</span>
            <span class="ocaml-keyword-other">end</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-keyword-operator">=</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-keyword-other">struct</span>
            <span class="ocaml-source">
</span>
            <span class="ocaml-source">  </span>
            <span class="ocaml-keyword-other">type</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-source">t</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-keyword-operator">=</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-support-type">int</span>
            <span class="ocaml-source">
</span>
            <span class="ocaml-source">  </span>
            <span class="ocaml-keyword">let</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-entity-name-function-binding">add</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-keyword-operator">=</span>
            <span class="ocaml-source"> </span>
            <span class="ocaml-constant-language-capital-identifier">Int</span>
            <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
            <span class="ocaml-source">add</span>
            <span class="ocaml-source">
</span>
            <span class="ocaml-keyword-other">end</span>
            <span class="ocaml-source">
</span>
          </code>
        </pre>
        <p xmlns:html="http://www.w3.org/1999/xhtml">In this post, however, I use abstraction to refer to the notion of code-reuse. Using features of the OCaml language to allow one piece of code to be used across different implementations or instantiations of a particular kind of value.</p>
        <p xmlns:html="http://www.w3.org/1999/xhtml">The goal of this post is to eventually discuss OCaml 5.5's <a href="https://patrick.sirref.org/abs-modular-explicits/">modular explicits</a> which is yet another feature that can allow a single piece of code to be used in various situations.</p>
        <section>
          <header>
            <h2>Polymorphism </h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">The most prevalent kind of abstraction is polymorphism. For example, <code>List.length</code> will work for all lists regardless of what kind of elements the list contains. However, polymorphism requires you to keep the polymorphic part of the type at arm's length. This can lead to suboptimal performance and/or limited usefulness.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml"><code>List.mem</code> is a good example; in order to be polymorphic <code>List.mem</code> relies on <code>Stdlib.(=)</code>, the polymorphic equality operator. In turn, this operator achieves its polymorphism by performing a structural comparison of the runtime representation of its arguments.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">A common way to overcome this is to use higher-order functions (functions that take functions as arguments).</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-mdx-hash">#</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword">rec </span>
              <span class="ocaml-entity-name-function-binding">mem</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-variable-parameter-optional">?</span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-variable-parameter-optional">eq</span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-constant-language-capital-identifier">Stdlib</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">v</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other">function</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-keyword-other">|</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-list"><![CDATA[[]]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-boolean">false</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-keyword-other">|</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">x</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">xs</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">eq</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">v</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">x</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">||</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">mem</span>
              <span class="ocaml-source"> ~</span>
              <span class="ocaml-source">eq</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">v</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">xs</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-other">val</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">mem</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> ?</span>
              <span class="ocaml-source">eq</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-storage-type">'a</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-storage-type">'a</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-support-type">bool</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-storage-type">'a</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-storage-type">'a</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">list</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-support-type">bool</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">&lt;</span>
              <span class="ocaml-keyword-other">fun</span>
              <span class="ocaml-keyword-operator">&gt;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-mdx-hash">#</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">mem_int_list</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">mem</span>
              <span class="ocaml-source"> ~</span>
              <span class="ocaml-source">eq</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-constant-language-capital-identifier">Int</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">equal</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-other">val</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">mem_int_list</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-support-type">int</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-support-type">int</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">list</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-support-type">bool</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">&lt;</span>
              <span class="ocaml-keyword-other">fun</span>
              <span class="ocaml-keyword-operator">&gt;</span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">This works well in plenty of cases (<code>List.map</code>, <code>Hashtbl.iter</code>, etc.), however, it doesn't scale well from a user's perspective if the body of the function requires lots of specific functions (e.g. <code>compare</code>, <code>length</code>, <code>pp</code>). At the same time, we want to avoid the precarious duck-typing of something like Python too.</p>
        </section>
        <section>
          <header>
            <h2>Functors </h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Functors are perhaps the second most prevalent feature of OCaml when it comes to code reuse. In the OCaml sense, a functor is a module that is parameterised by other modules. <code>Set.Make</code> is a functor that requires a module adhereing to the <code>Set.OrderedType</code> interface.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">IntSet</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Set</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">Make</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Int</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">StringSet</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Set</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">Make</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">String</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Functors make it a lot easier to write implementations that depend on a large variety of functionality. <code>Set.OrderedType</code> is relatively tame in this sense, only needing a type <code>t</code> and a <code>compare : t -&gt; t -&gt; int</code> function.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml"><a href="https://patrick.sirref.org/irmin/">Irmin</a>, on the other hand, has functors that require users to provide <a href="https://ocaml.org/p/irmin/3.11.0/doc/irmin/Irmin/Schema/module-type-S/index.html">Schemas</a>. I have more thoughts about this API design in <a href="https://patrick.sirref.org/irmin-retro/">my Irmin retrospective</a>.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">It is important to consider the runtime costs of functors too. Whilst most of the time functors are instantiated at the toplevel, it does not come for free. You can have a play around with <a href="https://patricoferris.github.io/js_of_ocamlopt/#code=bGV0IGYgaSA9CiAgbGV0IG1vZHVsZSBJID0gU2V0Lk1ha2UgKEludCkgaW4KICBJLmNhcmRpbmFsIGk=">js_of_ocamlopt</a> and see the generated output for how functors are applied.</p>
        </section>
        <section>
          <header>
            <h2>First-class Modules and Existentials </h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Sitting somewhere inbetween polymorphism and functors are first-class modules with existentials. This is a rather advanced use of OCaml's type system to be able to <em>pack</em> together a value of a particular type alongside a module that works with those kinds of values.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-keyword-other">type</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">set</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Set</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Set</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other">with</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other">type</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">t</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-storage-type">'a</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">*</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-storage-type">'a</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">set</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">size</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Set</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">s</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">cardinal</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">s</span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Packaging up integer sets is fairly straight-forward.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-mdx-hash">#</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">int_empty_set</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Set</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">IntSet</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">IntSet</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">empty</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-other">val</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">int_empty_set</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">set</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Set</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-operator">&lt;</span>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-keyword-operator">&gt;</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">&lt;</span>
              <span class="ocaml-source">poly</span>
              <span class="ocaml-keyword-operator">&gt;</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">From a user's perspective we are now closer to the realm of dynamic typing. Indeed, existentials are the way to do that in OCaml.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-mdx-hash">#</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other">type</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">any</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Any</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-storage-type">'a</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">any</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-other">type</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">any</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Any</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-storage-type">'a</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">any</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-mdx-hash">#</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">any</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">v</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Any</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">v</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-other">val</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">any</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-storage-type">'a</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">any</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">&lt;</span>
              <span class="ocaml-keyword-other">fun</span>
              <span class="ocaml-keyword-operator">&gt;</span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Getting back into a typed world often involves some <a href="https://github.com/dbuenzli/hmap/blob/e54eb3f7d7dbada0724fd023c334d0b5a29c8479/src/hmap.ml#L120-L127">type witness gymnastics</a> or runtime exceptions. Used sparingly, however, it can be very effective particularly when a user is none the wiser about the use of FCMs and existentials. I have made use of this trick to <a href="https://github.com/fn06/shelter/blob/e71d6df79ab7c43b092de145e9e80482ae3af118/src/lib/store.ml#L1-L10">package together Irmin stores with implementations</a>.</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">You could not, however, simply return the value that was packed away inside the existential.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-mdx-hash">#</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">woops</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language-capital-identifier">Set</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-constant-language">_</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">s</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">s</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-constant-language-capital-identifier">Line</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-numeric-decimal-integer">1</span>
              <span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">characters</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-numeric-decimal-integer">26</span>
              <span class="ocaml-keyword-operator">-</span>
              <span class="ocaml-constant-numeric-decimal-integer">27</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-constant-language-capital-identifier">Error</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">The</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">value</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">s</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">has</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other">type</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">$</span>
              <span class="ocaml-source">a</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">but</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">an</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">expression</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">was</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">expected</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other">of</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other">type</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-storage-type">'a</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">       </span>
              <span class="ocaml-constant-language-capital-identifier">The</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other">type</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">constructor</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">$</span>
              <span class="ocaml-source">a</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">would</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">escape</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">its</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">scope</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">       </span>
              <span class="ocaml-constant-language-capital-identifier">Hint</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">$</span>
              <span class="ocaml-source">a</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">is</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">an</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">existential</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other">type</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">bound</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">by</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">the</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">constructor</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Set</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">There is also a runtime cost to the packing (and unpacking) of the module, not to mention the need for the extra allocation to create the existential in the first place. This will likely not be too significant, but is worth considering.</p>
        </section>
        <section>
          <header>
            <h2>Modular Explicits </h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">OCaml 5.5 has <em>module-dependent function types</em> also known as <em>explicits modular</em>. The type of a function can now depend on types that come from a module that is also part of the function definition.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-mdx-hash">#</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">set_length</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Set</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">t</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-support-type">int</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-keyword-other">fun</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">v</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">cardinal</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">v</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-other">val</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">set_length</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Set</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">t</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-support-type">int</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">&lt;</span>
              <span class="ocaml-keyword-other">fun</span>
              <span class="ocaml-keyword-operator">&gt;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-mdx-hash">#</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">set_length</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">IntSet</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">IntSet</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">empty</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-operator">-</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-support-type">int</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-numeric-decimal-integer">0</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-mdx-hash">#</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">set_length</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">StringSet</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">StringSet</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">empty</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-operator">-</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-support-type">int</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-numeric-decimal-integer">0</span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">In fact, we can now <em>return</em> values of a particular type that depends on a particular module!</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-mdx-hash">#</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">empty_set</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Set</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">t</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> 
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-keyword-other">fun</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">empty</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-other">val</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">empty_set</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Set</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">t</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">&lt;</span>
              <span class="ocaml-keyword-other">fun</span>
              <span class="ocaml-keyword-operator">&gt;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-mdx-hash">#</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">empty_set</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">IntSet</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-operator">-</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">IntSet</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">t</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">&lt;</span>
              <span class="ocaml-source">abstr</span>
              <span class="ocaml-keyword-operator">&gt;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-mdx-hash">#</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">empty_set</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">StringSet</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-operator">-</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">StringSet</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">t</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">&lt;</span>
              <span class="ocaml-source">abstr</span>
              <span class="ocaml-keyword-operator">&gt;</span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">Or, we can dynamically select implementations and values.</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml" class="hilite">
            <code>
              <span class="ocaml-mdx-hash">#</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword">let</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-entity-name-function-binding">with_impl</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> 
</span>
              <span class="ocaml-source">    </span>
              <span class="ocaml-source">config</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-support-type">string</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Set</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">t</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-storage-type">'a</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-storage-type">'a</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source"> 
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-keyword-other">fun</span>
              <span class="ocaml-source"> ~</span>
              <span class="ocaml-source">config</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">fn</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-keyword-other">match</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">String</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">lowercase_ascii</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">config</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other">with</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-keyword-other">|</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">string</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">fn</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">StringSet</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">StringSet</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">empty</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-keyword-other">|</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-string-quoted-double">int</span>
              <span class="ocaml-string-quoted-double">"</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">fn</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">IntSet</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">IntSet</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">empty</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-keyword-other">|</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">c</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">invalid_arg</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">c</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-keyword-other">val</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">with_impl</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source">config</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-support-type">string</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-source"><![CDATA[(]]></span>
              <span class="ocaml-keyword-other">module</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">Set</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-constant-language-capital-identifier">S</span>
              <span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</span>
              <span class="ocaml-source">t</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-storage-type">'a</span>
              <span class="ocaml-source"><![CDATA[)]]></span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">-&gt;</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-storage-type">'a</span>
              <span class="ocaml-source"> </span>
              <span class="ocaml-keyword-operator">=</span>
              <span class="ocaml-source">
</span>
              <span class="ocaml-source">  </span>
              <span class="ocaml-keyword-operator">&lt;</span>
              <span class="ocaml-keyword-other">fun</span>
              <span class="ocaml-keyword-operator">&gt;</span>
              <span class="ocaml-source">
</span>
            </code>
          </pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">This is like a more usable version of the FCM-existential trick, though does require more manual type annotations on functions. For instance, I tried switching out <a href="https://github.com/ocurrent/obuilder">OBuilder's</a> use of existentials with modular explicits:</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[-type builder = Builder : (module Obuilder.BUILDER with type t = 'a) * 'a -> builder
-
 let log tag msg =
   match tag with
   | `Heading -> Fmt.pr "%a@." Fmt.(styled (`Fg (`Hi `Blue)) string) msg
   | `Note -> Fmt.pr "%a@." Fmt.(styled (`Fg `Yellow) string) msg
   | `Output -> output_string stdout msg; flush stdout

-let create_builder store_spec conf =
+let create_builder :
+  Store_spec.store Lwt.t -> Native_sandbox.config ->
+    ((module B : Obuilder.BUILDER) -> B.t -> 'a) -> 'a Lwt.t =
+  fun store_spec conf fn ->
   store_spec >>= fun (Store_spec.Store ((module Store), store)) ->
   let module Builder = Obuilder.Builder (Store) (Native_sandbox) (Docker_extract) in
   Native_sandbox.create ~state_dir:(Store.state_dir store / "sandbox") conf >|= fun sandbox ->
   let builder = Builder.v ~store ~sandbox in
-  Builder ((module Builder), builder)
+  fn (module Builder) builder]]></pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">I think the code is more pragmatic; there is no longer an indirection via a type called <code>builder</code>. The extra type annotations do add a little noise. Roll on <em>modular implicits</em>.</p>
        </section>
      </div>
    </content>
  </entry>
</feed>
