<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/default.xsl"?>
<fr:tree xmlns:fr="http://www.forester-notes.org" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:xml="http://www.w3.org/XML/1998/namespace" root="false" base-url="/">
  <fr:frontmatter>
    <fr:authors>
      <fr:author>
        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
      </fr:author>
    </fr:authors>
    <fr:date>
      <fr:year>2026</fr:year>
      <fr:month>3</fr:month>
      <fr:day>9</fr:day>
    </fr:date>
    <fr:uri>https://patrick.sirref.org/vibecoding-etiquette/</fr:uri>
    <fr:display-uri>vibecoding-etiquette</fr:display-uri>
    <fr:route>/vibecoding-etiquette/</fr:route>
    <fr:title text="Vibecoding Etiquette">Vibecoding Etiquette</fr:title>
  </fr:frontmatter>
  <fr:mainmatter>
    <html:p>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. </html:p>
    <html:p>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  <![CDATA[US Department of War (I struggle to find the meaningful difference between]]> <fr:link href="https://www.anthropic.com/news/where-stand-department-war" type="external">"opertational planning" vs. "operational decision-making" given the leaders of  the US DoW </fr:link><![CDATA[),]]> 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. </html:p>
    <html:p>Everybody can draw their line where they want, and I am, in good faith, trying to find  where mine should be. </html:p>
    <html:p>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. </html:p>
    <html:p>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.  <fr:link href="https://github.com/ocaml-multicore/eio/blob/main/HACKING.md#ai-generated-code" type="external">Eio's "AI-generated  Code" </fr:link> subsection is succinct and prohibits contributions that  <html:em>solely </html:em> use AI. </html:p>
    <html:blockquote>
      <html: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. </html:p>
      <html: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. </html:p>
      <html: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. </html:p>
    </html:blockquote>
    <html:p>Additionally, I plead to other developers to  <html:em>own </html:em> their use of these tools.  Please, make Claude a co-author of the commits where Claude has generated  <html:em>any </html: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  <fr:link href="https://github.com/ocaml/ocaml/blob/trunk/AI.md" type="external">OCaml compiler's AI notice </fr:link> which includes: </html:p>
    <html:blockquote>
      <html: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. </html:p>
    </html:blockquote>
  </fr:mainmatter>
  <fr:backmatter>
    <fr:tree show-metadata="false" hidden-when-empty="true">
      <fr:frontmatter>
        <fr:authors />
        <fr:title text="References">References</fr:title>
      </fr:frontmatter>
      <fr:mainmatter />
    </fr:tree>
    <fr:tree show-metadata="false" hidden-when-empty="true">
      <fr:frontmatter>
        <fr:authors />
        <fr:title text="Context">Context</fr:title>
      </fr:frontmatter>
      <fr:mainmatter>
        <fr:tree show-metadata="true" expanded="false" toc="false" numbered="false">
          <fr:frontmatter>
            <fr:authors>
              <fr:author>
                <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
              </fr:author>
            </fr:authors>
            <fr:date>
              <fr:year>2026</fr:year>
              <fr:month>3</fr:month>
              <fr:day>10</fr:day>
            </fr:date>
            <fr:uri>https://patrick.sirref.org/ocaml-roundup-february-2026/</fr:uri>
            <fr:display-uri>ocaml-roundup-february-2026</fr:display-uri>
            <fr:route>/ocaml-roundup-february-2026/</fr:route>
            <fr:title text="OCaml Roundup: February 2026">OCaml Roundup: February 2026</fr:title>
          </fr:frontmatter>
          <fr:mainmatter>
            <html:p>Much like last month, this month has been busy with lots of work on  <fr:link href="/ocaml-tiff/" title="ocaml-tiff" uri="https://patrick.sirref.org/ocaml-tiff/" display-uri="ocaml-tiff" type="local">ocaml-tiff </fr:link> thanks to  <fr:link href="https://patrick.sirref.org/tambe salome/" type="external">Tambe Salome </fr:link> and  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link>. </html:p>
            <fr:tree show-metadata="false" numbered="false">
              <fr:frontmatter>
                <fr:authors>
                  <fr:author>
                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                  </fr:author>
                </fr:authors>
                <fr:date>
                  <fr:year>2026</fr:year>
                  <fr:month>3</fr:month>
                  <fr:day>10</fr:day>
                </fr:date>
                <fr:title text="Outreachy ">Outreachy </fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p><fr:link href="https://patrick.sirref.org/tambe salome/" type="external">Tambe Salome </fr:link>, at the time of writing, has completed her internship! We will  be hosting the biannual  <fr:link href="https://discuss.ocaml.org/t/outreachy-demo-day-for-december-2025-round/17883" type="external">Demo Day  celebration </fr:link> for this round's interns, so please do come along. </html:p>
                <html:p>Since the last update  <fr:link href="https://patrick.sirref.org/tambe salome/" type="external">Tambe Salome </fr:link> and I have been slowly making progress  on making the write-functionality more feature-complete. As I eluded  <fr:link href="/ocaml-roundup-january-2026/" title="OCaml Roundup: January 2026" uri="https://patrick.sirref.org/ocaml-roundup-january-2026/" display-uri="ocaml-roundup-january-2026" type="local">last  month </fr:link>, TIFF files are  <html:em>hard </html:em> to write. Their  internal structure is all over the place: directories, immediate and  non-immediate values, 32-bit or 64-bit, little or big endian etc. We're  tackling this bit by bit, evolving the library to be able to support writing to  files. In the early days, when we only read TIFF files there was no need to  <![CDATA[store information that we could readily pull from the file itself (via]]> something like  <html:code><![CDATA[pread(2)]]></html:code><![CDATA[). Now, we need to be able to hold those same values]]> in memory before writing them to the file, so we will need some kind of API  change internally to support this. </html:p>
                <html:p>This month, I also bumped up against well-meaning contributions to  <fr:link href="/ocaml-tiff/" title="ocaml-tiff" uri="https://patrick.sirref.org/ocaml-tiff/" display-uri="ocaml-tiff" type="local">ocaml-tiff </fr:link> that made  use of AI. This left me with some thoughts that I am adding below. </html:p>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2026</fr:year>
                      <fr:month>3</fr:month>
                      <fr:day>9</fr:day>
                    </fr:date>
                    <fr:uri>https://patrick.sirref.org/vibecoding-etiquette/</fr:uri>
                    <fr:display-uri>vibecoding-etiquette</fr:display-uri>
                    <fr:route>/vibecoding-etiquette/</fr:route>
                    <fr:title text="Vibecoding Etiquette">Vibecoding Etiquette</fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>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. </html:p>
                    <html:p>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  <![CDATA[US Department of War (I struggle to find the meaningful difference between]]> <fr:link href="https://www.anthropic.com/news/where-stand-department-war" type="external">"opertational planning" vs. "operational decision-making" given the leaders of  the US DoW </fr:link><![CDATA[),]]> 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. </html:p>
                    <html:p>Everybody can draw their line where they want, and I am, in good faith, trying to find  where mine should be. </html:p>
                    <html:p>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. </html:p>
                    <html:p>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.  <fr:link href="https://github.com/ocaml-multicore/eio/blob/main/HACKING.md#ai-generated-code" type="external">Eio's "AI-generated  Code" </fr:link> subsection is succinct and prohibits contributions that  <html:em>solely </html:em> use AI. </html:p>
                    <html:blockquote>
                      <html: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. </html:p>
                      <html: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. </html:p>
                      <html: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. </html:p>
                    </html:blockquote>
                    <html:p>Additionally, I plead to other developers to  <html:em>own </html:em> their use of these tools.  Please, make Claude a co-author of the commits where Claude has generated  <html:em>any </html: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  <fr:link href="https://github.com/ocaml/ocaml/blob/trunk/AI.md" type="external">OCaml compiler's AI notice </fr:link> which includes: </html:p>
                    <html:blockquote>
                      <html: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. </html:p>
                    </html:blockquote>
                  </fr:mainmatter>
                </fr:tree>
              </fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="false" numbered="false">
              <fr:frontmatter>
                <fr:authors>
                  <fr:author>
                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                  </fr:author>
                </fr:authors>
                <fr:date>
                  <fr:year>2026</fr:year>
                  <fr:month>3</fr:month>
                  <fr:day>10</fr:day>
                </fr:date>
                <fr:title text="Ppxlib ">Ppxlib </fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>We are still in the throes of supporting OCaml 5.5 in  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link>. Some of the  features have proved more complicated to encode into migrations that  "roundtrip". Roundtripping, in the context of  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link>, is when a modern  feature of OCaml must be preserved in older abstract syntax trees which may  have no specific node to encode them. </html:p>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2026</fr:year>
                      <fr:month>3</fr:month>
                      <fr:day>10</fr:day>
                    </fr:date>
                    <fr:title text="Bugs in Ptyp_open ">Bugs in Ptyp_open </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>Unfortunately,  <fr:link href="/jonmsterling/" title="Jon Sterling" uri="https://patrick.sirref.org/jonmsterling/" display-uri="jonmsterling" type="local">Jon Sterling </fr:link> was  <fr:link href="https://mastodon.social/@jonmsterling@mathstodon.xyz/116085163199163273" type="external">bitten by this  recently </fr:link>.  <![CDATA[The feature in question was locally opening modules in types (added in OCaml]]> <![CDATA[5.2). For example:]]></html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">M</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">struct</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword-other">type</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">int</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-other">end</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-other">type</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">M</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">list</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>Here, the  <html:code><![CDATA[M.(t list)]]></html:code> is an example of a new AST node called  <html:code>Ptyp_open</html:code>. I  had hastily not migrated  <html:code>Ptyp_open</html:code> to older compilers. So what happened? Jon had used  this new feature in his project with a 5.3 compiler with  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link> 0.35. This is before  our  <fr:link href="/ppxlib-5-2/" title="Bumping Ppxlib's AST to 5.2" uri="https://patrick.sirref.org/ppxlib-5-2/" display-uri="ppxlib-5-2" type="local">internal bump to the 5.2 AST </fr:link> so the code migrated all the way down to  OCaml 4.14! Whilst passing from 5.2 to 5.1 we raised an error saying: </html:p>
                    <html:blockquote>
                      <html:p>Error: migration error: module open in types is not supported before OCaml  5.02 </html:p>
                    </html:blockquote>
                    <html:p><![CDATA[The error is confusing (least of all because there is a typo on the OCaml]]> <![CDATA[version number). Since then, we have]]><fr:link href="https://github.com/ocaml-ppx/ppxlib/pull/625" type="external">patched this  issue </fr:link> and have planned to  <fr:link href="https://github.com/ocaml-ppx/ppxlib/compare/main...0.35" type="external">release a patched  0.35 </fr:link> in the not too  distant future. </html:p>
                    <html:p>If you can bump to  <html:code>ppxlib&gt;=0.36</html:code> then you will not face this issue. </html:p>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2026</fr:year>
                      <fr:month>3</fr:month>
                      <fr:day>10</fr:day>
                    </fr:date>
                    <fr:title text="Modular Explicits ">Modular Explicits </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>We ran into a fairly interesting corner of the OCaml language whilst trying to  migrate modular explicits in  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link>. As a recap, in OCaml 5.5 you can now  right function types that depend on modules. For example: </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">type</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Add</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">sig</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword">type</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">t</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword">val</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">add</html:span>
                        <html:span class="ocaml-source"> : t -&gt; t -&gt; t
