<?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>30</fr:day>
    </fr:date>
    <fr:uri>https://patrick.sirref.org/ppxlib-release-0-38-0/</fr:uri>
    <fr:display-uri>ppxlib-release-0-38-0</fr:display-uri>
    <fr:route>/ppxlib-release-0-38-0/</fr:route>
    <fr:title text="Ppxlib Releases › 0.38.0 "><fr:link href="/ppxlib-releases/" title="Ppxlib Releases" uri="https://patrick.sirref.org/ppxlib-releases/" display-uri="ppxlib-releases" type="local">Ppxlib Releases</fr:link> › 0.38.0 </fr:title>
  </fr:frontmatter>
  <fr:mainmatter>
    <html:p><fr:link href="/nathanreb/" title="Nathan Rebours" uri="https://patrick.sirref.org/nathanreb/" display-uri="nathanreb" type="local">Nathan</fr:link> and I <fr:link href="https://github.com/ocaml/opam-repository/pull/29563" type="external">released ppxlib.0.38.0</fr:link> last week. Its main feature is full <html:em>migration</html:em> support for the upcoming OCaml 5.5 compiler (currently in its <html:code>alpha3</html:code> release). This means supporting the handful of new features landing in OCaml 5.5: <fr:link href="/modular-explicits/" title="Modular Explicits in OCaml" uri="https://patrick.sirref.org/modular-explicits/" display-uri="modular-explicits" type="local">modular explicits</fr:link>, external type declarations and arbitrary "local" structure items.</html:p>
    <html:p>As <fr:link href="https://patrick.sirref.org/nathenreb/" type="external">Nathan</fr:link> and I continue to find a plausible maintenance story for <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib</fr:link>, <fr:link href="https://patrick.sirref.org/nathenreb/" type="external">Nathan</fr:link> has opened <fr:link href="https://github.com/ocaml/ocaml/issues/14668" type="external">an issue on the OCaml compiler to discuss the idea of adding additional extension points to the language</fr:link>.</html:p>
    <html:p>This comes from the desire to be able to store encoded versions of new OCaml features inside older abstract syntax trees.</html:p>
    <html:p>There are also some nice bug fixes in there too:</html:p>
    <html:ul>
      <html:li>
        <html:p><fr:link href="https://github.com/ocaml-ppx/ppxlib/pull/613" type="external">A potential OOM</fr:link> loop has now been removed.</html:p>
      </html:li>
      <html:li>
        <html:p>
          <fr:link href="https://github.com/ocaml-ppx/ppxlib/pull/619" type="external">Locations have been restored to long identifiers!</fr:link>
        </html:p>
      </html:li>
    </html:ul>
  </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>4</fr:month>
              <fr:day>3</fr:day>
            </fr:date>
            <fr:uri>https://patrick.sirref.org/weekly-2026-w14/</fr:uri>
            <fr:display-uri>weekly-2026-w14</fr:display-uri>
            <fr:route>/weekly-2026-w14/</fr:route>
            <fr:title text="Forking in Shells &amp; Library Maintenance">Forking in Shells &amp; Library Maintenance</fr:title>
          </fr:frontmatter>
          <fr:mainmatter>
            <html:p>This week, <fr:link href="/merry/" title="Merry" uri="https://patrick.sirref.org/merry/" display-uri="merry" type="local">Merry</fr:link> got close to executing <html:code>apt-get install ca-certificates</html:code> and running Debian's <html:code>debootstrap</html:code> scripts correctly. <fr:link href="https://patrick.sirref.org/nathan/" type="external">Nathan</fr:link> and I released <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">Ppxlib</fr:link> <html:code>0.38.0</html:code>, I added support to <fr:link href="https://github.com/geocaml/ocaml-proj" type="external">ocaml-proj</fr:link> for compiling to the browser and I fixed a long-standing bug in <fr:link href="https://github.com/patricoferris/hilite" type="external">hilite</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>4</fr:month>
                  <fr:day>3</fr:day>
                </fr:date>
                <fr:title text="Forking in Merry">Forking in Merry</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>So far, <fr:link href="/merry/" title="Merry" uri="https://patrick.sirref.org/merry/" display-uri="merry" type="local">Merry</fr:link> has managed to support many features of the POSIX shell specification without needing to do a <html:code>fork(2)</html:code> without an <html:code>exec</html:code>. Or, to put it another way, all the forking that <fr:link href="/merry/" title="Merry" uri="https://patrick.sirref.org/merry/" display-uri="merry" type="local">Merry</fr:link> does, will only be followed by running C code. This is actually a feature of <fr:link href="/eio/" title="Eio" uri="https://patrick.sirref.org/eio/" display-uri="eio" type="local">Eio</fr:link>'s <html:code>Process</html:code> API. It is required to make process execution safe in the context of multiple domains in OCaml (mostly due to ensuring consistency within the garbage collector). However, it is perfectly okay to <html:code>fork</html:code> and run OCaml code provided there is only a single domain.</html:p>
                <html:p>In a shell, many features of the shell language require that commands (or built-ins, function applications etc.) execute within a <html:code>subshell</html:code>. The specification does not go into detail about how shells should implement this, but many choose to <html:code>fork</html:code> in order to preserve some state in the parent (for example, the file descriptor table). Some shells try to minimise the number of forks as an optimisation. The <fr:link href="/korn1996korn/" title="The New Korn Shell" uri="https://patrick.sirref.org/korn1996korn/" display-uri="korn1996korn" type="local">korn shell (ksh)</fr:link> is one such shell.</html:p>
                <html:blockquote>
                  <html:p>Using the notation <html:code>$(command)</html:code> will cause <html:code>command</html:code> to execute in a subshell of the current ksh. In many instances, ksh will not actually fork/exec a subshell when command is a built-in or a shell function.</html:p>
                </html:blockquote>
                <html:p>By trying to adhere to Multicore OCaml's "<html:em>thou shalt not fork</html:em>" commandment, <fr:link href="/merry/" title="Merry" uri="https://patrick.sirref.org/merry/" display-uri="merry" type="local">Merry</fr:link> is much more similar to <html:code>ksh</html:code> in this regard. However, whenever there is an interaction with a shell built-in and semantics that need a child process, things get tricky very quickly. Consider the following:</html:p>
                <html:pre class="hilite">
                  <html:code>
                    <html:span class="sh-keyword-control">while</html:span>
                    <html:span class="sh-meta-scope-while-loop"> </html:span>
                    <html:span class="sh-support-function-builtin">echo</html:span>
                    <html:span class="sh-meta-scope-while-loop"> </html:span>
                    <html:span class="sh-punctuation-definition-string-begin">"</html:span>
                    <html:span class="sh-string-quoted-double">hello</html:span>
                    <html:span class="sh-punctuation-definition-string-end">"</html:span>
                    <html:span class="sh-keyword-operator-list">;</html:span>
                    <html:span class="sh-meta-scope-while-loop"> </html:span>
                    <html:span class="sh-keyword-control">do</html:span>
                    <html:span class="sh-meta-scope-while-loop">
</html:span>
                    <html:span class="sh-meta-scope-while-loop">  </html:span>
                    <html:span class="sh-support-function-builtin">:</html:span>
                    <html:span class="sh-meta-scope-while-loop">
</html:span>
                    <html:span class="sh-keyword-control">done</html:span>
                    <html:span class="sh-source"> </html:span>
                    <html:span class="sh-keyword-operator-pipe">|</html:span>
                    <html:span class="sh-source"> head -n 3
</html:span>
                  </html:code>
                </html:pre>
                <html:p>We have a mix of shell built-ins, normal commands, a compound command (the <html:code>while</html:code> loop) and a pipeline. Each individual command in the pipeline requires you to run them in a subshell and set them up <html:em>before</html:em> executing them. Without a <html:code>fork</html:code> for that first command, you may end up looping forever which is not the intended behaviour here. I had a good conversation with <fr:link href="/mdales/" title="Michael W. Dales" uri="https://patrick.sirref.org/mdales/" display-uri="mdales" type="local">Michael</fr:link> about the implications of this for reproducibility.</html:p>
                <html:p>For now, I have started implementing a <html:code>fork</html:code> for some of the shell features whilst still trying to maintain the functional core of the implementation.</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>4</fr:month>
                  <fr:day>3</fr:day>
                </fr:date>
                <fr:title text="An OCaml 5.5 compatible Ppxlib">An OCaml 5.5 compatible Ppxlib</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p><fr:link href="/nathanreb/" title="Nathan Rebours" uri="https://patrick.sirref.org/nathanreb/" display-uri="nathanreb" type="local">Nathan</fr:link> and I released an OCaml 5.5 compatible version of <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>30</fr:day>
                    </fr:date>
                    <fr:uri>https://patrick.sirref.org/ppxlib-release-0-38-0/</fr:uri>
                    <fr:display-uri>ppxlib-release-0-38-0</fr:display-uri>
                    <fr:route>/ppxlib-release-0-38-0/</fr:route>
                    <fr:title text="Ppxlib Releases › 0.38.0 "><fr:link href="/ppxlib-releases/" title="Ppxlib Releases" uri="https://patrick.sirref.org/ppxlib-releases/" display-uri="ppxlib-releases" type="local">Ppxlib Releases</fr:link> › 0.38.0 </fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p><fr:link href="/nathanreb/" title="Nathan Rebours" uri="https://patrick.sirref.org/nathanreb/" display-uri="nathanreb" type="local">Nathan</fr:link> and I <fr:link href="https://github.com/ocaml/opam-repository/pull/29563" type="external">released ppxlib.0.38.0</fr:link> last week. Its main feature is full <html:em>migration</html:em> support for the upcoming OCaml 5.5 compiler (currently in its <html:code>alpha3</html:code> release). This means supporting the handful of new features landing in OCaml 5.5: <fr:link href="/modular-explicits/" title="Modular Explicits in OCaml" uri="https://patrick.sirref.org/modular-explicits/" display-uri="modular-explicits" type="local">modular explicits</fr:link>, external type declarations and arbitrary "local" structure items.</html:p>
                    <html:p>As <fr:link href="https://patrick.sirref.org/nathenreb/" type="external">Nathan</fr:link> and I continue to find a plausible maintenance story for <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib</fr:link>, <fr:link href="https://patrick.sirref.org/nathenreb/" type="external">Nathan</fr:link> has opened <fr:link href="https://github.com/ocaml/ocaml/issues/14668" type="external">an issue on the OCaml compiler to discuss the idea of adding additional extension points to the language</fr:link>.</html:p>
                    <html:p>This comes from the desire to be able to store encoded versions of new OCaml features inside older abstract syntax trees.</html:p>
                    <html:p>There are also some nice bug fixes in there too:</html:p>
                    <html:ul>
                      <html:li>
                        <html:p><fr:link href="https://github.com/ocaml-ppx/ppxlib/pull/613" type="external">A potential OOM</fr:link> loop has now been removed.</html:p>
                      </html:li>
                      <html:li>
                        <html:p>
                          <fr:link href="https://github.com/ocaml-ppx/ppxlib/pull/619" type="external">Locations have been restored to long identifiers!</fr:link>
                        </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>2026</fr:year>
                  <fr:month>4</fr:month>
                  <fr:day>3</fr:day>
                </fr:date>
                <fr:title text="Browser support for ocaml-proj">Browser support for ocaml-proj</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>A while ago <fr:link href="https://github.com/geocaml/ocaml-proj" type="external">I built some "modern" bindings to PROJ4 in OCaml</fr:link>. After reading <fr:link href="https://patrick.sirref.org/jonludlam/" type="external">Jon Ludlam</fr:link>'s <fr:link href="https://jon.recoil.org/blog/2026/03/weeknotes-2026-12.html" type="external">weeknotes</fr:link> (and speaking with him and <fr:link href="/anilmadhavapeddy/" title="Anil Madhavapeddy" uri="https://patrick.sirref.org/anilmadhavapeddy/" display-uri="anilmadhavapeddy" type="local">Anil</fr:link>, I thought it might be nice to add a Javascript backend to those bindings). This was relatively straight-forward using <fr:link href="https://dune.readthedocs.io/en/stable/virtual-libraries.html" type="external">Dune's virtual libraries</fr:link> and is <fr:link href="https://github.com/geocaml/ocaml-proj/blob/main/src/js/proj.ml" type="external">available on Github</fr:link>.</html:p>
                <html:p>With virtual libraries, your own data analysis could (if you wished) depend solely on the <html:code>proj</html:code> library and later choose to either link it with <html:code>proj.c</html:code> or <html:code>proj.js</html:code> depending on where the analysis is being deployed.</html:p>
                <html:p>I briefly looked at WASM support, but quickly realised there was not much appetite for it and trying to compile around the C FFI was going to be hard.</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>4</fr:month>
                  <fr:day>3</fr:day>
                </fr:date>
                <fr:title text="Hilite updates">Hilite updates</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>Since I helped <fr:link href="https://ocaml.org/" type="external">relaunch the ocaml.org</fr:link> website a few years ago, I have maintained <fr:link href="https://github.com/patricoferris/hilite" type="external">hilite</fr:link>, a tool for doing build-time syntax highligting.</html:p>
                <html:p>It is being used on the <fr:link href="https://ocaml.org/" type="external">ocaml.org</fr:link> website, <fr:link href="https://github.com/xhtmlboi/yocaml/blob/45858f4b25730149dae3735e7fcdb9111ac1f9eb/yocaml_markdown.opam#L18" type="external">in yocaml_markdown</fr:link> and also in <fr:link href="/mdales/" title="Michael W. Dales" uri="https://patrick.sirref.org/mdales/" display-uri="mdales" type="local">Michael's</fr:link> <fr:link href="https://github.com/mdales/webplats/blob/cf0ea95a66bae52f02a00739eb02564fc94183ee/webplats.opam#L19" type="external">webplats</fr:link> (when it works...).</html:p>
                <html:p>And it was <fr:link href="/mdales/" title="Michael W. Dales" uri="https://patrick.sirref.org/mdales/" display-uri="mdales" type="local">Michael</fr:link> who led me to finally fixing and adding syntax highlighting support for Python and Go. Once I was on this roll, I finally took a look at fixing the long-standing bug of trying to highlight ocaml-mdx code, like the following:</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-numeric-decimal-float">50.123</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-mdx-hash">#</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-string-quoted-double">"</html:span>
                    <html:span class="ocaml-string-quoted-double">file.ml</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-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                    <html:span class="ocaml-source">