</html:span>
                        <html:span class="ocaml-keyword-other">end</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">add</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">A</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Add</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">A</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">A</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">A</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword-other">fun</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">A</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Add</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">a</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">b</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">A</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">add</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">a</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">b</html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>We have to tell the compiler the module type of  <html:code>A</html:code> by adding  <html:code>: Add</html:code>. However,  there is another very similar syntax for these kinds of constraints,  <html:code><![CDATA[(module A : module Add)]]></html:code>. And in fact, the former syntax was syntactic sugar for the  latter. In OCaml 5.5, these two  <fr:link href="https://github.com/ocaml/ocaml/pull/14149" type="external">were distinguished from one  another </fr:link> and  <html:code><![CDATA[(module A : Add)]]></html:code> is  the required syntax for modular explicits. As you might imagine, this is a bit  of a headache in terms of  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link> migrations. In the end, we try to preserve  the original intent of the author where possible, and you can read more about  it on the PR for distinguishing the two. </html:p>
                  </fr:mainmatter>
                </fr:tree>
              </fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="false" numbered="false">
              <fr:frontmatter>
                <fr:authors>
                  <fr:author>
                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                  </fr:author>
                </fr:authors>
                <fr:date>
                  <fr:year>2026</fr:year>
                  <fr:month>3</fr:month>
                  <fr:day>10</fr:day>
                </fr:date>
                <fr:title text="Six Month Retrospective ">Six Month Retrospective </fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>This month marks the end of six months of work with  <fr:link href="https://tarides.com/" type="external">Tarides </fr:link>. I wrote a small retrospective and plan for my  next six months below. </html:p>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2026</fr:year>
                      <fr:month>2</fr:month>
                      <fr:day>9</fr:day>
                    </fr:date>
                    <fr:uri>https://patrick.sirref.org/fellowship-roundup/</fr:uri>
                    <fr:display-uri>fellowship-roundup</fr:display-uri>
                    <fr:route>/fellowship-roundup/</fr:route>
                    <fr:title text="Fellowship Roundup">Fellowship Roundup</fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <fr:tree show-metadata="false" numbered="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2026</fr:year>
                          <fr:month>2</fr:month>
                          <fr:day>9</fr:day>
                        </fr:date>
                        <fr:title text="Overview ">Overview </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>February is the final month of my current six-month fellowship work with  <fr:link href="https://tarides.com/" type="external">Tarides </fr:link>. A lot of the work can be summarised by reading  the  <fr:link href="/ocaml-blog/" title="Patrick's OCaml Blog" uri="https://patrick.sirref.org/ocaml-blog/" display-uri="ocaml-blog" type="local">roundups </fr:link><![CDATA[ (see]]><fr:link href="/ocaml-roundup-october-2025/" title="OCaml Roundup: October 2025" uri="https://patrick.sirref.org/ocaml-roundup-october-2025/" display-uri="ocaml-roundup-october-2025" type="local">October </fr:link>,  <fr:link href="/ocaml-roundup-november-2025/" title="OCaml Roundup: November 2025" uri="https://patrick.sirref.org/ocaml-roundup-november-2025/" display-uri="ocaml-roundup-november-2025" type="local">November </fr:link>,  <fr:link href="/ocaml-roundup-december-2025/" title="OCaml Roundup: December 2025" uri="https://patrick.sirref.org/ocaml-roundup-december-2025/" display-uri="ocaml-roundup-december-2025" type="local">December </fr:link> and  <fr:link href="/ocaml-roundup-january-2026/" title="OCaml Roundup: January 2026" uri="https://patrick.sirref.org/ocaml-roundup-january-2026/" display-uri="ocaml-roundup-january-2026" type="local">January </fr:link><![CDATA[). I have been writing throughout the fellowship.]]> However, they do not quite capture all the work I have been doing. </html:p>
                        <html:p>Below, I pick individual projects and expand on them more holistically rather  than pointing at individual PRs or issues. </html:p>
                        <fr:tree show-metadata="false" numbered="false">
                          <fr:frontmatter>
                            <fr:authors>
                              <fr:author>
                                <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                              </fr:author>
                            </fr:authors>
                            <fr:date>
                              <fr:year>2026</fr:year>
                              <fr:month>2</fr:month>
                              <fr:day>9</fr:day>
                            </fr:date>
                            <fr:title text="Ppxlib ">Ppxlib </fr:title>
                          </fr:frontmatter>
                          <fr:mainmatter>
                            <html:p>Most of my time over the past six months has been devoted to  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link> maintenance. A large proportion of this time has been solo development work.  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">Ppxlib </fr:link><![CDATA[ is a cornerstone library of the OCaml ecosystem (whether people like]]> <![CDATA[it or not).]]></html:p>
                            <html:pre><![CDATA[$ opam list --depends-on=ppxlib --recursive | wc -l
2030]]></html:pre>
                            <html:p>Moreover, it is completely invaluable to Jane Street too. Like other AST-based  <![CDATA[tools (e.g. ocamlformat, merlin),]]><fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link> must follow a regular release  schedule to support newer compilers. During the years of multicore OCaml development,  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link> maintenance was a little easier as the Parsetree rarely changed. However,  since then, the same cannot be said. Since OCaml 5.2, here are just some of the Parsetree  changes: </html:p>
                            <html:ul>
                              <html:li>
                                <html:p>Functions are represented according to their arity. </html:p>
                              </html:li>
                              <html:li>
                                <html:p>Local module opens on types. </html:p>
                              </html:li>
                              <html:li>
                                <html:p>Effect syntax. </html:p>
                              </html:li>
                              <html:li>
                                <html:p>Modular explicits. </html:p>
                              </html:li>
                              <html:li>
                                <html:p>External types. </html:p>
                              </html:li>
                              <html:li>
                                <html:p>Locations for all parts of long identifiers. </html:p>
                              </html:li>
                              <html:li>
                                <html:p>Labeled tuples. </html:p>
                              </html:li>
                            </html:ul>
                            <html:p>In a perfect world, each of these require a codec for serialising the feature  into ASTs that do not support the feature, plenty of tests and new  <html:code>Ast_builder</html:code>/ <html:code>Ast_pattern</html:code> functions for using the feature.  <fr:link href="/nathanreb/" title="Nathan Rebours" uri="https://patrick.sirref.org/nathanreb/" display-uri="nathanreb" type="local">Nathan </fr:link> and I have been managing pretty well I would say, though we  are not getting any technical debt work done. </html:p>
                          </fr:mainmatter>
                        </fr:tree>
                        <fr:tree show-metadata="false" numbered="false">
                          <fr:frontmatter>
                            <fr:authors>
                              <fr:author>
                                <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                              </fr:author>
                            </fr:authors>
                            <fr:date>
                              <fr:year>2026</fr:year>
                              <fr:month>2</fr:month>
                              <fr:day>9</fr:day>
                            </fr:date>
                            <fr:title text="Outreachy ">Outreachy </fr:title>
                          </fr:frontmatter>
                          <fr:mainmatter>
                            <html:p>As the OCaml coordinator for  <fr:link href="/outreachy/" title="Outreachy" uri="https://patrick.sirref.org/outreachy/" display-uri="outreachy" type="local">Outreachy </fr:link> I have been running the latest December 2025 round.  We are lucky to have  <html:em>four </html:em> projects on the go! </html:p>
                            <html:ul>
                              <html:li>
                                <html:p>Thibaut Mattio is mentoring two projects:  <fr:link href="https://www.outreachy.org/outreachy-december-2025-internship-cohort/communities/ocaml/#raven-create-a-monitoring-dashboard-for-deep-learn" type="external">an ML dashboard for Raven </fr:link> and  <fr:link href="https://www.outreachy.org/outreachy-december-2025-internship-cohort/communities/ocaml/#create-an-oxcaml-backend-for-raven" type="external">an OxCaml backend for Raven </fr:link>. </html:p>
                              </html:li>
                              <html:li>
                                <html:p><fr:link href="https://github.com/xvw" type="external">Xvw </fr:link> is mentoring a  <fr:link href="https://github.com/yocaml/" type="external">Yocaml </fr:link>  <fr:link href="https://www.outreachy.org/outreachy-december-2025-internship-cohort/communities/ocaml/#improve-yocaml-error-reporting-and-data-model" type="external">project </fr:link>. </html:p>
                              </html:li>
                              <html:li>
                                <html:p>I am  <fr:link href="/outreachy-ocaml-tiff/" title="Write support in OCaml TIFF library" uri="https://patrick.sirref.org/outreachy-ocaml-tiff/" display-uri="outreachy-ocaml-tiff" type="local">mentoring </fr:link> a  <fr:link href="/geocaml/" title="Geocaml" uri="https://patrick.sirref.org/geocaml/" display-uri="geocaml" type="local">Geocaml </fr:link> project. </html:p>
                              </html:li>
                            </html:ul>
                          </fr:mainmatter>
                        </fr:tree>
                        <fr:tree show-metadata="false" numbered="false">
                          <fr:frontmatter>
                            <fr:authors>
                              <fr:author>
                                <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                              </fr:author>
                            </fr:authors>
                            <fr:date>
                              <fr:year>2026</fr:year>
                              <fr:month>2</fr:month>
                              <fr:day>9</fr:day>
                            </fr:date>
                            <fr:title text="Eio ">Eio </fr:title>
                          </fr:frontmatter>
                          <fr:mainmatter>
                            <html:p>During my work on tools like  <fr:link href="/shelter/" title="Shelter" uri="https://patrick.sirref.org/shelter/" display-uri="shelter" type="local">Shelter </fr:link> I have made a few improvements to  <fr:link href="/eio/" title="Eio" uri="https://patrick.sirref.org/eio/" display-uri="eio" type="local">Eio </fr:link> including: </html:p>
                            <html:ul>
                              <html:li>
                                <html:p><fr:link href="https://github.com/ocaml-multicore/eio/pull/821" type="external">A draft PR for incremental reading of directories </fr:link>. </html:p>
                              </html:li>
                              <html:li>
                                <html:p><fr:link href="https://github.com/ocaml-multicore/eio/pull/803" type="external">New fork actions for processes: setgid, setuid and process groups </fr:link>. </html:p>
                              </html:li>
                              <html:li>
                                <html:p><fr:link href="https://github.com/ocaml-multicore/eio/pull/823" type="external">Utility functions for overriding standard environments </fr:link>. </html:p>
                              </html:li>
                              <html:li>
                                <html:p><fr:link href="https://github.com/ocaml-multicore/eio/pull/822" type="external">Fixing documentation </fr:link>. </html:p>
                              </html:li>
                            </html:ul>
                          </fr:mainmatter>
                        </fr:tree>
                        <fr:tree show-metadata="false" numbered="false">
                          <fr:frontmatter>
                            <fr:authors>
                              <fr:author>
                                <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                              </fr:author>
                            </fr:authors>
                            <fr:date>
                              <fr:year>2026</fr:year>
                              <fr:month>2</fr:month>
                              <fr:day>9</fr:day>
                            </fr:date>
                            <fr:title text="OxCaml ">OxCaml </fr:title>
                          </fr:frontmatter>
                          <fr:mainmatter>
                            <html:p>I have enjoyed my work on OxCaml went it has happend. I think a few tools have  been useful including the  <fr:link href="/try-oxcaml/" title="Try OxCaml" uri="https://patrick.sirref.org/try-oxcaml/" display-uri="try-oxcaml" type="local">try-oxcaml </fr:link> work.  <fr:link href="/dra27/" title="David Allsopp" uri="https://patrick.sirref.org/dra27/" display-uri="dra27" type="local">David </fr:link> and I also  had fun at  <fr:link href="/icfp-2025/" title="ICFP 2025" uri="https://patrick.sirref.org/icfp-2025/" display-uri="icfp-2025" type="local">ICFP </fr:link> discussing some quick experiments related to  <fr:link href="/icfp-oxcaml-uring/" title="OCaml Roundup: October 2025 › OxCaml Experiments  " uri="https://patrick.sirref.org/icfp-oxcaml-uring/" display-uri="icfp-oxcaml-uring" type="local">io_uring  and OxCaml </fr:link>. </html:p>
                            <html:p>One road-blocker here is the comparative amount of time spent trying to keep  the OxCaml ecosystem working. Given my limited time working on fellowship  <![CDATA[projects, the rate of change of OxCaml (including the opam ecosystem) meant]]> most of the time was spent making it just work, not exploring or experimenting  with the features themselves. I think this has got better in recent months  and perhaps jumping back in I would be surprised at the progress that has been  made there. </html:p>
                          </fr:mainmatter>
                        </fr:tree>
                        <fr:tree show-metadata="false" numbered="false">
                          <fr:frontmatter>
                            <fr:authors>
                              <fr:author>
                                <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                              </fr:author>
                            </fr:authors>
                            <fr:date>
                              <fr:year>2026</fr:year>
                              <fr:month>2</fr:month>
                              <fr:day>9</fr:day>
                            </fr:date>
                            <fr:title text="Forester ">Forester </fr:title>
                          </fr:frontmatter>
                          <fr:mainmatter>
                            <html:p><fr:link href="https://tarides.org/" type="external">Tarides </fr:link> are funding some work on  <fr:link href="/forester/" title="Forester" uri="https://patrick.sirref.org/forester/" display-uri="forester" type="local">forester </fr:link>. This site  uses  <fr:link href="/forester/" title="Forester" uri="https://patrick.sirref.org/forester/" display-uri="forester" type="local">forester </fr:link> by way of  <fr:link href="/graft/" title="Graft" uri="https://patrick.sirref.org/graft/" display-uri="graft" type="local">graft </fr:link> and I have spent some time working on  these tools during the fellowship. </html:p>
                            <html:p>This includes a  <html:code>bytesrw</html:code>-based  <fr:link href="/bib/" title="Bib" uri="https://patrick.sirref.org/bib/" display-uri="bib" type="local">bibtex </fr:link> library in OCaml that could be  released soon. </html:p>
                          </fr:mainmatter>
                        </fr:tree>
                        <fr:tree show-metadata="false" numbered="false">
                          <fr:frontmatter>
                            <fr:authors>
                              <fr:author>
                                <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                              </fr:author>
                            </fr:authors>
                            <fr:date>
                              <fr:year>2026</fr:year>
                              <fr:month>2</fr:month>
                              <fr:day>9</fr:day>
                            </fr:date>
                            <fr:title text="Papers ">Papers </fr:title>
                          </fr:frontmatter>
                          <fr:mainmatter>
                            <html:p>I had the great fortune of attending  <fr:link href="https://patrick.sirref.org/ifcp-2025/" type="external">ICFP </fr:link> where I presented two  talks and was co-author on a few others too. </html:p>
                            <html:hr />
                            <fr:tree show-metadata="false" expanded="false" numbered="false">
                              <fr:frontmatter>
                                <fr:authors>
                                  <fr:author>
                                    <fr:link href="https://patrick.sirref.org/Anil Madhavapeddy/" type="external">Anil Madhavapeddy</fr:link>
                                  </fr:author>
                                  <fr:author>
                                    <fr:link href="https://patrick.sirref.org/David J. Scott" type="external">David J. Scott</fr:link>
                                  </fr:author>
                                  <fr:author>
                                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                                  </fr:author>
                                  <fr:author>
                                    <fr:link href="https://patrick.sirref.org/Ryan T. Gibb" type="external">Ryan T. Gibb</fr:link>
                                  </fr:author>
                                  <fr:author>
                                    <fr:link href="https://patrick.sirref.org/Thomas Gazagnaire/" type="external">Thomas Gazagnaire</fr:link>
                                  </fr:author>
                                </fr:authors>
                                <fr:date>
                                  <fr:year>2025</fr:year>
                                </fr:date>
                                <fr:uri>https://patrick.sirref.org/madhavapeddy2025docker/</fr:uri>
                                <fr:display-uri>madhavapeddy2025docker</fr:display-uri>
                                <fr:route>/madhavapeddy2025docker/</fr:route>
                                <fr:title text="Functional Networking for Millions of Docker Desktops (Experience Report)">Functional Networking for Millions of Docker Desktops (Experience Report)</fr:title>
                                <fr:taxon>Reference</fr:taxon>
                                <fr:meta name="external">https://dl.acm.org/doi/10.1145/3747525</fr:meta>
                                <fr:meta name="journal">Proc. ACM Program. Lang.</fr:meta>
                                <fr:meta name="doi">10.1145/3747525</fr:meta>
                              </fr:frontmatter>
                              <fr:mainmatter>
                                <fr:tree show-metadata="false">
                                  <fr:frontmatter>
                                    <fr:authors>
                                      <fr:author>
                                        <fr:link href="https://patrick.sirref.org/Anil Madhavapeddy/" type="external">Anil Madhavapeddy</fr:link>
                                      </fr:author>
                                      <fr:author>
                                        <fr:link href="https://patrick.sirref.org/David J. Scott" type="external">David J. Scott</fr:link>
                                      </fr:author>
                                      <fr:author>
                                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                                      </fr:author>
                                      <fr:author>
                                        <fr:link href="https://patrick.sirref.org/Ryan T. Gibb" type="external">Ryan T. Gibb</fr:link>
                                      </fr:author>
                                      <fr:author>
                                        <fr:link href="https://patrick.sirref.org/Thomas Gazagnaire/" type="external">Thomas Gazagnaire</fr:link>
                                      </fr:author>
                                    </fr:authors>
                                    <fr:date>
                                      <fr:year>2025</fr:year>
                                    </fr:date>
                                    <fr:title text="Abstract ">Abstract </fr:title>
                                  </fr:frontmatter>
                                  <fr:mainmatter>
                                    <html:p>
	Docker is a developer tool used by millions of developers to build, share
	and run software stacks. The Docker Desktop clients for Mac and Windows
	have long used a novel combination of virtualisation and OCaml unikernels
	to seamlessly run Linux containers on these non-Linux hosts.

	We reflect on a decade of shipping this functional OCaml code into
	production across hundreds of millions of developer desktops, and discuss
	the lessons learnt from our experiences in integrating OCaml deeply into
	the container architecture that now drives much of the global cloud. We
	conclude by observing just how good a fit for systems programming that the
	unikernel approach has been, particularly when combined with the OCaml
	module and type system.
 </html:p>
                                  </fr:mainmatter>
                                </fr:tree>
                              </fr:mainmatter>
                            </fr:tree>
                            <fr:tree show-metadata="false" expanded="false" numbered="false">
                              <fr:frontmatter>
                                <fr:authors>
                                  <fr:author>
                                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                                  </fr:author>
                                </fr:authors>
                                <fr:date>
                                  <fr:year>2025</fr:year>
                                </fr:date>
                                <fr:uri>https://patrick.sirref.org/ferris2025scientific_programming/</fr:uri>
                                <fr:display-uri>ferris2025scientific_programming</fr:display-uri>
                                <fr:route>/ferris2025scientific_programming/</fr:route>
                                <fr:title text="What we talk about when we talk about scientific programming">What we talk about when we talk about scientific programming</fr:title>
                                <fr:taxon>Reference</fr:taxon>
                                <fr:meta name="external">https://watch.eeg.cl.cam.ac.uk/w/aYXqXLtgQawYMjVXjSQtjx</fr:meta>
                                <fr:meta name="doi" />
                              </fr:frontmatter>
                              <fr:mainmatter>
                                <fr:tree show-metadata="false">
                                  <fr:frontmatter>
                                    <fr:authors>
                                      <fr:author>
                                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                                      </fr:author>
                                    </fr:authors>
                                    <fr:date>
                                      <fr:year>2025</fr:year>
                                    </fr:date>
                                    <fr:title text="Abstract ">Abstract </fr:title>
                                  </fr:frontmatter>
                                  <fr:mainmatter>
                                    <html:p><![CDATA[	Programming for the planet undoubtedly involves programming
	scientifically, but what kind of programming are we talking about
	and what makes it scientific? In what ways does it differ from
	other forms of programming, if at all? Is scientific programming,
	data science or machine learning fundamentally different to
	constructing a compiler or building a high-throughput web server?
	By considering how the scientific method (with its falsifiable
	hypotheses and repeatable and reproducible experiments) relates to
	scientific programming, I hope to explore how computer science and
	traditional programming techniques are coming up short in meeting
	the requirements of scientific programmers.]]></html:p>
                                  </fr:mainmatter>
                                </fr:tree>
                              </fr:mainmatter>
                            </fr:tree>
                            <fr:tree show-metadata="false" expanded="false" numbered="false">
                              <fr:frontmatter>
                                <fr:authors>
                                  <fr:author>
                                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                                  </fr:author>
                                  <fr:author>
                                    <fr:link href="https://patrick.sirref.org/Anil Madhavapeddy/" type="external">Anil Madhavapeddy</fr:link>
                                  </fr:author>
                                </fr:authors>
                                <fr:date>
                                  <fr:year>2025</fr:year>
                                </fr:date>
                                <fr:uri>https://patrick.sirref.org/ferris2025hazel_of_ocaml/</fr:uri>
                                <fr:display-uri>ferris2025hazel_of_ocaml</fr:display-uri>
                                <fr:route>/ferris2025hazel_of_ocaml/</fr:route>
                                <fr:title text="Generating a corpus of Hazel programs from ill-typed OCaml programs">Generating a corpus of Hazel programs from ill-typed OCaml programs</fr:title>
                                <fr:taxon>Reference</fr:taxon>
                                <fr:meta name="external">https://patrick.sirref.org/var/tyde2025.pdf</fr:meta>
                                <fr:meta name="doi" />
                              </fr:frontmatter>
                              <fr:mainmatter>
                                <fr:tree show-metadata="false">
                                  <fr:frontmatter>
                                    <fr:authors>
                                      <fr:author>
                                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                                      </fr:author>
                                      <fr:author>
                                        <fr:link href="https://patrick.sirref.org/Anil Madhavapeddy/" type="external">Anil Madhavapeddy</fr:link>
                                      </fr:author>
                                    </fr:authors>
                                    <fr:date>
                                      <fr:year>2025</fr:year>
                                    </fr:date>
                                    <fr:title text="Abstract ">Abstract </fr:title>
                                  </fr:frontmatter>
                                  <fr:mainmatter>
                                    <html:p>
		When developing a new programming language, having a large corpus of
		both correct and incorrect programs allows language designers to test
		and explore the capabilities of their new language. However,
		bootstrapping such a corpus of incorrect programs is time-consuming and
		arduous. We therefore explore how to reuse code from more mature
		languages to generate a corpus of ill-typed code for newer ones. We
		have developed a compiler to Hazel, an emerging language with typed
		holes, from the more mature OCaml ecosystem. We find it practical to
		generate a comprehensive corpus of ill-typed programs for Hazel
		development, and discuss future larger scale efforts towards bridging
		ecosystems.
 </html:p>
                                  </fr:mainmatter>
                                </fr:tree>
                              </fr:mainmatter>
                            </fr:tree>
                            <html:p>See also <fr:link href="https://patricoferris.github.io/hazel_of_ocaml/" type="external">the online hazel of ocaml compiler</fr:link></html:p>
                            <fr:tree show-metadata="false" expanded="false" numbered="false">
                              <fr:frontmatter>
                                <fr:authors>
                                  <fr:author>
                                    <fr:link href="https://patrick.sirref.org/Max Carroll/" type="external">Max Carroll</fr:link>
                                  </fr:author>
                                  <fr:author>
                                    <fr:link href="https://patrick.sirref.org/Anil Madhavapeddy/" type="external">Anil Madhavapeddy</fr:link>
                                  </fr:author>
                                  <fr:author>
                                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                                  </fr:author>
                                </fr:authors>
                                <fr:date>
                                  <fr:year>2025</fr:year>
                                </fr:date>
                                <fr:uri>https://patrick.sirref.org/carroll2025decomposable_type_highlighting/</fr:uri>
                                <fr:display-uri>carroll2025decomposable_type_highlighting</fr:display-uri>
                                <fr:route>/carroll2025decomposable_type_highlighting/</fr:route>
                                <fr:title text="Decomposable Type Highlighting for Bidirectional Type and Cast Systems">Decomposable Type Highlighting for Bidirectional Type and Cast Systems</fr:title>
                                <fr:taxon>Reference</fr:taxon>
                                <fr:meta name="external">https://maxcarroll0.github.io/papers/workshops/HATRA-decomposable-type-highlighting/</fr:meta>
                                <fr:meta name="doi" />
                              </fr:frontmatter>
                              <fr:mainmatter>
                                <fr:tree show-metadata="false">
                                  <fr:frontmatter>
                                    <fr:authors>
                                      <fr:author>
                                        <fr:link href="https://patrick.sirref.org/Max Carroll/" type="external">Max Carroll</fr:link>
                                      </fr:author>
                                      <fr:author>
                                        <fr:link href="https://patrick.sirref.org/Anil Madhavapeddy/" type="external">Anil Madhavapeddy</fr:link>
                                      </fr:author>
                                      <fr:author>
                                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                                      </fr:author>
                                    </fr:authors>
                                    <fr:date>
                                      <fr:year>2025</fr:year>
                                    </fr:date>
                                    <fr:title text="Abstract ">Abstract </fr:title>
                                  </fr:frontmatter>
                                  <fr:mainmatter>
                                    <html:p>
		 We explore how to provide programmers with an interactive
		 interface for explaining the process by which static types and
		 dynamic casts are derived, with the goal of improving the
		 debugging of static and dynamic type errors. To this end, we
		 define mathematical foundations for a decomposable highlighting
		 system within a bidirectional system, and show how these can be
		 propagated through dynamic types in a cast system. Our prototype
		 implementation in the gradually typed Hazel language includes a
		 web-based user interface, through which we highlight the
		 importance of type level debugging.
 </html:p>
                                  </fr:mainmatter>
                                </fr:tree>
                              </fr:mainmatter>
                            </fr:tree>
                            <fr:tree show-metadata="false" expanded="false" numbered="false">
                              <fr:frontmatter>
                                <fr:authors>
                                  <fr:author>
                                    <fr:link href="https://patrick.sirref.org/Michael Winston Dales/" type="external">Michael Winston Dales</fr:link>
                                  </fr:author>
                                  <fr:author>
                                    <fr:link href="https://patrick.sirref.org/Alison Eyres/" type="external">Alison Eyres</fr:link>
                                  </fr:author>
                                  <fr:author>
                                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                                  </fr:author>
                                  <fr:author>
                                    <fr:link href="https://patrick.sirref.org/Francesca A. Ridley" type="external">Francesca A. Ridley</fr:link>
                                  </fr:author>
                                  <fr:author>
                                    <fr:link href="https://patrick.sirref.org/Simon Tarr/" type="external">Simon Tarr</fr:link>
                                  </fr:author>
                                  <fr:author>
                                    <fr:link href="https://patrick.sirref.org/Anil Madhavapeddy/" type="external">Anil Madhavapeddy</fr:link>
                                  </fr:author>
                                </fr:authors>
                                <fr:date>
                                  <fr:year>2025</fr:year>
                                </fr:date>
                                <fr:uri>https://patrick.sirref.org/dales2025yirgacheffe/</fr:uri>
                                <fr:display-uri>dales2025yirgacheffe</fr:display-uri>
                                <fr:route>/dales2025yirgacheffe/</fr:route>
                                <fr:title text="Yirgacheffe: A Declarative Approach to Geospatial Data">Yirgacheffe: A Declarative Approach to Geospatial Data</fr:title>
                                <fr:taxon>Reference</fr:taxon>
                                <fr:meta name="external">https://dl.acm.org/doi/10.1145/3759536.3763806</fr:meta>
                                <fr:meta name="doi">10.1145/3759536.3763806</fr:meta>
                              </fr:frontmatter>
                              <fr:mainmatter>
                                <fr:tree show-metadata="false">
                                  <fr:frontmatter>
                                    <fr:authors>
                                      <fr:author>
                                        <fr:link href="https://patrick.sirref.org/Michael Winston Dales/" type="external">Michael Winston Dales</fr:link>
                                      </fr:author>
                                      <fr:author>
                                        <fr:link href="https://patrick.sirref.org/Alison Eyres/" type="external">Alison Eyres</fr:link>
                                      </fr:author>
                                      <fr:author>
                                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                                      </fr:author>
                                      <fr:author>
                                        <fr:link href="https://patrick.sirref.org/Francesca A. Ridley" type="external">Francesca A. Ridley</fr:link>
                                      </fr:author>
                                      <fr:author>
                                        <fr:link href="https://patrick.sirref.org/Simon Tarr/" type="external">Simon Tarr</fr:link>
                                      </fr:author>
                                      <fr:author>
                                        <fr:link href="https://patrick.sirref.org/Anil Madhavapeddy/" type="external">Anil Madhavapeddy</fr:link>
                                      </fr:author>
                                    </fr:authors>
                                    <fr:date>
                                      <fr:year>2025</fr:year>
                                    </fr:date>
                                    <fr:title text="Abstract ">Abstract </fr:title>
                                  </fr:frontmatter>
                                  <fr:mainmatter>
                                    <html:p><![CDATA[		We present Yirgacheffe, a declarative geospatial library that
		allows spatial algorithms to be implemented concisely, supports
		parallel execution, and avoids common errors by automatically
		handling data (large geospatial rasters) and resources (cores,
		memory, GPUs). Our primary user domain comprises ecologists,
		where a typical problem involves cleaning messy occurrence data,
		overlaying it over tiled rasters, combining layers, and deriving
		actionable insights from the results. We describe the successes
		of this approach towards driving key pipelines related to global
		biodiversity and describe the capability gaps that remain, hoping
		to motivate more research into geospatial domain-specific
		languages.]]></html:p>
                                  </fr:mainmatter>
                                </fr:tree>
                              </fr:mainmatter>
                            </fr:tree>
                            <html:hr />
                            <html:p>I had some great conversations with  <fr:link href="/kc/" title="KC Sivaramakrishnan" uri="https://patrick.sirref.org/kc/" display-uri="kc" type="local">KC </fr:link> too with respect to my current research. </html:p>
                          </fr:mainmatter>
                        </fr:tree>
                      </fr:mainmatter>
                    </fr:tree>
                    <fr:tree show-metadata="false" numbered="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2026</fr:year>
                          <fr:month>2</fr:month>
                          <fr:day>9</fr:day>
                        </fr:date>
                        <fr:title text="Future Work ">Future Work </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>As I enter my final year of the PhD, my goal would be to try and align more of  my fellowship work with my own research wherever it makes sense. This research  focuses on the following hypothesis: </html:p>
                        <html:blockquote>
                          <html:p>Embedding deep provenance tracking, reversible execution and mergeable  <![CDATA[histories directly into an interactive programming environment (a POSIX-like]]> <![CDATA[shell) greatly decreases the gap between exploratory scientific work and]]> reproducible, publishable results; all whilst leaving existing workflows  intact and being programming language agnostic. </html:p>
                        </html:blockquote>
                        <html:p>I want to focus on building these tools using  <fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link>,  <fr:link href="/eio/" title="Eio" uri="https://patrick.sirref.org/eio/" display-uri="eio" type="local">Eio </fr:link>,  <fr:link href="https://patrick.sirref.org/oxcaml/" type="external">OxCaml </fr:link> etc. There are other projects I wish to continue regardless, like  <fr:link href="/outreachy/" title="Outreachy" uri="https://patrick.sirref.org/outreachy/" display-uri="outreachy" type="local">Outreachy </fr:link><![CDATA[, though just as a coordinator (not a mentor).]]></html:p>
                        <fr:tree show-metadata="false" numbered="false">
                          <fr:frontmatter>
                            <fr:authors>
                              <fr:author>
                                <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                              </fr:author>
                            </fr:authors>
                            <fr:date>
                              <fr:year>2026</fr:year>
                              <fr:month>2</fr:month>
                              <fr:day>9</fr:day>
                            </fr:date>
                            <fr:title text="Overlapping PhD Work ">Overlapping PhD Work </fr:title>
                          </fr:frontmatter>
                          <fr:mainmatter>
                            <html:p>There are multiple projects that overlap with my work. For example,  <fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link>,  which I wrote a  <fr:link href="/irmin-retro/" title="Irmin Retrospective" uri="https://patrick.sirref.org/irmin-retro/" display-uri="irmin-retro" type="local">retrospective </fr:link> for. This is at the core of  <fr:link href="/shelter/" title="Shelter" uri="https://patrick.sirref.org/shelter/" display-uri="shelter" type="local">Shelter </fr:link> and suggests an extremely valid use case for a brancheable,  mergeable database. </html:p>
                            <html:p>In addition to this, continuing to work on  <fr:link href="/eio/" title="Eio" uri="https://patrick.sirref.org/eio/" display-uri="eio" type="local">Eio </fr:link> makes sense to me too.  <fr:link href="/eio/" title="Eio" uri="https://patrick.sirref.org/eio/" display-uri="eio" type="local">Eio </fr:link> currently has no maintainer and no active development, but the  <fr:link href="https://github.com/ocaml-multicore/eio/issues" type="external">issues  are piling up </fr:link>. In particular, I  am making heavy use of  <fr:link href="/eio/" title="Eio" uri="https://patrick.sirref.org/eio/" display-uri="eio" type="local">Eio </fr:link> in  <fr:link href="/merry/" title="Merry" uri="https://patrick.sirref.org/merry/" display-uri="merry" type="local">Merry </fr:link><![CDATA[, a POSIX(ish) shell written in]]> OCaml. Aside from research angles on brancheable and mergeable shells, I am  also quite interested in how this might look in terms of OxCaml. I met with  <fr:link href="/anilmadhavapeddy/" title="Anil Madhavapeddy" uri="https://patrick.sirref.org/anilmadhavapeddy/" display-uri="anilmadhavapeddy" type="local">Anil </fr:link> and  <fr:link href="/talex5/" title="Thomas Leonard" uri="https://patrick.sirref.org/talex5/" display-uri="talex5" type="local">Thomas </fr:link> recently to discuss the future of  <fr:link href="/eio/" title="Eio" uri="https://patrick.sirref.org/eio/" display-uri="eio" type="local">Eio </fr:link> and there was some agreement that we are all heavy users of it and hope  to keep up its maintenance and set of features. </html:p>
                            <html:p>One large piece of work that is sorely needed here is moving  <fr:link href="/eio/" title="Eio" uri="https://patrick.sirref.org/eio/" display-uri="eio" type="local">Eio </fr:link> to  <html:code>bytes</html:code> and not bigarray-backed  <html:code>Cstruct</html:code>s. Any libraries using  <html:code>bytesrw</html:code><![CDATA[ (e.g.]]> <html:code>jsont</html:code><![CDATA[) incur an extra copy of data into and out of the bytes.]]> <fr:link href="/anilmadhavapeddy/" title="Anil Madhavapeddy" uri="https://patrick.sirref.org/anilmadhavapeddy/" display-uri="anilmadhavapeddy" type="local">Anil </fr:link> has been  <fr:link href="https://anil.recoil.org/notes/oxcaml-httpz" type="external">working on some of the  pieces </fr:link> recently to make this  better! </html:p>
                          </fr:mainmatter>
                        </fr:tree>
                        <fr:tree show-metadata="false" numbered="false">
                          <fr:frontmatter>
                            <fr:authors>
                              <fr:author>
                                <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                              </fr:author>
                            </fr:authors>
                            <fr:date>
                              <fr:year>2026</fr:year>
                              <fr:month>2</fr:month>
                              <fr:day>9</fr:day>
                            </fr:date>
                            <fr:title text="Maintaining and Releasing my own libraries ">Maintaining and Releasing my own libraries </fr:title>
                          </fr:frontmatter>
                          <fr:mainmatter>
                            <html:p>I have published quite a few OCaml libraries in my time, below is just a few  <![CDATA[libraries (filtered to not include OCurrent projects).]]></html:p>
                            <html:pre><![CDATA[$ opam list --all --no-switch --columns=name,authors: | grep -E "sirref|Ferris" | cut -d " " -f1
carbon
geojson
geojsone
graft
hilite
ISO3166
jekyll-format
ppx_deriving_ezjsonm
ppx_deriving_yaml
rtree
search
topojson
topojsone
cid
multibase
multicodec
multihash
multihash-digestif]]></html:pre>
                            <html:p>Some of these are used in the community including  <html:code>hilite</html:code>,  <html:code>ppx_deriving_yaml</html:code> and the multi-codecs. I would like to do some general maintenance of some of  these tools and release a few iterations of  <fr:link href="/graft/" title="Graft" uri="https://patrick.sirref.org/graft/" display-uri="graft" type="local">graft </fr:link> which now makes use of  <fr:link href="/bib/" title="Bib" uri="https://patrick.sirref.org/bib/" display-uri="bib" type="local">bib </fr:link>. </html:p>
                          </fr:mainmatter>
                        </fr:tree>
                        <fr:tree show-metadata="false" numbered="false">
                          <fr:frontmatter>
                            <fr:authors>
                              <fr:author>
                                <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                              </fr:author>
                            </fr:authors>
                            <fr:date>
                              <fr:year>2026</fr:year>
                              <fr:month>2</fr:month>
                              <fr:day>9</fr:day>
                            </fr:date>
                            <fr:title text="Ppxlib Maintenance ">Ppxlib Maintenance </fr:title>
                          </fr:frontmatter>
                          <fr:mainmatter>
                            <html:p>By far, maintenance of  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link> takes up a majority of my time. I think,  given the other work I need to focus on, it would be great to try to minimise  the amount of time working on  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link>. In particular, perhaps only  maintaining  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link> as far as OCaml release-readiness is a possibility and  <![CDATA[important bug fixes (like]]><fr:link href="https://github.com/ocaml-ppx/ppxlib/pull/613" type="external">the OOM bug reported by  Jane Street </fr:link><![CDATA[).]]></html:p>
                          </fr:mainmatter>
                        </fr:tree>
                        <fr:tree show-metadata="false" numbered="false">
                          <fr:frontmatter>
                            <fr:authors>
                              <fr:author>
                                <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                              </fr:author>
                            </fr:authors>
                            <fr:date>
                              <fr:year>2026</fr:year>
                              <fr:month>2</fr:month>
                              <fr:day>9</fr:day>
                            </fr:date>
                            <fr:title text="Forester, Graft and Writing ">Forester, Graft and Writing </fr:title>
                          </fr:frontmatter>
                          <fr:mainmatter>
                            <html:p>With all of this work, I am eager to communicate what I am up to and my  thoughts on open source, OCaml, OxCaml etc. I am glad to be using  <fr:link href="/forester/" title="Forester" uri="https://patrick.sirref.org/forester/" display-uri="forester" type="local">Forester </fr:link> <![CDATA[to do this, particularly as it is written in OCaml (and could make great use of]]> my own work on  <fr:link href="/eio/" title="Eio" uri="https://patrick.sirref.org/eio/" display-uri="eio" type="local">Eio </fr:link><![CDATA[).]]></html:p>
                            <html:p>I hope to continue working on  <fr:link href="/graft/" title="Graft" uri="https://patrick.sirref.org/graft/" display-uri="graft" type="local">Graft </fr:link> and related tools like  <fr:link href="/bib/" title="Bib" uri="https://patrick.sirref.org/bib/" display-uri="bib" type="local">bib </fr:link>. But I  would also like to start writing some long-form content similar to the  <fr:link href="/irmin-retro/" title="Irmin Retrospective" uri="https://patrick.sirref.org/irmin-retro/" display-uri="irmin-retro" type="local">Irmin  retrospective </fr:link>. </html:p>
                          </fr:mainmatter>
                        </fr:tree>
                      </fr:mainmatter>
                    </fr:tree>
                  </fr:mainmatter>
                </fr:tree>
              </fr:mainmatter>
            </fr:tree>
          </fr:mainmatter>
        </fr:tree>
        <fr:tree show-metadata="true" expanded="false" toc="false" numbered="false">
          <fr:frontmatter>
            <fr:authors />
            <fr:uri>https://patrick.sirref.org/posts/</fr:uri>
            <fr:display-uri>posts</fr:display-uri>
            <fr:route>/posts/</fr:route>
            <fr:title text="Posts">Posts</fr:title>
          </fr:frontmatter>
          <fr:mainmatter>
            <html:p>Occasionally I write posts, mostly about OCaml or something related. </html:p>
            <html:p><fr:link href="/posts/atom.xml" type="external">An RSS feed is available </fr:link>. </html:p>
            <fr:tree show-metadata="false" expanded="false" toc="false" numbered="false">
              <fr:frontmatter>
                <fr:authors>
                  <fr:author>
                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                  </fr:author>
                </fr:authors>
                <fr:uri>https://patrick.sirref.org/modular-explicits/</fr:uri>
                <fr:display-uri>modular-explicits</fr:display-uri>
                <fr:route>/modular-explicits/</fr:route>
                <fr:title text="Modular Explicits in OCaml">Modular Explicits in OCaml</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>Abstraction, in OCaml, often refers to hiding a particular type's implementation  using a  <html:em>signature </html:em>. For example: </html:p>
                <html:pre class="hilite">
                  <html:code>
                    <html:span class="ocaml-keyword-other">module</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other">sig</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-keyword">type</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-entity-name-function-binding">t</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-keyword">val</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-entity-name-function-binding">add</html:span>
                    <html:span class="ocaml-source"> : t -&gt; t -&gt; t
</html:span>
                    <html:span class="ocaml-keyword-other">end</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other">struct</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-keyword-other">type</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">t</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-support-type">int</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-keyword">let</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-entity-name-function-binding">add</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Int</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">add</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-keyword-other">end</html:span>
                    <html:span class="ocaml-source">
</html:span>
                  </html:code>
                </html:pre>
                <html:p>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. </html:p>
                <html:p>The goal of this post is to eventually discuss OCaml 5.5's  <fr:link href="/abs-modular-explicits/" title="Modular Explicits  " uri="https://patrick.sirref.org/abs-modular-explicits/" display-uri="abs-modular-explicits" type="local">modular  explicits </fr:link> which is yet another feature that can allow  a single piece of code to be used in various situations. </html:p>
                <fr:tree show-metadata="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:uri>https://patrick.sirref.org/abs-polymorphism/</fr:uri>
                    <fr:display-uri>abs-polymorphism</fr:display-uri>
                    <fr:route>/abs-polymorphism/</fr:route>
                    <fr:title text="Polymorphism  ">Polymorphism  </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>The most prevalent kind of abstraction is polymorphism. For example,  <html:code>List.length</html: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. </html:p>
                    <html:p><html:code>List.mem</html:code> is a good example; in order to be polymorphic  <html:code>List.mem</html:code> relies on  <html:code><![CDATA[Stdlib.(=)]]></html:code>, the polymorphic equality operator. In turn, this operator  achieves its polymorphism by performing a structural comparison of the runtime  representation of its arguments. </html:p>
                    <html:p><![CDATA[A common way to overcome this is to use higher-order functions (functions that]]> <![CDATA[take functions as arguments).]]></html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-mdx-hash">#</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword">rec </html:span>
                        <html:span class="ocaml-entity-name-function-binding">mem</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-variable-parameter-optional">?</html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-variable-parameter-optional">eq</html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Stdlib</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">v</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">function</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword-other">|</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-list"><![CDATA[[]]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-boolean">false</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword-other">|</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">x</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">xs</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">eq</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">v</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">x</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">||</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">mem</html:span>
                        <html:span class="ocaml-source"> ~</html:span>
                        <html:span class="ocaml-source">eq</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">v</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">xs</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-other">val</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">mem</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> ?</html:span>
                        <html:span class="ocaml-source">eq</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-storage-type">'a</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-storage-type">'a</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">bool</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-storage-type">'a</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-storage-type">'a</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">list</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">bool</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">&lt;</html:span>
                        <html:span class="ocaml-keyword-other">fun</html:span>
                        <html:span class="ocaml-keyword-operator">&gt;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-mdx-hash">#</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">mem_int_list</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">mem</html:span>
                        <html:span class="ocaml-source"> ~</html:span>
                        <html:span class="ocaml-source">eq</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Int</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">equal</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-other">val</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">mem_int_list</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">int</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">int</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">list</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">bool</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">&lt;</html:span>
                        <html:span class="ocaml-keyword-other">fun</html:span>
                        <html:span class="ocaml-keyword-operator">&gt;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p><![CDATA[This works well in plenty of cases (]]><html:code>List.map</html:code>,  <html:code>Hashtbl.iter</html:code><![CDATA[, etc.), however,]]> it doesn't scale well from a user's perspective if the body of the function  <![CDATA[requires lots of specific functions (e.g.]]><html:code>compare</html:code>,  <html:code>length</html:code>,  <html:code>pp</html:code><![CDATA[). At the]]> same time, we want to avoid the precarious duck-typing of something like Python  too. </html:p>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:uri>https://patrick.sirref.org/abs-functors/</fr:uri>
                    <fr:display-uri>abs-functors</fr:display-uri>
                    <fr:route>/abs-functors/</fr:route>
                    <fr:title text="Functors  ">Functors  </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>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.  <html:code>Set.Make</html:code> is a functor that requires a module  adhereing to the  <html:code>Set.OrderedType</html:code> interface. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">IntSet</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Set</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Make</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Int</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">StringSet</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Set</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Make</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">String</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>Functors make it a lot easier to write implementations that depend on a large  variety of functionality.  <html:code>Set.OrderedType</html:code> is relatively tame in this sense,  only needing a type  <html:code>t</html:code> and a  <html:code>compare : t -&gt; t -&gt; int</html:code> function. </html:p>
                    <html:p><fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link>, on the other hand, has functors that require users to provide  <fr:link href="https://ocaml.org/p/irmin/3.11.0/doc/irmin/Irmin/Schema/module-type-S/index.html" type="external">Schemas </fr:link>.  I have more thoughts about this API design in  <fr:link href="/irmin-retro/" title="Irmin Retrospective" uri="https://patrick.sirref.org/irmin-retro/" display-uri="irmin-retro" type="local">my Irmin  retrospective </fr:link>. </html:p>
                    <html:p>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  <fr:link href="https://patricoferris.github.io/js_of_ocamlopt/#code=bGV0IGYgaSA9CiAgbGV0IG1vZHVsZSBJID0gU2V0Lk1ha2UgKEludCkgaW4KICBJLmNhcmRpbmFsIGk=" type="external">js_of_ocamlopt </fr:link> and see the generated output for how functors are applied. </html:p>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:uri>https://patrick.sirref.org/abs-fcm-exist/</fr:uri>
                    <fr:display-uri>abs-fcm-exist</fr:display-uri>
                    <fr:route>/abs-fcm-exist/</fr:route>
                    <fr:title text="First-class Modules and Existentials  ">First-class Modules and Existentials  </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>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  <html:em>pack </html:em> together a value of a particular type alongside a module that  works with those kinds of values. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-keyword-other">type</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">set</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Set</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Set</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">with</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">type</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-storage-type">'a</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">*</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-storage-type">'a</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">set</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">size</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Set</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">s</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">cardinal</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">s</html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>Packaging up integer sets is fairly straight-forward. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-mdx-hash">#</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">int_empty_set</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Set</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">IntSet</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">IntSet</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">empty</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-other">val</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">int_empty_set</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">set</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Set</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-operator">&lt;</html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-keyword-operator">&gt;</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">&lt;</html:span>
                        <html:span class="ocaml-source">poly</html:span>
                        <html:span class="ocaml-keyword-operator">&gt;</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>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. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-mdx-hash">#</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">type</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">any</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Any</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-storage-type">'a</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">any</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-other">type</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">any</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Any</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-storage-type">'a</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">any</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-mdx-hash">#</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">any</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">v</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Any</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">v</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-other">val</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">any</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-storage-type">'a</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">any</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">&lt;</html:span>
                        <html:span class="ocaml-keyword-other">fun</html:span>
                        <html:span class="ocaml-keyword-operator">&gt;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>Getting back into a typed world often involves some  <fr:link href="https://github.com/dbuenzli/hmap/blob/e54eb3f7d7dbada0724fd023c334d0b5a29c8479/src/hmap.ml#L120-L127" type="external">type witness  gymnastics </fr:link> 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  <fr:link href="https://github.com/fn06/shelter/blob/e71d6df79ab7c43b092de145e9e80482ae3af118/src/lib/store.ml#L1-L10" type="external">package together Irmin stores with implementations </fr:link>. </html:p>
                    <html:p>You could not, however, simply return the value that was packed away inside the existential. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-mdx-hash">#</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">woops</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Set</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language">_</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">s</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">s</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Line</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-numeric-decimal-integer">1</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">characters</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-numeric-decimal-integer">26</html:span>
                        <html:span class="ocaml-keyword-operator">-</html:span>
                        <html:span class="ocaml-constant-numeric-decimal-integer">27</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Error</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">The</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">value</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">s</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">has</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">type</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">$</html:span>
                        <html:span class="ocaml-source">a</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">but</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">an</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">expression</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">was</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">expected</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">of</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">type</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-storage-type">'a</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">       </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">The</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">type</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">constructor</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">$</html:span>
                        <html:span class="ocaml-source">a</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">would</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">escape</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">its</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">scope</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">       </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Hint</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">$</html:span>
                        <html:span class="ocaml-source">a</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">is</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">an</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">existential</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">type</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">bound</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">by</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">the</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">constructor</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Set</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p><![CDATA[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. </html:p>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:uri>https://patrick.sirref.org/abs-modular-explicits/</fr:uri>
                    <fr:display-uri>abs-modular-explicits</fr:display-uri>
                    <fr:route>/abs-modular-explicits/</fr:route>
                    <fr:title text="Modular Explicits  ">Modular Explicits  </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>OCaml 5.5 has  <html:em>module-dependent function types </html:em> also known as  <html:em>explicits  modular </html:em>. The type of a function can now depend on types that come from a  module that is also part of the function definition. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-mdx-hash">#</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">set_length</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Set</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">int</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword-other">fun</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">v</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">cardinal</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">v</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-other">val</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">set_length</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Set</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">int</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">&lt;</html:span>
                        <html:span class="ocaml-keyword-other">fun</html:span>
                        <html:span class="ocaml-keyword-operator">&gt;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-mdx-hash">#</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">set_length</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">IntSet</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">IntSet</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">empty</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-operator">-</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">int</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-numeric-decimal-integer">0</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-mdx-hash">#</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">set_length</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">StringSet</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">StringSet</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">empty</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-operator">-</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">int</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-numeric-decimal-integer">0</html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>In fact, we can now  <html:em>return </html:em> values of a particular type that depends on a  particular module! </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-mdx-hash">#</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">empty_set</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Set</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> 
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword-other">fun</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">empty</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-other">val</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">empty_set</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Set</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">&lt;</html:span>
                        <html:span class="ocaml-keyword-other">fun</html:span>
                        <html:span class="ocaml-keyword-operator">&gt;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-mdx-hash">#</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">empty_set</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">IntSet</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-operator">-</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">IntSet</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">&lt;</html:span>
                        <html:span class="ocaml-source">abstr</html:span>
                        <html:span class="ocaml-keyword-operator">&gt;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-mdx-hash">#</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">empty_set</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">StringSet</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-operator">-</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">StringSet</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">&lt;</html:span>
                        <html:span class="ocaml-source">abstr</html:span>
                        <html:span class="ocaml-keyword-operator">&gt;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>Or, we can dynamically select implementations and values. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-mdx-hash">#</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">with_impl</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> 
</html:span>
                        <html:span class="ocaml-source">    </html:span>
                        <html:span class="ocaml-source">config</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-support-type">string</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Set</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-storage-type">'a</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-storage-type">'a</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> 
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword-other">fun</html:span>
                        <html:span class="ocaml-source"> ~</html:span>
                        <html:span class="ocaml-source">config</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">fn</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword-other">match</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">String</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">lowercase_ascii</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">config</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">with</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword-other">|</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">string</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">fn</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">StringSet</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">StringSet</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">empty</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword-other">|</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">int</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">fn</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">IntSet</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">IntSet</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">empty</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword-other">|</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">c</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">invalid_arg</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">c</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-other">val</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">with_impl</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">config</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-support-type">string</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Set</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">S</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-storage-type">'a</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-storage-type">'a</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword-operator">&lt;</html:span>
                        <html:span class="ocaml-keyword-other">fun</html:span>
                        <html:span class="ocaml-keyword-operator">&gt;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>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  <fr:link href="https://github.com/ocurrent/obuilder" type="external">OBuilder's </fr:link> use of  existentials with modular explicits: </html:p>
                    <html:pre><![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]]></html:pre>
                    <html:p>I think the code is more pragmatic; there is no longer an indirection via a  type called  <html:code>builder</html:code>. The extra type annotations do add a little noise. Roll  on  <html:em>modular implicits </html:em>. </html:p>
                  </fr:mainmatter>
                </fr:tree>
              </fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="false" expanded="false" toc="false" numbered="false">
              <fr:frontmatter>
                <fr:authors>
                  <fr:author>
                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                  </fr:author>
                </fr:authors>
                <fr:date>
                  <fr:year>2026</fr:year>
                  <fr:month>3</fr:month>
                  <fr:day>9</fr:day>
                </fr:date>
                <fr:uri>https://patrick.sirref.org/vibecoding-etiquette/</fr:uri>
                <fr:display-uri>vibecoding-etiquette</fr:display-uri>
                <fr:route>/vibecoding-etiquette/</fr:route>
                <fr:title text="Vibecoding Etiquette">Vibecoding Etiquette</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>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. </html:p>
                <html:p>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  <![CDATA[US Department of War (I struggle to find the meaningful difference between]]> <fr:link href="https://www.anthropic.com/news/where-stand-department-war" type="external">"opertational planning" vs. "operational decision-making" given the leaders of  the US DoW </fr:link><![CDATA[),]]> 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. </html:p>
                <html:p>Everybody can draw their line where they want, and I am, in good faith, trying to find  where mine should be. </html:p>
                <html:p>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. </html:p>
                <html:p>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.  <fr:link href="https://github.com/ocaml-multicore/eio/blob/main/HACKING.md#ai-generated-code" type="external">Eio's "AI-generated  Code" </fr:link> subsection is succinct and prohibits contributions that  <html:em>solely </html:em> use AI. </html:p>
                <html:blockquote>
                  <html: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. </html:p>
                  <html: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. </html:p>
                  <html: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. </html:p>
                </html:blockquote>
                <html:p>Additionally, I plead to other developers to  <html:em>own </html:em> their use of these tools.  Please, make Claude a co-author of the commits where Claude has generated  <html:em>any </html: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  <fr:link href="https://github.com/ocaml/ocaml/blob/trunk/AI.md" type="external">OCaml compiler's AI notice </fr:link> which includes: </html:p>
                <html:blockquote>
                  <html: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. </html:p>
                </html:blockquote>
              </fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="false" expanded="false" toc="false" numbered="false">
              <fr:frontmatter>
                <fr:authors>
                  <fr:author>
                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                  </fr:author>
                </fr:authors>
                <fr:date>
                  <fr:year>2025</fr:year>
                  <fr:month>10</fr:month>
                  <fr:day>24</fr:day>
                </fr:date>
                <fr:uri>https://patrick.sirref.org/icfp-2025/</fr:uri>
                <fr:display-uri>icfp-2025</fr:display-uri>
                <fr:route>/icfp-2025/</fr:route>
                <fr:title text="ICFP 2025">ICFP 2025</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>Two weeks ago I was fortunate enough to attend the  <fr:link href="https://icfp25.sigplan.org/" type="external">International Conference on  Functional Programming </fr:link> 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. </html:p>
                <html:p><![CDATA[I must thank my office mate (and friend!)]]><fr:link href="https://ryan.freumh.org/" type="external">Ryan Gibb </fr:link> for his camaraderie and sage advice: "the best track is  <html:em>hallway </html:em> track". Not  to mention all of his  <fr:link href="https://ryan.freumh.org/photos.html" type="external">photos </fr:link> too. Thanks  Ryan! </html:p>
                <html:div style="text-align: center">
  <html:img class="inner-img" src="/bafkrmid2d6u3qdufa6m5gogavtwm6uqksaicozrc5s2unrtzjtth3hpvey.jpeg" alt="Description follows image." />
</html:div>
                <html:p>From right to left, top to bottom:  <fr:link href="https://patrick.sirref.org/anil madhavapeddy/" type="external">Anil Madhavapeddy </fr:link>,  <fr:link href="https://patrick.sirref.org/sadiq jaffer/" type="external">Sadiq Jaffer </fr:link>,  <fr:link href="https://patrick.sirref.org/patrick ferris/" type="external">Patrick Ferris </fr:link>,  <fr:link href="https://patrick.sirref.org/ryan gibb/" type="external">Ryan Gibb </fr:link> and  <fr:link href="https://patrick.sirref.org/roy ang/" type="external">Roy Ang </fr:link>. </html:p>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>10</fr:month>
                      <fr:day>24</fr:day>
                    </fr:date>
                    <fr:title text="Random Hacking ">Random Hacking </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>Below are just some of the pieces of random hacking I got up to whilst in  Singapore. </html:p>
                    <fr:tree show-metadata="false" numbered="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:uri>https://patrick.sirref.org/oxcaml-and-uring/</fr:uri>
                        <fr:display-uri>oxcaml-and-uring</fr:display-uri>
                        <fr:route>/oxcaml-and-uring/</fr:route>
                        <fr:title text="OxCaml and Uring">OxCaml and Uring</fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>Jane Street were a big presence at ICFP 2025, carting along with  them a shiny new OCaml compiler:  <fr:link href="https://oxcaml.org/" type="external">OxCaml </fr:link>. If have been  <fr:link href="/try-oxcaml/" title="Try OxCaml" uri="https://patrick.sirref.org/try-oxcaml/" display-uri="try-oxcaml" type="local">playing around with OxCaml recently </fr:link> but nothing outside  toplevels in Javascript. Until now! </html:p>
                        <html:p>After talking to  <fr:link href="/dra27/" title="David Allsopp" uri="https://patrick.sirref.org/dra27/" display-uri="dra27" type="local">David </fr:link>, I spent some time converting a small corner of  the  <fr:link href="https://github.com/ocaml-multicore/ocaml-uring" type="external">ocaml-uring </fr:link> library to use  a part of  <fr:link href="https://patrick.sirref.org/oxcaml/" type="external">OxCaml </fr:link>. In particular making the following change: </html:p>
                        <html:pre class="hilite">
                          <html:code>
                            <html:span class="ocaml-source">  </html:span>
                            <html:span class="ocaml-keyword-other">module</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">Heap</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other">struct</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">    </html:span>
                            <html:span class="ocaml-keyword-other">type</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">ptr</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-support-type">int32</html:span>
                            <html:span class="ocaml-keyword-other">#</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">    </html:span>
                            <html:span class="ocaml-comment-block"><![CDATA[(*]]></html:span>
                            <html:span class="ocaml-comment-block"> ... </html:span>
                            <html:span class="ocaml-comment-block"><![CDATA[*)]]></html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">  </html:span>
                            <html:span class="ocaml-keyword-other">end</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">  </html:span>
                            <html:span class="ocaml-keyword-other">type</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">cqe</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[{]]></html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">    </html:span>
                            <html:span class="ocaml-source">user_data_id</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">Heap</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                            <html:span class="ocaml-source">ptr</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">    </html:span>
                            <html:span class="ocaml-source">res</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-support-type">int32</html:span>
                            <html:span class="ocaml-keyword-other">#</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">  </html:span>
                            <html:span class="ocaml-source"><![CDATA[}]]></html:span>
                            <html:span class="ocaml-source">
</html:span>
                          </html:code>
                        </html:pre>
                        <html:p><![CDATA[The idea being that a completion queue entry (a notification that some]]> <![CDATA[operation has completed) could be fully represented using 64 bits (two 32-bit,]]> <fr:link href="https://oxcaml.org/documentation/unboxed-types/01-intro/" type="external">unboxed values </fr:link><![CDATA[).]]> You can  <fr:link href="https://github.com/ocaml-multicore/ocaml-uring/compare/main...patricoferris:ocaml-uring:oxcaml?expand=1" type="external">see how this impacted the  library </fr:link>!  <![CDATA[I'm not certain about this change (and I'm sure I did it wrong) but it was nice]]> to realise  <fr:link href="https://patrick.sirref.org/oxcaml/" type="external">OxCaml </fr:link> gives you this kind of control. However, I am worried  about the ergonomics of manipulating values like  <html:code>int32#</html:code> and the temptation to  case it into an  <html:code>int</html:code><![CDATA[ (presumably losing a good portion of the value of having]]> <![CDATA[an unboxed value in the first place).]]></html:p>
                      </fr:mainmatter>
                    </fr:tree>
                    <fr:tree show-metadata="false" numbered="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2025</fr:year>
                          <fr:month>10</fr:month>
                          <fr:day>24</fr:day>
                        </fr:date>
                        <fr:title text="Bibtex Parser ">Bibtex Parser </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>On the flight over to Singapore, I started to write a post for this website.  Some readers may remember that I use  <fr:link href="/forester/" title="Forester" uri="https://patrick.sirref.org/forester/" display-uri="forester" type="local">forester </fr:link> after a preprocessing step  via  <fr:link href="/graft/" title="Graft" uri="https://patrick.sirref.org/graft/" display-uri="graft" type="local">graft </fr:link> to build this site. Part of that preprocessing consumes bibtex  files and outputs forester trees. For the initial  <fr:link href="/graft/" title="Graft" uri="https://patrick.sirref.org/graft/" display-uri="graft" type="local">graft </fr:link> release I used the  excellent  <fr:link href="https://github.com/Octachron/talaria_bibtex" type="external">Talaria Bibtex </fr:link> 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  <![CDATA[straight-forward to use (if a little fast-and-loose when it comes to types...).]]> And so I built  <fr:link href="/bib/" title="Bib" uri="https://patrick.sirref.org/bib/" display-uri="bib" type="local">bib </fr:link>. </html:p>
                        <html:p>This was my first real attempt at using the  <fr:link href="https://ocaml.org/p/bytesrw" type="external">Bytesrw </fr:link> library. I was happy with the results,  although I did have to copy a substantial amount of code from  <fr:link href="https://ocaml.org/p/jsont" type="external">other  bytesrw-compatible libraries </fr:link>. I'd be happy to shift  to this  <html:code>bytes</html:code>-first world if it wasn't for the ever-present-in-my-mind issue  of relocatable values in the OCaml heap! </html:p>
                      </fr:mainmatter>
                    </fr:tree>
                    <fr:tree show-metadata="false" numbered="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2025</fr:year>
                          <fr:month>10</fr:month>
                          <fr:day>24</fr:day>
                        </fr:date>
                        <fr:title text="Geocaml Libraries ">Geocaml Libraries </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>There has been some excellent  <fr:link href="/outreachy/" title="Outreachy" uri="https://patrick.sirref.org/outreachy/" display-uri="outreachy" type="local">outreachy </fr:link> work happening on the  <fr:link href="https://github.com/geocaml/ocaml-tiff" type="external">geocaml/ocaml-tiff </fr:link> library which is a  potential Outreachy internship project for December 2025. More on this in a future post. </html:p>
                        <html:p><![CDATA[On the way back (and a little during the conference), I spent some time building an OCaml]]> counterpart to  <fr:link href="https://github.com/ucam-eo/geotessera/" type="external">geotessera </fr:link>, a library for working  with  <fr:link href="/tessera2025/" title="TESSERA: Temporal Embeddings of Surface Spectra for Earth Representation and Analysis" uri="https://patrick.sirref.org/tessera2025/" display-uri="tessera2025" type="local">Tessera </fr:link>. The library is not ready for people to use directly, but I was  working on various constituent parts including: </html:p>
                        <html:ul>
                          <html:li>
                            <html:p><fr:link href="https://github.com/geocaml/ocaml-proj" type="external">Modern OCaml bindings to PROJ </fr:link><![CDATA[ (a coordinate reference system projection library)]]></html:p>
                          </html:li>
                          <html:li>
                            <html:p>
                              <fr:link href="https://github.com/geocaml/ocaml-wkt" type="external">Further work on a WKT library for OCaml </fr:link>
                            </html:p>
                          </html:li>
                          <html:li>
                            <html:p>Coming soon... ocaml-geotessera </html:p>
                          </html:li>
                        </html:ul>
                      </fr:mainmatter>
                    </fr:tree>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>10</fr:month>
                      <fr:day>24</fr:day>
                    </fr:date>
                    <fr:title text="Talks ">Talks </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <fr:tree show-metadata="false" numbered="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2025</fr:year>
                          <fr:month>10</fr:month>
                          <fr:day>24</fr:day>
                        </fr:date>
                        <fr:title text="Hazel of OCaml at TyDe ">Hazel of OCaml at TyDe </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>The  <html:em>type-driven development </html:em><![CDATA[ (TyDe) workshop was held on the first day of ICFP at the]]> <fr:link href="https://www.comp.nus.edu.sg/" type="external">NUS School of Computing </fr:link>. 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  <html:em>theory </html:em>, presenting the formal mathematics of  interesting type systems with less focus on  <html:em>why </html:em> it might be useful to have  such an exotic type system... but then again, that was the nature of the entire  conference. </html:p>
                        <html:p>I presented a talk on  <fr:link href="/hazel-of-ocaml/" title="A Transpiler from OCaml to Hazel" uri="https://patrick.sirref.org/hazel-of-ocaml/" display-uri="hazel-of-ocaml" type="local">hazel_of_ocaml </fr:link>. The  <fr:link href="https://patrick.sirref.org/var/tyde2025.pdf" type="external">slides are  here </fr:link>, along with the  <fr:link href="https://patrick.sirref.org/var/tyde2025-ea.pdf" type="external">extended  abstract </fr:link>. 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  <fr:link href="https://maxcarroll0.github.io/" type="external">Max  Carroll's </fr:link> excellent  <fr:link href="/part-ii-hazel/" title="Type Error Debugging in Hazel" uri="https://patrick.sirref.org/part-ii-hazel/" display-uri="part-ii-hazel" type="local">part II </fr:link> project, which he presented at the  <fr:link href="https://maxcarroll0.github.io/papers/workshops/HATRA-decomposable-type-highlighting/" type="external">HATRA  workshop </fr:link>:  <html:em>Decomposable Type Highlighting for Bidirectional Type and Cast Systems </html:em>. </html:p>
                      </fr:mainmatter>
                    </fr:tree>
                    <fr:tree show-metadata="false" numbered="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2025</fr:year>
                          <fr:month>10</fr:month>
                          <fr:day>24</fr:day>
                        </fr:date>
                        <fr:title text="Scientific Programming at PROPL ">Scientific Programming at PROPL </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>I think it is important to be honest whenever you get a talk accepted that you  otherwise feel should not have been. My talk " <html:em>about scientific programming  what we talk about when we talk </html:em>" is one such talk. The  <fr:link href="https://patrick.sirref.org/var/propl2025.pdf" type="external">slides are  here </fr:link>. 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. </html:p>
                        <fr:tree show-metadata="false" numbered="false">
                          <fr:frontmatter>
                            <fr:authors>
                              <fr:author>
                                <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                              </fr:author>
                            </fr:authors>
                            <fr:date>
                              <fr:year>2025</fr:year>
                              <fr:month>10</fr:month>
                              <fr:day>24</fr:day>
                            </fr:date>
                            <fr:title text="TMF Data Discrepancies Redux ">TMF Data Discrepancies Redux </fr:title>
                          </fr:frontmatter>
                          <fr:mainmatter>
                            <html:p>On the eve of my talk, I decided to re-run some analysis I did a few years ago  on the  <fr:link href="https://forobs.jrc.ec.europa.eu/TMF/data#downloads" type="external">tropical moist forest  dataset </fr:link>, 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. </html:p>
                            <html:table>
    <html:tbody>
    <html:tr>
    <html:td><html:strong>Land Use Class</html:strong></html:td>
    <html:td><html:strong>Percent Change</html:strong></html:td>
    </html:tr>
    <html:tr>
    <html:td>Undisturbed</html:td>
    <html:td> -2.9</html:td>
    </html:tr>
    <html:tr>
    <html:td>Degraded</html:td>
    <html:td> -5.5</html:td>
    </html:tr>
    <html:tr style="background: yellow">
    <html:td>Deforested</html:td>
    <html:td> 8.6</html:td>
    </html:tr>
    <html:tr>
    <html:td>Regrowth</html:td>
    <html:td> 0.5</html:td>
    </html:tr>
    <html:tr>
    <html:td>Water</html:td>
    <html:td> 0.0</html:td>
    </html:tr>
    <html:tr>
    <html:td>Other</html:td>
    <html:td>-0.6</html:td>
    </html:tr>
    </html:tbody>