</html:span>
                  </html:code>
                </html:pre>
                <html:p>In fact, this code now highlights fine, but was the source of the bug. The syntax highlighting grammer confuses the ocaml-mdx <html:code>#</html:code> as a toplevel directive and trouble ensues.</html:p>
              </fr:mainmatter>
            </fr:tree>
          </fr:mainmatter>
        </fr:tree>
        <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>30</fr:day>
            </fr:date>
            <fr:uri>https://patrick.sirref.org/weekly-2026-w13/</fr:uri>
            <fr:display-uri>weekly-2026-w13</fr:display-uri>
            <fr:route>/weekly-2026-w13/</fr:route>
            <fr:title text="Ppxlib release and Merry updates">Ppxlib release and Merry updates</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>3</fr:month>
                  <fr:day>30</fr:day>
                </fr:date>
                <fr:uri>https://patrick.sirref.org/ppxlib-release-0-38-0/</fr:uri>
                <fr:display-uri>ppxlib-release-0-38-0</fr:display-uri>
                <fr:route>/ppxlib-release-0-38-0/</fr:route>
                <fr:title text="Ppxlib Releases › 0.38.0 "><fr:link href="/ppxlib-releases/" title="Ppxlib Releases" uri="https://patrick.sirref.org/ppxlib-releases/" display-uri="ppxlib-releases" type="local">Ppxlib Releases</fr:link> › 0.38.0 </fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p><fr:link href="/nathanreb/" title="Nathan Rebours" uri="https://patrick.sirref.org/nathanreb/" display-uri="nathanreb" type="local">Nathan</fr:link> and I <fr:link href="https://github.com/ocaml/opam-repository/pull/29563" type="external">released ppxlib.0.38.0</fr:link> last week. Its main feature is full <html:em>migration</html:em> support for the upcoming OCaml 5.5 compiler (currently in its <html:code>alpha3</html:code> release). This means supporting the handful of new features landing in OCaml 5.5: <fr:link href="/modular-explicits/" title="Modular Explicits in OCaml" uri="https://patrick.sirref.org/modular-explicits/" display-uri="modular-explicits" type="local">modular explicits</fr:link>, external type declarations and arbitrary "local" structure items.</html:p>
                <html:p>As <fr:link href="https://patrick.sirref.org/nathenreb/" type="external">Nathan</fr:link> and I continue to find a plausible maintenance story for <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib</fr:link>, <fr:link href="https://patrick.sirref.org/nathenreb/" type="external">Nathan</fr:link> has opened <fr:link href="https://github.com/ocaml/ocaml/issues/14668" type="external">an issue on the OCaml compiler to discuss the idea of adding additional extension points to the language</fr:link>.</html:p>
                <html:p>This comes from the desire to be able to store encoded versions of new OCaml features inside older abstract syntax trees.</html:p>
                <html:p>There are also some nice bug fixes in there too:</html:p>
                <html:ul>
                  <html:li>
                    <html:p><fr:link href="https://github.com/ocaml-ppx/ppxlib/pull/613" type="external">A potential OOM</fr:link> loop has now been removed.</html:p>
                  </html:li>
                  <html:li>
                    <html:p>
                      <fr:link href="https://github.com/ocaml-ppx/ppxlib/pull/619" type="external">Locations have been restored to long identifiers!</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>3</fr:month>
                  <fr:day>30</fr:day>
                </fr:date>
                <fr:title text="Merry updates">Merry updates</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>It turns out writing a POSIX(ish) shell is hard; at least, there is a vast number of slightly obscure features that one needs to support. I think this is surprising because most people writing shell scripts write simple shell scripts; scripts that use a much smaller subset of features. In the same breath, those same developers are likely to use something like <html:code>apt-get install bash</html:code> which runs a plethora of more advanced (and non-POSIX) shell scripts!</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>30</fr:day>
                    </fr:date>
                    <fr:title text="Exec redirects">Exec redirects</fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>In a shell script, you can use the built-in command <html:code>exec</html:code> to replace the current process with a new one (e.g. <html:code>exec vim</html:code>). However, there is a <fr:link href="https://pubs.opengroup.org/onlinepubs/9799919799/utilities/V3_chap02.html#tag_19_21" type="external"><html:em>different</html:em> mode of operation</fr:link> for <html:code>exec</html:code>:</html:p>
                    <html:blockquote>
                      <html:p>If exec is specified with no operands, any redirections associated with the exec command shall be made in the current shell execution environment.</html:p>
                    </html:blockquote>
                    <html:p>One of my litmus tests for <fr:link href="/merry/" title="Merry" uri="https://patrick.sirref.org/merry/" display-uri="merry" type="local">Merry</fr:link> is the <fr:link href="https://wiki.debian.org/Debootstrap" type="external">Debian debootstrap scripts</fr:link> (h/t <fr:link href="/anilmadhavapeddy/" title="Anil Madhavapeddy" uri="https://patrick.sirref.org/anilmadhavapeddy/" display-uri="anilmadhavapeddy" type="local">Anil</fr:link>). One thing that it does is the following:</html:p>
                    <html:pre class="hilite">
                      <html:code>
                        <html:span class="sh-entity-name-function">err</html:span>
                        <html:span class="sh-meta-function"> </html:span>
                        <html:span class="sh-punctuation-definition-arguments"><![CDATA[()]]></html:span>
                        <html:span class="sh-meta-function"> </html:span>
                        <html:span class="sh-punctuation-definition-group"><![CDATA[{]]></html:span>
                        <html:span class="sh-meta-scope-group">
</html:span>
                        <html:span class="sh-meta-scope-group">  </html:span>
                        <html:span class="sh-support-function-builtin">printf</html:span>
                        <html:span class="sh-meta-scope-group"> </html:span>
                        <html:span class="sh-punctuation-definition-string-begin">"</html:span>
                        <html:span class="sh-string-quoted-double">err </html:span>
                        <html:span class="sh-punctuation-definition-variable">$</html:span>
                        <html:span class="sh-variable-other-positional">1</html:span>
                        <html:span class="sh-punctuation-definition-string-end">"</html:span>
                        <html:span class="sh-meta-scope-group"> </html:span>
                        <html:span class="sh-keyword-operator-redirect">&gt;&amp;4</html:span>
                        <html:span class="sh-meta-scope-group">
</html:span>
                        <html:span class="sh-punctuation-definition-group"><![CDATA[}]]></html:span>
                        <html:span class="sh-punctuation-definition-function">