</html:table>
                            <html:p>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  <html:em>8.6 </html:em> percent! </html:p>
                            <html:p>As a somewhat tangential, though related, aside, I had the pleasure of talking  to  <fr:link href="https://cs.nyu.edu/~shw8119/" type="external">Sam Westrick </fr:link>,  <fr:link href="https://forthoney.github.io/" type="external">Seong-Heon  Jung </fr:link> and  <fr:link href="https://svishnus.github.io/" type="external">Sundara Vishnu  Satish </fr:link> of the  <fr:link href="https://nyu-parcour.github.io/" type="external">ParCour </fr:link> research group. They were telling me  about  <fr:link href="https://github.com/mpllang/mpl" type="external">MaPLe </fr:link>, a programming language from the  MLs built for parallelism. We discussed some ideas of using real-world, geospatial  algorithms as benchmarks for MaPLe.  <fr:link href="/mdales/" title="Michael W. Dales" uri="https://patrick.sirref.org/mdales/" display-uri="mdales" type="local">Michael </fr:link>, if you got this far  remind me to chat to you about this! </html:p>
                          </fr:mainmatter>
                        </fr:tree>
                        <fr:tree show-metadata="false" numbered="false">
                          <fr:frontmatter>
                            <fr:authors>
                              <fr:author>
                                <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                              </fr:author>
                            </fr:authors>
                            <fr:date>
                              <fr:year>2025</fr:year>
                              <fr:month>10</fr:month>
                              <fr:day>24</fr:day>
                            </fr:date>
                            <fr:title text="Shelter Reactions ">Shelter Reactions </fr:title>
                          </fr:frontmatter>
                          <fr:mainmatter>
                            <html:p>At the end of my talk, I briefly mentioned  <fr:link href="/shelter/" title="Shelter" uri="https://patrick.sirref.org/shelter/" display-uri="shelter" type="local">shelter </fr:link>. 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  <html:em>undo </html:em>" seemed to capture the attention of most people. </html:p>
                            <html:p>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  <fr:link href="https://kcsrk.info/" type="external">KC </fr:link> about the underlying  <fr:link href="https://patrick.sirref.org/mrdt/" type="external">MRDT </fr:link> in  <fr:link href="/shelter/" title="Shelter" uri="https://patrick.sirref.org/shelter/" display-uri="shelter" type="local">Shelter </fr:link> and how we might think about collaborating in the future on  MRDT-related work. </html:p>
                            <html:p>Related to that, I managed to spend the evening in  <fr:link href="https://www.openstreetmap.org/relation/18195609#map=16/1.28090/103.84222" type="external">Chinatown </fr:link> with  <fr:link href="https://dynamicaspects.org/research/" type="external">Roly Perera </fr:link>. Roly's work has  focused on  <fr:link href="https://f.luid.org/" type="external">Fluid </fr:link>, a transparency-based programming  language that allows authors to reveal their computation to their user.  Excitingly, Roly presented a  <fr:link href="https://conf.researchr.org/details/icfp-splash-2025/propl-2025-papers/10/Authoring-Tools-for-Transparent-Climate-Reporting" type="external">new text-based part of the  language </fr:link> 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  <html:em>preserve </html:em> existing workflows. Roly was great at pulling that  out of the current work I have been doing. </html:p>
                          </fr:mainmatter>
                        </fr:tree>
                      </fr:mainmatter>
                    </fr:tree>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>10</fr:month>
                      <fr:day>24</fr:day>
                    </fr:date>
                    <fr:title text="Other Talks and Highlights ">Other Talks and Highlights </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>I was a part of, often in a very small way, some other talks that were presented at ICFP including </html:p>
                    <html:ul>
                      <html:li>
                        <html:p><fr:link href="https://www.youtube.com/watch?v=j84ocjlj1JA&amp;amp;t=12880s" type="external">Functional Networking for Docker </fr:link>, I encourage you to read  <fr:link href="/anilmadhavapeddy/" title="Anil Madhavapeddy" uri="https://patrick.sirref.org/anilmadhavapeddy/" display-uri="anilmadhavapeddy" type="local">Anil's </fr:link>  <fr:link href="https://anil.recoil.org/notes/icfp25-ocaml5-js-docker#functional-networking-at-docker" type="external">notes on the topic </fr:link>. It is also worth mentioning  <fr:link href="/anilmadhavapeddy/" title="Anil Madhavapeddy" uri="https://patrick.sirref.org/anilmadhavapeddy/" display-uri="anilmadhavapeddy" type="local">Anil's </fr:link>  <fr:link href="https://anil.recoil.org/notes/icfp25-post-posix" type="external">post-posix talk </fr:link><![CDATA[ (not unrelated to my Uring musings above).]]></html:p>
                      </html:li>
                      <html:li>
                        <html:p><fr:link href="/mdales/" title="Michael W. Dales" uri="https://patrick.sirref.org/mdales/" display-uri="mdales" type="local">Michael </fr:link> gave an excellent,  <html:em>very live </html:em>, talk about  <fr:link href="https://conf.researchr.org/details/icfp-splash-2025/propl-2025-papers/6/Yirgacheffe-a-declarative-approach-to-geospatial-data" type="external">Yirgacheffe </fr:link> at PROPL which I thoroughly enjoyed. I'm also excited about his recent developments which I'm sure you can clue into  <fr:link href="https://digitalflapjack.com/weeknotes/" type="external">over on his blog </fr:link>. </html:p>
                      </html:li>
                    </html:ul>
                    <html:p>Below is a non-exhaustive list of talks I enjoyed whilst at the conference.  Some relevant, most of them not! </html:p>
                    <html:ul>
                      <html:li>
                        <html:p>By far, one of the best talks was  <fr:link href="https://icfp25.sigplan.org/details/icfp-2025-papers/13/Polynomial-Time-Program-Equivalence-for-Machine-Knitting" type="external">Polynomial-time Program Equivalence for Machine Knitting </fr:link>. 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". </html:p>
                      </html:li>
                      <html:li>
                        <html:p>I attended most of the  <fr:link href="https://conf.researchr.org/details/icfp-splash-2025/icfp-splash-2025-tutorials/5/A-guided-tour-through-Oxidized-OCaml" type="external">OxCaml tutorial </fr:link> presented by the incredibly friendly  <fr:link href="https://gavinleroy.com/" type="external">Gavin Gray </fr:link>. </html:p>
                      </html:li>
                      <html:li>
                        <html:p><fr:link href="/ryangibb/" title="Ryan Gibb" uri="https://patrick.sirref.org/ryangibb/" display-uri="ryangibb" type="local">Ryan </fr:link>'s talk  <fr:link href="https://conf.researchr.org/details/icfp-splash-2025/propl-2025-papers/13/Spatial-Programming-for-Environmental-Monitoring" type="external">Spatial Programming for Environmental Monitoring </fr:link> at PROPL was excellent. </html:p>
                      </html:li>
                    </html:ul>
                    <html:p>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! </html:p>
                  </fr:mainmatter>
                </fr:tree>
              </fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="false" expanded="false" toc="false" numbered="false">
              <fr:frontmatter>
                <fr:authors>
                  <fr:author>
                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                  </fr:author>
                </fr:authors>
                <fr:date>
                  <fr:year>2025</fr:year>
                  <fr:month>8</fr:month>
                  <fr:day>7</fr:day>
                </fr:date>
                <fr:uri>https://patrick.sirref.org/irmin-retro/</fr:uri>
                <fr:display-uri>irmin-retro</fr:display-uri>
                <fr:route>/irmin-retro/</fr:route>
                <fr:title text="Irmin Retrospective">Irmin Retrospective</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p><fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link> is an OCaml library for building  <html:em>branchable </html:em> and  <html:em>mergeable </html:em> data stores. The data is  <html:em>mergeable </html:em> in the  sense of  <fr:link href="/kcrsk-mrdts-2022/" title="Certified mergeable replicated data types" uri="https://patrick.sirref.org/kcrsk-mrdts-2022/" display-uri="kcrsk-mrdts-2022" type="local">mergeable replicated data types </fr:link>. </html:p>
                <html:p>I have been using Irmin for over five years to build different kinds of  interesting data stores including: </html:p>
                <html:ul>
                  <html:li>
                    <html:p>A  <fr:link href="https://github.com/patricoferris/omditor" type="external">simple markdown-based note-taking web application </fr:link>. </html:p>
                  </html:li>
                  <html:li>
                    <html:p>A  <fr:link href="https://github.com/carboncredits/retirement-db" type="external">content-addressed database </fr:link>. </html:p>
                  </html:li>
                  <html:li>
                    <html:p>Mentoring an intern who  <fr:link href="https://tarides.com/blog/2022-08-02-irmin-in-the-browser/" type="external">worked on Irmin in the browser </fr:link>. </html:p>
                  </html:li>
                  <html:li>
                    <html:p>Most recently, an  <fr:link href="/shelter/" title="Shelter" uri="https://patrick.sirref.org/shelter/" display-uri="shelter" type="local">Irmin-backed shell session manager </fr:link>. </html:p>
                  </html:li>
                </html:ul>
                <html:p>I was asked to provide some feedback recently on  <fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link>, so I thought writing a  little retrospective here would be a good way to do that. The remit for the retrospective  was about improving  <fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link>, so the content is focussed on pain points and areas of  improvement. </html:p>
                <html:pre class="hilite">
                  <html:code>
                    <html:span class="ocaml-comment-block"><![CDATA[(*]]></html:span>
                    <html:span class="ocaml-comment-block"> An in-memory Irmin store </html:span>
                    <html:span class="ocaml-comment-block"><![CDATA[*)]]></html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-keyword-other">module</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Store</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Irmin_mem</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">KV</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Make</html:span>
                    <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Irmin</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Contents</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">String</html:span>
                    <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                    <html:span class="ocaml-source">
</html:span>
                  </html:code>
                </html:pre>
                <fr:tree show-metadata="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>8</fr:month>
                      <fr:day>7</fr:day>
                    </fr:date>
                    <fr:title text="What is Irmin? ">What is Irmin? </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p><fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link>, at its simplest, is a key-value database. Users associate keys with  values and can query and update these bindings. </html:p>
                    <html:p>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. </html:p>
                    <html:p>Different versions of the database can be combined by  <html:em>merging </html:em>. When you set up your instance  of an  <fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link> database, you also provide it with a  <fr:link href="/kcrsk-mrdts-2022/" title="Certified mergeable replicated data types" uri="https://patrick.sirref.org/kcrsk-mrdts-2022/" display-uri="kcrsk-mrdts-2022" type="local">merge function </fr:link>. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-mdx-hash">#</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">#</html:span>
                        <html:span class="ocaml-keyword-other">show_type</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Irmin</html:span>
                        <html:span class="ocaml-source">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Merge</html:span>
                        <html:span class="ocaml-source">.</html:span>
                        <html:span class="ocaml-source">f</html:span>
                        <html:span class="ocaml-source">;;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-other">type</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">nonrec</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-storage-type">'a</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">f</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">    </html:span>
                        <html:span class="ocaml-source">old</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-storage-type">'a</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Irmin</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Merge</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">promise</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">    </html:span>
                        <html:span class="ocaml-storage-type">'a</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-storage-type">'a</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-storage-type">'a</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Irmin</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Merge</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">conflict</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">result</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Lwt</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>8</fr:month>
                      <fr:day>7</fr:day>
                    </fr:date>
                    <fr:title text="Design and API ">Design and API </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p><fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link>'s API is very git-inspired. There is a large overlap of shared  vocabulary and concepts:  <html:em>repositories </html:em>,  <html:em>branches </html:em>,  <html:em>commits </html:em>,  <html:em>heads </html:em> etc. </html:p>
                    <html:p>Probably the most confusing aspect of this is the notion of a  <html:code>Store</html:code>. When I was  describing  <fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link> above, I used the term  <html:em>database </html:em> to help distinguish  between some of these concepts. In Irmin's documentation, it is used for multiple  <![CDATA[related (but different) concepts. In "]]><fr:link href="https://irmin.org/tutorial/getting-started/#creating-a-store" type="external">Creating a  Store </fr:link>" stores  refer to the entire database, whereas in the  <fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link> API docs we have that: </html:p>
                    <html:blockquote>
                      <html:p>There are two kinds of store in Irmin: the ones based on persistent named  branches and the ones based temporary detached heads. </html:p>
                    </html:blockquote>
                    <html:p>For  <fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link> library users, a  <html:code>Store.t</html: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. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-mdx-hash">#</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Store</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">of_branch</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-operator">-</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Store</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">repo</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">string</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Store</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Lwt</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">&lt;</html:span>
                        <html:span class="ocaml-keyword-other">fun</html:span>
                        <html:span class="ocaml-keyword-operator">&gt;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-mdx-hash">#</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Store</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">of_commit</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-operator">-</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Store</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">commit</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Store</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Lwt</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">&lt;</html:span>
                        <html:span class="ocaml-keyword-other">fun</html:span>
                        <html:span class="ocaml-keyword-operator">&gt;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>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. </html:p>
                    <fr:tree show-metadata="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2025</fr:year>
                          <fr:month>8</fr:month>
                          <fr:day>7</fr:day>
                        </fr:date>
                        <fr:title text="Module and Functor Soup ">Module and Functor Soup </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>Undoubtedly for a majority of use-cases and users,  <fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link> 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  <fr:link href="https://mirage.github.io/irmin/irmin/Irmin/module-type-S/Schema/index.html" type="external"><html:code>Schema</html:code> module </fr:link> when describing the types they want to instantiate their store with. </html:p>
                        <html:p>To counteract this, Irmin has plenty of  <html:code>KV</html:code> modules that provide  a  <html:code>Make</html:code> functor that only requires a user to provide a suitable  <html:em>content </html:em> module  <![CDATA[for their store (i.e. something that provides a type, a runtime representation]]> <![CDATA[of that type and a merge function).]]></html:p>
                        <html:pre class="hilite">
                          <html:code>
                            <html:span class="ocaml-mdx-hash">#</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other">#</html:span>
                            <html:span class="ocaml-keyword-other">show_module</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">Irmin_mem</html:span>
                            <html:span class="ocaml-source">.</html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">KV</html:span>
                            <html:span class="ocaml-source">;;</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-keyword-other">module</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">KV</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">  </html:span>
                            <html:span class="ocaml-keyword-other">sig</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">    </html:span>
                            <html:span class="ocaml-keyword">type</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-entity-name-function-binding">endpoint</html:span>
                            <html:span class="ocaml-source"> = unit
</html:span>
                            <html:span class="ocaml-source">    </html:span>
                            <html:span class="ocaml-keyword">type</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-entity-name-function-binding">metadata</html:span>
                            <html:span class="ocaml-source"> = unit
</html:span>
                            <html:span class="ocaml-source">    </html:span>
                            <html:span class="ocaml-keyword">type</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-entity-name-function-binding">hash</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">    </html:span>
                            <html:span class="ocaml-keyword">type</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-entity-name-function-binding">info</html:span>
                            <html:span class="ocaml-source"> = Store.info