</html:span>
                        <html:span class="sh-source">
</html:span>
                        <html:span class="sh-support-function-builtin">exec</html:span>
                        <html:span class="sh-source"> </html:span>
                        <html:span class="sh-keyword-operator-redirect">4&gt;&amp;1</html:span>
                        <html:span class="sh-source"> 
</html:span>
                      </html:code>
                    </html:pre>
                    <html:p>A lot of detail has been elided for clarity. <html:code>exec 4&gt;&amp;1</html:code> sets up a redirection for the shell's execution environment in which file descriptor <html:code>4</html:code> is now an alias for standard output. So, writing to <html:code>4</html:code> (by redirecting a command's standard output to <html:code>4</html:code> i.e. <html:code>&gt;&amp;4</html:code>) will output to where standard output is going (most likely the terminal).</html:p>
                    <html:p>For this to work, shell's must <fr:link href="https://www.man7.org/linux/man-pages/man2/dup.2.html" type="external"><html:code>dup2</html:code></fr:link> the relevant file descriptors which have the following condition:</html:p>
                    <html:blockquote>
                      <html:p>If the file descriptor newfd was previously open, it is closed before being reused; the close is performed silently (i.e., any errors during the close are not reported by dup2()).</html:p>
                    </html:blockquote>
                    <html:p>This is all very well, unless your program has an important file already open that happens to have file descriptor <html:code>4</html:code>. The <fr:link href="/eio/" title="Eio" uri="https://patrick.sirref.org/eio/" display-uri="eio" type="local">Eio</fr:link> Linux and POSIX backends suffer from this problem. Both make use of a file-based synchronisation mechanism for waking up the eventloop should another domain push a completion to the scheduler's run queue. On Linux this is <fr:link href="https://github.com/ocaml-multicore/eio/blob/c44ee5ce96c120b7ccc23a12d241dc8672e2888f/lib_eio_linux/sched.ml#L501" type="external">via an eventfd</fr:link> and in <fr:link href="https://github.com/ocaml-multicore/eio/blob/c44ee5ce96c120b7ccc23a12d241dc8672e2888f/lib_eio_posix/sched.ml#L20" type="external">POSIX, a pipe</fr:link>.</html:p>
                    <html:p>This <html:code>dup2</html:code> will close the <html:code>eventfd</html:code> and will likely grind Eio to a halt (or an <html:code>assert false</html:code>). For now, I have resorted to vendoring <fr:link href="/eio/" title="Eio" uri="https://patrick.sirref.org/eio/" display-uri="eio" type="local">Eio</fr:link> and moving the <html:code>eventfd</html:code> file descriptors to higher values, though I <fr:link href="https://github.com/ocaml-multicore/eio/pull/836" type="external">have opened a PR to make this more configurable</fr:link>. This bug is quite easy to write up... it was not so easy to find!</html:p>
                    <html:p>As a random example, consider the <html:code>debconf/confmodule</html:code> <fr:link href="https://sources.debian.org/src/debconf/1.5.77/confmodule/" type="external">script</fr:link> which offers very little room for a buggy implementation!</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>30</fr:day>
                </fr:date>
                <fr:title text="Outreachy">Outreachy</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>The presentations from the demonstrations for this round of Outreachy are now online!</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/outreachy-ocaml-tiff/</fr:uri>
                    <fr:display-uri>outreachy-ocaml-tiff</fr:display-uri>
                    <fr:route>/outreachy-ocaml-tiff/</fr:route>
                    <fr:title text="Write support in OCaml TIFF library">Write support in OCaml TIFF library</fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>I am mentoring <fr:link href="/tambe-salome/" title="Tambe Salome" uri="https://patrick.sirref.org/tambe-salome/" display-uri="tambe-salome" type="local">Tambe Salome</fr:link> during the December 2025 Outreachy round to add support for writing TIFF files in the <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> library.</html:p>
                    <html:p>You can now see the video of the demonstration day presentation:</html:p>
                    <html:div style="text-align: center">
<html:iframe title="Outreachy Demo Day December 2025 Round" width="560" height="315" src="https://watch.ocaml.org/videos/embed/8aUqMhFvhQGq4WJLH3ukjA?start=1h18m33s" frameborder="0" allowfullscreen="" sandbox="allow-same-origin allow-scripts allow-popups allow-forms" />
</html:div>
                  </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: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/ppxlib-releases/</fr:uri>
            <fr:display-uri>ppxlib-releases</fr:display-uri>
            <fr:route>/ppxlib-releases/</fr:route>
            <fr:title text="Ppxlib Releases">Ppxlib Releases</fr:title>
          </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>2026</fr:year>
                  <fr:month>3</fr:month>
                  <fr:day>30</fr:day>
                </fr:date>
                <fr:uri>https://patrick.sirref.org/ppxlib-release-0-38-0/</fr:uri>
                <fr:display-uri>ppxlib-release-0-38-0</fr:display-uri>
                <fr:route>/ppxlib-release-0-38-0/</fr:route>
                <fr:title text="0.38.0 ">0.38.0 </fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p><fr:link href="/nathanreb/" title="Nathan Rebours" uri="https://patrick.sirref.org/nathanreb/" display-uri="nathanreb" type="local">Nathan</fr:link> and I <fr:link href="https://github.com/ocaml/opam-repository/pull/29563" type="external">released ppxlib.0.38.0</fr:link> last week. Its main feature is full <html:em>migration</html:em> support for the upcoming OCaml 5.5 compiler (currently in its <html:code>alpha3</html:code> release). This means supporting the handful of new features landing in OCaml 5.5: <fr:link href="/modular-explicits/" title="Modular Explicits in OCaml" uri="https://patrick.sirref.org/modular-explicits/" display-uri="modular-explicits" type="local">modular explicits</fr:link>, external type declarations and arbitrary "local" structure items.</html:p>
                <html:p>As <fr:link href="https://patrick.sirref.org/nathenreb/" type="external">Nathan</fr:link> and I continue to find a plausible maintenance story for <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib</fr:link>, <fr:link href="https://patrick.sirref.org/nathenreb/" type="external">Nathan</fr:link> has opened <fr:link href="https://github.com/ocaml/ocaml/issues/14668" type="external">an issue on the OCaml compiler to discuss the idea of adding additional extension points to the language</fr:link>.</html:p>
                <html:p>This comes from the desire to be able to store encoded versions of new OCaml features inside older abstract syntax trees.</html:p>
                <html:p>There are also some nice bug fixes in there too:</html:p>
                <html:ul>
                  <html:li>
                    <html:p><fr:link href="https://github.com/ocaml-ppx/ppxlib/pull/613" type="external">A potential OOM</fr:link> loop has now been removed.</html:p>
                  </html:li>
                  <html:li>
                    <html:p>
                      <fr:link href="https://github.com/ocaml-ppx/ppxlib/pull/619" type="external">Locations have been restored to long identifiers!</fr:link>
                    </html:p>
                  </html:li>
                </html:ul>
              </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 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: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>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>A common way to overcome this is to use higher-order functions (functions that 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>This works well in plenty of cases (<html:code>List.map</html:code>, <html:code>Hashtbl.iter</html:code>, etc.), however, it doesn't scale well from a user's perspective if the body of the function requires lots of specific functions (e.g. <html:code>compare</html:code>, <html:code>length</html:code>, <html:code>pp</html:code>). 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>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="true" expanded="false" toc="false" numbered="false">
          <fr:frontmatter>
            <fr:authors />
            <fr:uri>https://patrick.sirref.org/nathanreb/</fr:uri>
            <fr:display-uri>nathanreb</fr:display-uri>
            <fr:route>/nathanreb/</fr:route>
            <fr:title text="Nathan Rebours">Nathan Rebours</fr:title>
            <fr:taxon>person</fr:taxon>
            <fr:meta name="external">https://github.com/nathanreb</fr:meta>
          </fr:frontmatter>
          <fr:mainmatter>
            <html:p>Maintainer of <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">Ppxlib</fr:link>.</html:p>
          </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/ppxlib/</fr:uri>
            <fr:display-uri>ppxlib</fr:display-uri>
            <fr:route>/ppxlib/</fr:route>
            <fr:title text="Ppxlib">Ppxlib</fr:title>
            <fr:meta name="external">https://github.com/ocaml-ppx/ppxlib</fr:meta>
          </fr:frontmatter>
          <fr:mainmatter>
            <html:p>An OCaml library and ecosystem for preprocessing.</html:p>
          </fr:mainmatter>
        </fr:tree>
      </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>