</html:span>
                            <html:span class="ocaml-source">    </html:span>
                            <html:span class="ocaml-keyword">type</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[('h, _)]]></html:span>
                            <html:span class="ocaml-entity-name-function-binding">contents_key</html:span>
                            <html:span class="ocaml-source"> = 'h
</html:span>
                            <html:span class="ocaml-source">    </html:span>
                            <html:span class="ocaml-keyword">type</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">'h </html:span>
                            <html:span class="ocaml-entity-name-function-binding">node_key</html:span>
                            <html:span class="ocaml-source"> = 'h
</html:span>
                            <html:span class="ocaml-source">    </html:span>
                            <html:span class="ocaml-keyword">type</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">'h </html:span>
                            <html:span class="ocaml-entity-name-function-binding">commit_key</html:span>
                            <html:span class="ocaml-source"> = 'h
</html:span>
                            <html:span class="ocaml-source">    </html:span>
                            <html:span class="ocaml-keyword-other-ocaml">module</html:span>
                            <html:span class="ocaml-source"><![CDATA[ Make : (C : Irmin__.Contents.S) ->]]></html:span>
                            <html:span class="ocaml-keyword-other-ocaml">sig</html:span>
                            <html:span class="ocaml-source"> ... </html:span>
                            <html:span class="ocaml-keyword-other">end</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">  </html:span>
                            <html:span class="ocaml-keyword-other">end</html:span>
                            <html:span class="ocaml-source">
</html:span>
                          </html:code>
                        </html:pre>
                        <html:p>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  <html:code>irmin.3.11.0</html:code>, starting at  <fr:link href="https://ocaml.org/p/irmin/latest/doc/index.html" type="external">the  toplevel documentation page </fr:link> our path to finding this paricular module and functor is as follows: </html:p>
                        <html:ol>
                          <html:li>
                            <html:p>We jump into  <fr:link href="https://ocaml.org/p/irmin/latest/doc/irmin.mem/Irmin_mem/index.html" type="external"><html:code>Irmin_mem</html:code></fr:link> from the nicely written landing page. </html:p>
                          </html:li>
                          <html:li>
                            <html:p>We scroll down to find  <fr:link href="https://ocaml.org/p/irmin/latest/doc/irmin.mem/Irmin_mem/index.html#module-KV" type="external">the KV module </fr:link>. </html:p>
                          </html:li>
                          <html:li>
                            <html:p>We now make sense of the module's signature by following the  <fr:link href="https://ocaml.org/p/irmin/latest/doc/irmin/Irmin/module-type-KV_maker/index.html" type="external">KV_maker link </fr:link>. </html:p>
                          </html:li>
                          <html:li>
                            <html:p>We see a  <html:code><![CDATA[Make (C : Contents.S) : sig ... end]]></html:code> at the end of the module, and  <fr:link href="https://ocaml.org/p/irmin/latest/doc/irmin/Irmin/module-type-KV_maker/Make/index.html#module-Schema" type="external">we navigate through that </fr:link>. </html:p>
                          </html:li>
                          <html:li>
                            <html:p>Finally we have come to our journey's end, and find the  <fr:link href="https://ocaml.org/p/irmin/latest/doc/irmin/Irmin/module-type-KV_maker/Make/index.html#module-Schema" type="external">schema module </fr:link> with type constraints like  <html:code>type Branch.t = string</html:code>. </html:p>
                          </html:li>
                        </html:ol>
                        <html:p>There is a big assumption there that you know what the  <html:code>Schema</html:code> module is  telling you and how it relates to your "store". </html:p>
                        <html:p>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  <fr:link href="https://github.com/patricoferris/ocaml-cid/blob/main/test/irmin_cid.ml" type="external"><![CDATA[Irmin stores that use CIDs (self-describing content identifiers)]]></fr:link> for example. </html:p>
                        <html:p>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  <fr:link href="https://ocaml.org/p/irmin-containers/latest/doc/irmin-containers/Irmin_containers/index.html" type="external">introductory libraries like  irmin-containers </fr:link> would be helpful. Perhaps a  <html:em>standalone </html:em> library that acts as an interface to  Irmin stores would be helpful. I find myself time and again implementing  <fr:link href="https://github.com/fn06/shelter/blob/main/src/lib/store.ml" type="external">something like  that </fr:link>. </html:p>
                      </fr:mainmatter>
                    </fr:tree>
                    <fr:tree show-metadata="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2025</fr:year>
                          <fr:month>8</fr:month>
                          <fr:day>7</fr:day>
                        </fr:date>
                        <fr:title text="Backends Galore ">Backends Galore </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>Irmin has plenty of backends including  <fr:link href="https://ocaml.org/p/irmin-git/latest" type="external">a git-compatible  one </fr:link>,  <fr:link href="https://ocaml.org/p/irmin-mirage/latest" type="external">a MirageOS  backend </fr:link>,  <fr:link href="https://ocaml.org/p/irmin-indexeddb/latest" type="external">an in-browser IndexedDB  backend </fr:link> and even a  <fr:link href="https://github.com/andreas/irmin-fdb" type="external">FoundationDB  backend </fr:link>. </html:p>
                        <html:p><fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link> 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,  <fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link> 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  <fr:link href="https://lofi.so/" type="external">local-first  applications </fr:link>. </html:p>
                      </fr:mainmatter>
                    </fr:tree>
                    <fr:tree show-metadata="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2025</fr:year>
                          <fr:month>8</fr:month>
                          <fr:day>7</fr:day>
                        </fr:date>
                        <fr:title text="Syncing Remote Stores ">Syncing Remote Stores </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>The  <fr:link href="https://ocaml.org/p/irmin/3.11.0/doc/irmin/Irmin/Sync/index.html" type="external">synchronisation mechanisms in  Irmin </fr:link> 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  <fr:link href="https://ocaml.org/p/irmin-git/latest/doc/irmin-git.unix/Irmin_git_unix/Maker/Make/index.html#val-remote" type="external">remote endpoint </fr:link>.  Once they have found this function, using it is not easy as it requires them  to learn about the  <fr:link href="https://ocaml.org/p/mimic/latest" type="external"><html:code>Mimic.ctx</html:code></fr:link>, which  is an abstraction of the networking stack! </html:p>
                      </fr:mainmatter>
                    </fr:tree>
                    <fr:tree show-metadata="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2025</fr:year>
                          <fr:month>8</fr:month>
                          <fr:day>7</fr:day>
                        </fr:date>
                        <fr:title text="Do Fewer Things and Do Them Well ">Do Fewer Things and Do Them Well </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>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. </html:p>
                        <html:p>When building the  <fr:link href="https://github.com/carboncredits/retirement-db" type="external">content-addressed  database </fr:link> I needed strong  guarantees about some atomic actions to perform on the underlying store. For  example,  <fr:link href="https://github.com/mirage/irmin/issues/2073" type="external">setting the value and accessing the commit associated with  it </fr:link> 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. </html:p>
                      </fr:mainmatter>
                    </fr:tree>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>8</fr:month>
                      <fr:day>7</fr:day>
                    </fr:date>
                    <fr:title text="Documentation ">Documentation </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>It will probably come as no surprise that one of the main limitations of using  <fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link> is the lack of documentation and tutorials. This is a particular pain  point as the API is not very straightforward. </html:p>
                    <html:p>A while back, I started an  <fr:link href="https://patricoferris.github.io/irmin-book/" type="external">Irmin  book </fr:link> intending to help document  the kinds of things real-world users would need in order to use  <fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link> in earnest.  For example: ways to  <fr:link href="https://patricoferris.github.io/irmin-book/contents/versioned-data.html" type="external">deal with type  migrations </fr:link> or  <fr:link href="https://patricoferris.github.io/irmin-book/arch/runtime-types.html" type="external">primers on runtime  types </fr:link>. 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. </html:p>
                    <html:p>The  <fr:link href="https://irmin.org/tutorial/introduction/" type="external">tutorials on the irmin website </fr:link> are still good starting points for most new users. But they quickly lack the depth  for real-world scenarios. </html:p>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>8</fr:month>
                      <fr:day>7</fr:day>
                    </fr:date>
                    <fr:title text="Feature Wishlist ">Feature Wishlist </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>What follows are additional ideas for improving  <fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link>. </html:p>
                    <fr:tree show-metadata="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2025</fr:year>
                          <fr:month>8</fr:month>
                          <fr:day>7</fr:day>
                        </fr:date>
                        <fr:title text="Heterogeneous Stores ">Heterogeneous Stores </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p><![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. </html:p>
                        <html:p>This leads to a few common workarounds: </html:p>
                        <html:ul>
                          <html:li>
                            <html:p>Storing a serealised version of your values, essentially escaping the type-system  and implementing a form of dynamic typing. </html:p>
                          </html:li>
                          <html:li>
                            <html:p>Growing your value to hold lots of different types via some large variant type. </html:p>
                          </html:li>
                        </html:ul>
                        <html:p>Both of these options are feasible and have been used in practice. However,  they are workarounds. A long time ago  <fr:link href="https://craigfe.io/" type="external">CraigFe </fr:link> created an  <fr:link href="https://github.com/mirage/irmin/issues/909" type="external">RFC for heterogeneous stores </fr:link>,  which I think about a lot. The main idea is to augment  <fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link><![CDATA[ paths (keys)]]> to be GADTs that carry type information about the kinds of values they access  <![CDATA[(similar to]]><fr:link href="https://ocaml.org/p/hmap" type="external">heterogeneuous variants of other data  structures </fr:link><![CDATA[). Something like this alongside a simplified]]> API would make Irmin more appealing as a library for persistent data storage. </html:p>
                      </fr:mainmatter>
                    </fr:tree>
                    <fr:tree show-metadata="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2025</fr:year>
                          <fr:month>8</fr:month>
                          <fr:day>7</fr:day>
                        </fr:date>
                        <fr:title text="Real-world Retrospectives ">Real-world Retrospectives </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>This echos some thoughts from the  <html:em>Documentation </html:em> section. There are some very  real-world  <fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link><![CDATA[ use-cases out there. For example, for a long time (I'm not]]> <![CDATA[sure if this is still the case) parts of the]]><fr:link href="https://ocaml.org/p/tezos-context/latest#dependencies" type="external">Tezos blockchain were using  Irmin </fr:link> which uses the  <fr:link href="https://ocaml.org/p/irmin-pack/latest" type="external">irmin-pack </fr:link> 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  <fr:link href="https://tarides.com/blog/2020-09-01-introducing-irmin-pack/" type="external">blogs  on tarides.com about the irmin-pack backend </fr:link>,  but they might be outdated and should not be the first place to find advice on  which Irmin backend to use. </html:p>
                      </fr:mainmatter>
                    </fr:tree>
                    <fr:tree show-metadata="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2025</fr:year>
                          <fr:month>8</fr:month>
                          <fr:day>7</fr:day>
                        </fr:date>
                        <fr:title text="Active Development and Engagement ">Active Development and Engagement </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>As far as I know,  <fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link> was at the forefront of technologies that have come  to be described as  <fr:link href="https://lofi.so/" type="external">local-first </fr:link>. There is a growing interest  <![CDATA[in this area (particularly as it acts as a counter-argument to an increasingly]]> <![CDATA[online, centralised model). I highly recommend reading]]><fr:link href="https://patrick.sirref.org/ink &amp; switch's essay on the matter/" type="external">Ink &amp; Switch's essay on  the matter </fr:link>. And it would be great to see more research via  <fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link> at  things like  <fr:link href="https://lu.ma/localfirstswunconf-stlouis" type="external">the lofi unconference </fr:link> and the  <fr:link href="https://2023.splashcon.org/home/plf-2023" type="external">PLF workshop at SPLASH  2023 </fr:link>! </html:p>
                        <html:p>Thank you for reading! And thank you to all the  <fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link> contributors. I hope this  might be useful in the future for building the next-generation  <fr:link href="/irmin/" title="Irmin" uri="https://patrick.sirref.org/irmin/" display-uri="irmin" type="local">Irmin </fr:link>! </html:p>
                      </fr:mainmatter>
                    </fr:tree>
                  </fr:mainmatter>
                </fr:tree>
              </fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="false" expanded="false" toc="false" numbered="false">
              <fr:frontmatter>
                <fr:authors />
                <fr:date>
                  <fr:year>2025</fr:year>
                  <fr:month>7</fr:month>
                  <fr:day>23</fr:day>
                </fr:date>
                <fr:uri>https://patrick.sirref.org/slipshow-x-xocaml/</fr:uri>
                <fr:display-uri>slipshow-x-xocaml</fr:display-uri>
                <fr:route>/slipshow-x-xocaml/</fr:route>
                <fr:title text="Slipshow x x-ocaml">Slipshow x x-ocaml</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>A short, explanatory post about combining two very fun pieces of work in  OCaml. </html:p>
                <html:p><fr:link href="https://github.com/panglesd" type="external">Paul-Elliot </fr:link> has been building  <fr:link href="https://github.com/panglesd/slipshow" type="external">Slipshow </fr:link> for some time now where slides  are  <html:em>slips </html:em> and your presentations run vertically. More recently,  <fr:link href="/artw/" title="Arthur Wendling" uri="https://patrick.sirref.org/artw/" display-uri="artw" type="local">Arthur </fr:link> has built  <fr:link href="https://github.com/art-w/x-ocaml" type="external">x-ocaml </fr:link>, a web component library  for executable OCaml cells embedded into OCaml. </html:p>
                <html:p>Using  <fr:link href="https://github.com/patricoferris/xocmd" type="external">xocmd </fr:link>, a small tool I built for  translating markdown codeblocks to x-ocaml components, your Slipshow's can now  be  <html:em>executable </html:em>! </html:p>
                <html:pre><![CDATA[xocmd learn-effects.md | slipshow compile - > learn-effects.html]]></html:pre>
                <html:p>
    Take a look at 
    <html:a href="/bafkrmictvc3ap2ah37cbcdoo6rsl7vxqu6srogmgzx6iml45bq7zz5weo4.html">an example</html:a>!
    (or the 
    <html:a href="/bafkrmib3jugpkznxcftqjvhbbtfqgx4oz2m32p5xloh4nxia3lhxy2momq.md">source markdown</html:a>).
</html:p>
                <html:p>I really like this light-weight approach to building interactive presentations  <![CDATA[for explaining things in OCaml (e.g. over running a jupyter notebook server).]]></html:p>
              </fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="false" expanded="false" toc="false" numbered="false">
              <fr:frontmatter>
                <fr:authors>
                  <fr:author>
                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                  </fr:author>
                </fr:authors>
                <fr:date>
                  <fr:year>2025</fr:year>
                  <fr:month>7</fr:month>
                  <fr:day>18</fr:day>
                </fr:date>
                <fr:uri>https://patrick.sirref.org/ocaml-quarterly-q2/</fr:uri>
                <fr:display-uri>ocaml-quarterly-q2</fr:display-uri>
                <fr:route>/ocaml-quarterly-q2/</fr:route>
                <fr:title text="Quarterly OCaml Q2">Quarterly OCaml Q2</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>Thanks to  <fr:link href="https://patrick.sirref.org/tarides/" type="external">Tarides </fr:link> sponsorship, I get to work on open-source OCaml.  This quarterly is a companion to my  <fr:link href="/weeklies/" title="Patrick Ferris' Weeklies" uri="https://patrick.sirref.org/weeklies/" display-uri="weeklies" type="local">weeklies </fr:link>, summarising the last  three months of development, peppered with ideas and thoughts about OCaml,  its community and its future. </html:p>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>7</fr:month>
                      <fr:day>18</fr:day>
                    </fr:date>
                    <fr:title text="What I wanted to work on? ">What I wanted to work on? </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>There were two main things I hoped to  <html:em>continue </html:em> working on:  <html:strong>ppxlib </html:strong> and  <html:strong>outreachy </html:strong>. These are projects that I was previously working on, and in the  case of Outreachy I have now been involved for many years. </html:p>
                    <html:p>In addition to this, all of my  <fr:link href="/part-ii-2024/" title="Part II Students 2024" uri="https://patrick.sirref.org/part-ii-2024/" display-uri="part-ii-2024" type="local">Part II </fr:link> 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  <fr:link href="https://ocaml-explore.netlify.app/" type="external">my initial work on developing  workflows for OCaml that just turned five years  old </fr:link>. This directly fed into the rebranding  and rethinking of  <fr:link href="https://ocaml.org/" type="external">ocaml.org </fr:link> itself. </html:p>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>7</fr:month>
                      <fr:day>18</fr:day>
                    </fr:date>
                    <fr:title text="What I worked on? ">What I worked on? </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <fr:tree show-metadata="false" numbered="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2025</fr:year>
                          <fr:month>7</fr:month>
                          <fr:day>18</fr:day>
                        </fr:date>
                        <fr:title text="Ppxlib ">Ppxlib </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p><fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">Ppxlib </fr:link> is the de facto standard library for building OCaml preprocessors.  At the time of writing,  <html:code>opam list --depends-on=ppxlib</html:code> informs me that there  are 267 reverse dependencies.  <fr:link href="https://www.janestreet.com/" type="external">Janestreet </fr:link> is a  heavy user of ppxes and has  <fr:link href="https://github.com/orgs/janestreet/repositories?language=&amp;amp;q=ppx&amp;amp;sort=&amp;amp;type=all" type="external">authored  many </fr:link>. </html:p>
                        <html:p>One of the main accomplishments this quarter was  <fr:link href="/ppxlib-5-2/" title="Bumping Ppxlib's AST to 5.2" uri="https://patrick.sirref.org/ppxlib-5-2/" display-uri="ppxlib-5-2" type="local">bumping the internal AST to  5.2 </fr:link>. 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  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link>. </html:p>
                        <html:p>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  <![CDATA[factor in the churn of breaking changes (in the case of OCaml this is via]]><fr:link href="https://github.com/ocaml/opam-repository/" type="external">PRs  to the opam-repository </fr:link><![CDATA[). 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. </html:p>
                        <html:p><fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">Ppxlib </fr:link> sits awkwardly in the space of possible breaking changes. Tied to  OCaml's parsetree, impacts of changes there ripple down to  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link>. The  compiler itself can remain internally consistent, and is protected as it need  only parse source code.  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">Ppxlib </fr:link>, 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  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link>, it feels as though the number of syntax changes  <![CDATA[has gone up (primarily from Janestreet work). Unless we make changes to how we provide]]> support for these, maintainers of  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link> will forever be stuck doing busy work!  Thankfully,  <fr:link href="/nathanreb/" title="Nathan Rebours" uri="https://patrick.sirref.org/nathanreb/" display-uri="nathanreb" type="local">Nathan </fr:link>  <fr:link href="/ocaml-weekly-2025-w29/" title="OCaml Weekly 2025 w29" uri="https://patrick.sirref.org/ocaml-weekly-2025-w29/" display-uri="ocaml-weekly-2025-w29" type="local">has thoughts on how to improve  this </fr:link>. </html:p>
                        <html:p>There are a slew of other features I have added to  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link> including: </html:p>
                        <html:ul>
                          <html:li>
                            <html:p>Support for deriving from classes. </html:p>
                          </html:li>
                          <html:li>
                            <html:p>Support for deriving from module bindings and signatures. </html:p>
                          </html:li>
                          <html:li>
                            <html:p>Fixing compiler and ppxlib dummy locations. </html:p>
                          </html:li>
                          <html:li>
                            <html:p>Bumping to 5.3. </html:p>
                          </html:li>
                          <html:li>
                            <html:p>Migrations for 5.4. </html:p>
                          </html:li>
                        </html:ul>
                      </fr:mainmatter>
                    </fr:tree>
                    <fr:tree show-metadata="false" numbered="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2025</fr:year>
                          <fr:month>7</fr:month>
                          <fr:day>18</fr:day>
                        </fr:date>
                        <fr:title text="Outreachy ">Outreachy </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>Our two projects this year, one on  <fr:link href="https://github.com/claudiusFX/claudius" type="external">claudius </fr:link> and one on  <fr:link href="https://github.com/ocaml/dune" type="external">dune </fr:link>, are going extremely well. At the time of  writing, we just had  <fr:link href="/ocaml-weekly-2025-w29/" title="OCaml Weekly 2025 w29" uri="https://patrick.sirref.org/ocaml-weekly-2025-w29/" display-uri="ocaml-weekly-2025-w29" type="local">a mid-internship call to catch  up </fr:link>, and I was blown away by the progress each intern  has made. Unfortunately,  <fr:link href="/outreachy/" title="Outreachy" uri="https://patrick.sirref.org/outreachy/" display-uri="outreachy" type="local">Outreachy </fr:link> 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. </html:p>
                        <html:p>Outreachy has been a wonderful source of new, committed OCaml developers. If  you haven't already, do peruse the  <fr:link href="https://ocaml.org/outreachy" type="external">webpage on  OCaml.org </fr:link> to see past internships or  <fr:link href="https://watch.ocaml.org/c/outreachy_ocaml/videos" type="external">watch the  demo day presentations </fr:link>. For the mentors involved,  <![CDATA[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  <fr:link href="/patrickferris/" title="Patrick Ferris" uri="https://patrick.sirref.org/patrickferris/" display-uri="patrickferris" type="local">do reach out to me </fr:link> if you are interested. </html:p>
                      </fr:mainmatter>
                    </fr:tree>
                    <fr:tree show-metadata="false" numbered="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2025</fr:year>
                          <fr:month>7</fr:month>
                          <fr:day>18</fr:day>
                        </fr:date>
                        <fr:title text="Hazel ">Hazel </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p><![CDATA[OCaml's feature set allows it to shine at writing programming languages (and]]> <![CDATA[things of that ilk: compilers, interpretters, static analysis tools).]]><fr:link href="/hazel/" title="Hazel" uri="https://patrick.sirref.org/hazel/" display-uri="hazel" type="local">Hazel </fr:link> is a research programming language with typed holes written completely in OCaml  <![CDATA[(via the]]><fr:link href="https://reasonml.github.io/" type="external">reason dialect </fr:link><![CDATA[).]]></html:p>
                        <html:p>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  <fr:link href="/hazel_of_ocaml/" title="hazel_of_ocaml" uri="https://patrick.sirref.org/hazel_of_ocaml/" display-uri="hazel_of_ocaml" type="local">OCaml to Hazel </fr:link>. Whilst  new features are still being added to  <fr:link href="/hazel/" title="Hazel" uri="https://patrick.sirref.org/hazel/" display-uri="hazel" type="local">Hazel </fr:link>, I hope this could serve as a  tool to help develop test-suites and standard library functions using existing  <![CDATA[OCaml solutions. In a student's work (]]><fr:link href="/part-ii-hazel/" title="Type Error Debugging in Hazel" uri="https://patrick.sirref.org/part-ii-hazel/" display-uri="part-ii-hazel" type="local">Typed Debugging for  Hazel </fr:link><![CDATA[), we used this tool to build a corpus of ill-typed]]> <fr:link href="/hazel/" title="Hazel" uri="https://patrick.sirref.org/hazel/" display-uri="hazel" type="local">Hazel </fr:link> programs to great effect. </html:p>
                        <html:p>OCaml should continue to be a world-class programming language for building  other programming languages. I hope to upstream some of this work to  <fr:link href="/hazel/" title="Hazel" uri="https://patrick.sirref.org/hazel/" display-uri="hazel" type="local">Hazel </fr:link> and provide some low effort maintenance to help keep their compiler in good  shape. </html:p>
                      </fr:mainmatter>
                    </fr:tree>
                    <fr:tree show-metadata="false" numbered="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2025</fr:year>
                          <fr:month>7</fr:month>
                          <fr:day>18</fr:day>
                        </fr:date>
                        <fr:title text="Systems Programming in OCaml ">Systems Programming in OCaml </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>In a cross-over with my own research, I have been developing many tools related  to systems programming in OCaml including: </html:p>
                        <html:ul>
                          <html:li>
                            <html:p>An eBPF-based  <fr:link href="/open-trace/" title="Opentrace" uri="https://patrick.sirref.org/open-trace/" display-uri="open-trace" type="local"><html:code>open</html:code> syscall tracing tool </fr:link>. </html:p>
                          </html:li>
                          <html:li>
                            <html:p>A library in OCaml for  <fr:link href="https://github.com/quantifyearth/void" type="external">spawning void processes </fr:link>. </html:p>
                          </html:li>
                          <html:li>
                            <html:p>A  <fr:link href="/shelter/" title="Shelter" uri="https://patrick.sirref.org/shelter/" display-uri="shelter" type="local">shell session manager </fr:link> that uses  <fr:link href="https://irmin.org/" type="external">Irmin </fr:link> to manage sessions.  It is nice to see a new push to  <fr:link href="https://github.com/mirage/irmin/pull/2149" type="external">finally land the direct-style Irmin PR </fr:link>! </html:p>
                          </html:li>
                        </html:ul>
                        <html:p>This work is means to develop the underlying libraries that support it. For  example, I have opened a few PRs to  <fr:link href="https://github.com/ocaml-multicore/eio" type="external">Eio </fr:link> to add new "fork actions" to the  spawn API. I also investigated the feasibility of changing the underlying  mechanisms in  <fr:link href="/eio/" title="Eio" uri="https://patrick.sirref.org/eio/" display-uri="eio" type="local">Eio </fr:link> to use  <fr:link href="https://github.com/ocaml-multicore/picos" type="external">Picos </fr:link>.  In the future, I think this could be important avoid further splitting the OCaml  ecosystem. </html:p>
                        <fr:tree show-metadata="false" numbered="false">
                          <fr:frontmatter>
                            <fr:authors>
                              <fr:author>
                                <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                              </fr:author>
                            </fr:authors>
                            <fr:date>
                              <fr:year>2025</fr:year>
                              <fr:month>7</fr:month>
                              <fr:day>18</fr:day>
                            </fr:date>
                            <fr:title text="OxCaml ">OxCaml </fr:title>
                          </fr:frontmatter>
                          <fr:mainmatter>
                            <html:p>I dabbled a little with  <fr:link href="https://oxcaml.org/" type="external">OxCaml </fr:link> and build  <fr:link href="/try-oxcaml/" title="Try OxCaml" uri="https://patrick.sirref.org/try-oxcaml/" display-uri="try-oxcaml" type="local">try-oxcaml </fr:link> 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  <![CDATA[(type definitions differeing between js_of_ocaml and the OxCaml compiler, resulting]]> <![CDATA[in different Javascript runtime representations...).]]></html:p>
                            <html:p>This unblocked a few of my colleagues to get OxCaml working on tools like  <fr:link href="https://jon.recoil.org/notebooks/foundations/foundations1.html" type="external">odoc_notebooks </fr:link> and  <fr:link href="https://github.com/art-w/x-ocaml" type="external">x-ocaml </fr:link>. </html:p>
                          </fr:mainmatter>
                        </fr:tree>
                      </fr:mainmatter>
                    </fr:tree>
                    <fr:tree show-metadata="false" numbered="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2025</fr:year>
                          <fr:month>7</fr:month>
                          <fr:day>18</fr:day>
                        </fr:date>
                        <fr:title text="Forester ">Forester </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>A good proportion of my work this quarter has been focused on how to present  the very work that I am doing.  <fr:link href="/jonmsterling/" title="Jon Sterling" uri="https://patrick.sirref.org/jonmsterling/" display-uri="jonmsterling" type="local">Jon Sterling </fr:link> has been developing  a tool for scientific thought called  <fr:link href="/forester/" title="Forester" uri="https://patrick.sirref.org/forester/" display-uri="forester" type="local">Forester </fr:link> which seemed like a possible  candidate for writing and sharing my work. </html:p>
                        <html:p>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  <![CDATA[made use of additional markdown-based tools (like]]><fr:link href="https://github.com/realworldocaml/mdx" type="external">ocaml-mdx </fr:link><![CDATA[).]]></html:p>
                        <html:p>This lead to the development of  <fr:link href="/graft/" title="Graft" uri="https://patrick.sirref.org/graft/" display-uri="graft" type="local">Graft </fr:link>: a preprocessor for Forester forests,  converting markdown and bibtex to trees. </html:p>
                      </fr:mainmatter>
                    </fr:tree>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>7</fr:month>
                      <fr:day>18</fr:day>
                    </fr:date>
                    <fr:title text="What's next? ">What's next? </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>So, I worked on most of what I wanted to work on and then some! Going forward I  hope to keep maintaining  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link> in some capacity and coordinating the OCaml  community's  <fr:link href="/outreachy/" title="Outreachy" uri="https://patrick.sirref.org/outreachy/" display-uri="outreachy" type="local">Outreachy </fr:link> efforts. </html:p>
                    <html:p><![CDATA[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  <fr:link href="https://github.com/raven-ml/" type="external">Raven </fr:link>: I am interested to  use this library in  <fr:link href="/geocaml/" title="Geocaml" uri="https://patrick.sirref.org/geocaml/" display-uri="geocaml" type="local">Geocaml </fr:link>, a suite of geospatial tools written in OCaml  that I maintain. </html:p>
                    <html:p>I feel conflicted about the  <fr:link href="https://patrick.sirref.org/oxcaml/" type="external">OxCaml </fr:link> 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  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link> 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  <fr:link href="https://patrick.sirref.org/oxcaml/" type="external">OxCaml </fr:link> 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. </html:p>
                    <html:p>Finally, over the past two years I have done a lot of teaching. From  <fr:link href="/part-ii/" title="Part II Projects" uri="https://patrick.sirref.org/part-ii/" display-uri="part-ii" type="local">Part II  projects </fr:link> to  <fr:link href="/focs/" title="Foundations of Computer Science" uri="https://patrick.sirref.org/focs/" display-uri="focs" type="local">supervisions </fr:link><![CDATA[. 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  <fr:link href="https://beautifulracket.com/" type="external">Beautiful  Racket </fr:link>. I have tried in the past to do these sorts  of things, for example  <fr:link href="https://patricoferris.github.io/irmin-book/" type="external">The Irmin Book </fr:link>. </html:p>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>7</fr:month>
                      <fr:day>18</fr:day>
                    </fr:date>
                    <fr:title text="Thank you ">Thank you </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>Thank you for reading this wrap up! And thank you again to  <fr:link href="https://patrick.sirref.org/tarides/" type="external">Tarides </fr:link> for  letting me work so freely on things that I think are good for the OCaml  community. </html:p>
                  </fr:mainmatter>
                </fr:tree>
              </fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="false" expanded="false" toc="false" numbered="false">
              <fr:frontmatter>
                <fr:authors>
                  <fr:author>
                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                  </fr:author>
                </fr:authors>
                <fr:date>
                  <fr:year>2025</fr:year>
                  <fr:month>5</fr:month>
                  <fr:day>19</fr:day>
                </fr:date>
                <fr:uri>https://patrick.sirref.org/open-trace/</fr:uri>
                <fr:display-uri>open-trace</fr:display-uri>
                <fr:route>/open-trace/</fr:route>
                <fr:title text="Opentrace">Opentrace</fr:title>
                <fr:meta name="external">https://tangled.sh/@patrick.sirref.org/opentrace</fr:meta>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>Thanks to  <fr:link href="https://github.com/koonwen/" type="external">Koonwen's </fr:link> excellent  <fr:link href="https://github.com/koonwen/ocaml-libbpf" type="external">libbpf bindings in OCaml </fr:link>,  I have been building a little tool called  <html:code>opentrace</html:code> to make it easier to track an executable's inputs and outputs. </html:p>
                <html:p>This work was inspired my  <fr:link href="/mdales/" title="Michael W. Dales" uri="https://patrick.sirref.org/mdales/" display-uri="mdales" type="local">Michael's </fr:link> self-proclaimed "gross hack":  <fr:link href="https://github.com/quantifyearth/pyshark" type="external">pyshark </fr:link>.  Whilst pyshark achieves its goals by injecting code into commonly used python objects and methods,  <fr:link href="/opentrace/" title="Opentrace" uri="https://patrick.sirref.org/opentrace/" display-uri="opentrace" type="local">opentrace </fr:link> uses  <fr:link href="https://ebpf.io/" type="external">eBPF </fr:link><![CDATA[. By using a lower-level API (hooks in the kernel),]]><fr:link href="/opentrace/" title="Opentrace" uri="https://patrick.sirref.org/opentrace/" display-uri="opentrace" type="local">opentrace </fr:link> can remain programming language agnostic.  However, less information is none about the user's intent compared to something like pyshark. </html:p>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>5</fr:month>
                      <fr:day>19</fr:day>
                    </fr:date>
                    <fr:title text="Monitoring the System ">Monitoring the System </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p><fr:link href="/opentrace/" title="Opentrace" uri="https://patrick.sirref.org/opentrace/" display-uri="opentrace" type="local">opentrace </fr:link> has an  <html:code>all</html:code> command that will trace the entire system. </html:p>
                    <html:pre><![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]]></html:pre>
                    <html:p>The  <html:code>--flags=O_WRONLY</html:code> argument filters the events where the  <html:code>O_WRONLY</html:code> flag was set in the call to  <html:code>open</html:code>. </html:p>
                    <html:p><![CDATA[We also get the name of the current executable linked to the task (]]><html:code>comm</html:code><![CDATA[). The]]><html:code>-wrapped</html:code> is an artefact of using Nix. </html:p>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>5</fr:month>
                      <fr:day>19</fr:day>
                    </fr:date>
                    <fr:title text="Tracing an Executable ">Tracing an Executable </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>The primary use case for this tool is to inspect what files your program might be reading and writing. </html:p>
                    <html:pre><![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"]]></html:pre>
                    <html:p>The "flags" argument can specify a small boolean formula for checking the open flags of a particular event with  <html:code>|</html:code><![CDATA[ (or),]]><html:code>&amp;</html:code><![CDATA[ (and), and]]><html:code>~</html:code><![CDATA[ (not).]]> Parentheses can be used for precedence. </html:p>
                    <html:pre><![CDATA[$ sudo opentrace exec --flags="O_WRONLY|O_RDONLY" -- ocaml --version]]></html:pre>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>5</fr:month>
                      <fr:day>19</fr:day>
                    </fr:date>
                    <fr:title text="Spawning Subprocesses ">Spawning Subprocesses </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>One feature  <fr:link href="/opentrace/" title="Opentrace" uri="https://patrick.sirref.org/opentrace/" display-uri="opentrace" type="local">opentrace </fr:link><![CDATA[ needs (in this proof-of-concept phase) is the ability to also trace subprocesses.]]></html:p>
                    <html:p><fr:link href="/opentrace/" title="Opentrace" uri="https://patrick.sirref.org/opentrace/" display-uri="opentrace" type="local">opentrace </fr:link> 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,  <fr:link href="/opentrace/" title="Opentrace" uri="https://patrick.sirref.org/opentrace/" display-uri="opentrace" type="local">opentrace </fr:link><![CDATA[ creates a new control group (cgroup) and places the new process into that group.]]> This gives  <fr:link href="/opentrace/" title="Opentrace" uri="https://patrick.sirref.org/opentrace/" display-uri="opentrace" type="local">opentrace </fr:link> a new identifier to track, namely the cgroup. </html:p>
                    <html:p>So consider the following program. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-keyword-other">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-unit"><![CDATA[()]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Eio_posix</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">run</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">@@</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">fun</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">env</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Eio</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Path</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source">save</html:span>
                        <html:span class="ocaml-source"> ~</html:span>
                        <html:span class="ocaml-source">create</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-polymorphic-variant">`Or_truncate</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-numeric-octal-integer">0o664</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source">env</html:span>
                        <html:span class="ocaml-keyword-other">#</html:span>
                        <html:span class="ocaml-source">fs</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">/</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">hello.txt</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">hello</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Eio</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Process</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">run</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">env</html:span>
                        <html:span class="ocaml-keyword-other">#</html:span>
                        <html:span class="ocaml-source">process_mgr</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">    </html:span>
                        <html:span class="ocaml-source"><![CDATA[[]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">/bin/bash</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">-c</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">echo 'heya' &gt; heya.txt</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[]]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>It first creates a file using direct calls to functions like  <html:code>openat</html:code>.  Then it spawns a process which creates a new file called  <html:code>heya.txt</html:code>. This happens in a separate process.  However, with the  <html:code>--cgroups</html:code> flag we can capture both interactions with the operating system. </html:p>
                    <html:pre><![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]]></html:pre>
                    <fr:tree show-metadata="false" numbered="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2025</fr:year>
                          <fr:month>5</fr:month>
                          <fr:day>19</fr:day>
                        </fr:date>
                        <fr:title text="Eio's Process API ">Eio's Process API </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>I have used the  <html:code>Eio_unix</html:code>  <fr:link href="https://ocaml.org/p/eio/latest/doc/Eio_unix/Process/index.html" type="external">fork action process API </fr:link> 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  <html:code>sudo</html:code>.  When a user requests for a particular program to be executed and traced,  <fr:link href="/opentrace/" title="Opentrace" uri="https://patrick.sirref.org/opentrace/" display-uri="opentrace" type="local">opentrace </fr:link> spawns a process via the Eio Process API.  <fr:link href="/opentrace/" title="Opentrace" uri="https://patrick.sirref.org/opentrace/" display-uri="opentrace" type="local">Opentrace </fr:link> defines a few new so-called "fork actions", little fragments of C code that are run after the call to  <html:code>fork</html:code><![CDATA[ (]]><html:code>clone</html:code><![CDATA[).]]> Most likely this ends with a call to  <html:code>execve</html:code>, but other calls are possible for example  <html:code>setuid</html:code> allowing  <fr:link href="/opentrace/" title="Opentrace" uri="https://patrick.sirref.org/opentrace/" display-uri="opentrace" type="local">opentrace </fr:link> to change  the user of the child process so it does not run as  <html:code>root</html:code><![CDATA[. Similarly, this is where (if used) we create the cgroup and place the process]]> into that group. </html:p>
                      </fr:mainmatter>
                    </fr:tree>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>5</fr:month>
                      <fr:day>19</fr:day>
                    </fr:date>
                    <fr:title text="Limitations: Io_uring ">Limitations: Io_uring </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>Whilst testing  <html:code>opentrace</html:code> against some of the tools I use nearly daily, I noticed some events were being missed.  I tried tracing  <fr:link href="/forester/" title="Forester" uri="https://patrick.sirref.org/forester/" display-uri="forester" type="local">forester </fr:link>, and only the initial read of  <html:code>forest.toml</html:code> was logged.  It dawned on me that the reason for this was that  <fr:link href="/forester/" title="Forester" uri="https://patrick.sirref.org/forester/" display-uri="forester" type="local">forester </fr:link><![CDATA[ (via]]><fr:link href="/eio/" title="Eio" uri="https://patrick.sirref.org/eio/" display-uri="eio" type="local">eio </fr:link><![CDATA[) was using]]><fr:link href="https://patrick.sirref.org/io_uring/" type="external">io_uring </fr:link> 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  <html:code>openat2</html:code>-style call! </html:p>
                    <html:p>This is not news to seasoned, Linux systems programmers.  Io_uring  <fr:link href="https://blog.0x74696d.com/posts/iouring-and-seccomp/" type="external">bypasses  <html:code>SECCOMP</html:code> filters </fr:link> for exactly the same reasons. </html:p>
                    <html:pre><![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]]></html:pre>
                    <html:p>It is interesting to note two things here: </html:p>
                    <html:ol>
                      <html:li>
                        <html:p>We can tell that  <fr:link href="/forester/" title="Forester" uri="https://patrick.sirref.org/forester/" display-uri="forester" type="local">forester </fr:link> reads the configuration file probably using something like  <html:code>In_channel</html:code><![CDATA[ in OCaml (]]><fr:link href="https://git.sr.ht/~jonsterling/ocaml-forester/tree/7f275290e211db2590b0d715d8fb47fc1de36550/item/lib/frontend/Config.ml#L22" type="external">it does </fr:link><![CDATA[).]]></html:p>
                      </html:li>
                      <html:li>
                        <html:p>It appears that Uring is performing IO in both worker threads and directly. </html:p>
                      </html:li>
                    </html:ol>
                    <html:p>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.  <![CDATA[I have tried quite a few methods (e.g. tracing]]><html:code>do_filp_open</html:code><![CDATA[) and at the moment I am tracing]]><html:code>io_openat2</html: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! </html:p>
                  </fr:mainmatter>
                </fr:tree>
              </fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="false" expanded="false" toc="false" numbered="false">
              <fr:frontmatter>
                <fr:authors>
                  <fr:author>
                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                  </fr:author>
                </fr:authors>
                <fr:date>
                  <fr:year>2025</fr:year>
                  <fr:month>5</fr:month>
                  <fr:day>9</fr:day>
                </fr:date>
                <fr:uri>https://patrick.sirref.org/try-oxcaml/</fr:uri>
                <fr:display-uri>try-oxcaml</fr:display-uri>
                <fr:route>/try-oxcaml/</fr:route>
                <fr:title text="Try OxCaml">Try OxCaml</fr:title>
                <fr:meta name="external">https://patrick.sirref.org/oxcaml</fr:meta>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>This week, I have been trying out Janestreet's  <fr:link href="https://blog.janestreet.com/oxidizing-ocaml-locality/" type="external">Oxidised OCaml </fr:link><![CDATA[ (see their]]><fr:link href="/oxcaml-2024/" title="Oxidizing OCaml with Modal Memory Management" uri="https://patrick.sirref.org/oxcaml-2024/" display-uri="oxcaml-2024" type="local">ICFP paper </fr:link><![CDATA[).]]> This adds a system of  <html:em>modes </html:em> to OCaml for expressing things like locality. </html:p>
                <html:blockquote>
                  <html: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. </html:p>
                </html:blockquote>
                <html:p>For example, you might say: </html:p>
                <html:pre class="hilite">
                  <html:code>
                    <html:span class="ocaml-keyword">let</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-entity-name-function-binding">is_empty</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                    <html:span class="ocaml-source">s</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-support-type">string</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">@@</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">local</html:span>
                    <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">String</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">length</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">s</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-numeric-decimal-integer">0</html:span>
                    <html:span class="ocaml-source">
</html:span>
                  </html:code>
                </html:pre>
                <html:p>To get a feel for how this changes the language, you can follow their  <fr:link href="https://github.com/janestreet/opam-repository/tree/with-extensions" type="external">instructions on their custom opam-repository </fr:link>. Alternatively, you can  <fr:link href="https://patrick.sirref.org/oxcaml" type="external">give it a go in your browser </fr:link>! This is a full toplevel running with  <html:code>Base</html:code><![CDATA[ installed (which has plenty of OxCaml annotations on Stdlib-like functions).]]></html:p>
                <html:p>Happy OxCamling! </html:p>
              </fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="false" expanded="false" toc="false" numbered="false">
              <fr:frontmatter>
                <fr:authors>
                  <fr:author>
                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                  </fr:author>
                </fr:authors>
                <fr:date>
                  <fr:year>2025</fr:year>
                  <fr:month>5</fr:month>
                  <fr:day>2</fr:day>
                </fr:date>
                <fr:uri>https://patrick.sirref.org/hazel-of-ocaml/</fr:uri>
                <fr:display-uri>hazel-of-ocaml</fr:display-uri>
                <fr:route>/hazel-of-ocaml/</fr:route>
                <fr:title text="A Transpiler from OCaml to Hazel">A Transpiler from OCaml to Hazel</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>Over the past few months, I have been piecing together a transpiler from  <fr:link href="/hazel/" title="Hazel" uri="https://patrick.sirref.org/hazel/" display-uri="hazel" type="local">Hazel </fr:link> to OCaml. This is, in part, to help one of my third-year  undergraduate students who is working on  <fr:link href="/part-ii-hazel/" title="Type Error Debugging in Hazel" uri="https://patrick.sirref.org/part-ii-hazel/" display-uri="part-ii-hazel" type="local">type error debugging in Hazel </fr:link>. </html:p>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>5</fr:month>
                      <fr:day>2</fr:day>
                    </fr:date>
                    <fr:title text="Typed Holes ">Typed Holes </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p><fr:link href="/hazel/" title="Hazel" uri="https://patrick.sirref.org/hazel/" display-uri="hazel" type="local">Hazel </fr:link> is a  <fr:link href="/omar-hazel-2017/" title="Hazelnut: a bidirectionally typed structure editor calculus" uri="https://patrick.sirref.org/omar-hazel-2017/" display-uri="omar-hazel-2017" type="local">functional programming language with typed holes </fr:link>. 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. </html:p>
                    <html:p>To get a flavour of Hazel, take a regular map function for lists. </html:p>
                    <html:pre><![CDATA[let map = fun f -> fun xs -> case xs
  | [] => []
  | x :: xs => f (x) :: map(f)(xs) 
end in
map(fun x -> ?)([1, 2, 3])]]></html:pre>
                    <html:p><![CDATA[The question mark (]]><html:code>?</html:code><![CDATA[) is a hole. The program evaluates to the following expression of type]]><html:code><![CDATA[[?]]]></html:code><![CDATA[ (for people more]]> familiar with OCaml types  <html:code>? list</html:code><![CDATA[).]]></html:p>
                    <html:pre><![CDATA[[ ?, ?, ? ]]]></html:pre>
                    <html:p>Hazel supports  <fr:link href="/zhao-typeerror-2024/" title="Total Type Error Localization and Recovery with Holes" uri="https://patrick.sirref.org/zhao-typeerror-2024/" display-uri="zhao-typeerror-2024" type="local">local type inference </fr:link> but nothing involving unification variables. For example,  a simple  <html:code>add_one</html:code> function in  <fr:link href="/hazel/" title="Hazel" uri="https://patrick.sirref.org/hazel/" display-uri="hazel" type="local">Hazel </fr:link><![CDATA[ (]]><html:code>fun x -&gt; x + 1</html:code><![CDATA[) has type]]><html:code>? -&gt; Int</html:code>. </html:p>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>5</fr:month>
                      <fr:day>2</fr:day>
                    </fr:date>
                    <fr:title text="From OCaml to Hazel ">From OCaml to Hazel </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>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  <![CDATA[boilerplate code (e.g. URI parsing or standard library functions for strings).]]></html:p>
                    <fr:tree show-metadata="false" numbered="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2025</fr:year>
                          <fr:month>5</fr:month>
                          <fr:day>2</fr:day>
                        </fr:date>
                        <fr:title text="A Transformation of Syntax ">A Transformation of Syntax </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>Hazel markets itself as an "Elm/ML-like functional programming language". From  the previous example of  <html:code>map</html:code>, it should be apparent just how close to OCaml  the language is. </html:p>
                        <html:p>It turns out that a majority of the transpiler is a  <html:em>transformation of syntax </html:em>.  Take a simple ADT for an arithmetic programming language. </html:p>
                        <html:pre class="hilite">
                          <html:code>
                            <html:span class="ocaml-keyword-other">type</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">expr</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">  </html:span>
                            <html:span class="ocaml-keyword-other">|</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">Float</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other">of</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-support-type">float</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">  </html:span>
                            <html:span class="ocaml-keyword-other">|</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">Add</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other">of</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">expr</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">*</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">expr</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">  </html:span>
                            <html:span class="ocaml-keyword-other">|</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">Sub</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other">of</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">expr</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">*</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">expr</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">  </html:span>
                            <html:span class="ocaml-keyword-other">|</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">Mul</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other">of</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">expr</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">*</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">expr</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">  </html:span>
                            <html:span class="ocaml-keyword-other">|</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">Div</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other">of</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">expr</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">*</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">expr</html:span>
                            <html:span class="ocaml-source">
</html:span>
                          </html:code>
                        </html:pre>
                        <html:p>And when we run  <fr:link href="/hazel_of_ocaml/" title="hazel_of_ocaml" uri="https://patrick.sirref.org/hazel_of_ocaml/" display-uri="hazel_of_ocaml" type="local">hazel_of_ocaml </fr:link> over this OCaml type declaration. </html:p>
                        <html:pre><![CDATA[type expr =
  + Float(Float)
  + Add((expr, expr))
  + Sub((expr, expr))
  + Mul((expr, expr))
  + Div((expr, expr))
 in ?]]></html:pre>
                        <html:p>Not much has changed expect some syntax.  <fr:link href="/hazel/" title="Hazel" uri="https://patrick.sirref.org/hazel/" display-uri="hazel" type="local">Hazel </fr:link> does not have a notion of top-level expression so  <fr:link href="/hazel_of_ocaml/" title="hazel_of_ocaml" uri="https://patrick.sirref.org/hazel_of_ocaml/" display-uri="hazel_of_ocaml" type="local">hazel_of_ocaml </fr:link> 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  <![CDATA[with no support for modules or labelled records out of the box (there are plenty of development branches]]> <![CDATA[with these features).]]></html:p>
                        <html:p>If we try out the same  <html:code>map</html:code> function but written in OCaml and transpiled to Hazel we get. </html:p>
                        <html:pre class="hilite">
                          <html:code>
                            <html:span class="ocaml-keyword">let</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword">rec </html:span>
                            <html:span class="ocaml-entity-name-function-binding">map</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">f</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other">function</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">  </html:span>
                            <html:span class="ocaml-keyword-other">|</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-language-list"><![CDATA[[]]]></html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-language-list"><![CDATA[[]]]></html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">  </html:span>
                            <html:span class="ocaml-keyword-other">|</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">x</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">xs</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">f</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">x</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">map</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">f</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">xs</html:span>
                            <html:span class="ocaml-source">
</html:span>
                          </html:code>
                        </html:pre>
                        <html:p>Which becomes the following hazel program. </html:p>
                        <html:pre><![CDATA[let map = fun f -> fun x1 -> case x1
  | [] => []
  | x :: xs => f(x) :: map(f)(xs)
end in ?]]></html:pre>
                        <html:p>We could have a field day discussing the syntax of OCaml and Hazel  <![CDATA[(parentheses for function arguments, well-scoped cases for pattern-matching, a]]> <![CDATA[different arrow for pattern-matching etc.). What would be more interesting is]]> taking a look at how to handle polymorphism in Hazel. </html:p>
                      </fr:mainmatter>
                    </fr:tree>
                    <fr:tree show-metadata="false" numbered="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2025</fr:year>
                          <fr:month>5</fr:month>
                          <fr:day>2</fr:day>
                        </fr:date>
                        <fr:title text="Explicit Polymorphism ">Explicit Polymorphism </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>Hazel has  <html:em>explicit polymorphism </html:em>. So far, we have not seen it as we have let the types  have holes in them. The  <html:code>map</html:code> function in OCaml has the following type. </html:p>
                        <html:pre class="hilite">
                          <html:code>
                            <html:span class="ocaml-keyword-other">val</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">map</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                            <html:span class="ocaml-source"> 
</html:span>
                            <html:span class="ocaml-source">  </html:span>
                            <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                            <html:span class="ocaml-storage-type">'a</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-storage-type">'b</html:span>
                            <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-storage-type">'a</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">list</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-storage-type">'b</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">list</html:span>
                            <html:span class="ocaml-source">
</html:span>
                          </html:code>
                        </html:pre>
                        <html:p><![CDATA[We must remind ourselves (by reading]]><fr:link href="https://www.craigfe.io/posts/polymorphic-type-constraints" type="external">Craig's excellent blogpost on the matter </fr:link><![CDATA[) that in OCaml]]></html:p>
                        <html:blockquote>
                          <html:p>... type variables in signatures are implicitly universally-quantified </html:p>
                        </html:blockquote>
                        <html:p>So in reality, we have that  <html:code>map</html:code> has the following type. </html:p>
                        <html:pre><![CDATA[val map : ∀ a b. (a ->  b) -> a list -> b list]]></html:pre>
                        <html:p>In Hazel, we have to explicitly type our  <html:code>map</html: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  <html:code>map</html:code><![CDATA[ function (whether that be recursively or somewhere later in our]]> <![CDATA[program).]]></html:p>
                        <html:pre><![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])]]></html:pre>
                        <html:p><html:code>forall</html:code> introduces a universally quantified type variable into our type annotation,  and  <html:code>typfun</html:code><![CDATA[ introduces it into the function itself (à la System F). Type application]]> requires  <html:code>@&lt;T&gt;</html:code> where  <html:code>T</html:code> is some type. This allows hazel to quite easily support higher  rank polymorphism, but we will not worry too much about that. </html:p>
                      </fr:mainmatter>
                    </fr:tree>
                    <fr:tree show-metadata="false" numbered="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2025</fr:year>
                          <fr:month>5</fr:month>
                          <fr:day>2</fr:day>
                        </fr:date>
                        <fr:title text="Propagating OCaml Types into Hazel ">Propagating OCaml Types into Hazel </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>Most often, OCaml users interact with  <html:em>prenex </html:em><![CDATA[ polymorphism (rank-1) where the universal quantifiers are]]> at the front of the type.  <fr:link href="https://ocaml.org/manual/5.2/polymorphism.html#s:higher-rank-poly" type="external">OCaml does support quantifiers inside certain types like records </fr:link>. </html:p>
                        <html:p>What this means for the transpiler is that we can  <html:strong>reuse OCaml's type inference </html:strong> to safely  instantiate the correct type annotations and type applications in Hazel! To do this,  <html:code>hazel_of_ocaml</html:code> uses  <fr:link href="https://ocaml.github.io/merlin/" type="external">Merlin </fr:link> to inspect the type of the function in either  a value binding or at the point of a function application. </html:p>
                        <html:p>Take a simple, polymorphic  <html:code>length</html:code> function. </html:p>
                        <html:pre class="hilite">
                          <html:code>
                            <html:span class="ocaml-keyword">let</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword">rec </html:span>
                            <html:span class="ocaml-entity-name-function-binding">length</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other">function</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other">|</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-language-list"><![CDATA[[]]]></html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-integer">0</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other">|</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-language">_</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">xs</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-integer">1</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">+</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">length</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">xs</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-keyword">let</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-entity-name-function-binding">int_len</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">length</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[[]]></html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-integer">1</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-integer">2</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-integer">3</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[]]]></html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-keyword">let</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-entity-name-function-binding">str_len</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">length</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[[]]></html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-string-quoted-double">"</html:span>
                            <html:span class="ocaml-string-quoted-double">only</html:span>
                            <html:span class="ocaml-string-quoted-double">"</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-string-quoted-double">"</html:span>
                            <html:span class="ocaml-string-quoted-double">two</html:span>
                            <html:span class="ocaml-string-quoted-double">"</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[]]]></html:span>
                            <html:span class="ocaml-source">
</html:span>
                          </html:code>
                        </html:pre>
                        <html:p>When we run this through  <html:code>hazel_of_ocaml</html:code> with the  <html:code>-type</html:code> flag we get. </html:p>
                        <html:pre><![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 ?]]></html:pre>
                        <html:p><html:code>hazel_of_ocaml</html:code> has correctly instantiated the type for  <html:code>length</html:code> inside the recursive function  and then in each case with the integer list and the string list. </html:p>
                      </fr:mainmatter>
                    </fr:tree>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>5</fr:month>
                      <fr:day>2</fr:day>
                    </fr:date>
                    <fr:title text="A Corpus of Hazel Programs ">A Corpus of Hazel Programs </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>The impetus for this work was to derive a corpus of ill-typed Hazel programs.  Luckily, such a corpus exists for OCaml!  <fr:link href="/ocaml-corpus/" title="A Collection of Novice Interactions with the OCaml Top-Level System" uri="https://patrick.sirref.org/ocaml-corpus/" display-uri="ocaml-corpus" type="local">Seidel et al. </fr:link> created  a corpus of OCaml programs from their undergraduate students at UC San Diego.  <fr:link href="https://github.com/patricoferris/hazel-corpus" type="external">Some of these programs have been transpiled to Hazel </fr:link>. </html:p>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>5</fr:month>
                      <fr:day>2</fr:day>
                    </fr:date>
                    <fr:title text="Future Work ">Future Work </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p><fr:link href="/hazel/" title="Hazel" uri="https://patrick.sirref.org/hazel/" display-uri="hazel" type="local">Hazel </fr:link> 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  <![CDATA[(e.g. handling the]]><html:code>cmi</html:code><![CDATA[ files).]]></html:p>
                    <html:p>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? </html:p>
                  </fr:mainmatter>
                </fr:tree>
              </fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="false" expanded="false" toc="false" numbered="false">
              <fr:frontmatter>
                <fr:authors />
                <fr:date>
                  <fr:year>2025</fr:year>
                  <fr:month>2</fr:month>
                  <fr:day>18</fr:day>
                </fr:date>
                <fr:uri>https://patrick.sirref.org/ppxlib-5-2/</fr:uri>
                <fr:display-uri>ppxlib-5-2</fr:display-uri>
                <fr:route>/ppxlib-5-2/</fr:route>
                <fr:title text="Bumping Ppxlib's AST to 5.2">Bumping Ppxlib's AST to 5.2</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p><fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">Ppxlib </fr:link> is a libary for building OCaml preprocessors. Users can generate OCaml code  <html:em>from </html:em><![CDATA[ OCaml code (derivers) or replace parts of OCaml code with other OCaml code (rewriters).]]></html:p>
                <html:p>At the core of  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link> is the OCaml parsetree; a data structure in the compiler that represents OCaml source code.  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">Ppxlib </fr:link><![CDATA[ makes a distinction between the source parsetree (based on the version of the OCaml compiler you are using) and]]><fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link><![CDATA['s parsetree (a copy of]]><html:em>some </html:em><![CDATA[ parsetree from the compiler).]]></html:p>
                <html:p>In  <fr:link href="https://discuss.ocaml.org/t/ann-ppxlib-0-36-0" type="external">ppxlib.0.36.0 </fr:link>, 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. </html:p>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors />
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>2</fr:month>
                      <fr:day>18</fr:day>
                    </fr:date>
                    <fr:title text="Manual Migrations in Ppxlib ">Manual Migrations in Ppxlib </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>It is possible to perform migrations between parsetrees manually using the  <html:code>ppxlib.ast</html:code> package. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-keyword-other">open</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Ppxlib</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-other">open</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Ast_builder</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Make</html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">struct</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">loc</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Location</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">none</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">end</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">pp_expr</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Format</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">printf</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-constant-character-printf"><![CDATA[%a]]></html:span>
                        <html:span class="ocaml-constant-character-printf"><![CDATA[%!]]></html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pp_ast</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source">expression</html:span>
                        <html:span class="ocaml-source"> ?</html:span>
                        <html:span class="ocaml-source">config</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">None</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">loc</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Location</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">none</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">str</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">txt</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[{]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">txt</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">loc</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[}]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">To_408</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> 
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Ppxlib_ast</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Convert</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Ppxlib_ast</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Js</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Ppxlib_ast__</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Versions</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">OCaml_408</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>The  <html:code>Ppxlib_ast.Js</html:code> module is  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link><![CDATA['s AST (since]]><html:code>ppxlib.0.36.0</html:code><![CDATA[ OCaml 5.2.0). We can use functions]]> provided by the  <html:code>Convert</html:code> functor to copy parts of the AST from one version to another. Usually there is very little difference between the versioned parsetrees. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">func</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">arg</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">body</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-source">pexp_fun</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Nolabel</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">None</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source">ppat_var</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source">str</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">arg</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">body</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">add_expr</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">func</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">x</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source">func</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">y</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source">eapply</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source">evar</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">Int.add</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[[]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">evar</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">x</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">evar</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">y</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[]]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>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. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-mdx-hash">#</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">pp_expr</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">add_expr</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source"> 
</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pexp_function</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[[]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[{]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">pparam_loc</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">__loc</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">      </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">pparam_desc</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pparam_val</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Nolabel</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">None</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Ppat_var</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">x</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">      </html:span>
                        <html:span class="ocaml-source"><![CDATA[}]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">    </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[{]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">pparam_loc</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">__loc</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">      </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">pparam_desc</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pparam_val</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Nolabel</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">None</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Ppat_var</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">y</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">      </html:span>
                        <html:span class="ocaml-source"><![CDATA[}]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">    </html:span>
                        <html:span class="ocaml-source"><![CDATA[]]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">None</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pfunction_body</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">      </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pexp_apply</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">         </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pexp_ident</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Ldot</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Lident</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">Int</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">add</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">         </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[[]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Nolabel</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pexp_ident</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Lident</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">x</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">           </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Nolabel</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pexp_ident</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Lident</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">y</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">           </html:span>
                        <html:span class="ocaml-source"><![CDATA[]]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">         </html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-operator">-</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">unit</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-unit"><![CDATA[()]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>This is a relatively new feature of the parsetree, if we migrate the expression down to  <html:code>4.08</html: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. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">expr_408</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">To_408</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">copy_expression</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">add_expr</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors />
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>2</fr:month>
                      <fr:day>18</fr:day>
                    </fr:date>
                    <fr:title text="Function Arity in the OCaml Parsetree ">Function Arity in the OCaml Parsetree </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>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: </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">add</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">x</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">y</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">x</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">+</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">y</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>A two-argument  <html:code>add</html:code> function would be represented in the parsetree as  <html:code>fun x -&gt; fun y -&gt; x + y</html:code><![CDATA[. Using the nodes from the parsetree (with some details removed) it would be]]><html:code><![CDATA[Pexp_fun (x, Pexp_fun (y, Pexp_apply ...))]]></html:code>. </html:p>
                    <html:p>Now, since OCaml 5.2, functions can be expressed with their syntactic arity intact. The function  <html:code>add</html:code> would look something like  <html:code><![CDATA[Pexp_function ([ x; y ], Pfunction_body (Pexp_apply ...))]]></html:code>. Both arguments are stored as a list. </html:p>
                    <html:p>The constructor  <html:code>Pexp_function</html:code> was not a new addition to the parsetree. It used to represent pattern-matching expressions like  <html:code>function A -&gt; 1</html:code>. This can now be expressed as a function body of  <html:code>Pfunction_cases</html:code>. </html:p>
                    <html:p>Whilst these additions and modifications to the parsetree are arguably a better design, it has caused chaos in terms of  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link>'s reverse dependencies! </html:p>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors />
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>2</fr:month>
                      <fr:day>18</fr:day>
                    </fr:date>
                    <fr:title text="Coalescing Function Arguments ">Coalescing Function Arguments </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>In  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link>  <html:code>0.36.0</html:code>, functions from  <html:code>Ast_builder</html:code> will help ppx authors produce maximum arity functions. However, functions from  <html:code>Ast_helper</html:code> will not do this. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">ast_helper_func</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">arg</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">body</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Ast_helper</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Exp</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">fun_</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Nolabel</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">None</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source">ppat_var</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source">str</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">arg</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">body</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">ast_helper_expr</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">ast_helper_func</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">x</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source">ast_helper_func</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">y</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source">eapply</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source">evar</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">Int.equal</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[[]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">evar</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">x</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">evar</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">y</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[]]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>Here we recreate our helper function to create function expressions using  <html:code>Ast_helper.Exp.fun_</html:code> instead. We can now show the difference between the  <html:code>expr</html:code> expression and the  <html:code>ast_helper_expr</html:code> expression. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-mdx-hash">#</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">pp_expr</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">add_expr</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pexp_function</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[[]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[{]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">pparam_loc</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">__loc</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">      </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">pparam_desc</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pparam_val</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Nolabel</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">None</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Ppat_var</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">x</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">      </html:span>
                        <html:span class="ocaml-source"><![CDATA[}]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">    </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[{]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">pparam_loc</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">__loc</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">      </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">pparam_desc</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pparam_val</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Nolabel</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">None</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Ppat_var</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">y</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">      </html:span>
                        <html:span class="ocaml-source"><![CDATA[}]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">    </html:span>
                        <html:span class="ocaml-source"><![CDATA[]]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">None</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pfunction_body</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">      </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pexp_apply</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">         </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pexp_ident</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Ldot</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Lident</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">Int</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">add</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">         </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[[]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Nolabel</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pexp_ident</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Lident</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">x</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">           </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Nolabel</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pexp_ident</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Lident</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">y</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">           </html:span>
                        <html:span class="ocaml-source"><![CDATA[]]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">         </html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-operator">-</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">unit</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-unit"><![CDATA[()]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>Above, we see a function expression with arity  <html:em>two </html:em>. Below, we see nested function expressions each with arity  <html:em>one </html:em>. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-mdx-hash">#</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">pp_expr</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">ast_helper_expr</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pexp_function</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[[]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[{]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">pparam_loc</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">__loc</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">      </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">pparam_desc</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pparam_val</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Nolabel</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">None</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Ppat_var</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">x</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">      </html:span>
                        <html:span class="ocaml-source"><![CDATA[}]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">    </html:span>
                        <html:span class="ocaml-source"><![CDATA[]]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">None</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pfunction_body</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">      </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pexp_function</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">         </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[[]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[{]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">pparam_loc</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">__loc</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">             </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">pparam_desc</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pparam_val</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Nolabel</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">None</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Ppat_var</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">y</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">             </html:span>
                        <html:span class="ocaml-source"><![CDATA[}]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">           </html:span>
                        <html:span class="ocaml-source"><![CDATA[]]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">         </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">None</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">         </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pfunction_body</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">             </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pexp_apply</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">                </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pexp_ident</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Ldot</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Lident</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">Int</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">equal</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">                </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[[]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Nolabel</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pexp_ident</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Lident</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">x</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">                  </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Nolabel</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Pexp_ident</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Lident</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">y</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">                  </html:span>
                        <html:span class="ocaml-source"><![CDATA[]]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">                </html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">         </html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-operator">-</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">unit</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-unit"><![CDATA[()]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors />
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>2</fr:month>
                      <fr:day>18</fr:day>
                    </fr:date>
                    <fr:title text="Ramifications for Ppxlib Users ">Ramifications for Ppxlib Users </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>Many, many,  <html:em>many </html:em> ppxes broke after migrating the  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link> AST to 5.2. Mostly, this is due to pattern-matching.  Downstream users of  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link> frequently pattern-match directly against the parsetree. However, nodes such as  <html:code>Pexp_fun</html:code> no longer exist and  <html:code>Pexp_function</html:code> has completely different constructor arguments! </html:p>
                    <html:p><![CDATA[Patching all the ppxes has been quite difficult. Most ppxes only deal with single arguments at a time (e.g.]]><html:code>Pexp_fun x</html:code><![CDATA[) but now they must handle zero or more arguments at a time. (In the zero case, this will always correspond to a pattern-matching]]><html:code>function</html:code><![CDATA[).]]></html:p>
                    <html:p>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  <html:code>ppxlib.0.36.0</html:code>: </html:p>
                    <html:ul>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/patricoferris/ppx_deriving_yaml/pull/58" type="external">https://github.com/patricoferris/ppx_deriving_yaml/pull/58 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/mirage/ocaml-rpc/pull/181" type="external">https://github.com/mirage/ocaml-rpc/pull/181 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://gitlab.com/o-labs/ppx_deriving_jsoo/-/merge_requests/1" type="external">https://gitlab.com/o-labs/ppx_deriving_jsoo/-/merge_requests/1 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/ocaml-community/sedlex/pull/160" type="external">https://github.com/ocaml-community/sedlex/pull/160 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/ocaml-sys/config.ml/pull/22" type="external">https://github.com/ocaml-sys/config.ml/pull/22 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/vogler/ppx_distr_guards/pull/2" type="external">https://github.com/vogler/ppx_distr_guards/pull/2 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/ocaml-gospel/gospel/pull/424" type="external">https://github.com/ocaml-gospel/gospel/pull/424 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/teamwalnut/graphql-ppx/pull/299" type="external">https://github.com/teamwalnut/graphql-ppx/pull/299 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/ocsigen/lwt/pull/1033" type="external">https://github.com/ocsigen/lwt/pull/1033 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://gitlab.com/gopiandcode/ppx-inline-alcotest/-/merge_requests/3" type="external">https://gitlab.com/gopiandcode/ppx-inline-alcotest/-/merge_requests/3 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/dariusf/ppx_interact/pull/3" type="external">https://github.com/dariusf/ppx_interact/pull/3 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/ocaml-ppx/ppx_deriving_yojson/pull/160" type="external">https://github.com/ocaml-ppx/ppx_deriving_yojson/pull/160 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/lpcic/elpi/pull/276" type="external">https://github.com/LPCIC/elpi/pull/276 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/mirage/repr/pull/110" type="external">https://github.com/mirage/repr/pull/110 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/programingisthefuture/ppx_default/pull/3" type="external">https://github.com/ProgramingIsTheFuture/ppx_default/pull/3 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/codinuum/vlt/pull/3" type="external">https://github.com/codinuum/vlt/pull/3 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/sim642/ppx_deriving_hash/pull/6" type="external">https://github.com/sim642/ppx_deriving_hash/pull/6 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/ocsigen/tyxml/pull/340" type="external">https://github.com/ocsigen/tyxml/pull/340 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/sim642/ppx_viewpattern/pull/2" type="external">https://github.com/sim642/ppx_viewpattern/pull/2 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/little-arhat/ppx_jsobject_conv/pull/11" type="external">https://github.com/little-arhat/ppx_jsobject_conv/pull/11 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/robur-coop/lun/pull/1" type="external">https://github.com/robur-coop/lun/pull/1 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://gitlab.com/o-labs/ppx_deriving_encoding/-/merge_requests/4" type="external">https://gitlab.com/o-labs/ppx_deriving_encoding/-/merge_requests/4 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/francoisthire/bam/pull/12" type="external">https://github.com/francoisthire/bam/pull/12 </fr:link>
                        </html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/xguerin/bitstring/pull/36" type="external">https://github.com/xguerin/bitstring/pull/36 </fr:link>
                        </html:p>
                      </html:li>
                    </html:ul>
                    <html:p><![CDATA[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]]><fr:link href="https://www.cambridge.org/core/journals/journal-of-functional-programming/article/pattern-matching-with-abstract-data-types1/04DD26A0E6CA3A1E87E0E6AE8BC02EED" type="external">tension is not new </fr:link>. </html:p>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors />
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>2</fr:month>
                      <fr:day>18</fr:day>
                    </fr:date>
                    <fr:title text="The Future of Ppxlib ">The Future of Ppxlib </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p><fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">Ppxlib </fr:link> 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  <fr:link href="https://github.com/ocaml-ppx/ppxlib/pull/558" type="external">the 5.3 bump </fr:link>! </html:p>
                    <html:p>There have been many discussions about simplifying this process, but so far the time and effort to build a  <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib </fr:link><![CDATA[ that will result in fewer breakages is too high (see]]><fr:link href="https://github.com/ocaml-ppx/ppx" type="external">an attempt using views </fr:link><![CDATA[).]]></html:p>
                    <html:p>Thank you to Tarides and Jane Street for funding my time to work on this release and all the chaos it has caused. </html:p>
                    <html:p>Happy preprocessing! </html:p>
                  </fr:mainmatter>
                </fr:tree>
              </fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="false" expanded="false" toc="false" numbered="false">
              <fr:frontmatter>
                <fr:authors />
                <fr:date>
                  <fr:year>2025</fr:year>
                  <fr:month>2</fr:month>
                  <fr:day>28</fr:day>
                </fr:date>
                <fr:uri>https://patrick.sirref.org/vpnkit-upgrade/</fr:uri>
                <fr:display-uri>vpnkit-upgrade</fr:display-uri>
                <fr:route>/vpnkit-upgrade/</fr:route>
                <fr:title text="Defunctorising VPNKit">Defunctorising VPNKit</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p><fr:link href="/vpnkit/" title="VPNKit" uri="https://patrick.sirref.org/vpnkit/" display-uri="vpnkit" type="local">VPNKit </fr:link> 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. </html:p>
                <html:p>This short post discusses some of the recent changes to MirageOS and how they impact  <fr:link href="/vpnkit/" title="VPNKit" uri="https://patrick.sirref.org/vpnkit/" display-uri="vpnkit" type="local">VPNKit </fr:link>. </html:p>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors />
                    <fr:uri>https://patrick.sirref.org/dune-virt-libs/</fr:uri>
                    <fr:display-uri>dune-virt-libs</fr:display-uri>
                    <fr:route>/dune-virt-libs/</fr:route>
                    <fr:title text="Dune Virtual Libraries">Dune Virtual Libraries</fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>Dune, for quite some time, has supported  <html:em>virtual libraries </html:em><![CDATA[. This allows library authors to define a signature without an implementation (similar to OCaml's]]><html:code>module type S = struct ... end</html:code><![CDATA[). 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.]]></html:p>
                    <html:p>This feature has been quite widely used in OCaml. For example, the  <fr:link href="https://github.com/mirage/digestif" type="external">excellent  <html:code>digestif</html:code> library </fr:link> of hashing algorithms provides both C and OCaml implementations individually packaged into  <html:code>digestif.c</html:code> and  <html:code>digestif.ocaml</html:code><![CDATA[ respectively. Consider developing a browser application that needs some hashing algorithm (e.g.]]><fr:link href="https://github.com/patricoferris/omditor" type="external">Irmin in the browser </fr:link><![CDATA[). We can explicitly use the OCaml backend for digestif which]]><fr:link href="https://github.com/ocsigen/js_of_ocaml" type="external">js_of_ocaml </fr:link> will happily compile for us. </html:p>
                    <html:p>There are two distinct limitations to this approach. </html:p>
                    <html:ol>
                      <html:li>
                        <html:p>Applications can only link  <html:em>exactly one </html:em> implementation. </html:p>
                      </html:li>
                      <html:li>
                        <html:p><![CDATA[Implementations cannot expose additional functionality easily (see]]><fr:link href="https://github.com/ocaml/dune/issues/5997" type="external">dune#5597 </fr:link><![CDATA[).]]></html:p>
                      </html:li>
                    </html:ol>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors />
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>2</fr:month>
                      <fr:day>28</fr:day>
                    </fr:date>
                    <fr:title text="Functors in MirageOS ">Functors in MirageOS </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p><fr:link href="https://mirage.io/" type="external">MirageOS </fr:link><![CDATA[ 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.]]><html:code>unix</html:code>,  <html:code>hvt</html:code><![CDATA[ etc.)]]></html:p>
                    <html:p>Recently,  <fr:link href="https://github.com/mirage/mirage-skeleton/pull/407/" type="external">there has been a push </fr:link> to use  <fr:link href="/dune-virt-libs/" title="Dune Virtual Libraries" uri="https://patrick.sirref.org/dune-virt-libs/" display-uri="dune-virt-libs" type="local">dune virtual libraries </fr:link> instead. </html:p>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors />
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>2</fr:month>
                      <fr:day>28</fr:day>
                    </fr:date>
                    <fr:title text="VPNKit's Fake Clock &amp; Time ">VPNKit's Fake Clock &amp; Time </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p><![CDATA[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]]><html:code><![CDATA[(wrapped false)]]></html:code><![CDATA[). This allows implementers to expose additional modules alongside the implementation of the virtual library.]]></html:p>
                    <html:p>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. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">R</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Dns_forward</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Resolver</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Make</html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Proto_client</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Fake</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Time</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Fake</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Clock</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>In this new world of  <fr:link href="/dune-virt-libs/" title="Dune Virtual Libraries" uri="https://patrick.sirref.org/dune-virt-libs/" display-uri="dune-virt-libs" type="local">dune virtual libraries </fr:link>, our  <html:code>Resolver</html:code> is significantly more simple. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">R</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Dns_forward</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Resolver</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Make</html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Proto_client</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p><![CDATA[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.]]></html:p>
                    <html:p>The first thing I had to do was make the  <html:code>mirage-mtime</html:code> and  <html:code>mirage-sleep</html:code> virtual libraries unwrapped. This allowed me to make a new private dune library called  <html:code>fake_time</html:code> with  <html:em>two </html:em> public modules: the normal interface required by  <html:code>mirage-mtime</html:code> and another module called  <html:code>Fake_time_state</html:code> containing: </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">timeofday</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">ref</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-numeric-decimal-integer">0L</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">c</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Lwt_condition</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">create</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-unit"><![CDATA[()]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">advance</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">nsecs</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-source">timeofday</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Int64</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">add</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">!</html:span>
                        <html:span class="ocaml-source">timeofday</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">nsecs</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Lwt_condition</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">broadcast</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">c</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-unit"><![CDATA[()]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">reset</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-unit"><![CDATA[()]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-source">timeofday</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-numeric-decimal-integer">0L</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Lwt_condition</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">broadcast</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">c</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-unit"><![CDATA[()]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>I did the same for  <html:code>fake_sleep</html:code> which depended on the state from the  <html:code>fake_time</html:code><![CDATA[ library (something a normal library wouldn't).]]></html:p>
                    <html:p><![CDATA[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.  <![CDATA[You can only link one implementation at a time to an executable (or test).]]> Thus, the dune rules for running the  <html:code>dns_forward</html:code> test suite became: </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="dune-comment-line">; Uses the default  implementations provided by virtual libraries</html:span>
                        <html:span class="dune-source">
</html:span>
                        <html:span class="dune-meta-stanza"><![CDATA[(]]></html:span>
                        <html:span class="dune-meta-class-stanza">executable</html:span>
                        <html:span class="dune-meta-stanza">
</html:span>
                        <html:span class="dune-meta-stanza"> </html:span>
                        <html:span class="dune-meta-stanza-library-field"><![CDATA[(]]></html:span>
                        <html:span class="dune-keyword-other">name</html:span>
                        <html:span class="dune-meta-stanza-library-field"> </html:span>
                        <html:span class="dune-meta-atom">test</html:span>
                        <html:span class="dune-meta-stanza-library-field"><![CDATA[)]]></html:span>
                        <html:span class="dune-meta-stanza">
</html:span>
                        <html:span class="dune-meta-stanza"> </html:span>
                        <html:span class="dune-meta-stanza-lib-or-exec-buildable"><![CDATA[(]]></html:span>
                        <html:span class="dune-keyword-other">libraries</html:span>
                        <html:span class="dune-meta-stanza-lib-or-exec-buildable"> </html:span>
                        <html:span class="dune-meta-atom">dns_forward</html:span>
                        <html:span class="dune-meta-stanza-lib-or-exec-buildable"> </html:span>
                        <html:span class="dune-meta-atom">alcotest</html:span>
                        <html:span class="dune-meta-stanza-lib-or-exec-buildable"><![CDATA[)]]></html:span>
                        <html:span class="dune-meta-stanza"><![CDATA[)]]></html:span>
                        <html:span class="dune-source">
</html:span>
                        <html:span class="dune-source">
</html:span>
                        <html:span class="dune-comment-line">; Override the defaults and select the private fake libraries</html:span>
                        <html:span class="dune-source">
</html:span>
                        <html:span class="dune-meta-stanza"><![CDATA[(]]></html:span>
                        <html:span class="dune-meta-class-stanza">executable</html:span>
                        <html:span class="dune-meta-stanza">
</html:span>
                        <html:span class="dune-meta-stanza">  </html:span>
                        <html:span class="dune-meta-stanza-library-field"><![CDATA[(]]></html:span>
                        <html:span class="dune-keyword-other">name</html:span>
                        <html:span class="dune-meta-stanza-library-field"> </html:span>
                        <html:span class="dune-meta-atom">test_fake</html:span>
                        <html:span class="dune-meta-stanza-library-field"><![CDATA[)]]></html:span>
                        <html:span class="dune-meta-stanza">
</html:span>
                        <html:span class="dune-meta-stanza">  </html:span>
                        <html:span class="dune-meta-stanza-lib-or-exec-buildable"><![CDATA[(]]></html:span>
                        <html:span class="dune-keyword-other">libraries</html:span>
                        <html:span class="dune-meta-stanza-lib-or-exec-buildable"> </html:span>
                        <html:span class="dune-meta-atom">dns_forward</html:span>
                        <html:span class="dune-meta-stanza-lib-or-exec-buildable"> </html:span>
                        <html:span class="dune-meta-atom">alcotest</html:span>
                        <html:span class="dune-meta-stanza-lib-or-exec-buildable"> </html:span>
                        <html:span class="dune-meta-atom">fake_sleep</html:span>
                        <html:span class="dune-meta-stanza-lib-or-exec-buildable"> </html:span>
                        <html:span class="dune-meta-atom">fake_time</html:span>
                        <html:span class="dune-meta-stanza-lib-or-exec-buildable"><![CDATA[)]]></html:span>
                        <html:span class="dune-meta-stanza"><![CDATA[)]]></html:span>
                        <html:span class="dune-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>With all of this machinery in place, I could now update  <html:code>test_fake</html:code> to use the new modules that would provide the custom functionality for the clock and time implementations. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-comment-block"><![CDATA[(*]]></html:span>
                        <html:span class="ocaml-comment-block"> The bad server should be marked offline and no-one will wait for it </html:span>
                        <html:span class="ocaml-comment-block"><![CDATA[*)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Fake_time_state</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">reset</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-unit"><![CDATA[()]]></html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-comment-block"><![CDATA[(*]]></html:span>
                        <html:span class="ocaml-comment-block"> avoid the timeouts winning the race with the actual result </html:span>
                        <html:span class="ocaml-comment-block"><![CDATA[*)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Fake_time_state</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">advance</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Duration</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source">of_ms</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-numeric-decimal-integer">500</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source"> 
</html:span>
                      </html:code>
                    </html:pre>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors />
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>2</fr:month>
                      <fr:day>28</fr:day>
                    </fr:date>
                    <fr:title text="Conclusion ">Conclusion </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>The switch to  <fr:link href="/dune-virt-libs/" title="Dune Virtual Libraries" uri="https://patrick.sirref.org/dune-virt-libs/" display-uri="dune-virt-libs" type="local">dune virtual libraries </fr:link> 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. </html:p>
                    <html:p>The  <fr:link href="https://github.com/moby/vpnkit/pull/646" type="external">pull request to upgrade VPNKit is open </fr:link>. </html:p>
                  </fr:mainmatter>
                </fr:tree>
              </fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="false" expanded="false" toc="false" numbered="false">
              <fr:frontmatter>
                <fr:authors>
                  <fr:author>
                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                  </fr:author>
                </fr:authors>
                <fr:date>
                  <fr:year>2023</fr:year>
                  <fr:month>8</fr:month>
                  <fr:day>9</fr:day>
                </fr:date>
                <fr:uri>https://patrick.sirref.org/ocaml-rtree/</fr:uri>
                <fr:display-uri>ocaml-rtree</fr:display-uri>
                <fr:route>/ocaml-rtree/</fr:route>
                <fr:title text="Reviving OCaml R-Tree">Reviving OCaml R-Tree</fr:title>
                <fr:meta name="description">Fast-forwarding a decade-old OCaml implementation of the R-Tree geospatial data-structure.
</fr:meta>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>Antonin Guttman  <fr:link href="http://www-db.deis.unibo.it/courses/SI-LS/papers/Gut84.pdf" type="external">first proposed R-Trees in 1984 </fr:link>. </html:p>
                <html:blockquote>
                  <html: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... </html:p>
                </html:blockquote>
                <html:p><![CDATA[There are lots of excellent resources for understanding more about R-Trees and all of the wonderful variations there of (e.g.]]><fr:link href="http://www.cs.ucr.edu/~ravi/CS236Papers/rstar.pdf" type="external">R*-trees </fr:link><![CDATA[). This]]><fr:link href="https://www.bartoszsypytkowski.com/r-tree/" type="external">blog post </fr:link> seems to be the most popular introduction. </html:p>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:uri>https://patrick.sirref.org/ocaml-rtree-001/</fr:uri>
                    <fr:display-uri>ocaml-rtree-001</fr:display-uri>
                    <fr:route>/ocaml-rtree-001/</fr:route>
                    <fr:title text="An OCaml Rtree Implementation">An OCaml Rtree Implementation</fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>In the  <fr:link href="https://www.cst.cam.ac.uk/research/eeg" type="external">Energy and Environment Group </fr:link> 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  <fr:link href="https://github.com/mariusae/ocaml-rtree" type="external">an implementation in pure OCaml </fr:link>. After reaching out to the author, they were more than happy for their work to be maintained in the  <fr:link href="https://github.com/geocaml" type="external">Geocaml organisation </fr:link>, updated to the latest OCaml tools and  <fr:link href="https://github.com/ocaml/opam-repository/pull/24227" type="external">hopefully released on opam </fr:link>. </html:p>
                    <html:p>The  <fr:link href="https://github.com/geocaml/ocaml-rtree/commit/073d79ad34de15f0671f2faafb24b1edc5c2d8c7" type="external">dunification </fr:link><![CDATA[ went smoothly whilst fast-forwarding 15 OCaml compiler versions with no changes or problems (just dune unused variable warnings).]]></html:p>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:uri>https://patrick.sirref.org/ocaml-rtree-002/</fr:uri>
                    <fr:display-uri>ocaml-rtree-002</fr:display-uri>
                    <fr:route>/ocaml-rtree-002/</fr:route>
                    <fr:title text="OCaml Rtree Examples">OCaml Rtree Examples</fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p><![CDATA[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]]><html:code>Rectangle</html:code> envelope. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Line</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">struct</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword-other">type</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">    </html:span>
                        <html:span class="ocaml-source"><![CDATA[{]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">p0</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">float</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">*</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">float</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">p1</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">float</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">*</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">float</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[}]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">    </html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword">open</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Repr</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">in</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">    </html:span>
                        <html:span class="ocaml-source">record</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">line</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">fun</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">p0</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">p1</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[{]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">p0</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">p1</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[}]]></html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">    </html:span>
                        <html:span class="ocaml-keyword-operator">|+</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">field</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">p0</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source">pair</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">float</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">float</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">fun</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">p0</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">    </html:span>
                        <html:span class="ocaml-keyword-operator">|+</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">field</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-string-quoted-double">p1</html:span>
                        <html:span class="ocaml-string-quoted-double">"</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source">pair</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">float</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-support-type">float</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-keyword-other">fun</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">p1</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">    </html:span>
                        <html:span class="ocaml-keyword-operator">|&gt;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">sealr</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword-other">type</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">envelope</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Rtree</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Rectangle</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">t</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">  </html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">envelope</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[{]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">p0</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source">x1</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">y1</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">p1</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-source">x2</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">y2</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[}]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">    </html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">x0</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Float</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">min</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">x1</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">x2</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">in</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">    </html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">x1</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Float</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">max</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">x1</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">x2</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">in</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">    </html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">y0</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Float</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">min</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">y1</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">y2</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">in</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">    </html:span>
                        <html:span class="ocaml-keyword">let</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-entity-name-function-binding">y1</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Float</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">max</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">y1</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source">y2</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-other">in</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">    </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Rtree</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Rectangle</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-source">v</html:span>
                        <html:span class="ocaml-source"> ~</html:span>
                        <html:span class="ocaml-source">x0</html:span>
                        <html:span class="ocaml-source"> ~</html:span>
                        <html:span class="ocaml-source">y0</html:span>
                        <html:span class="ocaml-source"> ~</html:span>
                        <html:span class="ocaml-source">x1</html:span>
                        <html:span class="ocaml-source"> ~</html:span>
                        <html:span class="ocaml-source">y1</html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-keyword-other">end</html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>In addition to the  <html:code>envelope</html:code> function, we also need to provide a runtime representation using  <html:code>Repr</html:code>. In the example, we've constructed it by hand but I recommend using  <fr:link href="https://ocaml.org/p/ppx_repr/latest" type="external">ppx_repr </fr:link> to derive it for you. From here we can create our index. </html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="ocaml-keyword-other">module</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">R</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-keyword-operator">=</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Rtree</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Make</html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Rtree</html:span>
                        <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Rectangle</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source"> </html:span>
                        <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                        <html:span class="ocaml-constant-language-capital-identifier">Line</html:span>
                        <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                        <html:span class="ocaml-source">
</html:span>
                        <html:span class="ocaml-source">
</html:span>
                      </html:code>
                    </html:pre>
                    <fr:tree show-metadata="false" numbered="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:uri>https://patrick.sirref.org/ocaml-rtree-003/</fr:uri>
                        <fr:display-uri>ocaml-rtree-003</fr:display-uri>
                        <fr:route>/ocaml-rtree-003/</fr:route>
                        <fr:title text="Inserting Values">Inserting Values</fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>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. </html:p>
                        <html:pre class="hilite">
                          <html:code>
                            <html:span class="ocaml-mdx-hash">#</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword">let</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-entity-name-function-binding">r</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">    </html:span>
                            <html:span class="ocaml-keyword">let</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-entity-name-function-binding">i</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">R</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                            <html:span class="ocaml-source">empty</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-integer">4</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other">in</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">    </html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">R</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                            <html:span class="ocaml-source">insert</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">i</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">Line</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                            <html:span class="ocaml-source"><![CDATA[{]]></html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">p0</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">1.</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">1.</html:span>
                            <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">p1</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">2.</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">2.</html:span>
                            <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[}]]></html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-keyword-other">val</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">r</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">R</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                            <html:span class="ocaml-source">t</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">&lt;</html:span>
                            <html:span class="ocaml-source">abstr</html:span>
                            <html:span class="ocaml-keyword-operator">&gt;</html:span>
                            <html:span class="ocaml-source">
</html:span>
                          </html:code>
                        </html:pre>
                        <html:p>As you might expect, bulk loading takes a list of values instead. </html:p>
                        <html:pre class="hilite">
                          <html:code>
                            <html:span class="ocaml-mdx-hash">#</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword">let</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-entity-name-function-binding">r</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">    </html:span>
                            <html:span class="ocaml-keyword">let</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-entity-name-function-binding">lines</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">        </html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">Line</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                            <html:span class="ocaml-source"><![CDATA[[]]></html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">        </html:span>
                            <html:span class="ocaml-source"><![CDATA[{]]></html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">p0</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">0.</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">0.</html:span>
                            <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">p1</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">1.</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">1.</html:span>
                            <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[}]]></html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">        </html:span>
                            <html:span class="ocaml-source"><![CDATA[{]]></html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">p0</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">1.</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">1.</html:span>
                            <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">p1</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">2.</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">2.</html:span>
                            <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[}]]></html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">        </html:span>
                            <html:span class="ocaml-source"><![CDATA[{]]></html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">p0</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">2.</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">2.</html:span>
                            <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">p1</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">3.</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">3.</html:span>
                            <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[}]]></html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">        </html:span>
                            <html:span class="ocaml-source"><![CDATA[{]]></html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">p0</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">3.</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">3.</html:span>
                            <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">p1</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">4.</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">4.</html:span>
                            <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[}]]></html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">        </html:span>
                            <html:span class="ocaml-source"><![CDATA[]]]></html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">    </html:span>
                            <html:span class="ocaml-keyword-other">in</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source">    </html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">R</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                            <html:span class="ocaml-source">load</html:span>
                            <html:span class="ocaml-source"> ~</html:span>
                            <html:span class="ocaml-source">max_node_load</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                            <html:span class="ocaml-constant-numeric-decimal-integer">4</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">lines</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-keyword-other">val</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">r</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">R</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                            <html:span class="ocaml-source">t</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">&lt;</html:span>
                            <html:span class="ocaml-source">abstr</html:span>
                            <html:span class="ocaml-keyword-operator">&gt;</html:span>
                            <html:span class="ocaml-source">
</html:span>
                          </html:code>
                        </html:pre>
                      </fr:mainmatter>
                    </fr:tree>
                    <fr:tree show-metadata="false" numbered="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:uri>https://patrick.sirref.org/ocaml-rtree-004/</fr:uri>
                        <fr:display-uri>ocaml-rtree-004</fr:display-uri>
                        <fr:route>/ocaml-rtree-004/</fr:route>
                        <fr:title text="Spatial Queries">Spatial Queries</fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>The lines we loaded into the last index are really just four segments of the line  <html:code>y = x</html:code>. Let's spatially query for the first two segments. </html:p>
                        <html:pre class="hilite">
                          <html:code>
                            <html:span class="ocaml-mdx-hash">#</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">R</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                            <html:span class="ocaml-source">find</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">r</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">Rtree</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">Rectangle</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                            <html:span class="ocaml-source">v</html:span>
                            <html:span class="ocaml-source"> ~</html:span>
                            <html:span class="ocaml-source">x0</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">0.</html:span>
                            <html:span class="ocaml-source"> ~</html:span>
                            <html:span class="ocaml-source">y0</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">0.</html:span>
                            <html:span class="ocaml-source"> ~</html:span>
                            <html:span class="ocaml-source">x1</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">2.</html:span>
                            <html:span class="ocaml-source"> ~</html:span>
                            <html:span class="ocaml-source">y1</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">2.</html:span>
                            <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-keyword-operator">-</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">Line</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                            <html:span class="ocaml-source">t</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">list</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source"><![CDATA[[]]></html:span>
                            <html:span class="ocaml-source"><![CDATA[{]]></html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">Line</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                            <html:span class="ocaml-source">p0</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">0.</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">0.</html:span>
                            <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">p1</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">1.</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">1.</html:span>
                            <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                            <html:span class="ocaml-source"><![CDATA[}]]></html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[{]]></html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">Line</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                            <html:span class="ocaml-source">p0</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">1.</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">1.</html:span>
                            <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">p1</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">2.</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">2.</html:span>
                            <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                            <html:span class="ocaml-source"><![CDATA[}]]></html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source">
</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[{]]></html:span>
                            <html:span class="ocaml-constant-language-capital-identifier">Line</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                            <html:span class="ocaml-source">p0</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">2.</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">2.</html:span>
                            <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source">p1</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-keyword-operator">=</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">3.</html:span>
                            <html:span class="ocaml-keyword-other-ocaml punctuation-comma punctuation-separator">,</html:span>
                            <html:span class="ocaml-source"> </html:span>
                            <html:span class="ocaml-constant-numeric-decimal-float">3.</html:span>
                            <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                            <html:span class="ocaml-source"><![CDATA[}]]></html:span>
                            <html:span class="ocaml-source"><![CDATA[]]]></html:span>
                            <html:span class="ocaml-source">
</html:span>
                          </html:code>
                        </html:pre>
                        <html:p>You can see the query actually returned the first three, that's because all bound checks are inclusive. </html:p>
                      </fr:mainmatter>
                    </fr:tree>
                  </fr:mainmatter>
                </fr:tree>
                <html:p>The  <fr:link href="https://github.com/geocaml/ocaml-rtree/blob/d0a789b8eb6c594ed8c0f9c9a6c4b5cd7c734a03/test/image.ml#L95-L106" type="external">source repository includes a fairly simple example of rendering an R-Tree </fr:link> using  <fr:link href="https://github.com/dbuenzli/vg" type="external">Vg </fr:link>. This can be done outside of the repository using the  <html:code>tree</html:code> representation. </html:p>
                <html:pre class="hilite">
                  <html:code>
                    <html:span class="ocaml-mdx-hash">#</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other">#</html:span>
                    <html:span class="ocaml-keyword-other">show</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">R</html:span>
                    <html:span class="ocaml-source">.</html:span>
                    <html:span class="ocaml-source">tree</html:span>
                    <html:span class="ocaml-source">;;</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-keyword-other">val</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">tree</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">R</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">t</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">R</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">tree</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-keyword-other">type</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other">nonrec</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">tree</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">R</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">tree</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">    </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Node</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other">of</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Line</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">envelope</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">*</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">R</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">tree</html:span>
                    <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">list</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-keyword-other">|</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Leaf</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other">of</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Line</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">envelope</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">*</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Line</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">t</html:span>
                    <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">list</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-keyword-other">|</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Empty</html:span>
                    <html:span class="ocaml-source">
</html:span>
                  </html:code>
                </html:pre>
                <html:p>Here is an example rendering from the repository showing some random lines and the envelopes of the R-tree. </html:p>
                <html:p style="text-align:center">
    <html:img src="./rtree.svg" />
</html:p>
              </fr:mainmatter>
            </fr:tree>
          </fr:mainmatter>
        </fr:tree>
      </fr:mainmatter>
    </fr:tree>
    <fr:tree show-metadata="false" hidden-when-empty="true">
      <fr:frontmatter>
        <fr:authors />
        <fr:title text="Backlinks">Backlinks</fr:title>
      </fr:frontmatter>
      <fr:mainmatter />
    </fr:tree>
    <fr:tree show-metadata="false" hidden-when-empty="true">
      <fr:frontmatter>
        <fr:authors />
        <fr:title text="Related">Related</fr:title>
      </fr:frontmatter>
      <fr:mainmatter />
    </fr:tree>
    <fr:tree show-metadata="false" hidden-when-empty="true">
      <fr:frontmatter>
        <fr:authors />
        <fr:title text="Contributions">Contributions</fr:title>
      </fr:frontmatter>
      <fr:mainmatter />
    </fr:tree>
  </fr:backmatter>
</fr:tree>
