<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>KC Sivaramakrishnan - Scalable Functional Programming</title>
 <link href="https://kcsrk.info/atom.xml" rel="self"/>
 <link href="https://kcsrk.info/"/>
 <updated>2026-05-11T12:34:33+00:00</updated>
 <id>https://kcsrk.info</id>
 <author>
   <name>KC Sivaramakrishnan</name>
   <email>sk826@cl.cam.ac.uk</email>
 </author>

 
 <entry>
   <title>Shrinking the OxCaml js_of_ocaml bundle: 285 MB to 4 MB</title>
   <link href="https://kcsrk.info/ocaml/oxcaml/modes/2026/05/10/shrinking-the-oxcaml-bundle/"/>
   <updated>2026-05-10T11:00:00+00:00</updated>
   <id>https://kcsrk.info/ocaml/oxcaml/modes/2026/05/10/shrinking-the-oxcaml-bundle</id>
   <content type="html">&lt;script async=&quot;&quot; src=&quot;/assets/x-ocaml-ox/x-ocaml.js&quot; src-worker=&quot;/assets/x-ocaml-ox/x-ocaml.worker+effects.js&quot; src-load=&quot;/assets/x-ocaml-ox/portable.js&quot;&gt;&lt;/script&gt;

&lt;style&gt;
  x-ocaml { font-size: 0.8em; display: block; margin-bottom: 1.4rem; }
  x-ocaml.hidden { display: none; }
&lt;/style&gt;

&lt;p&gt;In the
&lt;a href=&quot;/ocaml/oxcaml/modes/blogging/2026/05/08/capsules-in-oxcaml/&quot;&gt;previous post&lt;/a&gt; on
capsules, I cheated. The lecture I was adapting (from my
&lt;a href=&quot;https://github.com/fplaunchpad/cs6868_s26&quot;&gt;CS6868&lt;/a&gt; course on
language abstractions for parallelism) used
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Await_capsule.Mutex.with_lock&lt;/code&gt;, the recommended non-deprecated way
to acquire a capsule mutex, but the post shipped
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Capsule_blocking_sync.Mutex&lt;/code&gt; instead with the deprecation alert
silenced. The reason was bundle size: the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;await&lt;/code&gt; library, once we
chased its transitive dependencies through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sexplib0&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base_quickcheck&lt;/code&gt; and the rest of Jane Street’s runtime, would have
ballooned the in-browser toplevel by roughly &lt;em&gt;285 MB&lt;/em&gt;. The right
API would not even fit through GitHub’s 100 MB per-file push limit,
let alone be reasonable to send to a reader’s browser.&lt;/p&gt;

&lt;p&gt;This post is the story of how we got from 285 MB down to 4 MB and
made the resulting bundle compose cleanly with the in-browser
toplevel, so the lecture’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Await_capsule&lt;/code&gt; form works end-to-end in
the cell at the bottom of this post. Most of the work happened on a
&lt;a href=&quot;https://github.com/kayceesrk/js_of_ocaml/tree/kc-toplevel-extend&quot;&gt;branch of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ocsigen/js_of_ocaml&lt;/code&gt;&lt;/a&gt;,
with a smaller piece in
&lt;a href=&quot;https://github.com/kayceesrk/x-ocaml/tree/oxcaml&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;art-w/x-ocaml&lt;/code&gt;&lt;/a&gt;,
the WebComponent that powers the cells.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;why-bundle-size-matters&quot;&gt;Why bundle size matters&lt;/h2&gt;

&lt;p&gt;I teach two OCaml-heavy courses at IIT Madras:
&lt;a href=&quot;https://github.com/fplaunchpad/cs3100_m20&quot;&gt;CS3100&lt;/a&gt;, the
undergraduate functional programming course, and
&lt;a href=&quot;https://github.com/fplaunchpad/cs6868_s26&quot;&gt;CS6868&lt;/a&gt;, the more
recent graduate course on language abstractions for parallelism.
The lecture notes, examples and homework for both would be much
more useful as &lt;em&gt;interactive books&lt;/em&gt; that a student can read, edit
and run entirely client-side, with no local installation. The same
shape would help us when we run hands-on OCaml and OxCaml
workshops, where the first session routinely gets eaten by the
&lt;em&gt;installation hump&lt;/em&gt;: getting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opam&lt;/code&gt;, the compiler and the required
libraries working on every attendee’s machine over patchy
conference WiFi, before the teaching can begin.&lt;/p&gt;

&lt;p&gt;The broader effort to make installation painless is the OCaml
Platform &lt;a href=&quot;https://ocaml.org/tools/platform-roadmap&quot;&gt;roadmap&lt;/a&gt;, which
we have been working on at Tarides as a “zero to OCaml in one
click” experience. That roadmap targets a developer who wants a
real local toolchain, with the full editor, debugger and
project-management story, and a generous latency budget since this
is a one-time setup. A workshop attendee has a much narrower
target: just &lt;em&gt;enough&lt;/em&gt; OCaml to complete the exercises in front of
them. The client-side &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x-ocaml&lt;/code&gt; toplevel fits that target
naturally, because everything ships as static assets and there is
no installation step. The bundle, in this setting, &lt;em&gt;is&lt;/em&gt; the latency
budget: 285 MB makes the in-browser path unshippable, 4 MB makes
it a realistic alternative to a local toolchain for a 90-minute
session.&lt;/p&gt;

&lt;h2 id=&quot;why-285-mb&quot;&gt;Why 285 MB?&lt;/h2&gt;

&lt;p&gt;The recipe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x-ocaml&lt;/code&gt; already had for “load extra libraries into a
running in-browser toplevel” goes like this. For each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cma&lt;/code&gt; you want
to ship, run&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ js_of_ocaml --toplevel &amp;lt;library&amp;gt;.cma -o lib.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;then concatenate the per-cma outputs into a single bundle and load
it via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;script src-load=...&amp;gt;&lt;/code&gt;. Each per-cma output is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kind=cma&lt;/code&gt;:
it registers the cma’s modules into the existing toplevel without
clobbering anything, the modules light up, and you can &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;open&lt;/code&gt; them
from a cell. This works, and it is what the previous two OxCaml
posts already use.&lt;/p&gt;

&lt;p&gt;The trouble is that &lt;em&gt;dead code elimination runs one cma at a time&lt;/em&gt;.
If you ship &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base&lt;/code&gt;, you ship &lt;em&gt;all&lt;/em&gt; of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base&lt;/code&gt;, because the per-cma
DCE pass never gets to look at the linked-together program and
notice that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;await&lt;/code&gt; library you actually want only touches a
small slice of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sexplib0&lt;/code&gt;. So the bundle for the closure
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;await + capsule + basement&lt;/code&gt; ends up being the union of every cma
in the transitive dependency, fully linked, which comes out to
roughly 285 MB after the OxCaml compiler’s normal optimisations and
before any of the JavaScript-side cleverness has had a chance to
run.&lt;/p&gt;

&lt;p&gt;In other words, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;await&lt;/code&gt;-based blessed API is unshippable not
because the bundling tooling is broken, but because per-cma DCE is
the wrong granularity for this problem.&lt;/p&gt;

&lt;h2 id=&quot;the-other-recipe-and-why-it-doesnt-compose&quot;&gt;The other recipe, and why it doesn’t compose&lt;/h2&gt;

&lt;p&gt;It turns out &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;js_of_ocaml&lt;/code&gt; already has a second recipe that
&lt;a href=&quot;https://ocsigen.org/js_of_ocaml/latest/manual/build-toplevel&quot;&gt;does perform cross-cma DCE&lt;/a&gt;,
which I learned about when &lt;a href=&quot;https://x.com/rickyvetter/status/2053215352301998424&quot;&gt;Ricky
Vetter&lt;/a&gt;
pointed me at the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--export&lt;/code&gt; route on X. The recipe has two steps:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Build a single bytecode that links every library you want, with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-linkall&lt;/code&gt; so nothing gets pruned at the bytecode level.&lt;/li&gt;
  &lt;li&gt;Hand that single bytecode to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;js_of_ocaml --toplevel --export
units.txt&lt;/code&gt;. The export list names the compilation units that
should remain visible to the toplevel; everything else is fair
game for DCE on the unified intermediate representation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;await + capsule + basement&lt;/code&gt; set, this recipe produces
a &lt;em&gt;4 MB&lt;/em&gt; bundle, almost two orders of magnitude smaller than the
per-cma concatenation. The link-step DCE works at function
granularity over the whole linked program, so the unused parts of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sexplib&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base_quickcheck&lt;/code&gt; and the rest of the dependency
closure get pruned away cleanly.&lt;/p&gt;

&lt;p&gt;So why aren’t we already using this recipe?&lt;/p&gt;

&lt;p&gt;Because the artifact that comes out the other end is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kind=exe&lt;/code&gt;,
that is, a self-contained executable rather than a library. When
you load such a bundle into a Web Worker that already has a running
toplevel, its initialisation runs in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caml_main&lt;/code&gt; style and starts
by overwriting the host’s globals:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;caml_global_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;symbols&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;s symbol table&amp;gt;
caml_global_data.sections   = &amp;lt;bundle&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bytecode&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sections&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;caml_global_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prim_count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;s primitive count&amp;gt;
caml_global_data.aliases    = &amp;lt;bundle&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Those four assignments &lt;em&gt;overwrite&lt;/em&gt; the host toplevel’s tables. After
the bundle loads, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caml_get_global_data().symbols&lt;/code&gt; is the bundle’s
symbols, not the worker’s, and anything in the host toplevel that
does name-based symbol resolution (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Toploop&lt;/code&gt;, hover-types lookup,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;open Stdlib&lt;/code&gt;) now consults a table that does not know about the
modules the worker had already linked. The toplevel survives, but
its typing environment is wrong, and cells stop being able to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;open&lt;/code&gt; anything. We hit this dead end in the &lt;a href=&quot;/ocaml/oxcaml/modes/blogging/2026/05/08/capsules-in-oxcaml/&quot;&gt;capsules
post&lt;/a&gt;; the bundle was
correct and the sizes were great, but the integration step that
connects an exe-shaped bundle to an existing toplevel was the
missing piece.&lt;/p&gt;

&lt;h2 id=&quot;the-patch&quot;&gt;The patch&lt;/h2&gt;

&lt;p&gt;The fix is a flag, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--toplevel-extend&lt;/code&gt;, that I added on a &lt;a href=&quot;https://github.com/kayceesrk/js_of_ocaml/tree/kc-toplevel-extend&quot;&gt;branch of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ocsigen/js_of_ocaml&lt;/code&gt;&lt;/a&gt;.
When it is set, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;js_of_ocaml --toplevel --export …&lt;/code&gt; emits exactly
the same DCE output as before, with the same bytes for the
registered modules and the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.cmi&lt;/code&gt; files embedded under
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/static/cmis/&lt;/code&gt;, but with three small changes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;packed as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~standalone:false&lt;/code&gt;, so there is no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;globalThis&lt;/code&gt;
polyfill IIFE wrapping the output,&lt;/li&gt;
  &lt;li&gt;with the four &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caml_js_set&lt;/code&gt; writes to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caml_global_data&lt;/code&gt; from
above skipped, and&lt;/li&gt;
  &lt;li&gt;tagged as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kind=cma&lt;/code&gt; in the buildInfo header.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The bundle’s modules still register themselves on load via the
ordinary
&lt;a href=&quot;https://github.com/kayceesrk/js_of_ocaml/blob/kc-toplevel-extend/runtime/js/stdlib.js#L265&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caml_register_global(n, v, name)&lt;/code&gt;&lt;/a&gt;,
which the runtime correctly merges via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;symidx&lt;/code&gt; into the host’s
existing tables. The result is &lt;em&gt;additive, not destructive&lt;/em&gt;: the host
toplevel’s symbol table, sections, primitives and aliases all
survive intact, and its typing environment continues to resolve
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Stdlib&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Toploop&lt;/code&gt; and everything else that was already linked.
The new modules from the bundle simply show up as new symbols on
top.&lt;/p&gt;

&lt;p&gt;The initial diff is small:
&lt;a href=&quot;https://github.com/kayceesrk/js_of_ocaml/commit/6ec194f&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parse_bytecode.ml&lt;/code&gt;&lt;/a&gt;
gates the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caml_js_set&lt;/code&gt; block on the new flag, and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmd_arg.ml&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compile.ml&lt;/code&gt; thread it through. That gets the bundle
composable. The actual debugging is what came afterwards, when we
tried to make the composed bundle behave the way the host
expected, and that is what the rest of this post is about.&lt;/p&gt;

&lt;h2 id=&quot;wiring-it-through-x-ocaml&quot;&gt;Wiring it through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x-ocaml&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;On the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x-ocaml&lt;/code&gt; side, the
&lt;a href=&quot;https://github.com/kayceesrk/x-ocaml/blob/oxcaml/bin/x_ocaml.ml#L139&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--dce&lt;/code&gt; flag&lt;/a&gt;
drives the single-bytecode + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--export&lt;/code&gt; build, invoking
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;js_of_ocaml --toplevel-extend --export units.txt&lt;/code&gt; for the bundles
we ship. The
&lt;a href=&quot;https://github.com/kayceesrk/x-ocaml/tree/oxcaml&quot;&gt;oxcaml branch of my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x-ocaml&lt;/code&gt; fork&lt;/a&gt;
carries the change; the patched &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;js_of_ocaml&lt;/code&gt; needs to be on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PATH&lt;/code&gt;
when the build runs.&lt;/p&gt;

&lt;h2 id=&quot;numbers&quot;&gt;Numbers&lt;/h2&gt;

&lt;p&gt;For the full closure of libraries the lecture’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gensym&lt;/code&gt; example
uses, the two paths come out very differently:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt; &lt;/th&gt;
      &lt;th&gt;Per-cma&lt;/th&gt;
      &lt;th&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--dce --toplevel-extend&lt;/code&gt;&lt;/th&gt;
      &lt;th&gt;Ratio&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;basement + capsule0 only&lt;/td&gt;
      &lt;td&gt;1.0 MB&lt;/td&gt;
      &lt;td&gt;1.0 MB&lt;/td&gt;
      &lt;td&gt;1×&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;+ capsule + await + portable&lt;/td&gt;
      &lt;td&gt;285 MB&lt;/td&gt;
      &lt;td&gt;4.0 MB&lt;/td&gt;
      &lt;td&gt;&lt;em&gt;~70×&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;basement + capsule0&lt;/code&gt; row is essentially a wash, because the
bundle size at that scale is dominated by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.cmi&lt;/code&gt; files and there
is very little JavaScript code for DCE to chew on. Once &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;await&lt;/code&gt; and
the curated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;capsule&lt;/code&gt; API enter the picture the per-cma path
balloons, because it has to ship every cma in the transitive
closure of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sexplib0&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bin_prot&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base_quickcheck&lt;/code&gt; and the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ppx_*&lt;/code&gt; runtime libraries, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--dce&lt;/code&gt; keeps only the functions
that are actually reachable from the export list, plus the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.cmi&lt;/code&gt;
files the toplevel needs to elaborate the signatures the user types
into a cell.&lt;/p&gt;

&lt;h2 id=&quot;a-few-more-snags&quot;&gt;A few more snags&lt;/h2&gt;

&lt;p&gt;Getting the bundle to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kind=cma&lt;/code&gt; was the easy part. Composing it
with an already-running toplevel turned out to surface a small
zoo of follow-on issues, each of which had a short fix once we
understood it. They all live on the same
&lt;a href=&quot;https://github.com/kayceesrk/js_of_ocaml/tree/kc-toplevel-extend&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kc-toplevel-extend&lt;/code&gt;&lt;/a&gt;
branch; the commit messages have the gory details.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;Predefined-exception identity drifts across bundles.&lt;/em&gt; The
bundle’s re-allocated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Not_found&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Sys_error&lt;/code&gt; and friends are
physically distinct from the host’s copies, so a
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;try ... with Not_found -&amp;gt;&lt;/code&gt; in stdlib code (the first place we
hit this was &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Hashtbl.randomized_default&lt;/code&gt; reading
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OCAMLRUNPARAM&lt;/code&gt;) fails to catch the host’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Not_found&lt;/code&gt; raised by
the runtime. The fix is to bind each predef-exn variable in the
bundle to a runtime &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caml_get_global_data&lt;/code&gt; lookup so the bundle
reuses the host’s instances.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;The pseudo-filesystem raises on duplicate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.cmi&lt;/code&gt; registrations.&lt;/em&gt;
The bundle wants to re-emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/static/cmis/stdlib.cmi&lt;/code&gt;, which the
host has already registered at boot, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MlFakeDevice.register&lt;/code&gt;
refuses to overwrite. Making &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;register&lt;/code&gt; idempotent removes the
conflict without losing anything: the two copies of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stdlib.cmi&lt;/code&gt;
agree, since they come from the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opam&lt;/code&gt; switch.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;Stdlib re-registration overwrites host modules.&lt;/em&gt; Without a
guard, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caml_register_global&lt;/code&gt; was cheerfully replacing the host’s
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caml_global_data[&quot;Format&quot;]&lt;/code&gt; (and every other stdlib module the
bundle’s bytecode happens to link in) with the bundle’s freshly
initialised copy. Adding an early return when the name is already
known fixes this without changing the behaviour for any name the
host does not yet have.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Domain.DLS&lt;/code&gt; slot collisions silently broke hover types.&lt;/em&gt; The
bundle re-runs stdlib’s module init when it loads, and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Stdlib__Domain.DLS&lt;/code&gt;’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let key_counter = Atomic.make 0&lt;/code&gt;
re-allocates the counter and starts it from zero. The bundle’s
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Format.stdbuf_key&lt;/code&gt; then ends up at a low DLS index the host had
already assigned to &lt;em&gt;its&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Format.stdbuf_key&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DLS.set&lt;/code&gt;
overwrites the host’s entry in the shared &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caml_domain_dls&lt;/code&gt;
array. The host’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Format.flush_str_formatter&lt;/code&gt; then reads from
the bundle’s empty buffer, merlin’s type-enclosing printer
(which flushes through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Format.str_formatter&lt;/code&gt;) returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;&quot;&lt;/code&gt; for
every query, and hover-on-identifier tooltips come up blank. The
fix is at the bundle-load boundary in
&lt;a href=&quot;https://github.com/kayceesrk/x-ocaml/blob/oxcaml/build_portable_js_extend.sh&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build_portable_js_extend.sh&lt;/code&gt;&lt;/a&gt;:
snapshot &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caml_domain_dls_get ()&lt;/code&gt; before the bundle’s IIFE runs,
and restore the host-owned slots afterwards. The bundle’s &lt;em&gt;new&lt;/em&gt;
high-index slots are left alone; only the host’s previously
populated slots get restored. I spent a while convinced this was
a Format DCE bug before tracing through the OCaml 5+
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Domain.DLS&lt;/code&gt; init path.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;Bundle build:&lt;/em&gt; the curated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;capsule&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;await.capsule&lt;/code&gt; APIs
both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;open! Base&lt;/code&gt; at the top of their files, so their interfaces
mention &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Base.unit&lt;/code&gt; rather than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Stdlib.unit&lt;/code&gt;. To elaborate those
signatures the host toplevel needs a small chain of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sexplib0&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.cmi&lt;/code&gt; files at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/static/cmis/&lt;/code&gt;. We ship three &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base&lt;/code&gt;
cmis (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base.cmi&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base__.cmi&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base__Unit.cmi&lt;/code&gt;) and two
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sexplib0&lt;/code&gt; cmis via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;js_of_ocaml&lt;/code&gt;’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--file=&amp;lt;src&amp;gt;:/static/cmis/&lt;/code&gt;
flag, which embeds the file directly without putting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base&lt;/code&gt; on
the bytecode-link line (which would drag the whole of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base&lt;/code&gt;
back in).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-cell&quot;&gt;The cell&lt;/h2&gt;

&lt;p&gt;The cell below uses the lecture’s
&lt;a href=&quot;https://github.com/fplaunchpad/cs6868_s26/blob/main/lectures/11_oxcaml/code/08_capsules/gensym_capsule.ml&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gensym_capsule.ml&lt;/code&gt;&lt;/a&gt;
shape directly: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Await_capsule.Mutex.with_lock&lt;/code&gt; taking an
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Await_kernel.Await.t&lt;/code&gt; witness, with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Capsule_expert.Data.create&lt;/code&gt;
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Capsule_expert.Data.unwrap&lt;/code&gt; for the brand-locked counter. No
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[@@@alert &quot;-deprecated&quot;]&lt;/code&gt;, no shim. Press Run.&lt;/p&gt;

&lt;x-ocaml&gt;
let make_gensym () =
  let (P mutex) = Await_capsule.Mutex.create () in
  let counter = Capsule_expert.Data.create (fun () -&amp;gt; ref 0) in
  let fetch_and_incr (w : Await_kernel.Await.t) =
    Await_capsule.Mutex.with_lock w mutex
      ~f:(fun access -&amp;gt;
        let c = Capsule_expert.Data.unwrap ~access counter in
        incr c;
        !c)
  in
  fun w prefix -&amp;gt; prefix ^ &quot;_&quot; ^ string_of_int (fetch_and_incr w)

let gensym = make_gensym ()
let w = Await_blocking.await Await_kernel.Terminator.never
let () = Printf.printf &quot;%s %s\n&quot; (gensym w &quot;x&quot;) (gensym w &quot;y&quot;)
&lt;/x-ocaml&gt;

&lt;p&gt;We cannot actually demonstrate parallelism in the browser worker
(it is single-domain), so we hand the body the trivial blocker
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Await_blocking.await Terminator.never&lt;/code&gt;. The mode-checking is the
&lt;a href=&quot;/ocaml/oxcaml/modes/blogging/2026/05/08/capsules-in-oxcaml/#with_lock-produces-an-access-token-briefly&quot;&gt;same brand/local/once dance&lt;/a&gt;
as in the capsules post; what is new is that the same dance now
type-checks against the blessed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Await_capsule&lt;/code&gt; API directly,
without the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Capsule_blocking_sync&lt;/code&gt; shim.&lt;/p&gt;

&lt;h2 id=&quot;what-next&quot;&gt;What next?&lt;/h2&gt;

&lt;p&gt;The fork is small enough that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--toplevel-extend&lt;/code&gt; is plausibly
upstreamable into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ocsigen/js_of_ocaml&lt;/code&gt;. The DLS-snapshot dance
would also be cleaner as a proper runtime primitive than as a
wrapper around the bundle’s IIFE. The
&lt;a href=&quot;https://github.com/kayceesrk/js_of_ocaml/tree/kc-toplevel-extend&quot;&gt;branch&lt;/a&gt;
is open for review.&lt;/p&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x-ocaml&lt;/code&gt; itself, the obvious next step is to broaden the set
of extension bundles. The current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;portable.js&lt;/code&gt; covers
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;basement + capsule0 + capsule + await + portable&lt;/code&gt;, which is just
enough for the capsule and parallelism material in
&lt;a href=&quot;https://github.com/fplaunchpad/cs6868_s26&quot;&gt;CS6868&lt;/a&gt;; the
&lt;a href=&quot;https://github.com/fplaunchpad/cs3100_m20&quot;&gt;CS3100&lt;/a&gt; material would
want a different slice, and an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eio&lt;/code&gt;-flavoured bundle
would let the same cells host concurrency examples. Once a small
library of these bundles exists, turning a lecture set or a
workshop tutorial into an interactive book becomes mostly a matter
of picking the right bundle, which is the workshop-scale “zero to
OxCaml” story I want to get to.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x-ocaml&lt;/code&gt; is one of &lt;a href=&quot;https://github.com/art-w&quot;&gt;Arthur Wendling’s&lt;/a&gt;
hacking expeditions, and it remains a pleasure to build on. Thanks
to &lt;a href=&quot;https://x.com/rickyvetter&quot;&gt;Ricky Vetter&lt;/a&gt; for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--export&lt;/code&gt;
pointer that got the whole thing started, and to the OxCaml team
for the libraries.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;em&gt;Written together with &lt;a href=&quot;https://www.anthropic.com/news/claude-opus-4-7&quot;&gt;Claude Opus 4.7 (1M
context)&lt;/a&gt;. The
&lt;a href=&quot;https://github.com/ocsigen/js_of_ocaml/compare/c3da0bb58eafe2d9ad3387cbbe9b8faf9ec91fb1...kayceesrk:js_of_ocaml:kc-toplevel-extend&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;js_of_ocaml&lt;/code&gt;
diff&lt;/a&gt;
against the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+ox&lt;/code&gt; base and the
&lt;a href=&quot;https://github.com/kayceesrk/x-ocaml/compare/d9160c5...oxcaml&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x-ocaml&lt;/code&gt; integration
diff&lt;/a&gt;
are both on GitHub.&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Capsules: compile-time lock discipline in OxCaml</title>
   <link href="https://kcsrk.info/ocaml/oxcaml/modes/blogging/2026/05/08/capsules-in-oxcaml/"/>
   <updated>2026-05-08T10:00:00+00:00</updated>
   <id>https://kcsrk.info/ocaml/oxcaml/modes/blogging/2026/05/08/capsules-in-oxcaml</id>
   <content type="html">&lt;script async=&quot;&quot; src=&quot;/assets/x-ocaml-ox/x-ocaml.js&quot; src-worker=&quot;/assets/x-ocaml-ox/x-ocaml.worker+effects.js&quot; src-load=&quot;/assets/x-ocaml-ox/portable.js&quot;&gt;&lt;/script&gt;

&lt;style&gt;
  x-ocaml { font-size: 0.8em; display: block; margin-bottom: 1.4rem; }
  x-ocaml.hidden { display: none; }
&lt;/style&gt;

&lt;p&gt;In the
&lt;a href=&quot;/ocaml/oxcaml/x-ocaml/blogging/2026/05/07/data-race-freedom-in-oxcaml/&quot;&gt;previous post&lt;/a&gt; we
fixed the racy &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gensym&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Portable.Atomic&lt;/code&gt;. That worked because
the shared state was a single integer with atomic primitives. What
about state that needs a hash table, a multi-step update, or any
structure where atomics aren’t enough? OxCaml’s answer is the
&lt;strong&gt;capsule&lt;/strong&gt;: a way to bundle state with its lock so the lock
discipline becomes a type-checker job rather than a programmer
convention.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;The example here is the capsule version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gensym&lt;/code&gt; from my
&lt;a href=&quot;https://github.com/fplaunchpad/cs6868_s26&quot;&gt;CS6868&lt;/a&gt; lecture
(&lt;a href=&quot;https://github.com/fplaunchpad/cs6868_s26/blob/main/lectures/11_oxcaml/handout.md#part-5-capsules--safe-shared-mutable-state&quot;&gt;handout&lt;/a&gt;).
Capsules don’t introduce a new mode axis; they’re a small library that
composes the axes we’ve already met:
&lt;a href=&quot;/ocaml/oxcaml/x-ocaml/blogging/2026/05/07/data-race-freedom-in-oxcaml/&quot;&gt;contention and portability&lt;/a&gt;,
&lt;a href=&quot;/ocaml/modes/oxcaml/2025/05/29/uniqueness_and_behavioural_types/&quot;&gt;uniqueness&lt;/a&gt;,
and &lt;a href=&quot;/ocaml/modes/oxcaml/2025/06/04/linearity_and_uniqueness/&quot;&gt;linearity&lt;/a&gt;.
The cells below run in the same in-browser OxCaml toplevel as the
previous post; the &lt;a href=&quot;#a-note-on-the-api&quot;&gt;&lt;em&gt;A note on the API&lt;/em&gt;&lt;/a&gt; section
at the end explains why we use a slightly older flavour of the capsule
API (it’s a bundle-size thing, not pedagogical).&lt;/p&gt;

&lt;h2 id=&quot;why-atomics-arent-enough&quot;&gt;Why atomics aren’t enough&lt;/h2&gt;

&lt;p&gt;For a single integer counter, atomics are perfect. Drop the size
constraint and they’re not. Suppose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gensym&lt;/code&gt; had to consult a hash
table of already-issued names, or update two counters in lockstep, or
do a multi-step modify-then-record. None of that fits an atomic word.
The standard OCaml answer is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mutex.t&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Mutex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Hashtbl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;safe_insert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Mutex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lock&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Hashtbl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Mutex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unlock&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;(* Nothing stops you from forgetting to lock: *)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unsafe_insert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Hashtbl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;   &lt;span class=&quot;c&quot;&gt;(* races, but compiles. *)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Two things are wrong here. First, the mutex and the data are separate
values; nothing at the type level connects &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mutex&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;table&lt;/code&gt;. Second,
“always lock before access” is a programmer convention. The compiler
can’t tell what mutex you meant for what state, and an unlocked
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Hashtbl.add&lt;/code&gt; is a runtime data race that nothing catches.&lt;/p&gt;

&lt;p&gt;Yes, OxCaml’s contention rule from the previous post would reject
direct mutation of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ contended&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;table&lt;/code&gt; in a parallel context. But
that only helps if the type system can see that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;table&lt;/code&gt; is contended
in the first place. Once you have a top-level shared mutable, you need
a structural reason for the type checker to &lt;em&gt;believe&lt;/em&gt; that “you are
holding the lock right now.” That’s exactly what a capsule provides.&lt;/p&gt;

&lt;h2 id=&quot;gensym-in-a-capsule&quot;&gt;Gensym in a capsule&lt;/h2&gt;

&lt;p&gt;The capsule pattern packs the counter inside a brand-locked container,
making the lock the only handle to the state:&lt;/p&gt;

&lt;x-ocaml&gt;
[@@@alert &quot;-deprecated&quot;]

module Cap = Capsule_expert
module Mtx = Capsule_blocking_sync.Mutex

let make_counter () =
  let Cap.Key.P key = Cap.create () in
  let counter = Cap.Data.create (fun () -&amp;gt; ref 0) in
  let mutex   = Mtx.create key in
  fun () -&amp;gt;
    Mtx.with_lock mutex ~f:(fun password -&amp;gt;
      Cap.access ~password ~f:(fun access -&amp;gt;
        let c = Cap.Data.unwrap ~access counter in
        incr c;
        !c))

let next   = make_counter ()
let gensym prefix = prefix ^ &quot;_&quot; ^ string_of_int (next ())

let () = Printf.printf &quot;%s %s\n&quot; (gensym &quot;x&quot;) (gensym &quot;y&quot;)
&lt;/x-ocaml&gt;

&lt;p&gt;Run it; you get two distinct ids, and the toplevel binds
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;val next : unit -&amp;gt; int&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;val gensym : string -&amp;gt; string&lt;/code&gt;. No
handle to the inner &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ref&lt;/code&gt; is in scope outside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mtx.with_lock&lt;/code&gt;. Let’s
read what’s making that true.&lt;/p&gt;

&lt;h3 id=&quot;the-brand-k-an-existential-tied-to-a-fresh-capsule&quot;&gt;The brand &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;k&lt;/code&gt;: an existential tied to a fresh capsule&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cap.create ()&lt;/code&gt; returns a key wrapped in an existential constructor
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cap.Key.P&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;packed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;P&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;packed&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unboxed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;packed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let Cap.Key.P key = Cap.create ()&lt;/code&gt; pattern unwraps it and
introduces a fresh type variable, call it &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$k&lt;/code&gt;, in the surrounding
scope. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;key&lt;/code&gt; is then bound at type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$k Cap.Key.t&lt;/code&gt;. A second
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cap.create ()&lt;/code&gt; would introduce &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$k2&lt;/code&gt;, distinct and unrelated. Each
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;P&lt;/code&gt; pattern brings a new type into the world.&lt;/p&gt;

&lt;p&gt;That brand is the static glue between capsule, data, and mutex. When
we call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cap.Data.create (fun () -&amp;gt; ref 0)&lt;/code&gt; next, the compiler unifies
the data’s type parameter with the brand of the key it’ll eventually
be unwrapped under, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;counter : (int ref, $k) Cap.Data.t&lt;/code&gt;. The
mutex created from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;key&lt;/code&gt; (consuming it as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ unique&lt;/code&gt;) is also branded
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$k&lt;/code&gt;. Henceforth this data only opens under this mutex’s lock.&lt;/p&gt;

&lt;p&gt;(Why is the existential pattern wrapped inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make_counter ()&lt;/code&gt;
rather than at the top level? OCaml refuses top-level let-bindings
that introduce existentials, so we hide the unwrap inside a function.
The closure returned by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make_counter&lt;/code&gt; carries the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$k&lt;/code&gt;-branded
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mutex&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;counter&lt;/code&gt; in its environment.)&lt;/p&gt;

&lt;h3 id=&quot;the-bare-ref-is-unreachable-from-outside-the-capsule&quot;&gt;The bare &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ref&lt;/code&gt; is unreachable from outside the capsule&lt;/h3&gt;

&lt;p&gt;Look at where the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ref 0&lt;/code&gt; lives:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;counter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Cap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ref&lt;/code&gt; has no binding outside the closure handed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cap.Data.create&lt;/code&gt;.
The only handle out is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cap.Data.t&lt;/code&gt; value branded &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$k&lt;/code&gt;. There is no
aliased reference to smuggle out: the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ref&lt;/code&gt;’s reachability is
single-pathed. This is exactly the configuration the
&lt;a href=&quot;/ocaml/modes/oxcaml/2025/05/29/uniqueness_and_behavioural_types/&quot;&gt;uniqueness post&lt;/a&gt;
was about, a unique reference with no aliases to it, but here we get
it for free from how the API is shaped, without writing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ unique&lt;/code&gt;
anywhere ourselves. The capsule API is &lt;em&gt;exploiting&lt;/em&gt; uniqueness as a
construction principle.&lt;/p&gt;

&lt;h3 id=&quot;capdatat-mode-crosses-contention-and-portability&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cap.Data.t&lt;/code&gt; mode-crosses contention and portability&lt;/h3&gt;

&lt;p&gt;Just like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Portable.Atomic.t&lt;/code&gt; from the previous post, the type
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&apos;a, &apos;k) Cap.Data.t&lt;/code&gt; carries the kind annotation
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value mod contended portable&lt;/code&gt;. A closure that captures a capsule
value stays &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ portable&lt;/code&gt;, and any domain may hold the capsule. So the
closure returned by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make_counter&lt;/code&gt; (which captures both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mutex&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;counter&lt;/code&gt;) type-checks at portable mode and is safe to send to another
domain.&lt;/p&gt;

&lt;p&gt;This is the same mode-crossing move we saw with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Portable.Atomic&lt;/code&gt;,
just applied to a more general container.&lt;/p&gt;

&lt;h3 id=&quot;with_lock-produces-an-access-token-briefly&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;with_lock&lt;/code&gt; produces an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access&lt;/code&gt; token, briefly&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mtx.with_lock&lt;/code&gt; is the only way into the critical section. Its
signature:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;with_lock&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Cap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;once&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;once&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;once&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Three different things in this signature are doing real work.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Brand &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;k&lt;/code&gt;&lt;/strong&gt;: the password’s brand matches the mutex’s brand. A
password from a &lt;em&gt;different&lt;/em&gt; mutex (different &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$k1&lt;/code&gt;) cannot unwrap
our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;counter&lt;/code&gt;. The type checker refuses to unify the two
existentials and the program does not compile.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ local&lt;/code&gt;&lt;/strong&gt;: the password is local to the body’s region. It
cannot escape &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; by being returned, stored in a global, or stuffed
into a closure that outlives the call. When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;with_lock&lt;/code&gt; returns the
lock is released, and there’s no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;password&lt;/code&gt; left in scope to attempt
to touch the data with. (Locality is the &lt;a href=&quot;/ocaml/modes/oxcaml/2025/06/04/linearity_and_uniqueness/&quot;&gt;stack-allocation /
no-escape axis we covered&lt;/a&gt;;
same mechanism, different use.)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ once&lt;/code&gt;&lt;/strong&gt; on the body: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; can be called at most once. This is
the linearity guarantee. The body cannot be re-entered with the
same password, and the runtime cannot smuggle it out for later. Each
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;with_lock&lt;/code&gt; use is a single shot.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cap.access ~password ~f:(fun access -&amp;gt; ...)&lt;/code&gt; converts
the password into a brand-matching &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;k Access.t&lt;/code&gt; for the inner body.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cap.Data.unwrap ~access counter&lt;/code&gt; then accepts the access and returns
the underlying &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int ref&lt;/code&gt; at &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ uncontended&lt;/code&gt;&lt;/strong&gt;. We hold the lock; no
other domain can be touching the data. The next two lines, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;incr c;
!c&lt;/code&gt;, are ordinary OCaml mutation; the contention rule is satisfied by
construction because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unwrap&lt;/code&gt; promised uncontended access.&lt;/p&gt;

&lt;p&gt;Outside the lock body, neither &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;password&lt;/code&gt; nor &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access&lt;/code&gt; exists in
scope, so there is no path from the outer program to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;incr c&lt;/code&gt; that
doesn’t go through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;with_lock&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;brand-mismatch-is-a-type-error&quot;&gt;Brand mismatch is a type error&lt;/h2&gt;

&lt;p&gt;The cell below tries the genuinely unsound case: protecting one
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cap.Data.t&lt;/code&gt; with two distinct mutexes. If this compiled, two
threads holding distinct mutexes could enter critical sections on the
same data simultaneously. The type checker refuses, and reports the
two existentials don’t match.&lt;/p&gt;

&lt;x-ocaml&gt;
[@@@alert &quot;-deprecated&quot;]

let abuse () =
  let Cap.Key.P key1 = Cap.create () in
  let Cap.Key.P key2 = Cap.create () in
  let data  = Cap.Data.create (fun () -&amp;gt; ref 0) in
  let m1 = Mtx.create key1 in
  let m2 = Mtx.create key2 in
  (* First unwrap pins data&apos;s brand to key1&apos;s $k. *)
  let _ = Mtx.with_lock m1 ~f:(fun password -&amp;gt;
            Cap.access ~password ~f:(fun access -&amp;gt;
              !(Cap.Data.unwrap ~access data))) in
  (* This second unwrap fails: data is branded with the FIRST key&apos;s $k,
     not the second&apos;s $k1. *)
  Mtx.with_lock m2 ~f:(fun password -&amp;gt;
    Cap.access ~password ~f:(fun access -&amp;gt;
      !(Cap.Data.unwrap ~access data)))
&lt;/x-ocaml&gt;

&lt;p&gt;The error names the two existentials and points out they cannot
unify. The handout’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;capsule_abuse.ml&lt;/code&gt; walks through two more
attempted escape hatches:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Leak the inner ref through a top-level &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Portable.Atomic&lt;/code&gt;.&lt;/strong&gt; The
store compiles, but anything inside a portable atomic is
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ contended&lt;/code&gt;, and the contention rule from the
&lt;a href=&quot;/ocaml/oxcaml/x-ocaml/blogging/2026/05/07/data-race-freedom-in-oxcaml/&quot;&gt;previous post&lt;/a&gt;
forbids reading or writing a mutable field of a contended value. So
you can park an alias, but you can’t dereference it.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;One mutex protecting two &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cap.Data.t&lt;/code&gt; values.&lt;/strong&gt; &lt;em&gt;Allowed&lt;/em&gt;, and
correctly so. Both data values are branded with the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$k&lt;/code&gt;, and
a single critical section can update both. (Equivalent to one mutex
guarding two fields of a struct.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first closes the obvious leak path (via the same uniqueness-of-paths
property that protects the bare &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ref&lt;/code&gt;); brand mismatch closes the
aliased-mutex case; the one-mutex-two-data case shows the rule isn’t
gratuitously restrictive.&lt;/p&gt;

&lt;h2 id=&quot;what-each-mode-is-doing&quot;&gt;What each mode is doing&lt;/h2&gt;

&lt;p&gt;Pulling the threads together, with one line per axis:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Contention&lt;/strong&gt; ensures shared mutable state can’t be read or
written from outside a critical section. Inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;with_lock&lt;/code&gt; we get
an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ uncontended&lt;/code&gt; view via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unwrap&lt;/code&gt;; outside, the contents aren’t
in scope at all.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Portability&lt;/strong&gt; lets the closure cross domain boundaries.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cap.Data.t&lt;/code&gt; mode-crosses, so the closure capturing it stays
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ portable&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Locality&lt;/strong&gt; confines the password (and the access derived from
it) to the body of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;with_lock&lt;/code&gt;. No way to keep a token past lock
release.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Linearity&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ once&lt;/code&gt; on the body) makes the critical section
single-shot. The body cannot be re-entered with the same password.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Uniqueness&lt;/strong&gt; isn’t an annotation we wrote; it’s the property
that the inner &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ref&lt;/code&gt; has exactly one path of access, through the
capsule. The API shape forces it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;a-note-on-the-api&quot;&gt;A note on the API&lt;/h2&gt;

&lt;p&gt;Two API choices in the cells above are worth flagging for anyone
transcribing this to a real &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.ml&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Curated vs expert capsule API.&lt;/strong&gt; The full &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;capsule&lt;/code&gt; opam library
wraps the brand-based primitives in a curated layer
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Capsule.Isolated&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Capsule.Guard&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Capsule.Shared&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Capsule.Data&lt;/code&gt;) that hides most of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Key.P&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;password&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;access&lt;/code&gt;
plumbing for common patterns. For most application code you reach for
those first. We use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Capsule_expert&lt;/code&gt; directly here because the curated
wrapper pulls in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sexplib0&lt;/code&gt;, and friends that would balloon
the in-browser bundle by ~270 MB. The lecture’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Capsule.Data&lt;/code&gt; calls
are syntactically identical to ours.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mutex flavour.&lt;/strong&gt; The lecture uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Await_capsule.Mutex.with_lock&lt;/code&gt;,
the recommended (non-deprecated) primitive that hands the body an
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Access.t&lt;/code&gt; directly. Bundling the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;await&lt;/code&gt; library into the in-browser
toplevel pulls in roughly &lt;strong&gt;280 MB&lt;/strong&gt; of transitive deps (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sexplib&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stdio&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ppx_*&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base.shadow_stdlib&lt;/code&gt;, …), so we use the
deprecated-but-equivalent &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Capsule_blocking_sync.Mutex&lt;/code&gt; with the
deprecation alert silenced. It hands the body a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;k Password.t @ local&lt;/code&gt;,
which we convert to a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;k Access.t&lt;/code&gt; via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Capsule_expert.access&lt;/code&gt;. One
extra line of plumbing; same modes are doing the work. In a real
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.ml&lt;/code&gt; file with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;await&lt;/code&gt; available, swap &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Capsule_blocking_sync.Mutex&lt;/code&gt;
for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Await_capsule.Mutex&lt;/code&gt; and drop the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Capsule_expert.access&lt;/code&gt; step;
the lecture’s verbatim form in the
&lt;a href=&quot;https://github.com/fplaunchpad/cs6868_s26/blob/main/lectures/11_oxcaml/handout.md#part-5-capsules--safe-shared-mutable-state&quot;&gt;handout&lt;/a&gt;
is what you want.&lt;/p&gt;

&lt;h2 id=&quot;whats-left&quot;&gt;What’s left&lt;/h2&gt;

&lt;p&gt;The capsule pattern is enough to put a hash table or a more elaborate
shared structure under a single mutex with a compile-time guarantee
that nothing touches it without the lock. To actually run gensym from
two domains in parallel we need the parallel scheduler:
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Parallel.fork_join2&lt;/code&gt; and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ portable once&lt;/code&gt; story for closures
crossing the fork boundary. That’s the next post.&lt;/p&gt;

&lt;p&gt;The point of stopping here is that the hard part of safe shared
mutable state in OxCaml isn’t the parallel primitive, it’s the lock
discipline. And the lock discipline turns out to be a small
composition of the mode axes we already had to learn anyway. The new
library is small; the framework was already in place.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Data race freedom in OxCaml</title>
   <link href="https://kcsrk.info/ocaml/oxcaml/x-ocaml/blogging/2026/05/07/data-race-freedom-in-oxcaml/"/>
   <updated>2026-05-07T10:00:00+00:00</updated>
   <id>https://kcsrk.info/ocaml/oxcaml/x-ocaml/blogging/2026/05/07/data-race-freedom-in-oxcaml</id>
   <content type="html">&lt;script async=&quot;&quot; src=&quot;/assets/x-ocaml-ox/x-ocaml.js&quot; src-worker=&quot;/assets/x-ocaml-ox/x-ocaml.worker+effects.js&quot; src-load=&quot;/assets/x-ocaml-ox/portable.js&quot;&gt;&lt;/script&gt;

&lt;style&gt;
  x-ocaml { font-size: 0.8em; display: block; margin-bottom: 1.4rem; }
  x-ocaml.hidden { display: none; }
&lt;/style&gt;

&lt;p&gt;A while back I &lt;a href=&quot;/ocaml/x-ocaml/blogging/2025/06/20/xocaml/&quot;&gt;wired up &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x-ocaml&lt;/code&gt;&lt;/a&gt; so this
blog could embed live, editable OCaml notebooks. That post used a vanilla
OCaml 5 toplevel. Today the toplevel running in your browser is built
from &lt;a href=&quot;https://oxcaml.org&quot;&gt;OxCaml&lt;/a&gt;, the Jane Street fork of the compiler.
That means we can prove a small parallel program is data-race free,
interactively, without ever spawning a thread.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;The examples below are adapted from the OxCaml team’s excellent
&lt;a href=&quot;https://oxcaml.org/documentation/tutorials/01-intro-to-parallelism-part-1/&quot;&gt;Intro to Parallelism (Part 1)&lt;/a&gt;
tutorial, by way of my recent
&lt;a href=&quot;https://github.com/fplaunchpad/cs6868_s26&quot;&gt;CS6868&lt;/a&gt; lecture on OxCaml
(&lt;a href=&quot;https://github.com/fplaunchpad/cs6868_s26/blob/main/lectures/11_oxcaml/handout.md&quot;&gt;handout&lt;/a&gt;).
The tutorial is the canonical reference and is worth reading in full;
this post tries to capture the essence in a more bite-sized form,
focused on the two new mode axes that together rule out data races at
compile time — and on one subtlety about portability that’s easy to
misread.&lt;/p&gt;

&lt;h2 id=&quot;a-quick-aside-data-races-in-ocaml-are-less-scary&quot;&gt;A quick aside: data races in OCaml are less scary&lt;/h2&gt;

&lt;p&gt;Before we dive in, it’s worth pausing on why we want to rule out data
races at all in OCaml. In C, C++, or unsafe Rust, a data race is
catastrophic: the standard licenses the compiler to do &lt;em&gt;anything&lt;/em&gt;,
including silent memory corruption, on the basis that your program had
no defined meaning to begin with. OCaml is considerably gentler.
&lt;a href=&quot;https://ocaml.org/manual/5.4/memorymodel.html&quot;&gt;OCaml’s memory model&lt;/a&gt;
guarantees that even programs with races preserve type safety and
memory safety — a racy program may observe weakly-consistent values
across domains, but it will not crash, won’t read uninitialised memory,
and won’t violate the type system’s invariants.&lt;/p&gt;

&lt;p&gt;So a race in OCaml is a logic bug, not a runtime footgun. Why bother
catching them statically, then? Because once a program is data-race
free, you get &lt;strong&gt;sequential consistency&lt;/strong&gt;: any observed behaviour can
be explained as some interleaving of the operations of the different
domains, with each domain’s own operations executed in program order.
That’s still concurrent reasoning — there are many possible
interleavings — but it’s the simplest model concurrent code can have,
and equational reasoning, induction, and the usual program-logic tools
all transfer over to each interleaving. Drop race freedom and you lose
this: observed behaviours can only be justified by allowing
&lt;em&gt;intra-thread&lt;/em&gt; reorderings as well, where a single domain’s operations
appear to execute out of program order to other domains. Sequential
consistency is the real prize. Race freedom is what buys it.&lt;/p&gt;

&lt;h2 id=&quot;hello-oxcaml&quot;&gt;Hello, OxCaml&lt;/h2&gt;

&lt;p&gt;A quick sanity check that your browser really is running an OxCaml
toplevel. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ local&lt;/code&gt; annotation is OxCaml-only syntax; on a stock OCaml
parser it wouldn’t even parse.&lt;/p&gt;

&lt;x-ocaml&gt;
let use_locally (x @ local) = x + 1

let () = Printf.printf &quot;use_locally 42 = %d\n&quot; (use_locally 42)
&lt;/x-ocaml&gt;

&lt;h2 id=&quot;a-racy-gensym&quot;&gt;A racy &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gensym&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Here’s the example we’ll keep coming back to: a symbol generator that
hands out distinct ids by incrementing a captured counter. Sequentially
it works; the cell prints two ids. The last line tries to ship &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gensym&lt;/code&gt;
to another domain, and that’s where the type checker stops us.&lt;/p&gt;

&lt;x-ocaml&gt;
[@@@alert &quot;-do_not_spawn_domains&quot;]

let gensym =
  let count = ref 0 in
  fun prefix -&amp;gt;
    count := !count + 1;
    prefix ^ &quot;_&quot; ^ string_of_int !count

let () = Printf.printf &quot;%s %s\n&quot; (gensym &quot;x&quot;) (gensym &quot;x&quot;)

let _ = Domain.Safe.spawn (fun () -&amp;gt; gensym &quot;x&quot;)
&lt;/x-ocaml&gt;

&lt;p&gt;Run it from two domains in parallel and you’d tick every box on the
four-ingredient recipe for a data race: two domains, a shared &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;count&lt;/code&gt;,
both writing, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;count&lt;/code&gt; is a plain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ref&lt;/code&gt; — not atomic. On stock OCaml
5, the compiler would happily let you ship this closure to another
domain. OxCaml refuses, before anything runs. The error names two things
— &lt;em&gt;nonportable&lt;/em&gt; and &lt;em&gt;portable&lt;/em&gt; — that aren’t in vanilla OCaml’s
vocabulary. What do they mean?&lt;/p&gt;

&lt;h2 id=&quot;two-new-modes-for-data-race-freedom&quot;&gt;Two new modes for data race freedom&lt;/h2&gt;

&lt;p&gt;OxCaml extends OCaml’s type system with several
&lt;a href=&quot;https://oxcaml.org/jane/doc/extensions/modes/intro/&quot;&gt;modes&lt;/a&gt; — annotations
that describe &lt;em&gt;how&lt;/em&gt; a value can be used, orthogonal to its type. I’ve
already written about two of them on this blog:
&lt;a href=&quot;/ocaml/modes/oxcaml/2025/05/29/uniqueness_and_behavioural_types/&quot;&gt;uniqueness&lt;/a&gt;,
which tracks whether a value has at most one reference, and
&lt;a href=&quot;/ocaml/modes/oxcaml/2025/06/04/linearity_and_uniqueness/&quot;&gt;linearity&lt;/a&gt;, which
tracks how often a value may be used. Today’s post is about a different
pair — the two modes that, together, rule out data races at compile time:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;contention&lt;/strong&gt; — &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uncontended&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contended&lt;/code&gt;: tracks whether multiple
domains can simultaneously access a value. A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contended&lt;/code&gt; value might
be in another domain’s hands right now, so the type system limits
what you can do with it.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;portability&lt;/strong&gt; — &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;portable&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nonportable&lt;/code&gt;: tracks whether a value
can safely &lt;em&gt;cross&lt;/em&gt; a domain boundary at all. Closures that are sent
to other domains must be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;portable&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The pair is enough to catch the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gensym&lt;/code&gt; race. Let’s look at each
restriction in isolation, then come back to the closure.&lt;/p&gt;

&lt;h3 id=&quot;contention-rejects-mutable-writes&quot;&gt;Contention rejects mutable writes&lt;/h3&gt;

&lt;p&gt;A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contended&lt;/code&gt; value might be mutated by another domain right now. So
OxCaml refuses to let you read or write its mutable fields:&lt;/p&gt;

&lt;x-ocaml&gt;
type mood = Happy | Neutral | Sad
type thing = { price : float; mutable mood : mood }

(* Reading an immutable field of a contended value is fine. *)
let price_contended (t @ contended) = t.price

(* Writing a mutable field is not. *)
let cheer_up_contended (t @ contended) = t.mood &amp;lt;- Happy
&lt;/x-ocaml&gt;

&lt;p&gt;The error on the last line names exactly the rule: &lt;em&gt;“This value is
contended but is expected to be uncontended because its mutable field
mood is being written.”&lt;/em&gt; Even &lt;em&gt;reading&lt;/em&gt; a mutable field on a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contended&lt;/code&gt;
value is rejected — another domain might be mid-write at the same
instant.&lt;/p&gt;

&lt;h3 id=&quot;portability-rejects-captured-refs&quot;&gt;Portability rejects captured refs&lt;/h3&gt;

&lt;p&gt;Portability is about closures. A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ portable&lt;/code&gt; closure is one the
compiler has verified is safe to ship to another domain, with one
critical catch: every value the closure &lt;em&gt;captures&lt;/em&gt; from its enclosing
scope is treated as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contended&lt;/code&gt; inside the closure body. A pure
function that doesn’t mutate anything is trivially portable — there’s
nothing the contention rule can object to:&lt;/p&gt;

&lt;x-ocaml&gt;
let test_portable () =
  let (f @ portable) = fun x y -&amp;gt; x + y in
  f 1 2

let () = Printf.printf &quot;test_portable () = %d\n&quot; (test_portable ())
&lt;/x-ocaml&gt;

&lt;p&gt;Capturing a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ref&lt;/code&gt; is fine on its own; &lt;em&gt;mutating&lt;/em&gt; one that’s been
captured is what falls afoul of the rule:&lt;/p&gt;

&lt;x-ocaml&gt;
let test_nonportable () =
  let r = ref 0 in
  let (counter @ portable) () = incr r; !r in
  counter ()
&lt;/x-ocaml&gt;

&lt;p&gt;Read the error carefully — it tells you &lt;em&gt;exactly why&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;counter&lt;/code&gt; isn’t
portable. The closure is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ portable&lt;/code&gt;, so the captured &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt; is treated
as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contended&lt;/code&gt; inside the body. But &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;incr r&lt;/code&gt; is a mutation, and writing
through a ref requires it to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uncontended&lt;/code&gt;. The two rules collide.
And now the original &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gensym&lt;/code&gt; rejection makes sense: it does exactly
the same thing — mutates a captured &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;count&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;the-trap-and-the-actual-rule&quot;&gt;The trap, and the actual rule&lt;/h2&gt;

&lt;p&gt;Read those last two cells together and it’s tempting to draw the wrong
moral: that to make a function safe to ship to another domain, you have
to give up side effects. That would be far too restrictive.&lt;/p&gt;

&lt;p&gt;The actual rule is narrower, and the difference matters.&lt;/p&gt;

&lt;p&gt;Portability constrains what a closure &lt;strong&gt;captures from its enclosing
scope&lt;/strong&gt;. Captured values become contended — that’s the rule, and it’s
why &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gensym&lt;/code&gt; got rejected. But a closure’s &lt;strong&gt;parameters&lt;/strong&gt; are not
captures. They’re handed in fresh at each call, so they can be passed at
any mode the type spells out — including &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ uncontended&lt;/code&gt;. The obligation
to provide an uncontended argument shifts to whoever is doing the
calling. That’s a much weaker requirement than “no side effects.”&lt;/p&gt;

&lt;h3 id=&quot;captured-vs-parameter-in-code&quot;&gt;Captured vs parameter, in code&lt;/h3&gt;

&lt;p&gt;Here’s the example that makes the distinction concrete. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loop&lt;/code&gt; is
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ portable&lt;/code&gt;, and its body mutates an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int ref&lt;/code&gt;. That works because the
ref is a &lt;em&gt;parameter&lt;/em&gt; annotated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ uncontended&lt;/code&gt;, not something captured:&lt;/p&gt;

&lt;x-ocaml&gt;
let (factorial_portable @ portable) n =
  let a = ref 1 in
  let rec (loop @ portable) (a @ uncontended) i =
    if i &amp;gt; 0 then begin
      a := !a * i;
      loop a (i - 1)
    end
  in
  loop a n;
  !a

let () = Printf.printf &quot;factorial_portable 10 = %d\n&quot; (factorial_portable 10)
&lt;/x-ocaml&gt;

&lt;p&gt;Two &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ portable&lt;/code&gt; annotations are doing work here. The inner one says
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loop&lt;/code&gt; is shippable to another domain — that’s the interesting one,
and it works because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loop&lt;/code&gt;’s &lt;em&gt;parameter&lt;/em&gt;, not a capture: when
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loop&lt;/code&gt; is eventually called from somewhere parallel, that somewhere
has to prove the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; it passes in is uncontended. Portability didn’t
ban mutation; it pushed the proof to the call site. The outer
annotation says the whole &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;factorial_portable&lt;/code&gt; is portable too — it
allocates a fresh &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; on each call and captures nothing from outside,
so we can ship the whole function to another domain. The compiler
verifies both annotations as part of accepting the program.&lt;/p&gt;

&lt;h2 id=&quot;a-formal-aside-defaults-and-submoding&quot;&gt;A formal aside: defaults and submoding&lt;/h2&gt;

&lt;p&gt;We’ve been writing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ contended&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ portable&lt;/code&gt; as if they were the
interesting modes and their absence was nothing in particular. There’s
actually a small lattice on each axis, with a default and a direction
of “how strong” the guarantee is. The handout summarises it like this:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Axis&lt;/th&gt;
      &lt;th&gt;Modes (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;⊑&lt;/code&gt;)&lt;/th&gt;
      &lt;th&gt;Default&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Contention&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uncontended&lt;/code&gt; ⊑ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shared&lt;/code&gt; ⊑ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contended&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uncontended&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Portability&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;portable&lt;/code&gt; ⊑ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nonportable&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nonportable&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The relation &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A ⊑ B&lt;/code&gt; is the &lt;strong&gt;submoding order&lt;/strong&gt;: a value at mode &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt;
may be used wherever mode &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B&lt;/code&gt; is expected, because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt; carries the
stronger guarantee and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B&lt;/code&gt; is the looser expectation. An &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uncontended&lt;/code&gt;
value satisfies a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ contended&lt;/code&gt; parameter (we just promised the callee
might let other domains touch it; if no other domain ever does, that
promise is trivially compatible). A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;portable&lt;/code&gt; closure satisfies a
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ nonportable&lt;/code&gt; slot. But not the other way around — submoding goes
one way only.&lt;/p&gt;

&lt;p&gt;The defaults are what you get when you write plain OCaml. Every value
starts out &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uncontended&lt;/code&gt; — no other domain has it, so reads and writes
are unrestricted. Every closure starts out &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nonportable&lt;/code&gt; — we make no
claim about shipping it elsewhere. That’s why ordinary OCaml code keeps
type-checking under OxCaml: defaults are the most permissive end of
each axis, and you only meet the new restrictions when you (or a
parallel API) ask for a stronger guarantee. The post uses only the two
endpoints of the contention chain — &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uncontended&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contended&lt;/code&gt; — and
skips &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shared&lt;/code&gt;, which permits read-only access across domains and isn’t
needed for the gensym story.&lt;/p&gt;

&lt;x-ocaml class=&quot;hidden&quot;&gt;
module Portable = struct
  module Atomic : sig
    type !&apos;a t : value mod contended portable
    val make : &apos;a @ portable contended -&amp;gt; &apos;a t
    val fetch_and_add : int t @ local -&amp;gt; int -&amp;gt; int
  end = struct
    type !&apos;a t : value mod contended portable =
      &apos;a Basement.Portable_atomic.t
    let make = Basement.Portable_atomic.make
    let fetch_and_add = Basement.Portable_atomic.fetch_and_add
  end
end
&lt;/x-ocaml&gt;

&lt;h2 id=&quot;back-to-gensym-the-fix&quot;&gt;Back to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gensym&lt;/code&gt;: the fix&lt;/h2&gt;

&lt;p&gt;The captured-vs-parameter distinction is enough to fix simple loops, but
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gensym&lt;/code&gt; is a different shape: there’s a single counter that must be
shared across calls. We need a counter type that’s &lt;em&gt;itself&lt;/em&gt; portable —
something whose values mode-cross both contention and portability, so a
closure capturing it stays portable. That’s exactly &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Portable.Atomic.t&lt;/code&gt;,
from OxCaml’s
&lt;a href=&quot;https://github.com/oxcaml/oxcaml/tree/main/portable&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;portable&lt;/code&gt;&lt;/a&gt;
library: a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;a Portable.Atomic.t&lt;/code&gt; is always portable and always
uncontended, regardless of where it lives.&lt;/p&gt;

&lt;p&gt;Wrap the counter and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gensym&lt;/code&gt; in a module so the toplevel can see the
whole bundle as portable, then actually do what got us in trouble at
the start: ship &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gensym&lt;/code&gt; to a freshly-spawned domain. The compiler
accepts it (it verified &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Gen&lt;/code&gt; is portable), and the program runs:&lt;/p&gt;

&lt;x-ocaml&gt;
[@@@alert &quot;-do_not_spawn_domains&quot;]

module Gen = struct
  open Portable
  let count = Atomic.make 0
  let gensym prefix =
    let n = Atomic.fetch_and_add count 1 in
    prefix ^ &quot;_&quot; ^ string_of_int n
end

let d  = Domain.Safe.spawn (fun () -&amp;gt; Gen.gensym &quot;y&quot;)
let s1 = Gen.gensym &quot;x&quot;
let s2 = Domain.join d
let () = Printf.printf &quot;%s %s\n&quot; s1 s2
&lt;/x-ocaml&gt;

&lt;p&gt;The toplevel reports &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;module Gen : sig ... end @@ portable&lt;/code&gt; — mode
inference noticed every value inside is portable and made the whole
module portable, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Gen.gensym&lt;/code&gt; survives extraction at portable mode.
You might wonder why we don’t just write &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let (gensym @ portable)
prefix = ...&lt;/code&gt; at the top level, the same shape we used for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;factorial_portable&lt;/code&gt; above. That’s a quirk of the toplevel: a bare
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let&lt;/code&gt; lands in the implicit toplevel module, which itself sits at the
default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nonportable&lt;/code&gt; mode, so when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Domain.Safe.spawn&lt;/code&gt; later reads
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gensym&lt;/code&gt; back out, it sees a nonportable binding and refuses — even
though the closure was verified portable at its binding site. The
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;factorial_portable&lt;/code&gt; cell got away with the simpler form only because
nothing else tried to extract the binding at portable mode. Wrapping
in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;module Gen&lt;/code&gt; gives the closure its own portable home, which is what
lets it actually cross a domain boundary. In a real &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.ml&lt;/code&gt; file the
whole compilation unit is a module that mode inference can mark
portable wholesale, so this dance isn’t necessary.&lt;/p&gt;

&lt;p&gt;(A note on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Portable.Atomic&lt;/code&gt; you see here: in a real program you’d
get it by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;open Portable&lt;/code&gt; from the
&lt;a href=&quot;https://github.com/oxcaml/oxcaml/tree/main/portable&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;portable&lt;/code&gt;&lt;/a&gt; opam
library. To keep the page weight reasonable, this notebook ships only
&lt;a href=&quot;https://github.com/oxcaml/oxcaml/tree/main/basement&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;basement&lt;/code&gt;&lt;/a&gt; — the
small library that provides the actual atomic operations — and a
hidden setup cell at the top of the page wraps it with the kind
annotation &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;: value mod contended portable&lt;/code&gt;. That kind is what tells the
compiler this type mode-crosses both axes — a closure capturing one
stays portable, and any domain may touch it.) The
&lt;a href=&quot;https://github.com/fplaunchpad/cs6868_s26/blob/main/lectures/11_oxcaml/handout.md&quot;&gt;handout&lt;/a&gt;
notes that for state more elaborate than a single atomic counter, the
right answer is &lt;strong&gt;capsules&lt;/strong&gt; — a structural way to bundle mutable state
with its access protocol so the whole package is portable.&lt;/p&gt;

&lt;h2 id=&quot;whats-left&quot;&gt;What’s left&lt;/h2&gt;

&lt;p&gt;The race-freedom guarantee here is independent of any test run: every
rejection above happened at the same compile step an OxCaml binary on
disk would go through, before any code executed. The final spawn is a
demonstration, not a proof — it’s the compiler accepting the program
in the first place that tells us no race is possible. Two mode axes, a
kind annotation, and a clear rule about what “portable” means were
enough to make data-race freedom a property the type checker enforces.&lt;/p&gt;

&lt;p&gt;The lecture this is drawn from goes further into capsules (for shared
state more elaborate than an atomic) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Parallel.fork_join2&lt;/code&gt; (for
structured parallelism). Material for another post.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>From Convergence to Confidence: Push-button verification for RDTs</title>
   <link href="https://kcsrk.info/verification/rdts/lean/2026/04/28/from-convergence-to-confidence/"/>
   <updated>2026-04-28T10:00:00+00:00</updated>
   <id>https://kcsrk.info/verification/rdts/lean/2026/04/28/from-convergence-to-confidence</id>
   <content type="html">&lt;p&gt;What does it mean for a replicated data type to be &lt;em&gt;correct&lt;/em&gt;? For most of the
literature, my own prior work included, the answer has been convergence: two
replicas that have applied the same operations end up in the same state. I
argued &lt;a href=&quot;/slides/RDT_verification_papoc_2026.pdf&quot;&gt;in my PaPoC 2026 keynote&lt;/a&gt; last
week that for many useful data types convergence is not enough, and agentic
proof-oriented programming can help close the gap between convergence and
confidence.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;A stronger answer,
&lt;a href=&quot;https://dl.acm.org/doi/10.1145/3314221.3314617&quot;&gt;replication-aware linearizability&lt;/a&gt;
from Wang et al. (PLDI 2019), asks for full functional equivalence with a
sequential specification: the merged state should behave as if the
operations everyone did had run in some sequential interleaving.
RA-linearizability is what our verification work has aimed at for the past
few years, and for a class of useful data types it still falls short: the
ones where the state is a grow-only bag and the interesting semantics live
in the read function. This post is the longer-form version of the keynote
argument, plus a digest of recent work on
&lt;a href=&quot;https://github.com/fplaunchpad/sal&quot;&gt;Sal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://papoc-workshop.github.io/2026/&quot;&gt;PaPoC 2026&lt;/a&gt; was co-located
with EuroSys in Edinburgh, and was a wonderful workshop. Thanks to
the program chairs, &lt;a href=&quot;https://decomposition.al/&quot;&gt;Lindsey Kuper&lt;/a&gt; and
&lt;a href=&quot;https://jopereira.github.io/&quot;&gt;José Orlando Pereira&lt;/a&gt;, for running
it. A permanent entry for the keynote is on &lt;a href=&quot;/talks#papoc_2026&quot;&gt;my talks
page&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;convergence-is-not-enough&quot;&gt;Convergence is not enough&lt;/h2&gt;

&lt;p&gt;The canonical example is the
&lt;a href=&quot;https://inria.hal.science/inria-00555588/document&quot;&gt;OR-Set&lt;/a&gt;. The
state is two sets, an &lt;em&gt;adds&lt;/em&gt; set
and a &lt;em&gt;tombstones&lt;/em&gt; set. Adding an element tags it with a fresh id and
stores the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(element, id)&lt;/code&gt; pair in &lt;em&gt;adds&lt;/em&gt;. Removing an element does not
delete anything; it adds a tombstone entry for each currently observed
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(element, id)&lt;/code&gt; pair to &lt;em&gt;tombstones&lt;/em&gt;. Reading filters &lt;em&gt;adds&lt;/em&gt; against
&lt;em&gt;tombstones&lt;/em&gt;, and merging unions both components componentwise. The data type converges, but tombstones accumulate without
bound. The fix is a bit cleverer than just tagging: each replica tracks
causality explicitly, by maintaining a context of operations it has
observed, and the merge uses that context to recognise when an element
was removed at another replica without having to keep a tombstone for it.
The result is the “efficient” OR-Set.&lt;/p&gt;

&lt;p&gt;In practice this is harder than it sounds. Riak’s
&lt;a href=&quot;https://github.com/basho/riak_dt&quot;&gt;riak_dt&lt;/a&gt;, a production CRDT library,
shipped an optimisation to its OR-Set Map that broke monotonicity
(&lt;a href=&quot;https://github.com/basho/riak_dt/issues/79&quot;&gt;issue #79&lt;/a&gt;). Christopher
Meiklejohn, one of the authors of the &lt;a href=&quot;https://doi.org/10.1145/2596631.2596633&quot;&gt;Riak DT Map
paper&lt;/a&gt;, &lt;a href=&quot;https://christophermeiklejohn.com/erlang/lasp/2019/03/08/monotonicity.html&quot;&gt;later
wrote&lt;/a&gt;
about how easy it is to get the inflationary, deterministic,
least-upper-bound conditions wrong, and noted that the team &lt;em&gt;“have even
got this wrong a few times”&lt;/em&gt; themselves. Martin Kleppmann’s &lt;a href=&quot;https://martin.kleppmann.com/2019/03/25/papoc-interleaving-anomalies.html&quot;&gt;2019 PaPoC
paper on collaborative-text
anomalies&lt;/a&gt;
had errata of the same flavour, appended to the publication page a few
years after the fact: the non-interleaving condition proposed in §2.1
“cannot be guaranteed by any algorithm,” and the algorithm in §3.1 does
not guarantee convergence.&lt;/p&gt;

&lt;p&gt;A well-defined join and a join that does what the user expects are not the
same thing, and the gap between the two is where most of these bugs live.&lt;/p&gt;

&lt;h2 id=&quot;a-short-history-of-how-we-tried-to-close-that-gap&quot;&gt;A short history of how we tried to close that gap&lt;/h2&gt;

&lt;p&gt;My group has been chipping at this for a few years. In
&lt;a href=&quot;/papers/certified_mrdt.pdf&quot;&gt;Peepul&lt;/a&gt; (PLDI 2022) we tried to capture intent
axiomatically: write the spec as a fold over a partially ordered event
graph, then prove the implementation simulates it. The proofs closed, but
the cost was telling. The queue MRDT case study took 1,123 lines of proof
spread over 75 lemmas against a 32-line implementation, with each F*
verification run taking on the order of 4,753 seconds. F*’s SMT-aided
proofs were brittle (z3 upgrades broke them, and the solver only ever
returned yes / no / timeout with no counterexample), and the methodology
did not really scale past a handful of carefully-chosen examples.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/papers/mrdtconverge_jan_25.pdf&quot;&gt;Neem&lt;/a&gt; (OOPSLA 2025) replaced the axiomatic
spec with RA-linearizability, with one twist:
instead of taking a separate sequential specification as input, Neem treats
the operational definition of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do_&lt;/code&gt; itself as the spec. The merge is
correct if the resulting state behaves like some sequential interleaving of
the updates under that definition. Neem also gave us a fixed schedule of 24
verification conditions (six on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do_&lt;/code&gt;, twelve on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;merge&lt;/code&gt;, six on conflict
resolution) that, if all closed, certify RA-linearizability. That was a
real upgrade. But it was still in F*, still SMT-fragile, and there was a
class of useful RDTs for which closing the 24 VCs left the correctness
statement itself near-vacuous.&lt;/p&gt;

&lt;p&gt;The pattern that exposes that vacuity is recognisable. When porting an
op-based CRDT to a state-based one, a common move is to dump every
operation into a grow-only set and leave the read function to
reconstruct the result. The merge is then set union, any sequence of
operations is trivially its own linearisation, and the 24
RA-linearizability VCs close without much work. The data type can still
be wrong, because nothing in that proof has said anything about
&lt;em&gt;intent&lt;/em&gt;: which characters are bold, which key sits at the head of the
queue. Peepul did try to capture intent, but it expressed the spec over
a partially ordered graph of events with no further structure, and that
turned out to be both an awkward medium to write specs in and a brittle
one to prove against.&lt;/p&gt;

&lt;p&gt;We have started calling these vacuous-convergence cases &lt;em&gt;Tier-C&lt;/em&gt;
RDTs, in a three-tier taxonomy that we settled on this past month:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Tier A&lt;/strong&gt;: state &lt;em&gt;is&lt;/em&gt; the semantic content. LWW-Register, PN-Counter,
Bounded-Counter, MAX-Map. The RA-linearizability VCs reduce to lattice
arithmetic and cover what one wants to know.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tier B&lt;/strong&gt;: merge does non-trivial computation. Multi-Valued-Register,
LWW-Element-Set. Still substantive.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tier C&lt;/strong&gt;: state is a grow-only bag, and the semantics live in the
&lt;em&gt;read&lt;/em&gt;. OR-Set, RGA, Add-Win Priority Queue, and Peritext (which the
rest of the post comes back to).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Roughly half the Sal suite, and most of the RDTs people actually want to
use, sit in Tier C. For Tier C, “verified” without read-side theorems is
an overclaim.&lt;/p&gt;

&lt;h2 id=&quot;what-sal-actually-is&quot;&gt;What Sal actually is&lt;/h2&gt;

&lt;p&gt;Sal is the work I presented at PaPoC, joint with Pranav Ramesh and Vimala
Soundarapandian. The wider line of work this builds on also involves
Adarsh Kamath, Aseem Rastogi, and Kartik Nagar. It ports Neem to Lean 4
and adds a multi-modal proof tactic. The repo is at
&lt;a href=&quot;https://github.com/fplaunchpad/sal&quot;&gt;https://github.com/fplaunchpad/sal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Lean choice is not original to us. Ilya Sergey is the one who
convinced me to take Lean seriously, and Sal’s multi-modal tactic stack
is directly inspired by &lt;a href=&quot;https://verse-lab.github.io/&quot;&gt;Loom&lt;/a&gt;, the
multi-modal proof-orchestration layer his group has been building.
&lt;a href=&quot;https://proofsandintuitions.net/2026/01/21/multi-modal-verification-velvet/&quot;&gt;Velvet&lt;/a&gt;,
the Lean library it sits inside, verifies imperative programs; Sal
verifies RDTs. The toolchain is shared.&lt;/p&gt;

&lt;p&gt;When you write &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;by sal&lt;/code&gt; in front of a verification condition, three things
happen in sequence. First, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dsimp + grind&lt;/code&gt;: pure rewriting plus Lean’s
bit-level automation. If this closes the goal, the proof term is checked
by the Lean kernel and the trusted base is just Lean. If it doesn’t, Sal
hands the goal to Z3 via
&lt;a href=&quot;https://github.com/argumentcomputer/LeanBlaster&quot;&gt;lean-blaster&lt;/a&gt;. Fast, but
Z3 is now in the trusted base, and Sal records this with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Blaster_admit&lt;/code&gt;
annotation so the borrowed trust is visible. If that does not close
either, an AI agent (Claude Code or &lt;a href=&quot;https://harmonic.fun&quot;&gt;Aristotle&lt;/a&gt;)
tries to write a proof term, which Lean then kernel-checks. The TCB
shrinks back to just Lean.&lt;/p&gt;

&lt;p&gt;For the LWW-Register all 24 VCs close at stage 1. The whole specification
fits on a screen:&lt;/p&gt;

&lt;div class=&quot;language-lean highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;abbrev&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;concrete_st&lt;/span&gt; := &lt;span class=&quot;o&quot;&gt;ℕ&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;×&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;ℕ&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;init_st&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;concrete_st&lt;/span&gt; := (&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;)

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lex_max&lt;/span&gt; (&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; : &lt;span class=&quot;o&quot;&gt;ℕ&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;×&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;ℕ&lt;/span&gt;) : &lt;span class=&quot;o&quot;&gt;ℕ&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;×&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;ℕ&lt;/span&gt; :=
  &lt;span class=&quot;n&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;≥&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;do_&lt;/span&gt; (&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;concrete_st&lt;/span&gt;) : &lt;span class=&quot;n&quot;&gt;op_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;→&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;concrete_st&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; (&lt;span class=&quot;n&quot;&gt;ts&lt;/span&gt;, &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;, &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;) &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lex_max&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; (&lt;span class=&quot;n&quot;&gt;ts&lt;/span&gt;, &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;)

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;merge&lt;/span&gt; (&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;concrete_st&lt;/span&gt;) : &lt;span class=&quot;n&quot;&gt;concrete_st&lt;/span&gt; := &lt;span class=&quot;n&quot;&gt;lex_max&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;theorem&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;merge_comm&lt;/span&gt; (&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;concrete_st&lt;/span&gt;) : &lt;span class=&quot;n&quot;&gt;eq&lt;/span&gt; (&lt;span class=&quot;n&quot;&gt;merge&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;) (&lt;span class=&quot;n&quot;&gt;merge&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;) := &lt;span class=&quot;k&quot;&gt;by&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sal&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;theorem&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;merge_idem&lt;/span&gt; (&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;concrete_st&lt;/span&gt;) : &lt;span class=&quot;n&quot;&gt;eq&lt;/span&gt; (&lt;span class=&quot;n&quot;&gt;merge&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;) &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;            := &lt;span class=&quot;k&quot;&gt;by&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sal&lt;/span&gt;&lt;span class=&quot;cd&quot;&gt;
-- ... 22 more, all closed by `by sal`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Across the current Sal suite (28 RDTs, 17 CRDTs and 11 MRDTs, 648
verification conditions) the breakdown from the paper was roughly 69%
closed at stage 1, 28% via Z3, and 3% via AI-completed ITP. That is the
“push-button” claim, and for Tier A and B it holds up well.&lt;/p&gt;

&lt;p&gt;Two practical notes. First, &lt;a href=&quot;https://harmonic.fun&quot;&gt;Aristotle&lt;/a&gt;
has been the workhorse at stage 3: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LWW-Map&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Shopping-Cart&lt;/code&gt;,
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAX-Map&lt;/code&gt; each had VCs that neither &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grind&lt;/code&gt; nor Z3 closed, and
Aristotle produced kernel-checked intermediate lemmas that did. Second,
on the brittleness-of-tooling worry, the suite was bumped from Lean
4.26 to 4.28 between the paper draft and PaPoC. One Shopping-Cart
obligation drifted under the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grind&lt;/code&gt; and needed a tweak; everything
else carried over. That is a different experience from the F* /
z3-upgrade story above.&lt;/p&gt;

&lt;p&gt;Tier C is where things get more involved.&lt;/p&gt;

&lt;h2 id=&quot;the-peritext-story&quot;&gt;The Peritext story&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://www.inkandswitch.com/peritext/&quot;&gt;Peritext&lt;/a&gt; is a CRDT for
collaborative rich-text editing, by Geoffrey Litt, Sarah Lim, Martin
Kleppmann, and Peter van Hardenberg (CSCW 2022). The design has four
state components (characters, parent pointers, tombstones, formatting
marks). What makes the paper unusually pleasant to mechanise is the
care its authors put into specifying intent. §3 walks through eight
worked examples of intent preservation, each spelled out as a small
concrete scenario, and appendix §A.2 catalogues them as a single
table for reference.&lt;/p&gt;

&lt;p&gt;In one, Alice bolds the entire sentence “The fox jumped” while Bob
inserts the word “brown” in the middle, and the result should be
&lt;strong&gt;The brown fox jumped&lt;/strong&gt;. In another, working with the same sentence,
Alice bolds “The fox” while Bob bolds “fox jumped”, and the
overlapping word “fox” ends up bold under both. A third concerns link
spans: a link has a hard right edge, so a concurrent insert at the
end of the link should not expand it. And so on for the rest of the
eight. The paper argues informally that the design handles each
example correctly, and ships a TypeScript reference plus
property-based tests, but no machine-checked proofs.&lt;/p&gt;

&lt;p&gt;The 24 RA-linearizability VCs are trivial here. Peritext’s state is
four grow-only components and componentwise union commutes; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;by sal&lt;/code&gt;
closes them in seconds. That work lives in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Peritext_CRDT.lean&lt;/code&gt; (571
lines, mostly state plumbing), and at the level of RA-linearizability
the data type is verified.&lt;/p&gt;

&lt;p&gt;The interesting questions, however, are about the &lt;em&gt;read&lt;/em&gt;: the function
that takes the state and renders it as formatted text. That function
lives in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Peritext_ReadSide.lean&lt;/code&gt;, currently 1,316 lines. It answers
questions like: do the start- and end-side anchor bits matter? do
overlapping bolds compose? does tombstoning a character preserve the
formatting of everything else? do insertions at a span boundary fall
inside or outside the span under the paper’s expand-vs-contract rules?
None of these are anywhere in the 24 VCs.&lt;/p&gt;

&lt;p&gt;The eight worked examples in §3 turn out to be a much better
starting point than the VCs for actually mechanising the data type. Each
example is small enough to write down as a &lt;em&gt;concrete&lt;/em&gt; state and a
&lt;em&gt;concrete&lt;/em&gt; claim about its read. Nik Swamy and Shuvendu Lahiri have
&lt;a href=&quot;https://risemsr.github.io/blog/2026-04-16-spotting-specs/&quot;&gt;a recent
post&lt;/a&gt;
calling this kind of artifact a &lt;em&gt;Small Proof-Oriented Test&lt;/em&gt;, or SPOT:
“a small, concrete, verified test case, proving that the test always
succeeds.” By writing §3 the way they did, the Peritext authors had
effectively done the specification-engineering half of that job for
us; all that was left was to translate each example into Lean and
prove it against the implementation. So we did.&lt;/p&gt;

&lt;p&gt;Take Example 1 from the paper. Alice bolds the entire sentence
“The fox jumped” while Bob concurrently inserts the word “brown”
in the middle. Convergence is not the question: both replicas will
agree on a state once they merge. The question is what the rendered
text looks like. Peritext’s expand-on-the-bold-side rule says the
inserted text should fall inside Alice’s bold span, so the merged
result reads &lt;strong&gt;“The brown fox jumped”&lt;/strong&gt;, with “brown” formatted bold
along with everything else. In Sal we simplify Bob’s insert to a
single character ‘b’ (enough to exercise the rule, and the proof
stays tractable), and the SPOT translates almost directly:&lt;/p&gt;

&lt;div class=&quot;language-lean highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cd&quot;&gt;-- Alice (rid 0) types &quot;The fox jumped&quot; and bolds the whole thing.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ex1_pre&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;Scenario&lt;/span&gt; :=
  &lt;span class=&quot;n&quot;&gt;the_fox_jumped&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bold&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    [&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;,&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;,&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;,&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;,&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;,&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;,&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;,&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;,&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;,&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;,&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;,&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;,&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;,&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;]

&lt;span class=&quot;cd&quot;&gt;-- Bob (rid 1) concurrently inserts &apos;b&apos; between &quot;The &quot; and &quot;fox&quot;.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ex1_post&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;Scenario&lt;/span&gt; := &lt;span class=&quot;n&quot;&gt;ex1_pre&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insertCharAfter&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; (&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;, &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;cd&quot;&gt;

-- Alice&apos;s bold mark, opId (15, 0), spans the original sentence.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ex1_mark&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;MarkOp&lt;/span&gt; := &lt;span class=&quot;n&quot;&gt;Mark&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bold&lt;/span&gt; (&lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;, &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;) (&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;) (&lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;, &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;)

&lt;span class=&quot;cd&quot;&gt;-- The intent claim: Bob&apos;s &apos;b&apos; ends up inside Alice&apos;s bold span.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;example&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;in_span_visible&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ex1_post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ex1_mark&lt;/span&gt; (&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;, &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;) := &lt;span class=&quot;k&quot;&gt;by&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The other seven worked examples take the same shape: an English
description in the paper, a few lines of DSL builder to set up the
concrete scenario, and a one-line theorem statement that captures
the paper’s intent claim. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Peritext_SPOT.lean&lt;/code&gt; is 323 lines for all
eight. The proofs themselves are unremarkable; the work was in
setting up the DSL so the scenario reads like the paper.&lt;/p&gt;

&lt;p&gt;The read-side theorems in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Peritext_ReadSide.lean&lt;/code&gt; are universally
quantified versions of the same statements: instead of “Bob’s ‘b’ is
in Alice’s bold span at this concrete state,” the theorem
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;insert_within_span_in_span_visible&lt;/code&gt; says “for any state, any mark,
any character inserted strictly inside the span at a fresh opId, the
inserted character is in the span.” Each SPOT then closes via that
universal theorem applied to its concrete state. Generalisation of
the SPOT &lt;em&gt;is&lt;/em&gt; the read-side proof, which I find a useful way to
think about the relationship.&lt;/p&gt;

&lt;p&gt;We have since written SPOTs for all 28 RDTs in the suite, and the
generalised read-side theorems for the Tier-C ones. The Tier-A SPOTs
are mostly there as documentation that a reader can confirm the read
function does what the lattice arithmetic suggests it does.&lt;/p&gt;

&lt;p&gt;It is worth saying how an early draft of the Peritext read-side
went wrong, since the failure is a sharp version of the talk’s
title. I had Claude draft a predicate called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;in_span_boundary&lt;/code&gt;
from a careful reading of paper §3.3, with four cases (start of
span, end of span, after-of-start, after-of-end) and a boolean side
bit. The proofs went through. About 400 lines of theorems closed
across both the CRDT and the MRDT versions, and I was about to
commit. Re-reading §3.3 with the predicate in front of me, the
predicate turned out to be backward. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;after_of c endId →
endSide&lt;/code&gt; clause encoded the opposite of the link-contract case: it
included post-&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;endId&lt;/code&gt; inserts in the span where the paper says they
should be excluded. The proofs validated the proof, not the spec.
Tests pass, code is wrong. The bug was caught only when I wrote an
alternative predicate (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;in_span_visible&lt;/code&gt;) and the two disagreed on
Example 8.&lt;/p&gt;

&lt;p&gt;The fix was a four-rule inductive characterising the RGA visible
order (parent-child, sibling via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opid_max&lt;/code&gt;,
left-descendant-of-older-sibling, transitive) plus a separate
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bold_expand_reach&lt;/code&gt; predicate for the bold-expand semantics in
Example 7. About 800 lines of the buggy parallel track were
deleted in the process. Eight &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_visible&lt;/code&gt; theorems now map
one-to-one to the paper’s eight worked examples; there is a
&lt;a href=&quot;https://github.com/fplaunchpad/sal/blob/main/docs/peritext-vs-paper.md&quot;&gt;crosswalk&lt;/a&gt;
for anyone who wants the full table.&lt;/p&gt;

&lt;p&gt;The piece of methodology I would recommend to someone starting out:
the SPOTs catch this kind of failure if the SPOT itself is faithful
to the paper’s example. Had I started by formalising the worked
examples as SPOTs and only then generalised, the disagreement on
Example 8 would have shown up immediately rather than after 400
lines of proofs against the wrong predicate. John Regehr’s &lt;a href=&quot;https://john.regehr.org/writing/zero_dof_programming.html&quot;&gt;zero-degree-of-freedom
LLM coding&lt;/a&gt;
post argues a similar point in a different domain: pin the agent
with fast, deterministic, executable oracles, and the agent has
nowhere to drift. The Peritext SPOTs are an executable oracle for
the read-side spec.&lt;/p&gt;

&lt;h2 id=&quot;beyond-peritext&quot;&gt;Beyond Peritext&lt;/h2&gt;

&lt;p&gt;Peritext is one example of a broader pattern. PaPoC 2026 had several
other talks where the hard work was not the merge but in writing
down what the data type was supposed to &lt;em&gt;mean&lt;/em&gt; in the presence of
concurrent edits. Three I want to flag, because they suggest the
intent-formalisation problem has finally become the bottleneck
people are willing to talk about openly.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://doi.org/10.1145/3806077.3806695&quot;&gt;AegisSheet&lt;/a&gt; (Florian
Pfeil, David Scandurra, and Julian Haas, TU Darmstadt) studies
collaborative spreadsheets. Their starting move is honest empirical
work: they tabulate how Google Sheets and Notion behave under all
combinations of concurrent &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EditCell&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;InsertR/C&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RemoveR/C&lt;/code&gt; /
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MoveR/C&lt;/code&gt; and classify each outcome as &lt;em&gt;desirable&lt;/em&gt;, &lt;em&gt;suboptimal&lt;/em&gt;,
or &lt;em&gt;destructive&lt;/em&gt;. Most of the cells in those tables are red. They
then design a compositional spreadsheet CRDT that turns the red
cells green. The CRDT is the easy half; the table of intended
semantics is the hard half, and they did it.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://doi.org/10.1145/3806077.3806691&quot;&gt;ERA&lt;/a&gt; (Kegan Dougal,
Element Creations) addresses the &lt;em&gt;duelling admins&lt;/em&gt; problem in
group-management CRDTs in Matrix and Keyhive: two
equally-permissioned admins concurrently revoke each other’s
permissions. Whose revocation wins? Kleppmann’s PaPoC 2025
keynote suggested seniority ranking, but a Byzantine admin can
backdate events to roll back their own revocation. ERA proposes
&lt;em&gt;epoch events&lt;/em&gt;: an external arbiter batches concurrent events into
epochs and imposes a bounded total order, which gives finality
without sacrificing availability. Like the spreadsheet case, the
contribution is mostly about specifying what &lt;em&gt;correct&lt;/em&gt; looks like
under adversarial concurrency, with the data structure designed to
match.&lt;/p&gt;

&lt;p&gt;The closing lightning talk by Florian Jacob, Johanna Stuber, and
Hannes Hartenstein (KIT) sketches a path to formal verification of
local-first access control. Same shape: write the intent down
precisely, then prove an implementation matches.&lt;/p&gt;

&lt;p&gt;None of these are RDT-specific. Each is a different domain
(rich-text, spreadsheets, group membership, access control) where
the merges are easy and the intent is hard. SPOTs, oracles, and the multi-modal Lean stack are
all reactions to the same shift in where the difficulty lives.&lt;/p&gt;

&lt;h2 id=&quot;the-past-three-weeks&quot;&gt;The past three weeks&lt;/h2&gt;

&lt;p&gt;Since the Sal paper was finalised, the repo has had something like 200
commits, overwhelmingly mine, with Pranav having landed the
architectural heavy lifting earlier on. The headline change is in
coverage: 13 new CRDTs and 2 new MRDTs since the paper, taking the
suite from 13 RDTs to 28. Most of the additions are smaller scalar,
set, and map types (MAX-Register, MIN-Register, LWW-Register,
LWW-Map, MAX-Map, Grow-Only-Set, Grow-Only-Multiset,
LWW-Element-Set, Shopping-Cart, and a few more) that fill out
Tier-A and Tier-B coverage and serve as documentation that the
obvious read functions do the obvious thing. The three additions
that took real work, and that the rest of this section is about,
are the paper-only designs that finally got machine-checked Lean
ports.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Peritext&lt;/strong&gt; is the largest of the three: 1,316 lines of read-side, 571
of CRDT, 291 of a small DSL for the §3 worked examples, and 323 of
SPOTs. Eight intent-preservation theorems matching the paper’s worked
examples one-to-one, plus a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wf_afters&lt;/code&gt; acyclicity invariant and a
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bold_expand_reach&lt;/code&gt; predicate for Example 7. Roughly two days of
agent-paired work, mostly spent on the spec rather than on the proofs.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Add-Wins Priority Queue&lt;/strong&gt; of &lt;a href=&quot;https://doi.org/10.1145/3609437.3609452&quot;&gt;Zhang et al. (Internetware
2023)&lt;/a&gt; is a 391-line CRDT
plus a 325-line read-side. The translation is interesting
in its own right. The paper has a per-record &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;count&lt;/code&gt; field that ties
commutativity in knots; in Sal we flatten it into a separate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;I&lt;/code&gt;
component for increment records and use a snapshot-in-op-payload trick
(the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rmv&lt;/code&gt; op carries the observed-set as a parameter), which gives us
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rc := Either&lt;/code&gt; everywhere and lets the RA-linearizability VCs drop out
without any SMT.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Bounded Counter&lt;/strong&gt; of &lt;a href=&quot;https://doi.org/10.1109/SRDS.2015.32&quot;&gt;Balegas et al. (SRDS
2015)&lt;/a&gt;, in the &lt;a href=&quot;https://www.bartoszsypytkowski.com/state-based-crdts-bounded-counter/&quot;&gt;state-based
formulation&lt;/a&gt;
that Sypytkowski wrote up in 2019, is a 465-line CRDT structurally a
PN-Counter plus a transfer matrix. The 24 VCs are
trivial. The bound itself is &lt;em&gt;not&lt;/em&gt; part of the verified model: it is
enforced operationally at the client boundary (a replica refuses to emit
a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dec&lt;/code&gt; that would push its quota negative), and that part is currently
unverified. The headline number alone might suggest more than is there,
so worth calling out.&lt;/p&gt;

&lt;p&gt;A separate cleanup is worth noting. About 85 Blaster-admits across the
suite closed via a single pattern, &lt;em&gt;per-component decomposition&lt;/em&gt;:
instead of one monolithic SMT call on the full state, split the state
into components, prove each component independently, then combine. The
OR-Set MRDT alone went from 20 VCs trusting Z3 down to 3 (closing 17
in a single commit). The pattern was human-found; the agent applied it
consistently across files.&lt;/p&gt;

&lt;p&gt;The qualifier from the Peritext section applies to all three of these
ports as well: the RA-linearizability VCs are easy, and the work that
took time was the spec.&lt;/p&gt;

&lt;p&gt;For readers who want to play with the data types directly,
&lt;a href=&quot;https://fplaunchpad.org/sal&quot;&gt;fplaunchpad.org/sal&lt;/a&gt; hosts an
interactive playground for every RDT in the suite. The CRDT pages let
you drive two replicas in parallel and merge one into the other;
toggling “show concrete state” exposes the lattice that the
convergence proofs are about. The MRDT pages render the operation
history as a git-style commit DAG and let you do three-way merges
over the lowest common ancestor. None of this is load-bearing for
the verification story, but it is a more direct way to see what the
data types actually do than reading the proofs.&lt;/p&gt;

&lt;h2 id=&quot;closing&quot;&gt;Closing&lt;/h2&gt;

&lt;p&gt;Agents have made proof-engineering noticeably cheaper. Spec engineering
still sits with the human author, and SPOTs, executable oracles, and the
multi-modal Lean stack each approach that from a different direction.
None of them is sufficient on its own; in combination they look like a
workable methodology.&lt;/p&gt;

&lt;p&gt;The slides are &lt;a href=&quot;/slides/RDT_verification_papoc_2026.pdf&quot;&gt;here&lt;/a&gt;, the repo
is at &lt;a href=&quot;https://github.com/fplaunchpad/sal&quot;&gt;https://github.com/fplaunchpad/sal&lt;/a&gt;, and the question I closed
the talk with was: &lt;em&gt;what will you prove next?&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Foundations for hacking on OCaml</title>
   <link href="https://kcsrk.info/ocaml/2025/11/10/hacking/"/>
   <updated>2025-11-10T10:35:00+00:00</updated>
   <id>https://kcsrk.info/ocaml/2025/11/10/hacking</id>
   <content type="html">&lt;p&gt;How do you acquire the fundamental computer skills to hack on a complex
systems project like OCaml? What’s missing and how do you go about
bridging the gap?&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;There are many fundamental systems skills that go into working on a
language like OCaml that only come with soaking in systems programming. By
systems programming, I mean the ability to use tools like the command-line,
editors, version control, build systems, compilers, debuggers, bash scripting,
and so on.  This is often something that one takes for granted when working on
such projects, but is often inscrutable for new contributors, who may not have
had the opportunity to develop these skills.&lt;/p&gt;

&lt;p&gt;I struggle with this in my own research group. Students approach me to work on
the OCaml compiler because they have studied OS, Compilers and Computer
Architecture in class. But once they understand that working on OCaml involves
actually hacking on systems, they are often lost. How do you build the compiler
from source? How do you manage your changes? Do I have to build the entire
compiler if I make a small change in the runtime system? The compiler crashes
with a segfault – how do I debug it? Worse, the students do not even know what
questions to ask, and come back with “This is all new to me, I don’t know where
to begin. ChatGPT doesn’t help.”&lt;/p&gt;

&lt;p&gt;The CS education in India often lacks a focus on these practical systems skills,
which can make it challenging for new contributors to get involved in systems
programming.  Looking at my own past, my undergraduate CS education, like many
others in India (and potentially elsewhere), had mandatory OS and Compiler
Construction courses. But neither had a dedicated lab component. It is natural
that these theoretical courses do not prepare the students for the practical
aspects of systems programming.&lt;/p&gt;

&lt;p&gt;I was privileged to have a computer at my school, an IBM PC AT Model 5170 and
later an IBM PC 340, and surprisingly, had an education where I got to do
programming from a very young age. There was lots of BASIC programming but also
just tinkering with the system, learning how to use DOS, and later Windows 3.1,
95, and of course playing games (Doom and Prince of Persia, mostly). This early
exposure to computers and systems programming gave me a head start. Many
students, especially those from less privileged backgrounds, do not have this
early exposure. They may have learned some programming, but not had the time to
tinker with systems for extended periods of time.&lt;/p&gt;

&lt;p&gt;This challenge of bridging the gap between theoretical CS education and
practical systems programming skills is a common one faced by professors working
in the broad systems area. The problem is compounded by the fact that these
skills are difficult to teach in a traditional classroom setting—they require
hands-on experience, experimentation, and often many hours of frustration and
debugging. These are skills that come from doing, not from reading or watching
lectures. I would be curious to hear from others about their experiences and how
they have addressed this challenge.&lt;/p&gt;

&lt;p&gt;That said, there are resources available online that can help new contributors
acquire these skills. This list is biased to the areas of the compiler that I
work on. I mainly work on the backend and the runtime system. The only reason I
usually touch the frontend is to lower the features that I care about to the
backend. Here are some I have found useful for working on the OCaml compiler:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Systems programming
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://missing.csail.mit.edu/&quot;&gt;Course: MIT Missing Semester&lt;/a&gt;: This is a
fantastic resource that covers a wide range of topics related to systems
programming, including command-line tools, version control, editors, and
more. The course is available online for free and includes video lectures,
notes, and exercises. I encourage you to read the &lt;a href=&quot;https://missing.csail.mit.edu/motivation.html&quot;&gt;motivation for this
course&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://cs45.stanford.edu/&quot;&gt;Course: Stanford CS45&lt;/a&gt;: CS45 is an extended version
of the MIT course, and delves into the topics in more detail.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=PorfLSr3DDI&quot;&gt;Video: CppCon 2015: Greg Law “Give me 15 minutes &amp;amp; I’ll change your view of
GDB”&lt;/a&gt;: The talk explores GDB’s
less-known features and sheds light on some advanced debugging techniques.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://rr-project.org/&quot;&gt;Tool: rr - Lightweight Recording and Deterministic Debugging&lt;/a&gt;:
rr is a powerful tool for recording and replaying program execution, which
can be invaluable for debugging complex issues in systems programming. I’ve
stopped using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gdb&lt;/code&gt; directly for anything non-trivial and have switched to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rr&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;OCaml
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/fplaunchpad/cs3100_m20&quot;&gt;Course: CS3100 Paradigms of Programming&lt;/a&gt;:
The course covers a significant chunk of the OCaml language. You should be able
to self-study the course to get a good understanding of the language. That said,
the course deliberately does not cover the build system (dune), package manager
(opam), command-line tools for the compiler (ocamlc, ocamlopt), editor
integration (merlin, ocaml-lsp, ocamlformat), etc.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://realworldocaml.org/&quot;&gt;Book: Real World OCaml&lt;/a&gt;: The book has a section on the
compiler and the runtime system, which gives a great overview of the memory
representation, garbage collection, and other aspects of the runtime system.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Diving deeper
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://www.brendangregg.com/blog/2020-07-15/systems-performance-2nd-edition.html&quot;&gt;Book: Systems Performance: Enterprise and the Cloud, 2nd Edition&lt;/a&gt;:
This book provides an in-depth look at systems performance, covering topics
such as CPU architecture, memory hierarchy, storage systems, and networking.
It is a valuable resource for understanding the underlying principles of
systems programming and performance optimization.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://gchandbook.org/&quot;&gt;Book: The Garbage Collection Handbook&lt;/a&gt;: This book
offers a comprehensive overview of garbage collection techniques, algorithms,
and implementations. It is an essential resource for understanding memory
management in programming languages like OCaml.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://www.elsevier.com/books/the-art-of-multiprocessor-programming/herlihy/978-0-12-397337-5&quot;&gt;Book: The Art of Multiprocessor Programming&lt;/a&gt;:
This book provides a deep dive into concurrent programming and
synchronization techniques, which are crucial for understanding
multi-threaded runtime systems like OCaml 5’s multicore runtime and the
programming model.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;I will probably keep editing this post as I find more resources. If you have
suggestions for other useful resources or experiences to share, please feel free
to reach out to me.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Testing x-ocaml, OCaml notebooks as a WebComponent</title>
   <link href="https://kcsrk.info/ocaml/x-ocaml/blogging/2025/06/20/xocaml/"/>
   <updated>2025-06-20T10:00:00+00:00</updated>
   <id>https://kcsrk.info/ocaml/x-ocaml/blogging/2025/06/20/xocaml</id>
   <content type="html">&lt;script async=&quot;&quot; src=&quot;https://kcsrk.info/assets/x-ocaml.js&quot; src-worker=&quot;https://kcsrk.info/assets/x-ocaml.worker+effects.js&quot; src-load=&quot;https://kcsrk.info/assets/digestif.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Can we have OCaml notebooks as pure client-side code? Can these notebooks have
rich editor support (highlighting, formatting, types on hover, autocompletion,
inline diagnostics, etc.)? Can you take packages from OPAM and use them in these
notebooks?&lt;/p&gt;

&lt;p&gt;The answer to all of these turns out to be a resounding yes thanks for
&lt;a href=&quot;https://github.com/art-w/x-ocaml&quot;&gt;x-ocaml&lt;/a&gt;. This post is my experiment playing
with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x-ocaml&lt;/code&gt; and integrating that into this blog.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;The most wonderful thing about programming is that it lets you experiment
freely. You can try out an idea, get instant feedback, and learn by doing—much
like playing with Lego bricks or sketching on a canvas. The two main courses
that I teach at IITM, &lt;a href=&quot;https://github.com/fplaunchpad/cs3100_m20&quot;&gt;CS3100&lt;/a&gt; and
&lt;a href=&quot;https://github.com/fplaunchpad/cs6225_s25_iitm/&quot;&gt;CS6225&lt;/a&gt;, both involve me
live-coding during every lecture. However, blogging about OCaml where the code
is static and non-interactive always felt a bit unsatisfying.&lt;/p&gt;

&lt;p&gt;Enter &lt;a href=&quot;https://github.com/art-w/x-ocaml&quot;&gt;x-ocaml&lt;/a&gt;, which allows for a way to
embed OCaml notebooks into any webpage thanks to WebComponents. All you need to
do is to load some JavaScript in your webpage and you can start embedding code
cells using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;x-ocaml&amp;gt;&lt;/code&gt; tag. The snippet below:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;x-ocaml&amp;gt;
print_endline &quot;Hello, world&quot;
&amp;lt;/x-ocaml&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;renders to:&lt;/p&gt;

&lt;x-ocaml&gt;
print_endline &quot;Hello, world&quot;
&lt;/x-ocaml&gt;

&lt;p&gt;The code is interpreted in the browser thanks to the OCaml interpreter compiled
to JavaScript through the
&lt;a href=&quot;https://ocsigen.org/js_of_ocaml/latest/manual/overview&quot;&gt;Js_of_ocaml&lt;/a&gt; compiler.
There is also support for &lt;a href=&quot;https://github.com/ocaml/merlin&quot;&gt;Merlin&lt;/a&gt; and
&lt;a href=&quot;https://github.com/ocaml-ppx/ocamlformat&quot;&gt;OCamlformat&lt;/a&gt; in the code editor. Try
hovering over the functions and writing some code. You should see inferred types
and auto-completion suggestions. It turns out that this solution integrates well
with Jekyll, which is what I use for this blog.&lt;/p&gt;

&lt;h2 id=&quot;reverse-mode-ad-using-effects&quot;&gt;Reverse-mode AD using Effects&lt;/h2&gt;

&lt;p&gt;Js_of_ocaml also supports &lt;a href=&quot;https://ocsigen.org/js_of_ocaml/latest/manual/effects&quot;&gt;effect
handlers&lt;/a&gt;. Here’s the
implementation of &lt;a href=&quot;https://github.com/ocaml-multicore/effects-examples/blob/master/algorithmic_differentiation.ml&quot;&gt;reverse-mode algorithmic
differentiation&lt;/a&gt;,
implemented using effect handlers running in the browser.&lt;/p&gt;

&lt;x-ocaml&gt;
open Effect
open Effect.Deep

module F : sig
  type t

  val mk : float -&amp;gt; t
  val ( +. ) : t -&amp;gt; t -&amp;gt; t
  val ( *. ) : t -&amp;gt; t -&amp;gt; t
  val grad : (t -&amp;gt; t) -&amp;gt; float -&amp;gt; float
  val grad2 : (t * t -&amp;gt; t) -&amp;gt; float * float -&amp;gt; float * float
end = struct
  type t = { v : float; mutable d : float }

  let mk v = { v; d = 0.0 }

  type _ eff += Add : t * t -&amp;gt; t eff
  type _ eff += Mult : t * t -&amp;gt; t eff

  let run f =
    ignore (match f () with
      | r -&amp;gt; r.d &amp;lt;- 1.0; r;
      | effect (Add(a,b)), k -&amp;gt;
          let x = {v = a.v +. b.v; d = 0.0} in
          ignore (continue k x);
          a.d &amp;lt;- a.d +. x.d;
          b.d &amp;lt;- b.d +. x.d;
          x
      | effect (Mult(a,b)), k -&amp;gt;
          let x = {v = a.v *. b.v; d = 0.0} in
          ignore (continue k x);
          a.d &amp;lt;- a.d +. (b.v *. x.d);
          b.d &amp;lt;- b.d +. (a.v *. x.d);
          x)

  let grad f x =
    let x = mk x in
    run (fun () -&amp;gt; f x);
    x.d

  let grad2 f (x, y) =
    let x, y = (mk x, mk y) in
    run (fun () -&amp;gt; f (x, y));
    (x.d, y.d)

  let ( +. ) a b = perform (Add (a, b))
  let ( *. ) a b = perform (Mult (a, b))
end
&lt;/x-ocaml&gt;

&lt;p&gt;Here are some tests.&lt;/p&gt;

&lt;x-ocaml&gt;

(* XXX KC: `assert` from standard library doesn&apos;t work. Why? *)
let assert&apos; c = 
  if not c then raise (Failure &quot;assertion failed!&quot;)

let test1 =
  (* f = x + x^3 =&amp;gt;
     df/dx = 1 + 3 * x^2 *)
  for x = 0 to 10 do
    let x = float_of_int x in
    let d1 = F.(grad (fun x -&amp;gt; x +. (x *. x *. x)) x) in
    let d2 = 1.0 +. (3.0 *. x *. x) in
    Printf.printf &quot;%f %f\n&quot; d1 d2;
    assert&apos; ( d1 = d2 )
  done

let test2 = 
  (* f = x^2 + x^3 =&amp;gt;
     df/dx = 2*x + 3 * x^2 *)
  for x = 0 to 10 do
    let x = float_of_int x in
    assert&apos; (
      F.(grad (fun x -&amp;gt; (x *. x) +. (x *. x *. x)) x)
      = (2.0 *. x) +. (3.0 *. x *. x))
  done

let test3 =
  (* f = x^2 * y^4 =&amp;gt;
     df/dx = 2 * x * y^4
     df/dy = 4 * x^2 * y^3 *)
  for x = 0 to 10 do
    for y = 0 to 10 do
      let x = float_of_int x in
      let y = float_of_int y in
      assert&apos; (
        F.(grad2 (fun (x, y) -&amp;gt; x *. x *. y *. y *. y *. y) (x, y))
        = (2.0 *. x *. y *. y *. y *. y, 4.0 *. x *. x *. y *. y *. y))
    done
  done
&lt;/x-ocaml&gt;

&lt;h2 id=&quot;using-other-libraries&quot;&gt;Using other libraries&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x-ocaml&lt;/code&gt; also supports loading any js_of_ocaml compatible library into the
webpage. Let’s use &lt;a href=&quot;https://github.com/mirage/digestif&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;digestif&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For any library that you want to export, install the library using opam.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x-ocaml&lt;/code&gt; provide a command-line utility to export the library.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;x-ocaml &lt;span class=&quot;nt&quot;&gt;--effects&lt;/span&gt; digestif.ocaml &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; digestif.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This produces the JavaScript artifact that can be used in the webpage. It may be
instructive to look at the
&lt;a href=&quot;https://github.com/kayceesrk/kayceesrk.github.io/blame/54ef5eea28c660aa0d8b3cd2e32d8e93d713ab19/_posts/2025-06-20-xocaml.md&quot;&gt;source&lt;/a&gt;
of this post to see how the compiler and the libraries are integrated into this
blog post. There is a little script at the top of the file:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;script&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;{{ &apos;/assets/x-ocaml.js&apos; | absolute_url }}&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;worker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;{{ &apos;/assets/x-ocaml.worker+effects.js&apos; | absolute_url }}&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;{{ &apos;/assets/digestif.js&apos; | absolute_url }}&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/script&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;x-ocaml&gt;
let hash = Digestif.MD5.(digest_string &quot;hello&quot; |&amp;gt; to_hex)
&lt;/x-ocaml&gt;

&lt;h2 id=&quot;what-next&quot;&gt;What next?&lt;/h2&gt;

&lt;p&gt;There is a number of rough edges to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x-ocaml&lt;/code&gt;. This is expected since this
project appears to be one of &lt;a href=&quot;https://github.com/art-w&quot;&gt;Arthur’s&lt;/a&gt; hacking
expeditions (which, as usual, is pushing the state of the art forward).&lt;/p&gt;

&lt;p&gt;It would be fun to use this for teaching
&lt;a href=&quot;https://github.com/fplaunchpad/cs3100_m20&quot;&gt;CS3100&lt;/a&gt; and also
&lt;a href=&quot;https://github.com/fplaunchpad/learn-ocaml-workshop-2024&quot;&gt;other&lt;/a&gt;
&lt;a href=&quot;https://github.com/ocaml-multicore/ocaml-effects-tutorial&quot;&gt;OCaml&lt;/a&gt;
&lt;a href=&quot;https://github.com/ocaml-multicore/parallel-programming-in-multicore-ocaml&quot;&gt;tutorials&lt;/a&gt;.
Perhaps even have an interactive version of &lt;a href=&quot;https://dev.realworldocaml.org/&quot;&gt;Real World OCaml
book&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Not all OCaml libraries can be compiled to JavaScript. The common reason being
that they may depend on features not available on JavaScript. In writing this
post, I unsuccessfully tried for a long time to get
&lt;a href=&quot;https://github.com/mirage/mirage-crypto/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mirage-cypto&lt;/code&gt;&lt;/a&gt; working.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mirage-crypto&lt;/code&gt; has a &lt;a href=&quot;https://github.com/mirage/mirage-crypto/tree/main/src/native&quot;&gt;large C
dependency&lt;/a&gt;, which
does not work with Js_of_ocaml. Js_of_ocaml promises to take any opam library
installed on your opam switch and compiles that to JavaScript. However, at that
point, we’re really cross compiling the opam packages installed on your switch to
JavaScript since the installed package may make some assumptions about the
platform that it is supposed to run on. Hence, JavaScript compilation of
arbitrary OCaml packages is unlikely to work in the general case. Unfortunately,
the error was difficult to debug since the failure was at runtime, and was not
apparent in the error messages (at least for me, who has little JavaScript
experience). It would be nice to have the opam packages explicitly say whether
they are JavaScript compatible, and have build tooling that reports errors like
these early.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Linearity and uniqueness</title>
   <link href="https://kcsrk.info/ocaml/modes/oxcaml/2025/06/04/linearity_and_uniqueness/"/>
   <updated>2025-06-04T10:00:00+00:00</updated>
   <id>https://kcsrk.info/ocaml/modes/oxcaml/2025/06/04/linearity_and_uniqueness</id>
   <content type="html">&lt;p&gt;In the &lt;a href=&quot;/ocaml/modes/oxcaml/2025/05/29/uniqueness_and_behavioural_types/&quot;&gt;last post&lt;/a&gt;,
we looked at &lt;em&gt;uniqueness&lt;/em&gt; mode and how uniqueness may be used to optimise. As we
will see, uniqueness alone is insufficient in practice, and we also need a
concept of &lt;em&gt;linearity&lt;/em&gt; for uniqueness to be useful.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;capturing-unique-values&quot;&gt;Capturing unique values&lt;/h2&gt;

&lt;p&gt;Let’s start with an example. Recall the signature of the unique reference
module.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Unique_ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Modes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Aliased&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Assume that we also have an implementation of the module:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Unique_ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Unique_ref&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Consider the following example, which works fine:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;works&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* Allocate a unique reference *)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* free it *)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now consider this modified example:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wat&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* Allocate a unique reference *)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* capture free in a closure *)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* free it *)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* free it again??? *)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Observe that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; has captured &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;t&lt;/code&gt; in the closure, and when called frees &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;t&lt;/code&gt;. It
should be clear that calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; &lt;em&gt;more than once&lt;/em&gt; is bad – leads to a
double-free issue! What property do we want of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt;? Uniqueness is insufficient;
we have a unique reference to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; in this program, with which we call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; twice.&lt;/p&gt;

&lt;p&gt;What we want to enforce is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; can be called &lt;em&gt;at most once&lt;/em&gt;. The compiler
has a &lt;em&gt;linearity&lt;/em&gt; mode which captures the idea of how many times a value can be
used. We have two modes in the linearity axis – &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;once&lt;/code&gt;, which stands for
“at most once” and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;many&lt;/code&gt; (the default one for all values), which allows values
to be used arbitrary number of times.&lt;/p&gt;

&lt;p&gt;Whenever a unique value is captured by a closure, the closure gets a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;once&lt;/code&gt;
mode, which allows the closure to be called at most once. This program rightly
gets rejected by the compiler.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;./unique_ref.ml&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;characters&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* free it again??? *)&lt;/span&gt;
       &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;This&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;used&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;here&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;but&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defined&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;once&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;already&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;been&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;used&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;./unique_ref.ml&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;31&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;characters&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;31&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* free it *)&lt;/span&gt;
       &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;a-linear-ref&quot;&gt;A linear ref&lt;/h2&gt;

&lt;p&gt;Now, one might wonder whether the unique reference that we’ve implemented may be
implemented with the linear mode. The answer is yes.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Linear_ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;once&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;once&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;once&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;once&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;once&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;once&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Linear_ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Linear_ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mutable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This works as expected:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Linear_ref&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;works&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;print_int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fails&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* fails here *)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;with the error message:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;./linear_ref.ml&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;34&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;characters&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;34&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* fails here *)&lt;/span&gt;
           &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;This&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;used&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;here&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;but&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defined&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;once&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;already&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;been&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;used&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;./linear_ref.ml&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;33&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;characters&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;33&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;why-both-linearity-and-uniqueness&quot;&gt;Why both linearity and uniqueness?&lt;/h2&gt;

&lt;p&gt;Given this example, you might be wondering, if the &lt;em&gt;safe&lt;/em&gt; reference may be
implemented equivalently using both uniqueness and linearity, why do we need
both? Obviously, there’s something interesting going on where unique values
captured in a closure needs linearity. Does that mean linearity is sufficient?&lt;/p&gt;

&lt;p&gt;It turns out that only recently was the relationship between the two formally
studied in the same type system. While linear types and uniqueness types have a
long history of being studied independently, Marshall et al. in their paper,
&lt;a href=&quot;https://starsandspira.ls/docs/esop22-draft.pdf&quot;&gt;“Linearity and Uniqueness: An Entente
Cordiale”&lt;/a&gt;, present the ideas in
the same type system. They provide some key insights.&lt;/p&gt;

&lt;p&gt;The first insight is that&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;in a setting where all values must be linear, we can also guarantee that every value is unique, and vice versa! Intuitively, if it is never possible to duplicate a value, then it will never be possible for said value to have multiple references.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Unique_ref&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Linear_ref&lt;/code&gt; every operation that operates on the ref
requires uniqueness or linearity, respectively. Hence, they seem almost
equivalent in expressive power.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;It is when we also have the ability for unrestricted use (non-linear/non-unique) that differences between linearity and uniqueness begin to arise, as we will soon see.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In our language, we do have the ability for unrestricted use. That is, in the
linearity axis, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;many&lt;/code&gt; is the default mode attributed to all the values not
tagged or inferred as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;once&lt;/code&gt;. Similarly, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aliased&lt;/code&gt; is the default mode
attributed to all the values not tagged or inferred as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unique&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The type system has &lt;em&gt;submoding&lt;/em&gt;: values may move freely to &lt;em&gt;greater&lt;/em&gt; modes
(which typically restrict what can be done with those values) but not to
&lt;em&gt;lesser&lt;/em&gt; modes. For example, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;many&lt;/code&gt; value may be safely use in a context where
a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;once&lt;/code&gt; value is expected.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;works&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set_to_20&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;once&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;many&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;set_to_20&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* [r @ many] is passed to a function that expects [int ref @ once] *)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Similarly, you can use a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unique&lt;/code&gt; value in a context where an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aliased&lt;/code&gt; value is
expected.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dup&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;works&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Unique_ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dup&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The type of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;works&lt;/code&gt; function is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;val works : unit -&amp;gt; int Unique_ref.t * int
Unique_ref.t&lt;/code&gt;, which crucially lacks the fact that the references are at unique
mode. We can’t call any functions from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Unique_ref&lt;/code&gt; module with these
references, all of which expect a reference with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unique&lt;/code&gt; mode.&lt;/p&gt;

&lt;h2 id=&quot;uniqueness-is-more-appropriate-for-safe-refs&quot;&gt;Uniqueness is more appropriate for safe refs&lt;/h2&gt;

&lt;p&gt;In our running example of implementing a safe ref, it turns out that uniqueness
is more appropriate. Consider the type signature of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;free&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Unique_ref&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The type signature says that there are no other aliases to this reference.
Hence, its memory may be safely deallocated. However, consider the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Linear_ref.free&lt;/code&gt; signature:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;once&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The signature says that this reference must be used at most once. In particular,
just by looking at the signature, we cannot conclude that there are no other
aliases to this reference. But we know that the API is safe since the only way
to create a safe reference is through the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alloc&lt;/code&gt; function, which returns a
once-usable reference, and every other operation also expects and returns a
once-usable reference.&lt;/p&gt;

&lt;p&gt;The correctness of the linear version depends on reasoning over the &lt;em&gt;whole
API&lt;/em&gt;, whereas the unique version can be concluded to be safe just by
looking at the signature of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;free&lt;/code&gt; function. This modular reasoning makes
uniqueness more appropriate for our safe reference API.&lt;/p&gt;

&lt;h2 id=&quot;past-and-the-future&quot;&gt;Past and the future&lt;/h2&gt;

&lt;p&gt;In a sense, uniqueness and linearity are duals of each other. Uniqueness talks
about the &lt;em&gt;past&lt;/em&gt; – whether a value may be aliased in the past. It is okay to
alias a unique value in the future and lose the uniqueness mode. Linearity talks
about the &lt;em&gt;future&lt;/em&gt; – whether a value may be used more than once in the future.
You can take any value and ascribe a linear mode to it, restricting its use in
the future. However, there may be other aliases to this value in the past.&lt;/p&gt;

&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h2&gt;

&lt;p&gt;The code examples are available
&lt;a href=&quot;https://github.com/kayceesrk/code-snippets/tree/master/oxcaml/linearity_june_2025&quot;&gt;here&lt;/a&gt;.
Section 2.1 of &lt;a href=&quot;https://starsandspira.ls/docs/esop22-draft.pdf&quot;&gt;Marshall et al.’s
paper&lt;/a&gt; is quite readable and
explains the distinction between linearity and uniqueness with some historical
context. I highly recommend it.&lt;/p&gt;

&lt;h2 id=&quot;acknowledgements&quot;&gt;Acknowledgements&lt;/h2&gt;

&lt;p&gt;Thanks to &lt;a href=&quot;https://richarde.dev/&quot;&gt;Richard Eisenberg&lt;/a&gt; for the discussions which
spurred this post.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Uniqueness for Behavioural Types</title>
   <link href="https://kcsrk.info/ocaml/modes/oxcaml/2025/05/29/uniqueness_and_behavioural_types/"/>
   <updated>2025-05-29T17:56:00+00:00</updated>
   <id>https://kcsrk.info/ocaml/modes/oxcaml/2025/05/29/uniqueness_and_behavioural_types</id>
   <content type="html">&lt;p&gt;Jane Street has been developing modal types for OCaml – an extension to the
type system where modes track properties of values, such as their scope, thread
sharing, and aliasing. These modes restrict which operations are permitted on
values, enabling safer and more efficient systems programming. In this post, I
focus on the uniqueness mode, which tracks aliasing, and show how it can
eliminate certain runtime checks.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;My intention in this post is not to explain how the different modes work. There
are a number of blog posts and academic papers written about modes. I recommend
the interested reader to have look at them. The following table summarizes the
main properties tracked by modes, the corresponding mode names, and resources
for further reading:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Property&lt;/th&gt;
      &lt;th&gt;Modes&lt;/th&gt;
      &lt;th&gt;Resources&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Scope&lt;/td&gt;
      &lt;td&gt;Locality&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;https://blog.janestreet.com/oxidizing-ocaml-locality/&quot;&gt;Blog&lt;/a&gt;, &lt;a href=&quot;https://dl.acm.org/doi/10.1145/3674642&quot;&gt;Paper&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Sharing between threads&lt;/td&gt;
      &lt;td&gt;Portability, Contention&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;https://blog.janestreet.com/oxidizing-ocaml-parallelism/&quot;&gt;Blog&lt;/a&gt;, &lt;a href=&quot;https://dl.acm.org/doi/10.1145/3704859&quot;&gt;Paper&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Aliasing&lt;/td&gt;
      &lt;td&gt;Uniqueness, Linearity&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;https://blog.janestreet.com/oxidizing-ocaml-ownership/&quot;&gt;Blog&lt;/a&gt;, &lt;a href=&quot;https://dl.acm.org/doi/10.1145/3674642&quot;&gt;Paper&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The OCaml compiler extended with modes is &lt;a href=&quot;https://github.com/ocaml-flambda/flambda-backend&quot;&gt;developed in the
open&lt;/a&gt;, and is used in
production at Jane Street. The repo also has some
&lt;a href=&quot;https://github.com/ocaml-flambda/flambda-backend/tree/main/jane/doc&quot;&gt;documentation&lt;/a&gt;
of the extensions.&lt;/p&gt;

&lt;p&gt;Be warned that the compiler and the language features are fast evolving. The
code examples presented in the blog and the paper referenced above are likely
not to work. I expect the same for the code examples in this post in the near
future, but that’s what one should expect with these bleeding-edge features.&lt;/p&gt;

&lt;h2 id=&quot;behavioural-types-and-runtime-overhead&quot;&gt;Behavioural types and runtime overhead&lt;/h2&gt;

&lt;p&gt;A couple of years ago, I wrote a post on &lt;a href=&quot;https://kcsrk.info/ocaml/types/2016/06/30/behavioural-types/&quot;&gt;behavioural
types&lt;/a&gt; where the
types capture the sequence of operations that may be performed on the values
with those types. The correctness of the system depended on the linear use of
the resources. Since OCaml does not provide support for enforcing linearity
statically, the implementation uses a dynamic check, using a fresh ref cell that
gets &lt;em&gt;consumed&lt;/em&gt; every time the type state changes. If we are guaranteed that the
resource is not aliased statically, then there’s no need for the dynamic check.
This is where &lt;em&gt;uniqueness&lt;/em&gt; helps.&lt;/p&gt;

&lt;p&gt;Uniqueness mode allows the OCaml compiler to statically guarantee that certain
values are not aliased. This enables optimizations and eliminates the need for
some runtime checks, which is particularly valuable in systems programming for
ensuring memory safety and efficient resource management.&lt;/p&gt;

&lt;h2 id=&quot;setting-up-ocaml-with-modes&quot;&gt;Setting up OCaml with modes&lt;/h2&gt;

&lt;p&gt;An opam repository with the modes extensions and packages supporting modes is
available
&lt;a href=&quot;https://github.com/janestreet/opam-repository/tree/with-extensions&quot;&gt;here&lt;/a&gt;.
Here’s how you can set up the new compiler:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# this will take time&lt;/span&gt;
opam switch create 5.2.0+flambda2 &lt;span class=&quot;nt&quot;&gt;--repos&lt;/span&gt; with-extensions&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;git+https://github.com/janestreet/opam-repository.git#with-extensions,default
&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;opam &lt;span class=&quot;nb&quot;&gt;env&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--switch&lt;/span&gt; 5.2.0+flambda2&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;an-explicitly-memory-managed-reference&quot;&gt;An explicitly memory-managed reference&lt;/h2&gt;

&lt;p&gt;Suppose you want to implement a mutable reference whose memory is explicitly
managed (not managed by the GC), you may go for the following interface:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* unsafe *)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This interface provides an explicit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;free&lt;/code&gt;, which releases the memory associated
with this reference. This opens up the possibility of memory safety bugs such as
use-after-free and double-free. We can use uniqueness modality to get a &lt;em&gt;safe&lt;/em&gt;
API. Here’s the interface:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Modes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Aliased&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unique&lt;/code&gt; annotation states that the value is not aliased. The operations on
the reference expect that this reference is not aliased. Observe that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set&lt;/code&gt; take in the unique reference and also return them unlike the original
interface. You can use this like so:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;okay&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;okay&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The key bit is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;free&lt;/code&gt; &lt;em&gt;consumes&lt;/em&gt; the unique reference; you can
no longer produce a unique handle to the same reference and hence, you cannot
call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;free&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set&lt;/code&gt; on this reference which has been freed.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wont_work&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;This&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;used&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;here&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;but&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;already&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;been&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;used&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;characters&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;modesaliasedt&quot;&gt;Modes.Aliased.t&lt;/h3&gt;

&lt;p&gt;Uniqueness applies deeply. If a value is marked as unique, then the transitive
closure of the reachable parts of the object is also expected to be unique. The
return value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get&lt;/code&gt; is a pair, which is marked as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unique&lt;/code&gt;&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. Hence, both
the components of the pair are expected to be unique. However, we don’t want to
impose uniqueness of the value stored in the reference. The language allows
parts of the value to be marked as aliased. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Modes.Aliased.t&lt;/code&gt; is defined as:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Aliased&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aliased&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aliased&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unboxed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The language allows record fields to be annotated as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aliased&lt;/code&gt;, while the record
itself may be uniquely referenced.&lt;/p&gt;

&lt;h3 id=&quot;implementation&quot;&gt;Implementation&lt;/h3&gt;

&lt;p&gt;Here’s an implementation of that satisfies the signature.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mutable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alloc&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Modes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Aliased&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;aliased&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There’s nothing surprising about this implementation. Note that the compiler is
doing a lot of work behind the scenes to ensure that the functions do in fact
satisfy the uniqueness requirements. For example, if you change the
implementation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set&lt;/code&gt; to do something &lt;em&gt;innocuous&lt;/em&gt; where the compiler cannot
prove that the value is not aliased, the program no longer compiles:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* compiler cannot prove [t&apos;] is not aliased *)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&apos;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;snip&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Values&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;included&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
 &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;The&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compatible&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;
 &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;refs-that-explain-their-work&quot;&gt;Refs that explain their work&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://kcsrk.info/ocaml/types/2016/06/30/behavioural-types/#refs-that-explain-their-work&quot;&gt;earlier blog
post&lt;/a&gt;
used polymorphic variants to encode the &lt;em&gt;protocol&lt;/em&gt; of operations that are
permitted on a ref cell. The implementation is reproduced below:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constraint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;mutable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* For linearity *)&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;constraint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LinearityViolation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;false&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fresh&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fresh&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;branch&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fresh&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Observe that we use a dynamic check to enforce linearity. It requires a &lt;em&gt;fresh&lt;/em&gt;
ref cell for each operation performed on this reference. With uniqueness, we can
enforce this statically, avoiding the dynamic check and the fresh ref cell
requirement.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constraint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;(* &apos;b is the behavioural type variable *)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Modes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Aliased&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;branch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt;
               &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
               &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mutable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constraint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Modes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Aliased&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;aliased&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;magic_at_unique&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;Obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;magic_at_unique&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;branch&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;magic_at_unique&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The only changes necessary in the signature were a number of uniqueness and
aliasing annotations. Notice that the implementation no longer needs the
dynamic check! &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Obj.magic_at_unique&lt;/code&gt; has the type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;a @ unique -&amp;gt; &apos;b @ unique&lt;/code&gt;,
and is the version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Obj.magic&lt;/code&gt; with uniqueness annotation. We use it to
&lt;em&gt;advance&lt;/em&gt; the protocol type state.&lt;/p&gt;

&lt;h2 id=&quot;where-next&quot;&gt;Where next&lt;/h2&gt;

&lt;p&gt;The rest of the examples in the &lt;a href=&quot;https://kcsrk.info/ocaml/types/2016/06/30/behavioural-types/&quot;&gt;original
post&lt;/a&gt; should also
benefit from uniqueness annotations to remove the runtime overheads.&lt;/p&gt;

&lt;p&gt;The complete code examples are available
&lt;a href=&quot;https://github.com/kayceesrk/code-snippets/tree/master/oxcaml/uniqueness_may_2025&quot;&gt;here&lt;/a&gt;.
You can also play with the code examples &lt;a href=&quot;https://tinyurl.com/y7ku8r5h&quot;&gt;directly in the
browser&lt;/a&gt; thanks to &lt;a href=&quot;https://patrick.sirref.org/index/index.xml&quot;&gt;Patrick
Ferris’&lt;/a&gt; OCaml with extensions
&lt;a href=&quot;https://patrick.sirref.org/try-oxcaml/index.xml&quot;&gt;js_of_ocaml top-level&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since the modes features are constantly evolving, there are no stability
guarantees yet. However, I’m excited about the possibility of modes improving
how we do safe systems programming in OCaml.&lt;/p&gt;

&lt;h2 id=&quot;addendum&quot;&gt;Addendum&lt;/h2&gt;

&lt;p&gt;Looks like there’s a &lt;a href=&quot;https://kcsrk.info/ocaml/modes/oxcaml/2025/06/04/linearity_and_uniqueness/&quot;&gt;part 2&lt;/a&gt; of this post.&lt;/p&gt;

&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h2&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Unclear whether it is possible to return a pair where one of the
components is unique, but the other one is not. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Joining my group</title>
   <link href="https://kcsrk.info/ocaml/iitm/community/2025/04/28/working-with-me/"/>
   <updated>2025-04-28T12:10:00+00:00</updated>
   <id>https://kcsrk.info/ocaml/iitm/community/2025/04/28/working-with-me</id>
   <content type="html">&lt;p&gt;Recently, I posted on &lt;a href=&quot;https://x.com/kc_srk/status/1912008952340164804&quot;&gt;X&lt;/a&gt; and
&lt;a href=&quot;https://www.linkedin.com/posts/kc-sivaramakrishnan-25061a14_kc-sivaramakrishnan-activity-7317777561936183296-8hH-/&quot;&gt;LinkedIn&lt;/a&gt;
that I am always looking for excellent people to join my group. I received a lot
of enquiries, some of which led to internship hires (yay!). But mostly, I seemed
to offer similar advice. I thought I’d write a post that summarise my responses.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;At IIT Madras, my &lt;a href=&quot;https://github.com/prismlab&quot;&gt;research group&lt;/a&gt; develops
programming language abstractions to solve systems problems. The group is
composed of research associates (fixed-term project staff), PhD, MS and MTech
students, undergraduate research students (who are typically BTech students from
IIT Madars) and interns. I made the following post a few weeks ago, for which I
received a lots of enquiries, and I have been busy writing similar responses to
many of them, which I summarise below.&lt;/p&gt;

&lt;center&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;PSA: I&amp;#39;m always looking for excellent folks to join my research group at IIT Madras to work on building &amp;quot;functional&amp;quot; systems. This includes internships, MS and PhD studentships, research staff positions, and post-baccalaureate fellowships. &lt;br /&gt;&lt;br /&gt;Reach out to me if you are keen!&lt;/p&gt;&amp;mdash; KC Sivaramakrishnan (@kc_srk) &lt;a href=&quot;https://twitter.com/kc_srk/status/1912008952340164804?ref_src=twsrc%5Etfw&quot;&gt;April 15, 2025&lt;/a&gt;&lt;/blockquote&gt; &lt;script async=&quot;&quot; src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
&lt;/center&gt;

&lt;h2 id=&quot;internship-positions&quot;&gt;Internship positions&lt;/h2&gt;

&lt;p&gt;Internship enquiries are the most frequent ones that I receive. Here’s how you
can make it work.  Please do go through my &lt;a href=&quot;https://kcsrk.info&quot;&gt;web page&lt;/a&gt; to
look at what areas I work on. Write to me about what interests you and what your
goals are.&lt;/p&gt;

&lt;p&gt;My group works on systems. To make the internship work well, we require that you
have demonstrable systems building experience. Do build projects that go beyond
your coursework.  Make sure that the projects are developed publicly on GitHub
or other similar platforms so that one can take a look at what you’ve
built. Even better is contributions to other open-source projects.&lt;/p&gt;

&lt;p&gt;The group solves systems problems with functional programming. If you have prior
experience with functional programming, such as building small projects with
OCaml, Haskell, Scala, Scheme or other languages, it is easier for me to assess
your interest. That said, if you are great at any programming language, having
built non-trivial projects in any language, then you have the right skills for
internships in my group. Generally, I expect the interns to have done course
work on OS, compilers and computer architecture. Significant projects in any of
those areas is a huge plus.&lt;/p&gt;

&lt;p&gt;I should clarify that my recommendation letters for graduate programs will
reflect my honest assessment of the internship. I will decline writing a
recommendation letter if I think I may not be able to provide a strong one.&lt;/p&gt;

&lt;p&gt;I do not work on projects that are primarily AI/ML or Web Development. If you
write to me looking for projects in those areas, it is very likely that you
won’t hear from me. Please don’t bulk email faculty CCing or BCCing everyone in
the department. It is likely that no one will read such an email.&lt;/p&gt;

&lt;h2 id=&quot;phdmsmtech-positions&quot;&gt;PhD/MS/MTech positions&lt;/h2&gt;

&lt;p&gt;For academic positions, please have a look at &lt;a href=&quot;https://research.iitm.ac.in/&quot;&gt;https://research.iitm.ac.in/&lt;/a&gt;.
There are alternative ways to enter MS and PhD positions by being a reserach
associate and completing some coursework at IITM. For more information, see
&lt;a href=&quot;https://cystar.iitm.ac.in/join-us/#:~:text=Pathways%20to%20IIT%20Madras&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;contributing-to-the-ocaml-community&quot;&gt;Contributing to the OCaml community&lt;/h2&gt;

&lt;p&gt;A significant chunk of the enquiries were from folks who hold full-time
positions looking to be involved in the research group. Unfortunately, making
part-time positions work is a challenge for both sides. I would encourage
contributions to the wider OCaml community.&lt;/p&gt;

&lt;p&gt;There are several great ways to get involved with the community. Here’s what I
usually recommend.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Learn the basics.
    &lt;ul&gt;
      &lt;li&gt;Go through the OCaml part of my &lt;a href=&quot;https://github.com/fplaunchpad/cs3100_m20&quot;&gt;CS3100 course&lt;/a&gt;. The course has a YouTube
playlist and programming assignments. Complete the programming assignments.&lt;/li&gt;
      &lt;li&gt;Read the &lt;a href=&quot;https://dev.realworldocaml.org/&quot;&gt;Real World OCaml&lt;/a&gt; book.&lt;/li&gt;
      &lt;li&gt;There are lots of other resources at &lt;a href=&quot;https://ocaml.org/&quot;&gt;OCaml.org&lt;/a&gt;, the official website of the OCaml community and the ecosystem.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Join the community.
    &lt;ul&gt;
      &lt;li&gt;OCaml &lt;a href=&quot;https://discord.com/invite/ZBgYuvR&quot;&gt;discord&lt;/a&gt; and &lt;a href=&quot;https://discuss.ocaml.org/&quot;&gt;discuss&lt;/a&gt; are great places to hang out with other OCaml folks and ask questions.&lt;/li&gt;
      &lt;li&gt;Discord is better for quick clarifications and discuss for longer form discussions.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Look for “good first issues” in the OCaml projects and work on them
    &lt;ul&gt;
      &lt;li&gt;Check out the core platform tools under the &lt;a href=&quot;https://github.com/search?q=label%3A%22good+first+issue%22+language%3AOCaml+state%3Aopen+org%3Aocaml&amp;amp;type=issues&quot;&gt;OCaml github org&lt;/a&gt;. See &lt;a href=&quot;https://github.com/ocaml/ocaml/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22&quot;&gt;OCaml compiler&lt;/a&gt;, &lt;a href=&quot;https://github.com/ocaml/dune/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22&quot;&gt;dune build system&lt;/a&gt;, &lt;a href=&quot;https://github.com/ocaml/opam/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22easy%20first%20issue%22&quot;&gt;opam package manager&lt;/a&gt;, &lt;a href=&quot;https://github.com/ocaml/ocaml.org/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22&quot;&gt;ocaml.org&lt;/a&gt;, etc.&lt;/li&gt;
      &lt;li&gt;Across the wider ecosystem – &lt;a href=&quot;https://github.com/semgrep/semgrep/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22%20&quot;&gt;SemGrep&lt;/a&gt;, &lt;a href=&quot;https://github.com/opengrep/opengrep/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22&quot;&gt;OpenGrep&lt;/a&gt;, &lt;a href=&quot;https://github.com/rocq-prover/rocq/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22&quot;&gt;Rocq&lt;/a&gt;, etc.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Work on self-directed projects. Here is my &lt;a href=&quot;https://github.com/tarides/hackocaml&quot;&gt;list of ideas&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OCaml community also participates in &lt;a href=&quot;https://ocaml.org/outreachy&quot;&gt;Outreachy
internships&lt;/a&gt;. Outreachy internships are paid
internships for underrepresented groups. It is a great way to contribute to the
community while being mentored by folks from the OCaml community. Here’s a &lt;a href=&quot;https://www.youtube.com/watch?v=5eLRm8riAnI&amp;amp;t=970s&quot;&gt;nice
intro (in Tamil)&lt;/a&gt; to the
impact that Outreachy program had on an Outreachy intern. Look out for
&lt;a href=&quot;https://discuss.ocaml.org/t/outreachy-june-2025/16154&quot;&gt;announcements&lt;/a&gt; about
Outreachy internships in the OCaml discuss forum.&lt;/p&gt;

&lt;h2 id=&quot;research-associate-positions&quot;&gt;Research Associate positions&lt;/h2&gt;

&lt;p&gt;This is for folks who want to contribute to the core research programme but do
not see themselves joining academic programs. The expectation here is that you
are an experiened systems engineer, who should see themselves easily qualifying
for the internship positions in the group.&lt;/p&gt;

&lt;p&gt;One useful way to look at this position is similar to a research software
development engineer who helps build out the systems used for research or
translate research to practice. In the past, research associates have &lt;a href=&quot;https://kcsrk.info/ocaml/multicore/job/2019/09/16/1115-multicore-job/&quot;&gt;helped
upstream multicore
OCaml&lt;/a&gt;.
The easiest way to get into this role would be to do an internship, see whether
you like this area, do well in the internship and then choose to apply to
research associate position.&lt;/p&gt;

&lt;p&gt;Another variant is a post-bacc or a pre-doc position aimed at highly motivated
recent graduates, who are looking to build research experience. The expectation
here is that we get papers into top venues in PL and Systems. For such students,
I recommend going through my &lt;a href=&quot;https://github.com/fplaunchpad/cs6225_s25_iitm&quot;&gt;CS6225 Programs and Proofs
course&lt;/a&gt;, watch the &lt;a href=&quot;https://www.youtube.com/playlist?list=PLt0HgEXFOHdkfd7phdKKmTIuwHEvPX0qb&quot;&gt;video
lectures&lt;/a&gt;
and complete the
&lt;a href=&quot;https://github.com/fplaunchpad/cs6225_s25_iitm/tree/main/assignments&quot;&gt;assignments&lt;/a&gt;.
The course is not an easy one, but will expose you to the broad area of PL and
specifically to deductive program verification. At the very least, you will come
out with an understanding of what it is to think rigorously about program
correctness.&lt;/p&gt;

&lt;p&gt;Research associate positions are fixed-term positions. In order to make this
work, the tenure should be at least 18 months to make it work.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;While I may not be hiring actively all the time, do reach out to me if you are
interested in any of hte above. Please follow me on
&lt;a href=&quot;https://www.linkedin.com/in/kc-sivaramakrishnan-25061a14/&quot;&gt;LinkedIn&lt;/a&gt;,
&lt;a href=&quot;https://x.com/kc_srk&quot;&gt;X&lt;/a&gt; or &lt;a href=&quot;https://bsky.app/profile/kcsrk.info&quot;&gt;Bluesky&lt;/a&gt;,
where I am likely to announce any open positions.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Off-CPU-time analysis</title>
   <link href="https://kcsrk.info/ocaml/offcputime/bpfcc/2024/07/24/offcputime-analysis/"/>
   <updated>2024-07-24T09:48:00+00:00</updated>
   <id>https://kcsrk.info/ocaml/offcputime/bpfcc/2024/07/24/offcputime-analysis</id>
   <content type="html">&lt;p&gt;Off-CPU analysis is where the program behavior when it is not running is
recorded and analysed. See &lt;a href=&quot;https://www.brendangregg.com/offcpuanalysis.html&quot;&gt;Brendan Gregg’s eBPF based off-CPU
analysis&lt;/a&gt;. While on-CPU
performance monitoring tools such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;perf&lt;/code&gt; give you an idea of where the
program is &lt;em&gt;actively&lt;/em&gt; spending its time, they won’t tell you where the program
is spending time &lt;em&gt;blocked&lt;/em&gt; waiting for an action. Off-CPU analysis reveals
information about where the program is spending time &lt;em&gt;passively&lt;/em&gt;.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;/h2&gt;

&lt;p&gt;Install the tools from &lt;a href=&quot;https://github.com/iovisor/bcc/&quot;&gt;https://github.com/iovisor/bcc/&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;enabling-frame-pointers&quot;&gt;Enabling frame pointers&lt;/h2&gt;

&lt;p&gt;The off-CPU stack trace collection, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;offcputime-bpfcc&lt;/code&gt;, requires the programs to
be compiled with frame pointers for full backtraces.&lt;/p&gt;

&lt;h3 id=&quot;ocaml&quot;&gt;OCaml&lt;/h3&gt;

&lt;p&gt;For OCaml, you’ll need a compiler variant with frame pointers enabled. If you
are installing a released compiler using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opam&lt;/code&gt;, you can create one the following 
switch command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opam switch create 5.2.0+fp 5.2.0 ocaml-option-fp&lt;/code&gt;. Change out 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5.2.0&lt;/code&gt; for your preferred OCaml version.&lt;/p&gt;

&lt;p&gt;Instead, if you are building the OCaml compiler from source, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;configure&lt;/code&gt; the
compiler with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--enable-frame-pointers&lt;/code&gt; option:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ./configure --enable-frame-pointers
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Lastly, there is an option to create an opam switch with the development branch
of the compiler. The instructions are in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ocaml/HACKING.adoc&lt;/code&gt;. In order to
create an opam switch from the current working directory, do:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ opam switch create . &apos;ocaml-option-fp&apos; --working-dir
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;glibc&quot;&gt;glibc&lt;/h2&gt;

&lt;p&gt;The libc is not compiled with frame pointers by default. This will lead to many
truncated stack traces. On Ubuntu, I did the following to get a glibc with frame
pointers enabled:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Install glibc with frame pointers
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sudo apt install libc6-prof
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;LD_PRELOAD the glibc with frame pointers
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ LD_PRELOAD=/lib/libc6-prof/x86_64-linux-gnu/libc.so.6 ./myapp.exe
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;running&quot;&gt;Running&lt;/h2&gt;

&lt;p&gt;On one terminal run the program that you want to analyze:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ LD_PRELOAD=/lib/libc6-prof/x86_64-linux-gnu/libc.so.6 ./ocamlfoo.exe
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On another terminal run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;offcputime-bpfcc&lt;/code&gt; tool:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sudo offcputime-bpfcc --stack-storage-size 2097152 -p $(pgrep -f ocamlfoo.exe) 10 &amp;gt; offcputime.out
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The command instruments the watches for 10s and the writes out the stack traces
corresponding to blocking calls in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;offcputime.out&lt;/code&gt;. We use a large stack
storage size argument so as to not lose stack traces. Otherwise, you will see
many &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[Missing User Stack]&lt;/code&gt; errors in the back traces.&lt;/p&gt;

&lt;h2 id=&quot;caveats&quot;&gt;Caveats&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;offcputime-bpfcc&lt;/code&gt; must run longer than the program being instrumented by a few
seconds so that the function symbols are resolved. Otherwise you may see
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[unknown]&lt;/code&gt; in the backtrace for function names.&lt;/p&gt;

&lt;h2 id=&quot;oddities&quot;&gt;Oddities&lt;/h2&gt;

&lt;p&gt;I still see an order of magnitude difference between the maximum pauses observed
using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;offcputime-bpfcc&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;olly trace&lt;/code&gt;. Something is off.&lt;/p&gt;

&lt;h2 id=&quot;other-links&quot;&gt;Other links&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.pingcap.com/blog/how-to-trace-linux-system-calls-in-production-with-minimal-impact-on-performance/&quot;&gt;https://www.pingcap.com/blog/how-to-trace-linux-system-calls-in-production-with-minimal-impact-on-performance/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Getting Started with GDB on OCaml</title>
   <link href="https://kcsrk.info/ocaml/gdb/2024/01/20/gdb-ocaml/"/>
   <updated>2024-01-20T15:16:00+00:00</updated>
   <id>https://kcsrk.info/ocaml/gdb/2024/01/20/gdb-ocaml</id>
   <content type="html">&lt;p&gt;A number of folks who regularly use OCaml were surprised to learn that you can
reasonably debug OCaml programs using gdb. The aim of the post is to show the
first steps in using gdb on OCaml programs.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Let’s consider the following program:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;(* fib.ml *)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fib&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fib&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fib&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fib&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; 
  &lt;span class=&quot;nn&quot;&gt;Printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;fib(20) = %d&quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s compile this program. I’m using OCaml version 5.1.1.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ocamlopt &lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;
5.1.1
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ocamlopt &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; fib.exe fib.ml
&lt;span class=&quot;nv&quot;&gt;$ $ &lt;/span&gt;./fib.exe 20
fib&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;20&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 6765
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you can see, the program prints the 20th Fibonacci number. Let’s examine this
program under gdb. Before we venture any further, I highly recommend watching
this &lt;a href=&quot;https://www.youtube.com/watch?app=desktop&amp;amp;v=PorfLSr3DDI&quot;&gt;15-minute video&lt;/a&gt;
that shows a number of gdb tricks. Let’s start a gdb session.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gdb ./fib.exe
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;setting-breakpoints&quot;&gt;Setting breakpoints&lt;/h2&gt;

&lt;p&gt;Let’s set a break point at the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fib&lt;/code&gt; function. When OCaml functions are
compiled, their names are mangled. OCaml 5.1.1 uses the following mangling
scheme &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caml&amp;lt;MODULE_NAME&amp;gt;.&amp;lt;FUNCTION_NAME&amp;gt;_&amp;lt;NNN&amp;gt;&lt;/code&gt; where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NNN&lt;/code&gt; is a randomly
generated number. For the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fib&lt;/code&gt; function, since it is under the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fib.ml&lt;/code&gt;,
the module name is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Fib&lt;/code&gt;. Since we can’t guess &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NNN&lt;/code&gt;, we use tab completion to
help identify the function.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;break &lt;/span&gt;camlFib.fib_ &lt;span class=&quot;c&quot;&gt;#press tab&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;break &lt;/span&gt;camlFib.fib_269 &lt;span class=&quot;c&quot;&gt;#269 happens to be the randomly generated number&lt;/span&gt;
                            &lt;span class=&quot;c&quot;&gt;#on my machine.&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; Breakpoint 1 at 0x3d160: file fib.ml, line 1.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can also set a breakpoint using gdb’s file name and line number combination.
Let’s set another break point at the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; function, which is at line number 6
in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fib.ml&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;break &lt;/span&gt;fib.ml:6
Breakpoint 2 at 0x3d1d0: file fib.ml, line 6.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s run the program.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; r
Starting program: /home/kc/temp/fib.exe 
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Thread debugging using libthread_db enabled]
Using host libthread_db library &lt;span class=&quot;s2&quot;&gt;&quot;/lib/x86_64-linux-gnu/libthread_db.so.1&quot;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;

Breakpoint 2, camlFib.main_271 &lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; at fib.ml:6
6       &lt;span class=&quot;nb&quot;&gt;let &lt;/span&gt;main &lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The program execution starts in the gdb session and we stop at the breakpoint
installed at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt;. gdb has a nice TUI mode for stepping through the file. This
can be activated with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctrl+x+a&lt;/code&gt; key combination, which should show a screen
similar to the following.&lt;/p&gt;

&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/gdb/01.png&quot; /&gt; &lt;/p&gt;

&lt;p&gt;Notice that we can see both the breakpoints installed in this file. The current
line is highlighted.&lt;/p&gt;

&lt;h2 id=&quot;examining-the-stack&quot;&gt;Examining the stack&lt;/h2&gt;

&lt;p&gt;You can step through the OCaml program with gdb commands &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s&lt;/code&gt;. After a
few &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt;s, you can examine the backtrace using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bt&lt;/code&gt; command.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; bt
&lt;span class=&quot;c&quot;&gt;#0  camlFib.fib_269 () at fib.ml:1&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#1  0x00005555555911a1 in camlFib.fib_269 () at fib.ml:4&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#2  0x00005555555911a1 in camlFib.fib_269 () at fib.ml:4&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#3  0x00005555555911a1 in camlFib.fib_269 () at fib.ml:4&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#4  0x00005555555911a1 in camlFib.fib_269 () at fib.ml:4&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#5  0x00005555555911f1 in camlFib.main_271 () at fib.ml:7&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#6  0x000055555559129a in camlFib.entry () at fib.ml:10&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#7  0x000055555558eb0b in caml_program ()&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#8  &amp;lt;signal handler called&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#9  0x00005555555dd306 in caml_startup_common (pooling=&amp;lt;optimised out&amp;gt;, argv=0x7fffffffe008) at runtime/startup_nat.c:132&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#10 caml_startup_common (argv=0x7fffffffe008, pooling=&amp;lt;optimised out&amp;gt;) at runtime/startup_nat.c:88&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#11 0x00005555555dd37f in caml_startup_exn (argv=&amp;lt;optimised out&amp;gt;) at runtime/startup_nat.c:139&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#12 caml_startup (argv=&amp;lt;optimised out&amp;gt;) at runtime/startup_nat.c:144&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#13 caml_main (argv=&amp;lt;optimised out&amp;gt;) at runtime/startup_nat.c:151&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#14 0x000055555558e8f2 in main (argc=&amp;lt;optimised out&amp;gt;, argv=&amp;lt;optimised out&amp;gt;) at runtime/main.c:37&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you can see the backtrace includes the recursive calls to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fib&lt;/code&gt; function,
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; function in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fib.ml&lt;/code&gt;, followed by a number of functions from the
OCaml runtime, and finally ending at the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Note that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;signal handler called&amp;gt;&lt;/code&gt; is a misnomer and is not an actual signal
handler. OCaml 5 supports &lt;a href=&quot;https://v2.ocaml.org/manual/effects.html&quot;&gt;effect
handlers&lt;/a&gt; with the help of runtime
managed stack segments for the OCaml stack. There is also a single C stack that
is used by all the fibers that run on a
&lt;a href=&quot;https://v2.ocaml.org/manual/parallelism.html&quot;&gt;domain&lt;/a&gt;, our unit of parallelism.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;signal handler called&amp;gt;&lt;/code&gt; represents a frame where the control switches
between the C stack (managed by the OS) and the OCaml stack (managed by the
OCaml runtime). The OCaml runtime marks these frames where the stack are split
as signal handler frames so that gdb doesn’t complain about stack corruption;
gdb expects stacks to grow down, which may not be true if the stack segments are
in different parts of the memory address space. You will also find such &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;signal
handler called&amp;gt;&lt;/code&gt; frames between OCaml fibers (when using effect handlers) and
when OCaml calls into the (C) runtime. You can find more details about the stack
layout in the &lt;a href=&quot;https://dl.acm.org/doi/10.1145/3453483.3454039&quot;&gt;PLDI 2021 paper on OCaml effect
handlers&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;examining-values&quot;&gt;Examining values&lt;/h2&gt;

&lt;p&gt;There isn’t good support for examining OCaml values in gdb unlike C. That said,
given the &lt;a href=&quot;https://dev.realworldocaml.org/runtime-memory-layout.html&quot;&gt;uniform value representation of
OCaml&lt;/a&gt;, with a bit of
information about the OCaml calling convention, we can start to examine the
values. It is useful to note that OCaml 5.1.1 on x86 passes the first &lt;a href=&quot;https://github.com/ocaml/ocaml/blob/b2e7c4b7e93abb8faade7396730e59c1922c2e9f/asmcomp/amd64/proc.ml#L53&quot;&gt;10
arguments in
registers&lt;/a&gt;.
In particular, the first argument is in the register &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rax&lt;/code&gt;. So the argument to
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fib&lt;/code&gt; function should be in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rax&lt;/code&gt; register. We also know that the
argument to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fib&lt;/code&gt; is an integer. OCaml uses 63-bit tagged integers (on 64-bit
machines) with the least-significant bit is 1. Given a machine word or a
register holding an OCaml integer, the integer value is obtained by right
shifting the value by 1.&lt;/p&gt;

&lt;p&gt;Putting it all together, we can get the argument value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fib&lt;/code&gt; at the
breakpoint at the entry to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fib&lt;/code&gt; as follows:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; p &lt;span class=&quot;nv&quot;&gt;$rax&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; 1
&lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 12
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Given that we’ve already stepped through the program several times, the current
call for me corresponds to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fib(12)&lt;/code&gt;. Let’s see what’s the next argument by
continuing the program until we hit the breakpoint again.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; c
Continuing.

Breakpoint 1, camlFib.fib_269 &lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; at fib.ml:1
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; p &lt;span class=&quot;nv&quot;&gt;$rax&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; 1
&lt;span class=&quot;nv&quot;&gt;$3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Observe that this corresponds to the recursive call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fib(10)&lt;/code&gt;, which must mean
that the RHS recursive call is the one being invoked. Note that the evaluation
order of arguments in OCaml is unspecified. The 5.1.1 implementation does
right-to-left evaluation of arguments (to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(+)&lt;/code&gt; function in this case),
which can be confirmed with the following program:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eval_order&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ml&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print_endline&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print_endline&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;world&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ocamlopt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eval_order&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exe&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eval_order&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ml&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;./&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eval_order&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exe&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;world&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;hello&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;advanced-printing&quot;&gt;Advanced printing&lt;/h2&gt;

&lt;p&gt;As you can observe, examining values this way is cumbersome. The OCaml compiler
distribution has some rudimentary scripts to make it easier to examine OCaml
values in gdb. Note that this was developed by OCaml maintainers to develop the
compiler, and was not designed to serve end user needs. That said, let’s dive
in.&lt;/p&gt;

&lt;p&gt;Since we are on OCaml 5.1.1, let’s check out the source code for 5.1.1
first.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# I&apos;m in ~/repos directory on my machine *)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone https://github.com/ocaml/ocaml &lt;span class=&quot;nt&quot;&gt;--branch&lt;/span&gt; 5.1.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s start a new gdb session, load the gdb script and get to the desired
breakpoint.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gdb ./fib.exe
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ~/repos/ocaml/tools/gdb_ocamlrun.py
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;break &lt;/span&gt;fib.ml:1
Breakpoint 1 at 0x3d160: file fib.ml, line 1.
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; r
Starting program: /home/kc/temp/fib.exe 
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Thread debugging using libthread_db enabled]
Using host libthread_db library &lt;span class=&quot;s2&quot;&gt;&quot;/lib/x86_64-linux-gnu/libthread_db.so.1&quot;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;

Breakpoint 1, camlFib.fib_269 &lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; at fib.ml:1
1       &lt;span class=&quot;nb&quot;&gt;let &lt;/span&gt;rec fib n &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As earlier, the first argument is in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rax&lt;/code&gt; register. We can examine the value
now with the help of the script.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; p &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$rax&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; I&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;20&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt; is the type of OCaml values defined in OCaml runtime. The script
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tools/gdb_ocamlrun.py&lt;/code&gt; installs a pretty printer for the values of type
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt;. Here, it prints that the argument is the integer 20.&lt;/p&gt;

&lt;p&gt;We can also print other kinds of OCaml values. In order to illustrate this,
consider the following program:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test_blocks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ml&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;(* test_blocks.ml *)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;print_endline&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hello, world!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;print_endline&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;print_endline&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;foo&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bar&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s compile, start a gdb session and break at the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; function.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ocamlopt &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; test_blocks.exe test_blocks.ml                                                                                                               
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gdb ./test_blocks.exe
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;break &lt;/span&gt;camlTest_blocks.main_272 
Breakpoint 1 at 0x16ed0: file test_blocks.ml, line 5.
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; r
Starting program: /home/kc/temp/test_blocks.exe 
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Thread debugging using libthread_db enabled]
Using host libthread_db library &lt;span class=&quot;s2&quot;&gt;&quot;/lib/x86_64-linux-gnu/libthread_db.so.1&quot;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;

Breakpoint 1, camlTest_blocks.main_272 &lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; at test_blocks.ml:5
5       &lt;span class=&quot;nb&quot;&gt;let &lt;/span&gt;main a b &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ~/repos/ocaml/tools/gdb_ocamlrun.py 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s examine the two arguments to main.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; p &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$rax&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; String_tag&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;foo&quot;&lt;/span&gt;, NOT_MARKABLE&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The first argument is a string “foo”. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NOT_MARKABLE&lt;/code&gt; is one of the GC colours
used by OCaml 5, and represents objects that are not traced by the
mark-and-sweep (major) GC. The string happens to be allocated in the &lt;a href=&quot;https://en.wikipedia.org/wiki/Data_segment&quot;&gt;data
section&lt;/a&gt; of the address space, and
is not traced by the GC.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; info symbol &lt;span class=&quot;nv&quot;&gt;$rax&lt;/span&gt;
camlTest_blocks.4 &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;section .data of /home/kc/temp/test_blocks.exe
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s examine the second argument.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; p &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$rbx&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; Block&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0, &lt;span class=&quot;nv&quot;&gt;wosize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2, NOT_MARKABLE&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The second argument, which is passed in the register &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rbx&lt;/code&gt;, is a record with two
fields. Hence, the pretty printer says that it is a block with 2 fields.  We can
print both values using gdb’s support for printing a range of values.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; p &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$rbx&lt;/span&gt;@2                                                                 
&lt;span class=&quot;nv&quot;&gt;$3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;String_tag&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;bar&quot;&lt;/span&gt;, NOT_MARKABLE&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, I&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;42&lt;span class=&quot;o&quot;&gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We cast &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rbx&lt;/code&gt; to an array of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt;s and print the first two fields in the
array. This shows that the fields are the string “bar” and integer 42.&lt;/p&gt;

&lt;h2 id=&quot;more-for-later&quot;&gt;More for later&lt;/h2&gt;

&lt;p&gt;There is a lot more to be said about debugging OCaml programs using gdb. We
shall see them in subsequent posts if there is interest.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Teaching OCaml and Prolog through Jupyter Notebooks</title>
   <link href="https://kcsrk.info/ocaml/prolog/jupyter/notebooks/2020/01/19/OCaml-Prolog-Jupyter/"/>
   <updated>2020-01-19T15:16:00+00:00</updated>
   <id>https://kcsrk.info/ocaml/prolog/jupyter/notebooks/2020/01/19/OCaml-Prolog-Jupyter</id>
   <content type="html">&lt;p&gt;Last semester at IIT Madras, I taught a revamped core course &lt;a href=&quot;https://fplaunchpad.github.io/cs3100_f19/&quot;&gt;CS3100 Paradigms
of Programming&lt;/a&gt;, which introduces 3rd-year
students to functional and logic programming paradigms. While the course had
been traditionally offered in Lisp and Prolog, I introduced OCaml instead of
Lisp. All of the lectures were delivered through interactive Jupyter
notebooks. The assignments were also distributed as Jupyter notebooks and
evaluated through autograder facility in Jupyter. There has since been several
requests to replicate this setup elsewhere. Hence, I thought I should write
about the set up and experience of teaching through Jupyter notebooks.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;course-content&quot;&gt;Course Content&lt;/h2&gt;

&lt;p&gt;Having never taken a functional programming course, there was the question of
what I wanted the students to take away from the course. I wanted the course to
be a mixture of functional programming concepts (types and lambda calculus) as
well as advanced yet pragmatic concepts that one would find in modern functional
programming languages (such as GADTs and Monads). The OCaml part of the course
is based on the excellent &lt;a href=&quot;https://www.cs.cornell.edu/courses/cs3110/2019sp/&quot;&gt;CS3110 from
Cornell&lt;/a&gt; and &lt;a href=&quot;https://www.cl.cam.ac.uk/teaching/1718/L28/&quot;&gt;AFP from
Cambridge Computer Laboratory&lt;/a&gt;. In
particular, I would highly recommend the &lt;a href=&quot;https://www.cs.cornell.edu/courses/cs3110/2019sp/textbook/intro/3110.html&quot;&gt;CS3110
book&lt;/a&gt;
for anyone taking first steps into functional programming. Lambda calculus
lectures were based on Peter Selinger’s &lt;a href=&quot;https://arxiv.org/abs/0804.3434&quot;&gt;lecture notes on lambda
calculus&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Prolog part of the course were modelled on &lt;a href=&quot;https://www.cl.cam.ac.uk/teaching/1819/Prolog/&quot;&gt;Prolog lectures from Cambridge
Computer Laboratory&lt;/a&gt; and the
wonderful &lt;a href=&quot;https://mitpress.mit.edu/books/art-prolog-second-edition&quot;&gt;The Art of
Prolog&lt;/a&gt; book.&lt;/p&gt;

&lt;p&gt;Teaching functional and logic programming in the same course allowed me to
develop interesting content that intersected both of the paradigms. In the
functional programming part of the lecture, I had introduced &lt;a href=&quot;https://fplaunchpad.github.io/cs3100_f19/lectures/lec11/lec11.pdf&quot;&gt;simply typed
lambda calculus&lt;/a&gt;. In the
logic part of the course, we developed a type checker for simply typed lambda
calculus in Prolog. Merely encoding type checking rules for simply typed lambda
calculus in Prolog, &lt;a href=&quot;https://fplaunchpad.github.io/cs3100_f19/lectures/lec25/lec25.pdf&quot;&gt;type inference with polymorphic types falls
out&lt;/a&gt;. With a tiny bit of
coaxing, Prolog synthesizes programs for the given type. In the last assignment,
the students were asked to implement &lt;a href=&quot;https://github.com/fplaunchpad/cs3100_f19/blob/gh-pages/assignments/assignment6.ipynb&quot;&gt;a Prolog interpreter in
OCaml&lt;/a&gt;.
There was indeed some value in teaching multiple paradigms in the same course,
not just for a comparative study of strengths and weaknesses, but to be able to
teach the students to pick the right tool for the job.&lt;/p&gt;

&lt;h2 id=&quot;course-delivery&quot;&gt;Course Delivery&lt;/h2&gt;

&lt;p&gt;I had a clear idea that the course will have to be interactive where programs
are developed during the lectures. There was the option of using pdf slides and
switching to &lt;a href=&quot;https://opam.ocaml.org/packages/utop/&quot;&gt;utop&lt;/a&gt; for interactive
development. But this solution lacked the uniformity that the students would
like when reviewing the course materials. Moreover, switching between two
mediums made it difficult for me to plan the lectures and was a distraction for
the students.&lt;/p&gt;

&lt;h3 id=&quot;jupyter-notebooks&quot;&gt;Jupyter Notebooks&lt;/h3&gt;

&lt;p&gt;Hence, I decided to use Jupyter Notebooks for the course. Jupyter is a
collection of open source standards and software for interactive development.
Jupyter supports a variety of languages. For OCaml, I used
&lt;a href=&quot;https://github.com/akabe/ocaml-jupyter&quot;&gt;akabe/ocaml-jupyter&lt;/a&gt;, an OCaml kernel
for Jupyter notebooks. This uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;utop&lt;/code&gt;, an advanced OCaml top-level in the
backend and hence provides excellent interactive top-level support. The
situation for Prolog was not so great. Eventually, I zeroed in on
&lt;a href=&quot;https://github.com/targodan/jupyter-swi-prolog&quot;&gt;targodan/jupyter-swi-prolog&lt;/a&gt;
but ended up improving the solution a bit
&lt;a href=&quot;https://github.com/kayceesrk/jupyter-swi-prolog&quot;&gt;kayceesrk/jupyter-swi-prolog&lt;/a&gt;
(TODO KC: upstream fixes). Jupyter supports &lt;a href=&quot;https://www.mathjax.org/&quot;&gt;mathjax&lt;/a&gt;,
which allows typesetting LaTeX in the notebooks. This was great for writing the
lectures on lambda calculus.&lt;/p&gt;

&lt;h3 id=&quot;rise-for-slideshow&quot;&gt;RISE for slideshow&lt;/h3&gt;

&lt;p&gt;Jupyter notebooks are webpages that mixes text and code. For lectures, I much
prefer slides since they let you focus on a particular images, statement or an
inference rule. While Jupyter allows the conversion of notebooks to slides
&lt;em&gt;out-of-band&lt;/em&gt;, &lt;a href=&quot;https://github.com/damianavila/RISE&quot;&gt;RISE&lt;/a&gt; is an Jupyter
notebook extension that lets turn your Jupyter notebook into a slideshow. Adding
RISE to the setup makes the Jupyter experience compatible with traditional
slides based lectures.&lt;/p&gt;

&lt;h2 id=&quot;course-distribution&quot;&gt;Course Distribution&lt;/h2&gt;

&lt;p&gt;Apart from delivering the lectures through the notebooks, I also wanted the
students to be able to go through the notebooks and be able to run the snippets.
Installing all the required software (OPAM, OCaml, Prolog, Jupyter and its
extensions, Jupyter Kernels for OCaml and Prolog) and correctly was not
something I wanted the students to go through. I wasn’t even sure if this
software combination works on various Mac, Windows and Linux distributions.
Hence, everything was packaged as a &lt;a href=&quot;https://github.com/fplaunchpad/cs3100_f19/blob/gh-pages/_docker/dockerfile&quot;&gt;Docker
file&lt;/a&gt;,
and the latest version of the image uploaded to &lt;a href=&quot;https://hub.docker.com/r/kayceesrk/cs3100_iitm&quot;&gt;docker
hub&lt;/a&gt;. In order to review the
course, the students only had to install Docker and Git and run &lt;a href=&quot;https://github.com/fplaunchpad/cs3100_f19#running-the-jupyter-notebooks&quot;&gt;exactly 4
commands&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Docker is generally supported on all major OSes. Packaging up the course content
as a docker image and pushing it to dockerhub is insurance against the software
combination not working in the next offering of the course; if for some reason
one of the dependency does not work next year, I can always fallback to the
docker image while I find a fix. One of my TAs ran a tutorial on basic Docker
and Git in the first week of the course to ensure that everyone was setup. I
would consider Docker and Git as essential tools for modern software development
as well as research. After that, the students did not ever have to do anything
on the command line.&lt;/p&gt;

&lt;h2 id=&quot;assignments&quot;&gt;Assignments&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://nbgrader.readthedocs.io/en/stable/&quot;&gt;nbgrader&lt;/a&gt; is a tool that
facilitates creating and grading assignments in Jupyter notebook. It uses
language-agnostic logic to identify failing cells, which meant that it was easy
to set up nbgrader for OCaml and Prolog. The assignments were
&lt;a href=&quot;https://fplaunchpad.github.io/cs3100_f19/assignments/&quot;&gt;released&lt;/a&gt; as Jupyter notebooks,
which the students filled in and submitted. nbgrader has support for unit tests
which allowed the students to get instant feedback as they were developing the
solutions.&lt;/p&gt;

&lt;h2 id=&quot;wish-list&quot;&gt;Wish List&lt;/h2&gt;

&lt;p&gt;Overall, the students felt that the Jupyter notebooks were better than
slidedecks. However, not everything was perfect with the Jupyter notebook based
lecturing. Here are some of the things that could be improved.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;There is no good diagramming + animation support for Jupyter notebooks. The
best I could find was &lt;a href=&quot;https://github.com/kayceesrk/egal&quot;&gt;egal&lt;/a&gt; whose user
interface I did not find intuitive. Even for simple diagrams, it was much more
effort making diagrams there compared to Keynote, PowerPoint or OmniGraffle.
Eventually, I used &lt;a href=&quot;https://www.draw.io/&quot;&gt;draw.io&lt;/a&gt; to make the diagrams and
include the images in the slides for a few of the cases where I actually
needed to make diagrams.&lt;/li&gt;
  &lt;li&gt;Docker for Windows does not work on Windows Home or Student. Support for OPAM
on Windows is slowly improving, but it is not yet for novices. Hence, I had to
recommend the students to run an Ubuntu VM on their Windows machines in which
they ran the course’s docker container.&lt;/li&gt;
  &lt;li&gt;nbgrader had several bugs which caused the autograder to award marks even for
failing cells. The TAs had to go through a few of the assignments manually to
ensure that students were awarded grades correctly. This is something that
should be fixable easily.&lt;/li&gt;
  &lt;li&gt;RISE doesn’t easily let you change the size of the font. One has to edit the
CSS to change the font size. And the default style wastes too much space. This
meant that not much content can be fit into a single slide. Hence, I’ve had to
artificially split content into multiple slides or zoom out several steps to
show content that was cut off on the bottom.&lt;/li&gt;
  &lt;li&gt;The support for Prolog is not so great. There are a few advanced features in
Prolog for which the Prolog setup
&lt;a href=&quot;https://github.com/yuce/pyswip/issues/68&quot;&gt;fails&lt;/a&gt;. I had to switch to
SWI-Prolog top-level for a few lectures. That said, the Prolog support is
mostly there and the issues can be fixed with some effort.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I have started working on fixing some of these issues and upstreaming the
solutions. Hopefully the fixes should be ready for the next iteration of the
course. If you would like to replicate this setup for your course, do feel free
to utilise the course materials.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Multicore OCaml Jobs</title>
   <link href="https://kcsrk.info/ocaml/multicore/job/2019/09/16/1115-multicore-job/"/>
   <updated>2019-09-16T11:59:00+00:00</updated>
   <id>https://kcsrk.info/ocaml/multicore/job/2019/09/16/1115-multicore-job</id>
   <content type="html">&lt;p&gt;Multiple &lt;strong&gt;Research Software Engineer&lt;/strong&gt; positions are available in the
&lt;a href=&quot;https://www.cse.iitm.ac.in/&quot;&gt;Department of Computer Science and Engineering&lt;/a&gt; at
the &lt;a href=&quot;https://www.iitm.ac.in/&quot;&gt;Indian Institute of Technology, Madras&lt;/a&gt; to develop
&lt;a href=&quot;https://github.com/ocaml-multicore/ocaml-multicore&quot;&gt;Multicore OCaml&lt;/a&gt; and enable
&lt;a href=&quot;https://tezos.com/&quot;&gt;Tezos&lt;/a&gt; ecosystem to benefit from Multicore OCaml.&lt;/p&gt;

&lt;!--more--&gt;

&lt;center&gt;
&lt;figure&gt;
&lt;img src=&quot;/assets/dog_deer_monkey.jpg&quot; width=&quot;75%&quot; /&gt;
&lt;figcaption&gt; A dog, a deer and a monkey walk into a coffee shop... &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/center&gt;

&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;

&lt;p&gt;The Multicore OCaml project aims to add native support for scalable concurrency
and shared memory parallelism in OCaml. At its core, Multicore OCaml extends the
OCaml programming language with effect handlers for expressing scalable
concurrency and a high-performance concurrent garbage collector aimed at
responsive networked applications. Multicore OCaml is also the first
industrial-strength language to come equipped with an efficient yet modular
memory model, allowing high-level local program reasoning while retaining
performance. Multicore OCaml is actively being developed and core features are
being upstreamed to OCaml.&lt;/p&gt;

&lt;p&gt;Tezos is an open-source smart contract platform for decentralized applications
and assets. Tezos uses a self-amending cryptographic ledger - It achieves
consensus not just about the state of a ledger, but about the state of its own
protocol. The primary protocol of Tezos utilizes proof of stake and supports
Turing complete smart contracts in a domain-specific language called Michelson.
Tezos codebase is written in OCaml and extensively uses OCaml ecosystem
libraries and tools such as Lwt, OPAM, and Irmin.&lt;/p&gt;

&lt;h2 id=&quot;roles&quot;&gt;Roles&lt;/h2&gt;

&lt;p&gt;There are two roles:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Compiler Engineer:&lt;/strong&gt; Runtime system improvements to the OCaml programming
language in order to make it compatible with multicore support. Implementing
new features in Multicore OCaml compiler.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Application Engineer:&lt;/strong&gt; Developing core OCaml libraries that take advantage
of multicore support. Adding parallelism support for Tezos ecosystem libraries
and tools such as Lwt, Irmin, and dune.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;positions&quot;&gt;Positions&lt;/h3&gt;

&lt;p&gt;The positions available are:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Role&lt;/th&gt;
      &lt;th&gt;Minimum Qualification&lt;/th&gt;
      &lt;th&gt;Pay Range (Per Month)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Project Engineer&lt;/td&gt;
      &lt;td&gt;BE / BTech / Master’s in Science/MCA or equivalent&lt;/td&gt;
      &lt;td&gt;Rs.21,500 to Rs.75,000&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Senior Project Engineer&lt;/td&gt;
      &lt;td&gt;ME / MTech (or) BE / BTech / Master’s in Science / MCA or equivalent with 2 years experience&lt;/td&gt;
      &lt;td&gt;Rs.27,500 to Rs.1,00,000&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Senior Project Officer / Post-doctoral Researcher&lt;/td&gt;
      &lt;td&gt;Ph.D. in Engineering or Sciences (or) ME / MTech with 3 years experience (or) BE / BTech / Master’s in Science / MCA or equivalent with 5 years experience&lt;/td&gt;
      &lt;td&gt;Rs.35,000 to Rs.1,50,000&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Principal Project Officer&lt;/td&gt;
      &lt;td&gt;Ph.D. in Engineering or Sciences with 7 years experience (or) ME / MTech with 10 years experience (or) BE / BTech / Master’s in Science / MCA or equivalent with 12 years experience&lt;/td&gt;
      &lt;td&gt;Rs. 48,000 to Rs.2,25,000&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The appointment will be made for 6 months initially and can be extended up to 2
years. The project engineers have the option of enrolling in the MS program at
CSE, IIT Madras after 6 months. Such candidates may appear to the interview
directly, without having to write GATE.&lt;/p&gt;

&lt;p&gt;You will work closely with the &lt;a href=&quot;http://ocamllabs.io/&quot;&gt;OCaml Labs group&lt;/a&gt;,
University of Cambridge, UK and &lt;a href=&quot;https://tarides.com/&quot;&gt;Tarides&lt;/a&gt;, France. All of
the work done will be made available as liberally licensed open-source software.&lt;/p&gt;

&lt;h2 id=&quot;skills&quot;&gt;Skills&lt;/h2&gt;

&lt;h3 id=&quot;compiler-engineer&quot;&gt;Compiler Engineer&lt;/h3&gt;

&lt;h4 id=&quot;necessary&quot;&gt;Necessary:&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;Excellent working knowledge of C, concurrent and parallel programming&lt;/li&gt;
  &lt;li&gt;Knowledge of compilers (not necessarily of functional programming languages),
operating systems, x86 &amp;amp; ARM assembly programming&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;desired&quot;&gt;Desired:&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;Experience developing and/or maintaining performant software systems&lt;/li&gt;
  &lt;li&gt;Experience with a functional programming language such as Haskell, OCaml,
Scala, Scheme, Elm, or Elixir.&lt;/li&gt;
  &lt;li&gt;Track record of open source contributions.&lt;/li&gt;
  &lt;li&gt;Understanding of benchmarking techniques and analyzing results&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;applications-engineer&quot;&gt;Applications Engineer&lt;/h3&gt;

&lt;h4 id=&quot;necessary-1&quot;&gt;Necessary&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Excellent working knowledge of operating systems, concurrent and parallel
programming&lt;/li&gt;
  &lt;li&gt;Experience with a functional programming language such as Haskell, OCaml,
Scala, Scheme, Elm, or Elixir.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;desired-1&quot;&gt;Desired&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Track record of contributions to large open-source software systems&lt;/li&gt;
  &lt;li&gt;Understanding of benchmarking techniques and analyzing results&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;apply&quot;&gt;Apply&lt;/h2&gt;

&lt;p&gt;Write to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kcsrk@iitm.ac.in&lt;/code&gt; with the subject “IITM Multicore OCaml 2019:
Compiler Engineer” or “IITM Multicore OCaml 2019: Application Engineer” based on
the role to express interest. Please include:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Curriculum Vitae&lt;/li&gt;
  &lt;li&gt;A summary of your experience in relevant technologies and software&lt;/li&gt;
  &lt;li&gt;Any open source contributions&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Deterministically debugging concurrent GC bugs with rr</title>
   <link href="https://kcsrk.info/ocaml/multicore/rr/2019/04/28/0000-rr-debugging/"/>
   <updated>2019-04-28T00:00:00+00:00</updated>
   <id>https://kcsrk.info/ocaml/multicore/rr/2019/04/28/0000-rr-debugging</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://github.com/ocaml-multicore/ocaml-multicore&quot;&gt;Multicore OCaml&lt;/a&gt; comes with
a &lt;a href=&quot;http://kcsrk.info/multicore/gc/2017/07/06/multicore-ocaml-gc/&quot;&gt;concurrent garbage
collector&lt;/a&gt;, where
the garbage collector and the mutator threads run concurrently. Debugging
concurrent GC bugs has been the most frustrating / satisfying (when fixed) part
of Multicore OCaml development. &lt;a href=&quot;https://rr-project.org/&quot;&gt;rr&lt;/a&gt;, a record and
replay tool has made debugging concurrent GC bugs a sustainable exercise. In
this short post, I’ll describe why.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;A particularly tricky concurrent GC bug is one which occurs once every 10 to 100
runs due to non-determinism and any attempt to instrument the program to isolate
the bug (simplifying the program, adding print statements, etc.) makes it
disappear. The bug may only appear relatively late in the program run – after a
few major GC cycles, where the program might have allocated 10s of gigabytes of
memory by then. The bug usually manifests as a segfault due to illegal memory
access, but the source of the bug may lie in the previous GC cycle and perhaps
due to actions of a different thread than the one that is throwing up the error.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gdb&lt;/code&gt; often doesn’t help since finding the illegal memory access may not give
any clue as to &lt;em&gt;when&lt;/em&gt; the heap was corrupted.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rr&lt;/code&gt; to the rescue. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rr&lt;/code&gt; is an enhancement over &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gdb&lt;/code&gt; with support for recording
an execution and debugging in &lt;em&gt;reverse&lt;/em&gt;. Once a failing execution is recorded,
the execution can be replayed multiple times deterministically. This removes the
non-determinism from debugging session. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gdb&lt;/code&gt; does support record and replay,
but not on multi-threaded targets.&lt;/p&gt;

&lt;p&gt;The fact that the program can be run in reverse is the key for debugging heap
corruptions. An illegal access typically appears as a load or store to a illegal
memory address obtained from a heap object. When such an illegal access is
found, I set a hardware watchpoint on the heap address containing the illegal
address and continue the program in reverse. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rr&lt;/code&gt; runs the program in reverse until
the write that stored the illegal address in the heap object! Usually, several
transitive reverse runs are necessary to get to the source of the bug, but this
is just mechanics.&lt;/p&gt;

&lt;p&gt;While &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rr&lt;/code&gt; supports multi-threaded programs, it runs every thread on the same
core. This usually makes the bug disappear. Luckily, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rr&lt;/code&gt; comes with support for
forcing a context switch after a certain number of CPU ticks (measured in terms
of the number of retired conditional branches). Even with this option, you will
need many runs before &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rr&lt;/code&gt; comes across a buggy execution. So I use the
following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;for i in {1..10000}; do rr record -c 10000 &amp;lt;program&amp;gt; &amp;lt;args&amp;gt;; if (( $? == 0 )); then echo &quot;done $i&quot;; else break; fi; done
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;which runs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;prog&amp;gt; &amp;lt;args&amp;gt;&lt;/code&gt; under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rr&lt;/code&gt; where a thread is allowed to execute for a
maximum of 10,000 ticks before a context switch. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rr&lt;/code&gt; runs are repeated until a
crash is found or 10,000 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rr&lt;/code&gt; runs are successfully completed. Depending on the
program being debugged, I leave it running overnight. If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rr&lt;/code&gt; had in fact found
a crash, I can perform replay debugging with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rr replay&lt;/code&gt; the following morning
and have a deterministic and reversible recorded execution to work with.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rr&lt;/code&gt; has save countless hours in the development of Multicore OCaml, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rr&lt;/code&gt;
should be a essential tool in every GC hacker’s toolbox.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>ML Family Workshop 2019: Call for presentations</title>
   <link href="https://kcsrk.info/ocaml/haskell/standard%20ml/f%23/2019/04/22/1600-ml-workshop-2019/"/>
   <updated>2019-04-22T16:00:00+00:00</updated>
   <id>https://kcsrk.info/ocaml/haskell/standard%20ml/f%23/2019/04/22/1600-ml-workshop-2019</id>
   <content type="html">&lt;p&gt;I am chairing the PC for ML family workshop this year. The PC is happy to invite
submissions for the workshop to be held during the ICFP conference week on
Thursday 22nd August 2019.&lt;/p&gt;

&lt;p&gt;ML family workshop invites submissions touching on the programming languages
traditionally seen as part of the “ML family”. However, we are also keen to
receive submissions from other related language groups. If you have questions
about the suitability of your work for the workshop, please feel free to write
an email.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;The detailed CFP is available on the ICFP website:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://icfp19.sigplan.org/home/mlfamilyworkshop-2019#Call-for-Presentations&quot;&gt;https://icfp19.sigplan.org/home/mlfamilyworkshop-2019#Call-for-Presentations&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;important-dates&quot;&gt;Important dates&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Thu 16 May 2019 – (AoE)Submission deadline&lt;/li&gt;
  &lt;li&gt;Sun 30 Jun 2019 – Author Notification&lt;/li&gt;
  &lt;li&gt;Thu 22 Aug 2019 – ML Family Workshop&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;program-committee&quot;&gt;Program Committee&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Aggelos Biboudis – EPFL, Switzerland&lt;/li&gt;
  &lt;li&gt;Andreas Rossberg – Dfinity, Germany&lt;/li&gt;
  &lt;li&gt;Atsushi Igarashi – Kyoto University, Japan&lt;/li&gt;
  &lt;li&gt;Avik Chaudhuri – Facebook, USA&lt;/li&gt;
  &lt;li&gt;Cyrus Omar – University of Chicago, USA&lt;/li&gt;
  &lt;li&gt;David Allsopp – University of Cambridge, UK&lt;/li&gt;
  &lt;li&gt;Edwin Brady – University of St. Andrews, UK&lt;/li&gt;
  &lt;li&gt;Jacques-Henri Jourdan – CNRS, LRI, Université Paris-Sud, France&lt;/li&gt;
  &lt;li&gt;KC Sivaramakrishnan – IIT Madras, India&lt;/li&gt;
  &lt;li&gt;Lars Bergstrom – Mozilla Research, USA&lt;/li&gt;
  &lt;li&gt;Matthew Fluet – Rochester Institute of Technology, USA&lt;/li&gt;
  &lt;li&gt;Zoe Paraskevopoulou – Princeton University, USA&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;submission-details&quot;&gt;Submission details&lt;/h2&gt;

&lt;p&gt;We seek extended abstracts, up to 3 pages long. Submissions must be uploaded to
the workshop submission website:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://icfp19mlworkshop.hotcrp.com/&quot;&gt;https://icfp19mlworkshop.hotcrp.com/&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>OCaml on Baremetal Shakti RISC-V processor</title>
   <link href="https://kcsrk.info/ocaml/riscv/shakti/2019/03/29/1400-ocaml-baremetal-shakti/"/>
   <updated>2019-03-29T14:00:00+00:00</updated>
   <id>https://kcsrk.info/ocaml/riscv/shakti/2019/03/29/1400-ocaml-baremetal-shakti</id>
   <content type="html">&lt;p&gt;It has been 3 months since I joined &lt;a href=&quot;https://www.iitm.ac.in/&quot;&gt;IIT Madras&lt;/a&gt; and it
has been good fun so far. Along with the members of the &lt;a href=&quot;http://rise.cse.iitm.ac.in/&quot;&gt;RISE
group&lt;/a&gt;, we’ve initiated a project to build secure
applications on top of secure extensions of the open-source
&lt;a href=&quot;http://shakti.org.in/&quot;&gt;Shakti&lt;/a&gt; RISC-V processor ecosystem. Unsurprisingly, my
language of choice to build the applications is &lt;a href=&quot;http://www.ocaml.org/&quot;&gt;OCaml&lt;/a&gt;.
Given the availability of rich ecosystem of libraries under the
&lt;a href=&quot;https://mirage.io/&quot;&gt;MirageOS&lt;/a&gt; library operating system for building unikernels,
we hope to minimise the amount of unsafe C code that the hardware has to contend
with and protect exploits against. As a first step, we have managed to get OCaml
programs to run on directly on top of the Shakti processor running in simulation
under QEMU and Spike ISA simulators &lt;em&gt;without an intervening operating system&lt;/em&gt;.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;A custom bootloader performs the necessary hardware initialisation and
transfers control directly to the OCaml program. We have
&lt;a href=&quot;https://gitlab.com/shaktiproject/tools/shakti-tee/ocaml-baremetal-riscv&quot;&gt;open-sourced&lt;/a&gt;
all of the tools necessary to build your own kernel. This handy
&lt;a href=&quot;https://gitlab.com/shaktiproject/tools/shakti-tee/ocaml-baremetal-riscv/tree/master/docker&quot;&gt;dockerfile&lt;/a&gt;
documents the entire process. For the impatient, an image is available in the
dockerhub:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; iitmshakti/riscv-ocaml-baremetal:0.1.0

&lt;span class=&quot;c&quot;&gt;# Write your program&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;let _ = print_endline &quot;A camel treads on hardware!&quot;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; hello.ml
&lt;span class=&quot;c&quot;&gt;# Compile for Shakti&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ocamlopt &lt;span class=&quot;nt&quot;&gt;-output-obj&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; payload.o hello.ml
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;file payload.o
payload.o: ELF 64-bit LSB relocatable, UCB RISC-V, version 1 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;SYSV&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, not stripped

&lt;span class=&quot;c&quot;&gt;# Link with bootcode and build the kernel&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; ../build
make: Entering directory &lt;span class=&quot;s1&quot;&gt;&apos;/root/ocaml-baremetal-riscv/build&apos;&lt;/span&gt;
make[1]: Entering directory &lt;span class=&quot;s1&quot;&gt;&apos;/root/ocaml-baremetal-riscv/build&apos;&lt;/span&gt;
make[2]: Entering directory &lt;span class=&quot;s1&quot;&gt;&apos;/root/ocaml-baremetal-riscv/build&apos;&lt;/span&gt;
make[2]: Leaving directory &lt;span class=&quot;s1&quot;&gt;&apos;/root/ocaml-baremetal-riscv/build&apos;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; 64%] Built target boot
make[2]: Entering directory &lt;span class=&quot;s1&quot;&gt;&apos;/root/ocaml-baremetal-riscv/build&apos;&lt;/span&gt;
make[2]: Leaving directory &lt;span class=&quot;s1&quot;&gt;&apos;/root/ocaml-baremetal-riscv/build&apos;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; 78%] Built target freestanding-compat
make[2]: Entering directory &lt;span class=&quot;s1&quot;&gt;&apos;/root/ocaml-baremetal-riscv/build&apos;&lt;/span&gt;
make[2]: Leaving directory &lt;span class=&quot;s1&quot;&gt;&apos;/root/ocaml-baremetal-riscv/build&apos;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; 85%] Built target asmrun_t
make[2]: Entering directory &lt;span class=&quot;s1&quot;&gt;&apos;/root/ocaml-baremetal-riscv/build&apos;&lt;/span&gt;
make[2]: Leaving directory &lt;span class=&quot;s1&quot;&gt;&apos;/root/ocaml-baremetal-riscv/build&apos;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; 92%] Built target nolibc_t
make[2]: Entering directory &lt;span class=&quot;s1&quot;&gt;&apos;/root/ocaml-baremetal-riscv/build&apos;&lt;/span&gt;
make[2]: Leaving directory &lt;span class=&quot;s1&quot;&gt;&apos;/root/ocaml-baremetal-riscv/build&apos;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;100%] Built target kernel
make[1]: Leaving directory &lt;span class=&quot;s1&quot;&gt;&apos;/root/ocaml-baremetal-riscv/build&apos;&lt;/span&gt;
make: Leaving directory &lt;span class=&quot;s1&quot;&gt;&apos;/root/ocaml-baremetal-riscv/build&apos;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;file kernel 
kernel: ELF 64-bit LSB executable, UCB RISC-V, version 1 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;SYSV&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, statically linked, with debug_info, not stripped

&lt;span class=&quot;c&quot;&gt;# Run under spike RISC-V ISA simulator&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;spike kernel
ocaml-boot: heap@0x80042be8 stack@0x8002fbc0
A camel treads on hardware!
ocaml-boot: caml runtime returned. shutting down!

&lt;span class=&quot;c&quot;&gt;# Run under QEMU&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;qemu-system-riscv64 &lt;span class=&quot;nt&quot;&gt;-machine&lt;/span&gt; spike_v1.10 &lt;span class=&quot;nt&quot;&gt;-smp&lt;/span&gt; 1 &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; 1G &lt;span class=&quot;nt&quot;&gt;-serial&lt;/span&gt; stdio &lt;span class=&quot;nt&quot;&gt;-kernel&lt;/span&gt; kernel
VNC server running on 127.0.0.1:5900
ocaml-boot: heap@0x80042be8 stack@0x8002fbc0
A camel treads on hardware!
ocaml-boot: caml runtime returned. shutting down!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The immediate next step will be getting the code to run on a Shakti softcore on
an FPGA. In addition to targeting high-end FPGAs, we will also be targeting the
$100 &lt;a href=&quot;https://store.digilentinc.com/arty-a7-artix-7-fpga-development-board-for-makers-and-hobbyists/&quot;&gt;Arty
A7&lt;/a&gt;
hobbyist board and release all of the software under liberal open-source
licenses.&lt;/p&gt;

&lt;p&gt;Further along, we will port mirage libraries to Shakti following similar to the
setup in &lt;a href=&quot;https://github.com/well-typed-lightbulbs/&quot;&gt;Well-typed lightbulbs&lt;/a&gt; and
implementing hardware security enhancements in Shakti for preventing spatial and
temporal attacks while running unsafe C code (with the ability to dynamically
turn it off when running OCaml!), hardware-assisted compartments, etc. Lots of
exciting possibilities on the horizon!&lt;/p&gt;

&lt;h2 id=&quot;acknowledgements&quot;&gt;Acknowledgements&lt;/h2&gt;

&lt;p&gt;Much of this work was done by the incredible &lt;a href=&quot;https://github.com/sl33k&quot;&gt;Malte&lt;/a&gt;,
who is a visiting student at IIT Madras on a semester away from Leibniz
University Hannover,
&lt;a href=&quot;https://www.linkedin.com/in/arjun-menon/?originalSubdomain=in&quot;&gt;Arjun&lt;/a&gt;, Lavanya,
Ambika, &lt;a href=&quot;http://www.cse.iitm.ac.in/~chester/&quot;&gt;Chester&lt;/a&gt;, and the rest of the
Shakti team. The RISC-V port of OCaml is developed and maintained by &lt;a href=&quot;https://nojb.github.io/&quot;&gt;Nicolás
Ojeda Bär&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Continuous Benchmarking &amp; Call for Benchmarks</title>
   <link href="https://kcsrk.info/multicore/ocaml/benchmarks/2018/09/13/1543-multicore-ci/"/>
   <updated>2018-09-13T15:43:00+00:00</updated>
   <id>https://kcsrk.info/multicore/ocaml/benchmarks/2018/09/13/1543-multicore-ci</id>
   <content type="html">&lt;p&gt;Over the past few weeks, at &lt;a href=&quot;http://ocamllabs.io/&quot;&gt;OCaml Labs&lt;/a&gt;, we’ve deployed
continuous benchmarking infrastructure for &lt;a href=&quot;https://github.com/ocamllabs/ocaml-multicore&quot;&gt;Multicore
OCaml&lt;/a&gt;. Live results are available
at &lt;a href=&quot;http://ocamllabs.io/multicore&quot;&gt;http://ocamllabs.io/multicore&lt;/a&gt;. Continuous
benchmarking has already enabled us to make &lt;a href=&quot;https://github.com/ocamllabs/ocaml-multicore/pull/221&quot;&gt;informed
decisions&lt;/a&gt; about the
impact of our changes, and should come in handy over the next few months where
we polish off and tune the multicore runtime.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Currently, the benchmarks are all single-threaded and run on x86-64. Our current
aim is to quantify the performance impact of running single-threaded OCaml
programs using the multicore compiler. Moving forward, would would include
multi-threaded benchmarks and other architectures.&lt;/p&gt;

&lt;p&gt;The benchmarks and the benchmarking infrastructure were adapted from &lt;a href=&quot;https://github.com/OCamlPro/ocamlbench-repo&quot;&gt;OCamlPro’s
benchmark suite&lt;/a&gt; aimed at
benchmarking &lt;a href=&quot;https://bench.flambda.ocamlpro.com/&quot;&gt;Flambda optimisation passes&lt;/a&gt;.
The difference with the new infrastructure is that all the data is generated as
static HTML and CSV files with data processing performed on the client side in
JavaScript. I find the new setup easier to manage and deploy.&lt;/p&gt;

&lt;h2 id=&quot;quality-of-benchmarks&quot;&gt;Quality of benchmarks&lt;/h2&gt;

&lt;p&gt;If you observe the results, you will see that multicore is slowest compared to
trunk OCaml on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;menhir-standard&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;menhir-fancy&lt;/code&gt;. But if you look closely:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://kcsrk.info/assets/menhir-too-fast.png&quot; alt=&quot;Binary tree&quot; /&gt;&lt;/p&gt;

&lt;p&gt;these benchmarks complete in less than 10 milliseconds. This is not enough time
to faithfully compare the implementations as constant factors such as runtime
initialisation and costs of single untimely major GC dominate any useful work.
In fact, almost half of the benchmarks complete within a second. The quality of
this benchmark suite ought to be improved.&lt;/p&gt;

&lt;h2 id=&quot;call-for-benchmarks&quot;&gt;Call for benchmarks&lt;/h2&gt;

&lt;p&gt;While we want longer running benchmarks, we would also like those benchmarks to
represent real OCaml programs found in the wild. If you have long running &lt;em&gt;real&lt;/em&gt;
OCaml programs, please consider adding it to the benchmark suite. Your
contribution will ensure that performance-oriented OCaml features such as
multicore and flambda are evaluated on representative OCaml programs.&lt;/p&gt;

&lt;h2 id=&quot;how-to-contribute&quot;&gt;How to contribute&lt;/h2&gt;

&lt;p&gt;Make a PR to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;multicore&lt;/code&gt; branch of
&lt;a href=&quot;https://github.com/ocamllabs/ocamlbench-repo/tree/multicore&quot;&gt;ocamllabs/ocamlbench-repo&lt;/a&gt;.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;packages&lt;/code&gt; directory contains many examples for how to prepare programs for
benchmarking. Among these, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;numerical-analysis-bench&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;menhir-bench&lt;/code&gt; are
simple and illustrative.&lt;/p&gt;

&lt;p&gt;The benchmarks themselves are run using &lt;a href=&quot;https://github.com/kayceesrk/ocamlbench-scripts&quot;&gt;these
scripts&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;dockerfile&quot;&gt;Dockerfile&lt;/h3&gt;

&lt;p&gt;There is a handy Dockerfile to test benchmarking setup:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker build &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; multicore-cb &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; Dockerfile &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;#takes a while; grab a coffee&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This builds the docker image for the benchmarking infrastructure. You can run
the benchmarks as:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 8080:8080 &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; multicore-cb bash
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/ocamlbench-scripts
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./run-bench.sh &lt;span class=&quot;nt&quot;&gt;--nowait&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--lazy&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;#takes a while; grab lunch&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can view the results by:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/logs/operf
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;python &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; SimpleHTTPServer 8080&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now on your host machine, point your browser to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;localhost:8080&lt;/code&gt; to
interactively visualise the benchmark results.&lt;/p&gt;

&lt;h3 id=&quot;caveats&quot;&gt;Caveats&lt;/h3&gt;

&lt;p&gt;Aim to get your benchmark compiling with OCaml 4.06.1. You might have trouble
getting your benchmark to compile with the multicore compiler due to several
reasons:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Multicore compiler has syntax extensions for &lt;a href=&quot;http://kcsrk.info/ocaml/multicore/2015/05/20/effects-multicore/&quot;&gt;algebraic effect
handlers&lt;/a&gt;
which breaks packages that use ppx.&lt;/li&gt;
  &lt;li&gt;Multicore compiler has a different &lt;a href=&quot;https://github.com/ocaml/ocaml/pull/1003&quot;&gt;C
API&lt;/a&gt; which breaks core dependencies
such as Lwt.&lt;/li&gt;
  &lt;li&gt;Certain features such as marshalling closures and custom tag objects are
unimplemented.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you encounter trouble submitting benchmarks, please make an issue on
&lt;a href=&quot;https://github.com/kayceesrk/ocamlbench-scripts&quot;&gt;kayceesrk/ocamlbench-scripts&lt;/a&gt; repo.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>JFP Special Issue on Algebraic Effects and Handlers</title>
   <link href="https://kcsrk.info/handlers/paper/2018/08/16/jfp-effect-handlers/"/>
   <updated>2018-08-16T09:09:00+00:00</updated>
   <id>https://kcsrk.info/handlers/paper/2018/08/16/jfp-effect-handlers</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://www.andrej.com/&quot;&gt;Andrej Bauer&lt;/a&gt; and I are editing a special issue of JFP
on the theory and practice of algebraic effects and handlers. The CfP is below.&lt;/p&gt;

&lt;hr /&gt;

&lt;!--more--&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;CALL FOR PAPERS

JFP Special Issue
on
The Theory and Practice of Algebraic Effects and Handlers

Submission Deadline: 18 January 2019
Expected Publication Date: December 2019
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;scope&quot;&gt;Scope&lt;/h2&gt;

&lt;p&gt;An important aspect of real-world languages is their support for computational
effects such as raising exceptions, printing to the screen, accessing a
database, non-determinism, and concurrency. In order to reason about the
semantics of a programming language with computational effects, it is necessary
to separate the effects out from the rest of the language. To this end, algebraic
effects permit a wide class of computational effects to be specified in a pure
setting using only operations that give rise to them and equations that the
operations satisfy. The algebraic treatment of operations naturally leads to a
novel treatment of handlers for all computational effects, not just for
exceptions.&lt;/p&gt;

&lt;p&gt;Algebraic effect handlers have been steadily gaining attention as a programming
language feature since they generalise many control-flow abstractions such as
exception handling, iterators, async/await, or backtracking, while ensuring
that the composition of various features remains well-behaved. Indeed, there
are implementations of algebraic effects and effect handlers as libraries in C,
Clojure, F#, Haskell, OCaml, Scala, JavaScript, as well as full-fledged
languages such as Eff, Frank, Links, Koka, and Multicore OCaml. Algebraic effect
handlers have also influenced the design of software tools in industry
including Facebook’s React UI library and Uber’s Pyro probabilistic programming
language.&lt;/p&gt;

&lt;p&gt;To recognise and encourage the publication of mature research contributions in
this area, a special issue of the Journal of Functional Programming (JFP) will
be devoted to the same theme.&lt;/p&gt;

&lt;h2 id=&quot;topics&quot;&gt;Topics&lt;/h2&gt;

&lt;p&gt;Full-length, archival-quality submissions are solicited on theoretical and
practical aspects of algebraic effects and handlers. Examples
include, but are not limited to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Reasoning about algebraic effects and handlers (denotational semantics,
dependent types, logical relations, language support for equational reasoning)&lt;/li&gt;
  &lt;li&gt;Effect typing (subtyping, row-polymorphism, generativity, encapsulation)&lt;/li&gt;
  &lt;li&gt;Implementation of effect handlers (dynamic effects, selective CPS
translations, delimited continuations)&lt;/li&gt;
  &lt;li&gt;Applications of algebraic effect handlers (probabilistic programming, event
correlation, meta-programming, asynchronous I/O, debugging)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;
Reports on applications of these techniques to real-world problems are
especially encouraged, as are submissions that relate ideas and concepts from
several of these topics, or bridge the gap between theory and practice.&lt;/p&gt;

&lt;p&gt;Papers will be reviewed as regular JFP submissions, and acceptance in the
special issue will be based on both JFP’s quality standards and relevance to
the theme. The special issue also welcomes high-quality survey and position
papers that would benefit a wide audience.&lt;/p&gt;

&lt;p&gt;Authors are encouraged to indicate interest in submitting by &lt;strong&gt;December 14,
2018&lt;/strong&gt;, to aid in identifying suitable reviewers. The submission deadline is
&lt;strong&gt;January 18, 2019&lt;/strong&gt;. The expected submission length is 25-35 pages, excluding
bibliography and appendices. Shorter submissions are encouraged; prospective
authors of longer submissions should discuss their plans with the special issue
editors in advance.&lt;/p&gt;

&lt;p&gt;Submissions that are based on previously-published conference or workshop
papers must clearly describe the relationship with the initial publication, and
must differ sufficiently that the author can assign copyright to Cambridge
University Press. Prospective authors are welcome to discuss such submissions
with the editors to ensure compliance with this policy.&lt;/p&gt;

&lt;h2 id=&quot;submissions&quot;&gt;Submissions&lt;/h2&gt;

&lt;p&gt;Submissions should be sent through the JFP Manuscript Central system at
&lt;a href=&quot;https://mc.manuscriptcentral.com/cup/jfp_submit&quot;&gt;https://mc.manuscriptcentral.com/cup/jfp_submit&lt;/a&gt;.
Choose “Effects and Handlers” as the paper type, so that it gets assigned to the
special issue.&lt;/p&gt;

&lt;p&gt;For other submission details, please consult an issue of the Journal of
Functional Programming or see the Journal’s web page at
&lt;a href=&quot;http://journals.cambridge.org/jid_JFP&quot;&gt;http://journals.cambridge.org/jid_JFP&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;tentative-schedule&quot;&gt;Tentative Schedule&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;14 December 2018: Expression of interest&lt;/li&gt;
  &lt;li&gt;18 January 2019: Submission deadline&lt;/li&gt;
  &lt;li&gt;22 April 2019: First round of reviews&lt;/li&gt;
  &lt;li&gt;23 August 2019: Revision deadline&lt;/li&gt;
  &lt;li&gt;15 November 2019: Second round of reviews&lt;/li&gt;
  &lt;li&gt;13 December 2019: Final accepted versions due&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;guest-editors&quot;&gt;Guest Editors&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Andrej Bauer, Faculty of Mathematics and Physics, University of Ljubljana&lt;/li&gt;
  &lt;li&gt;KC Sivaramakrishnan, Department of Computer Science and Technology,
University of Cambridge&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;editors-in-chief&quot;&gt;Editors in Chief&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Jeremy Gibbons, Department of Computer Science, University of Oxford&lt;/li&gt;
  &lt;li&gt;Matthias Felleisen, College of Computer and Information Science, Northeastern
University&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>A deep dive into Multicore OCaml garbage collector</title>
   <link href="https://kcsrk.info/multicore/gc/2017/07/06/multicore-ocaml-gc/"/>
   <updated>2017-07-06T01:36:00+00:00</updated>
   <id>https://kcsrk.info/multicore/gc/2017/07/06/multicore-ocaml-gc</id>
   <content type="html">&lt;style&gt;
.annotslide{display:none}
&lt;/style&gt;

&lt;p&gt;I recently gave a talk on the internals of multicore OCaml GC at Jane Street
offices in NYC. The slides from the talk are available
&lt;a href=&quot;https://speakerdeck.com/kayceesrk/multicore-ocaml-gc&quot;&gt;online&lt;/a&gt;. But I felt that
the slides alone aren’t particularly edifying. This post is basically the slides
from the talk annotated with notes.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;In a mostly functional language like OCaml, it is desirable to have each domain
(our unit of parallelism) collect its own local garbage independently. Given
that OCaml is commonly used for writing latency sensitive code such as trading
systems, UIs, networked unikernels, it is also desirable to minimise the
stop-the-world phases in the GC. Although obvious, the difficulty is to make
this work in the presence of mutations and concurrency. In this talk, I will
present the overall design of Multicore OCaml GC, but also deep dive into a few
of the interesting techniques that make it work.&lt;/p&gt;

&lt;h2 id=&quot;slidedeck&quot;&gt;Slidedeck&lt;/h2&gt;

&lt;p align=&quot;center&quot;&gt;
  Slide &lt;input type=&quot;number&quot; id=&quot;slidenumber&quot; min=&quot;1&quot; /&gt; of &lt;span id=&quot;totalslides&quot;&gt;&lt;/span&gt;
  &lt;input type=&quot;button&quot; value=&quot;Go&quot; onclick=&quot;currentSlide()&quot; /&gt;
  &lt;button onclick=&quot;deltaSlide(-1)&quot;&gt;❮ Prev&lt;/button&gt;
  &lt;button onclick=&quot;deltaSlide(1)&quot;&gt;Next ❯&lt;/button&gt;
  ( ← and → arrow keys also work)
&lt;/p&gt;

&lt;div class=&quot;annotslide&quot;&gt;

&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.001.png&quot; border=&quot;1&quot; alt=&quot;GC.001&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;  
Multicore OCaml project is led from OCaml Labs within the University of
Cambridge. &lt;a href=&quot;http://stedolan.net/&quot;&gt;Stephen Dolan&lt;/a&gt; begun the project
while procrastinating on writing up his &lt;a href=&quot;http://stedolan.net/research/#thesis&quot;&gt;dissertation&lt;/a&gt;. Hurray to that! 
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt; 
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.006.png&quot; border=&quot;1&quot; alt=&quot;GC.006&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
Multicore OCaml extends OCaml with native support for concurrency and
parallelism. Unlike many other languages, we clearly separate concurrency from
parallelism in the language. Concurrency in Multicore OCaml is expressed through
lightweight language level threads called &lt;em&gt;fibers&lt;/em&gt;. The unit of
parallelism is a &lt;em&gt;domain&lt;/em&gt;, which maps to kernel threads. Many kernel
threads may service a particular domain, but only one of those kernel threads
ever runs OCaml code. A typical program is expected to have a large number of
fibers mapped over a few domains. In this talk, I provide an overview of the
Multicore OCaml GC design, with a few deep dives into some of the interesting
and novel techniques.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.007.png&quot; border=&quot;1&quot; alt=&quot;GC.007&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

It is difficult to appreciate the subtleties of the choice of GC techniques in
isolation. So we shall begin with a sane setup - a GC for a sequential purely
functional language. We shall subsequently extend the language with series of
reprehensible extensions including mutations, parallelism and concurrency, in
that order, and observe how the sane setup falls apart and what we shall do to
recover sanity while retaining efficiency. The early parts of the talk should be
unsurprising to someone familiar with GC internals, but is useful for setting up
the latter material. 
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.010.png&quot; border=&quot;1&quot; alt=&quot;GC.010&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

The figure shows the snapshot of the runtime state of a sequential purely
functional language. We have a set of objects allocated on the heap. These
objects may be pointed to be other heap objects as well as any of the registers
and the current runtime stack. The simplest GC strategy is to stop the program
and perform a mark-and-sweep garbage collection. The core idea is that we start
from the &lt;em&gt;roots&lt;/em&gt; of the program state i.e., current stack and registers, and
perform a depth-first traversal through the object graph. Any unreachable
objects are garbage and they can be reclaimed. 

Tri-colour marking is a standard marking algorithm. During marking, the objects
are in one of three states: white(unmarked), grey(marking) and black(marked). 
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.011.png&quot; border=&quot;1&quot; alt=&quot;GC.011&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

At the beginning of the GC, all objects are white. The GC marks grey any white
object it finds and pushes it into the &lt;em&gt;mark stack&lt;/em&gt;. Subsequently, objects are
popped off the mark stack, all of its white children marked, and the object is
marked black. We have the invariant that a black object does not point to a
white object. This is called the &lt;em&gt;tri-colour invariant&lt;/em&gt;. The figure shows the
state when object &lt;code class=&quot;highlighter-rouge&quot;&gt;A&lt;/code&gt; and its children have been marked (hence, &lt;code class=&quot;highlighter-rouge&quot;&gt;A&lt;/code&gt; is black),
object &lt;code class=&quot;highlighter-rouge&quot;&gt;B&lt;/code&gt; has been marked grey and is on the mark stack.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.012.png&quot; border=&quot;1&quot; alt=&quot;GC.012&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

GC is done when the mark stack is empty. At this point, all reachable objects
are black. Any unreachable objects are white. A sweeper examines &lt;em&gt;all&lt;/em&gt; the
allocated objects, and marks any object still white as free space that can
subsequently be reused. 
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.015.png&quot; border=&quot;1&quot; alt=&quot;GC.015&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

Mark and sweep GC has several advantages. For starters, it is a very simple
algorithm as GC algorithms go. The algorithm is also naturally incremental. The
mutator (OCaml code) and the GC work can alternate between each other,
minimizing the pause times in the GC. However, the primary disadvantage with
this scheme is that one needs to maintain a free-list of objects for
allocations. While there are many algorithms to find the best place to allocate
an object, all of them have non-trivial overheads. Functional programming
languages have high rate of allocation and would benefit fast allocations.
Moreover, free-list implementations also suffer from fragmentation. 
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.019.png&quot; border=&quot;1&quot; alt=&quot;GC.019&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

To alleviate this, functional programming languages typically implement a
generational GC. Generational hypothesis says that the young objects are far
more likely to die than older objects. To take advantage of this, the heap is
split into two -- a small minor heap, where new objects are allocated and a
larger major heap. In particular, objects in the minor heap are allocated by
bumping the frontier, leading to fast allocations. When the minor heap is full,
we garbage collect the minor heap.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.020.png&quot; border=&quot;1&quot; alt=&quot;GC.020&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

Minor heap is GCed with a &lt;em&gt;copying collector&lt;/em&gt;, and any object that survives the
minor GC is promoted to the major GC. A nice aspect of copying collection for
minor GC is that only the live objects need to be scanned, unlike mark and sweep
collection where the sweeper needs to examine every allocated object. Given the
generational hypothesis, we will not examine most of the objects in the minor
heap. As a data point, the minor GC survival rate while compiling the OCaml
compiler is around 10%.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.021.png&quot; border=&quot;1&quot; alt=&quot;GC.021&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

The roots for the minor collection are the current stack and the live register
set. Since our language is purely functional, there will be no pointers from the
major heap to the minor heap. This is because all the objects in major heap are
older than all the objects in the minor heap. The lack of mutations mean that an
object can only point to an older object. Hence, we don&apos;t need to care about
objects in the major heap for minor collections.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.022.png&quot; border=&quot;1&quot; alt=&quot;GC.022&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

With mutations, the major heap may point to the minor heap. For example, by
assigning a minor heap object to a major heap reference. We need to know these
references so that we can treat them as roots for the minor collection. 
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.023.png&quot; border=&quot;1&quot; alt=&quot;GC.023&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

Naively, we can scan the entire major heap for every minor GC to find such
pointers. But this is impractical. 
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.024.png&quot; border=&quot;1&quot; alt=&quot;GC.024&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

Instead, we intercept the writes with a &lt;em&gt;write barrier&lt;/em&gt; that records such
pointers in an auxiliary data structure called the &lt;em&gt;remembered set&lt;/em&gt;. 
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.025.png&quot; border=&quot;1&quot; alt=&quot;GC.025&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

Remembered set holds the set of pointers from the major heap to the minor heap,
and is used as the root for minor collections. After the minor collection, the
remembered set is cleared.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.026.png&quot; border=&quot;1&quot; alt=&quot;GC.026&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

Mutations breaks tri-colour invariant. Suppose our heap has these three
objects...
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.027.png&quot; border=&quot;1&quot; alt=&quot;GC.027&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

and we assign the white object &lt;code class=&quot;highlighter-rouge&quot;&gt;B&lt;/code&gt; to the
black object &lt;code class=&quot;highlighter-rouge&quot;&gt;C&lt;/code&gt;...
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.028.png&quot; border=&quot;1&quot; alt=&quot;GC.028&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

and we subsequently delete the pointer from &lt;code class=&quot;highlighter-rouge&quot;&gt;A&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;B&lt;/code&gt;.
If we perform a major GC now, 
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.029.png&quot; border=&quot;1&quot; alt=&quot;GC.029&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

&lt;code class=&quot;highlighter-rouge&quot;&gt;A&lt;/code&gt; will be eventually marked as black. But
the white object &lt;code class=&quot;highlighter-rouge&quot;&gt;B&lt;/code&gt; is only pointed to by
the black object &lt;code class=&quot;highlighter-rouge&quot;&gt;C&lt;/code&gt;, which will not be
marked, 
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.030.png&quot; border=&quot;1&quot; alt=&quot;GC.030&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

and the sweeper will mark it as free. This leaves the heap in an inconsistent
state.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.031.png&quot; border=&quot;1&quot; alt=&quot;GC.031&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

Mutations are problematic if two conditions hold. 1. there exists a black to
white pointer and 2. all references from a grey object through a chain of white
objects to that white object is deleted. We can recover correctness if we
disallow one of these conditions.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.034.png&quot; border=&quot;1&quot; alt=&quot;GC.034&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

An insertion barrier prohibits 1. Whenever a black to white pointer may be
established, the insertion barrier marks the target. 
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.035.png&quot; border=&quot;1&quot; alt=&quot;GC.035&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

This prevents &lt;code class=&quot;highlighter-rouge&quot;&gt;B&lt;/code&gt; from being GCed. The insertion barrier is said to preserve
&lt;em&gt;strong&lt;/em&gt; tri-colour invariant: A black object never points to a white
object. 
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.038.png&quot; border=&quot;1&quot; alt=&quot;GC.038&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

A deletion barrier prohibits 2. In particular, deletion barrier allows the black
to white pointer from &lt;code class=&quot;highlighter-rouge&quot;&gt;C&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;B&lt;/code&gt;. 
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.039.png&quot; border=&quot;1&quot; alt=&quot;GC.039&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

But when the pointer from the grey &lt;code class=&quot;highlighter-rouge&quot;&gt;A&lt;/code&gt; to
the white &lt;code class=&quot;highlighter-rouge&quot;&gt;B&lt;/code&gt; is deleted, &lt;code class=&quot;highlighter-rouge&quot;&gt;B&lt;/code&gt; is marked. This prevents &lt;code class=&quot;highlighter-rouge&quot;&gt;B&lt;/code&gt; from being GCed. The deletion barrier
preserves &lt;em&gt;weak&lt;/em&gt; tri-colour invariant: for any white object pointed to by
black object, there exists some grey object from which through a series of white
objects that white object is reachable.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.040.png&quot; border=&quot;1&quot; alt=&quot;GC.040&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

Deletion barrier is used by OCaml. We extend the write barrier to mark the
original object in the reference &lt;code class=&quot;highlighter-rouge&quot;&gt;r&lt;/code&gt; if
both &lt;code class=&quot;highlighter-rouge&quot;&gt;r&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;x&lt;/code&gt; are in the major heap. 
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.043.png&quot; border=&quot;1&quot; alt=&quot;GC.042&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

Let us extend the language by adding support for parallel execution. In
Multicore OCaml, &lt;code class=&quot;highlighter-rouge&quot;&gt;Domain.spawn&lt;/code&gt; forks off a
new domain to run the thunk in parallel with the calling domain. It is
reasonable to expect that most of the objects in the minor heap are in fact local
to the domain which allocated the object, and are never shared between domains.
Hence, it is desirable to collect each domain&apos;s young garbage independently
without having to synchronize all of the domains. 
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.044.png&quot; border=&quot;1&quot; alt=&quot;GC.044&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

This can be done if the minor heap objects are only accessed by the owning
domain.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.045.png&quot; border=&quot;1&quot; alt=&quot;GC.045&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;

In their &lt;a href=&quot;http://gallium.inria.fr/~xleroy/publi/concurrent-gc.pdf&quot;&gt;POPL&apos;93
paper&lt;/a&gt;, Doligez and Leroy built a concurrent garbage collector for concurrent
caml light which used domain local heaps. In their paper, the heap invariants
imposed are that there are no pointers between the local heaps and the major
heap does not point to any minor heaps. 
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.046.png&quot; border=&quot;1&quot; alt=&quot;GC.046&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
These heap invariants are enforced with the help of a write barrier that
intercepts writes, and whenever there is a pointer about to be created between
the major and a minor heap, the transitive closure of the minor heap object is
promoted to the major heap before the assignment.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.047.png&quot; border=&quot;1&quot; alt=&quot;GC.047&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
The problem with this strategy is that we end up with false promotions. Consider
a work stealing queue used for sharing work among multiple domains. It is very
likely that the work-stealing queue survives the minor collection and is
promoted to the major heap. Now, whenever a domain adds work to the queue, the
work needs to be promoted to preserve the heap invariant, even though we expect
that the domain which added the work to consume it in the common case. 
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.049.png&quot; border=&quot;1&quot; alt=&quot;GC.049&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
Hence, we relax this invariant to allow pointers from major heap to the minor.
We still do not allow pointers between minor heaps, but allow pointers from
major to minor heaps. 
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.050.png&quot; border=&quot;1&quot; alt=&quot;GC.050&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
We make sure that a domain does not access objects in a foreign domain with the
help of a read barrier. The read barrier intercepts reads to mutable fields. If
the value loaded is an integer, an object in the shared heap or own minor heap,
then we let the read continue. Otherwise, we interrupt the domain which owns the
object to promote the object closure. This operation returns the new location of
the object in the major heap. This scheme ensures that the minor heaps can be
independently GCed. &lt;a href=&quot;https://www.microsoft.com/en-us/research/wp-content/uploads/2016/07/local-gc.pdf&quot;&gt;Marlow
and Peyton Jones&lt;/a&gt; evaluated a local heap design with similar weaker heap
invariants for GHC Haskell.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.054.png&quot; border=&quot;1&quot; alt=&quot;GC.054&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
There is a surprisingly efficient way to implement the read barrier checks
through careful virtual memory mapping for minor heaps and a few bit twiddling
tricks. Recall that the fast path for the read barrier is the value read is
either an integer, or a shared heap value, or a value in own minor heap. Let us
assume a 16-bit address space. The minor heap are all allocated in a contiguous
power-of-2 aligned virtual memory area, where each minor heap is also a
power-of-2 aligned and sized. Not all of the virtual memory area need to be
allocated, but only needs to be reserved. In particular, we ensure that shared
heap pages are not allocated in the minor heap area.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.056.png&quot; border=&quot;1&quot; alt=&quot;GC.056&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
Addresses in this 16-bit address space can be written as 4 quads &lt;code class=&quot;highlighter-rouge&quot;&gt;0xPQRS&lt;/code&gt;. In OCaml, integer values are
represented by tagging the least significant bit to be 1. Hence, in this
example, integers have low bit of &lt;code class=&quot;highlighter-rouge&quot;&gt;S&lt;/code&gt; to be
1. Minor heap values have &lt;code class=&quot;highlighter-rouge&quot;&gt;PQ&lt;/code&gt; to be &lt;code class=&quot;highlighter-rouge&quot;&gt;42&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;R&lt;/code&gt; 
determines the domain. 

We can implement the read barrier check by comparing the given address with an
address from the minor heap. Luckily, we have such an address handily available
in the register -- the &lt;em&gt;allocation pointer&lt;/em&gt;. On amd64, the allocation
pointer is in register &lt;code class=&quot;highlighter-rouge&quot;&gt;r15&lt;/code&gt;.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.057.png&quot; border=&quot;1&quot; alt=&quot;GC.057&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
Here is our read barrier implementation for amd64 architecture. Assume that the
value of interest is in &lt;code class=&quot;highlighter-rouge&quot;&gt;rax&lt;/code&gt; register. At
the end of this sequence of instructions, if none of the enabled bits in &lt;code class=&quot;highlighter-rouge&quot;&gt;0xff01&lt;/code&gt; are set in &lt;code class=&quot;highlighter-rouge&quot;&gt;rax&lt;/code&gt;, then zero flag will be set, and we know
that the value is not a pointer into a foreign minor heap. Let&apos;s see how this
works for the different cases.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.058.png&quot; border=&quot;1&quot; alt=&quot;GC.058&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
In the case, of integer, the least significant bit remains set, and hence zero
flag will not be set. We are safe to read this value.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.059.png&quot; border=&quot;1&quot; alt=&quot;GC.059&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
In the case of a shared heap address, the &lt;code class=&quot;highlighter-rouge&quot;&gt;PQ&lt;/code&gt; bits will different between &lt;code class=&quot;highlighter-rouge&quot;&gt;r15&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;rax&lt;/code&gt;. Hence, zero flag will not be set.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.061.png&quot; border=&quot;1&quot; alt=&quot;GC.061&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
In the case of an address in own minor heap, the bits &lt;code class=&quot;highlighter-rouge&quot;&gt;PQR&lt;/code&gt; will be the same. Hence, the subtraction
underflows and sets all the bits in &lt;code class=&quot;highlighter-rouge&quot;&gt;PQ&lt;/code&gt;.
Hence, the zero flag will not be set.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.062.png&quot; border=&quot;1&quot; alt=&quot;GC.062&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt; 
In the case of an address in foreign minor heap, the bits &lt;code class=&quot;highlighter-rouge&quot;&gt;PQ&lt;/code&gt; will be the same. The bits in &lt;code class=&quot;highlighter-rouge&quot;&gt;R&lt;/code&gt; will be different, and &lt;code class=&quot;highlighter-rouge&quot;&gt;S&lt;/code&gt; will be zero in both values. After xoring,
&lt;code class=&quot;highlighter-rouge&quot;&gt;R&lt;/code&gt; will be non-zero and importantly, the
rest of the bits are zero. Subtracting 1 from a non-zero value does not
underflow, hence the rest of the bits remain zero. Now, the zero flag will be
set after the test, and we know that the pointer is in the foreign minor heap.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.065.png&quot; border=&quot;1&quot; alt=&quot;GC.065&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
&lt;p&gt;
We now have an efficient way to find out whether we need to promote. But how do
we perform the promotion on a read fault? The general strategy is to interrupt
the foreign domain to perform the promotion for us. There are several
alternatives here. 
&lt;/p&gt;

&lt;p&gt;
On receiving the interrupt, the foreign domain may copy the objects from its
minor heap to the major heap. While this strategy works for immutable objects,
mutable objects which are copied should somehow be kept in sync on updates. This
gets tricky especially with relaxed memory behaviours observed on modern
multicore hardware. Moreover, this scheme breaks OCaml objects with &lt;code class=&quot;highlighter-rouge&quot;&gt;Abstract_tag&lt;/code&gt; where a C library may map a C
structure onto the OCaml heap and modify it transparently without the knowledge
of the write barrier. Hence, the copies may go out of sync.
&lt;/p&gt;

&lt;p&gt;
We may instead move the object to the major heap and perform a minor GC to fix
any references to the promoted objects. However, this scheme suffers from false
promotions and long pauses during reads. To avoid false promotions, we may
promote the object and scan the roots and the entire minor heap to fix any
references to promoted objects. However, one needs to scan all the objects in
the minor heap, which even the minor collection doesn&apos;t have to do.
&lt;/p&gt;
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.067.png&quot; border=&quot;1&quot; alt=&quot;GC.067&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
We make the observation that most objects promoted on read faults happen to be
recently allocated. The reason being that such objects are messages placed into
channels where there is a waiting receiver on the other domain which can consume
the message immediately. In our experiments on a small corpus of parallel OCaml
programs, we found that 95% of objects promoted on read fault are among the
youngest 5%. To make use of this fact, we combine the solutions 2 and 3 from
above.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.071.png&quot; border=&quot;1&quot; alt=&quot;GC.071&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
If the objected to be promoted on read fault is among the youngest x% (in the
current implementation x = 10, but can be dynamically chosen), then we move the
transitive object closure to the major heap. We may have extant pointers into
the promoted objects. We need to fix those pointers such that they point to the
new location of these objects in the major heap. In particular, the pointers may
be found in the roots, objects younger than promoted object in the minor heap,
and older minor objects that point to younger minor objects due to mutations of
older objects. For the latter, we extend the write barrier to record such minor
to minor pointers in &lt;code class=&quot;highlighter-rouge&quot;&gt;promotion_set&lt;/code&gt;, which
is only scanned during the promotion process. Otherwise, we move the object
closure and perform a minor GC.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.073.png&quot; border=&quot;1&quot; alt=&quot;GC.073&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
That resolves the major pain points in the interaction of parallelism with minor
GC and promotion. The next is the interplay between parallelism and major GC.
Recall that OCaml&apos;s major GC is incremental -- the mutator and the GC (mark and
sweep) take turns to run. If we were to extend the scheme naively to parallel
execution, we would have a stop-the-world incremental collector, where all the
domains have to synchronize for GC work. This would introduce significant
latency overheads. Instead, we go for a concurrent collector design where the
mutator and the GC thread can run in parallel.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.076.png&quot; border=&quot;1&quot; alt=&quot;GC.076&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
Our design is based on the &lt;a href=&quot;http://doc.cat-v.org/inferno/concurrent_gc/concurrent_gc.pdf&quot;&gt;Very
Concurrent Mark-&amp;amp;-Sweep Garbage Collector (VCGC)&lt;/a&gt; design from the Inferno
project which allows the mutator, marker and the sweeper threads to run
concurrently. In VCGC design, there is a small stop-the-world phase at the end
of a cycle where the threads agree on the end of the current major GC cycle and
the beginning of the next one. Multicore OCaml&apos;s major GC is mostly concurrent
mark and sweep where the stop-the-world phase might need to do a small fraction
of major GC work left over before the end of the cycle, not unlike the VCGC
design with many mutators i.e., parallel execution.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.080.png&quot; border=&quot;1&quot; alt=&quot;GC.080&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
The major heap objects are in one of the 4 states: &lt;code class=&quot;highlighter-rouge&quot;&gt;Marked&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;Unmarked&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;Garbage&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;Free&lt;/code&gt;. The domains alternate between running the
mutator and performing GC work. The GC thread performs a depth-first traversal
of the heap. If it finds an &lt;code class=&quot;highlighter-rouge&quot;&gt;Unmarked&lt;/code&gt;
object, it changes its colour to &lt;code class=&quot;highlighter-rouge&quot;&gt;Marked&lt;/code&gt;
and pushes the object into a domain-local mark-stack. On the other hand, if it
finds a &lt;code class=&quot;highlighter-rouge&quot;&gt;Garbage&lt;/code&gt; object, it marks it as
&lt;code class=&quot;highlighter-rouge&quot;&gt;Free&lt;/code&gt; and adds it to the free list. Since
multiple GC threads operate on the heap simultaneously, marking is racy but
idempotent. In particular, there is no synchronization for marking the objects.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.082.png&quot; border=&quot;1&quot; alt=&quot;GC.082&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
If any domain thinks that all the work in the current major GC cycle is done (in
practice, close to being done), it calls for a global synchronization where all
the domains synchronize on the barrier. Once stopped, all the domains work to
actually finish marking, as some work may be left over at other domains. Once
that is done, the cores agree to flip the meaning of the colours. Anything that
is &lt;code class=&quot;highlighter-rouge&quot;&gt;Unmarked&lt;/code&gt; is considered &lt;code class=&quot;highlighter-rouge&quot;&gt;Garbage&lt;/code&gt;. Anything that is &lt;code class=&quot;highlighter-rouge&quot;&gt;Marked&lt;/code&gt; becomes &lt;code class=&quot;highlighter-rouge&quot;&gt;Unmarked&lt;/code&gt; for the next cycle. &lt;code class=&quot;highlighter-rouge&quot;&gt;Garbage&lt;/code&gt; objects are considered &lt;code class=&quot;highlighter-rouge&quot;&gt;Marked&lt;/code&gt;, but at the end of the major GC, all
&lt;code class=&quot;highlighter-rouge&quot;&gt;Garbage&lt;/code&gt; objects have been marked &lt;code class=&quot;highlighter-rouge&quot;&gt;Free&lt;/code&gt;. Hence, no objects fall into this
category. Anything that is marked &lt;code class=&quot;highlighter-rouge&quot;&gt;Free&lt;/code&gt;
still remains &lt;code class=&quot;highlighter-rouge&quot;&gt;Free&lt;/code&gt;. This concludes the
discussion on parallelism.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.083.png&quot; border=&quot;1&quot; alt=&quot;GC.083&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
We introduce concurrency into the mix next. Concurrency in Multicore OCaml is
expressed through fibers, which are language-level lightweight threads. Fibers
are implemented as heap allocated, dynamically resized stack segments. Just like
mutating a regular heap object, fibers can also be mutated by pushing and
popping values. However, unlike regular objects, fiber mutations are not
protected by a write barrier. This poses challenges to maintaining the heap
invariants.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.084.png&quot; border=&quot;1&quot; alt=&quot;GC.084&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
The main thread in Multicore OCaml is also a fiber. Hence, the GC root current
stack is just a pointer to the current fiber. Since we don&apos;t have write barrier
on pushing to a fiber, we need to approximate the pointers that may arise from a
fiber in the major heap which points to the minor heap. We do this with the help
of &lt;em&gt;remembered fiber set&lt;/em&gt;. 
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.085.png&quot; border=&quot;1&quot; alt=&quot;GC.085&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
This represents the set of fibers in the major heap that ran in the current
minor cycle on some domain. Similar to remembered set, the remembered fiber set
is also a domain local data structure. The remembered fiber set is a root for
minor GCs. The remembered fiber set is cleared along with the remembered set at
the end of minor GC.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.086.png&quot; border=&quot;1&quot; alt=&quot;GC.086&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
&lt;p&gt;
We also treat fibers specially during promotions on read faults. Fibers
transitively reachable are not promoted automatically in order to avoid
prematurely promoting the entire world. We envision work stealing schedulers
where the fiber only needs to be promoted when a different domain explicitly
demands it.
&lt;/p&gt;

In this example, when assigning &lt;code class=&quot;highlighter-rouge&quot;&gt;x&lt;/code&gt; to
&lt;code class=&quot;highlighter-rouge&quot;&gt;r&lt;/code&gt;, instead of promoting fiber &lt;code class=&quot;highlighter-rouge&quot;&gt;f&lt;/code&gt;, 
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.088.png&quot; border=&quot;1&quot; alt=&quot;GC.088&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
we leave it on the minor heap. We record &lt;code class=&quot;highlighter-rouge&quot;&gt;x&lt;/code&gt; in the remembered set.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.089.png&quot; border=&quot;1&quot; alt=&quot;GC.089&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
And when a different domain demands it i.e., tries to context switch to the
fiber &lt;code class=&quot;highlighter-rouge&quot;&gt;f&lt;/code&gt;,  
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.090.png&quot; border=&quot;1&quot; alt=&quot;GC.090&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
then we promote the fiber and its transitive closure.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.092.png&quot; border=&quot;1&quot; alt=&quot;GC.092&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
Since we&apos;ve added the domain-local remembered fiber set, at every instance the
fast path is taken on a read fault, we are obligated to scan this set just after
the promotion is done. But the remembered fiber set may be large, and the fiber
stacks themselves can be large. Hence, scanning the stack for most promotions
would introduce large pause times.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.093.png&quot; border=&quot;1&quot; alt=&quot;GC.093&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
We would like to break up the large pause time if possible. We can do this by
lazily scanning the fibers just before a context switch. We only need to scan a
fiber once per promotion. We also expect the rate of context switches to be much
smaller than the rate of promotions. Hence, in practice, the fiber only gets
scanned once per batch of promotions.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.096.png&quot; border=&quot;1&quot; alt=&quot;GC.096&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
How does concurrency affect the major GC? Recall that Multicore OCaml uses a
deletion barrier. In a deletion barrier, whenever a major heap object loses a
reference to another major heap object, we have to mark the target object.
However, fiber stack pops are not protected by a write barrier. Instead, we
conservatively mark all of the objects on the fiber before switching to it. This
is not to dissimilar to the current stock OCaml compiler scanning the current
stack (as part of the roots) at the beginning of the major GC cycle.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.097.png&quot; border=&quot;1&quot; alt=&quot;GC.097&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
In VCGC, marking is racy but idempotent. Hence, the mutators can freely read and
write the object while it is concurrently marked. In particular, no
synchronization such as compare-and-swap or locks are required to mediate access
between the mutator and the GC thread. However, this invariant does not hold for
fibers. Assume that a mutator is about to context switch to a thread while a GC
thread on another domain attempts to scan and mark the objects on the fiber.
Since the mutator may push and pop the fiber stack, the GC thread concurrently
scanning the stack may observe inconsistent state.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.098.png&quot; border=&quot;1&quot; alt=&quot;GC.098&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
In order to prevent this inconsistency, before switching to a unmarked fiber,
the fiber is marked and all the objects on the fiber are also marked -- fiber is
made &lt;code class=&quot;highlighter-rouge&quot;&gt;Black&lt;/code&gt;. And in order to prevent racy
access, the fiber is locked while marking. If the GC thread holds the lock on a
fiber and a mutator tries to context switch to it, the mutator blocks until the
fiber is marked. If the GC thread loses the race, it can safely skip marking the
fiber.
&lt;/div&gt;

&lt;div class=&quot;annotslide&quot;&gt;
&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/GC.099.png&quot; border=&quot;1&quot; alt=&quot;GC.099&quot; width=&quot;80%&quot; /&gt; &lt;/p&gt;
In summary, the Multicore OCaml GC optimizes for latency and minimizes the
maximum pause time through independent minor GCs and a mostly concurrent
mark-and-sweep collector for major GCs. The challenge is to consider the
interactions between mutations, concurrency and parallelism and the various GC
techniques in order to come up with a design that preserves safety and optimizes
our performance goals. I will have to save the performance analysis of the GC to
a different talk. 
&lt;/div&gt;

&lt;script&gt;
var slideIndex = 1;

function init() {
  showSlide(slideIndex);
  var x = document.getElementsByClassName(&quot;annotslide&quot;);
  document.getElementById(&quot;slidenumber&quot;).max = x.length;
  document.getElementById(&quot;totalslides&quot;).innerHTML = x.length;
}

init();

function deltaSlide(n) {
  showSlide(slideIndex += n);
}

function currentSlide() {
  showSlide(slideIndex = Number(document.getElementById(&quot;slidenumber&quot;).value));
}

function showSlide(n) {
  var i;
  var x = document.getElementsByClassName(&quot;annotslide&quot;);
  if (n &gt; x.length) {slideIndex = 1}    
  if (n &lt; 1) {slideIndex = x.length}
  for (i = 0; i &lt; x.length; i++) {
    x[i].style.display = &quot;none&quot;;  
  }
  x[slideIndex-1].style.display = &quot;block&quot;;  
  document.getElementById(&quot;slidenumber&quot;).value = slideIndex;
}

document.onkeydown = function(evt) {
	evt = evt || window.event;
	switch (evt.keyCode) {
		case 37:
			deltaSlide(-1);
			break;
		case 39:
			deltaSlide(1);
			break;
	}
};

&lt;/script&gt;

&lt;h2 id=&quot;further-reading&quot;&gt;Further Reading&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ocamllabs/ocaml-multicore&quot;&gt;Multicore OCaml&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;Concurrency
        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;http://kcsrk.info/ocaml/multicore/2015/05/20/effects-multicore/&quot;&gt;Effective Concurrency with Algebraic Effects&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;http://kcsrk.info/ocaml/multicore/effects/2015/05/27/more-effects/&quot;&gt;Pearls of Algebraic Effects and Handlers&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;https://github.com/kayceesrk/effects-examples&quot;&gt;Examples&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;http://kcsrk.info/&quot;&gt;and more papers&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/ocamllabs/ocaml-multicore/wiki&quot;&gt;Wiki&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;GC bibliography
    &lt;ul&gt;
      &lt;li&gt;Damien Doligez and Xavier Leroy. “A concurrent, generational garbage collector for a multithreaded implementation of ML.” POPL 1993.&lt;/li&gt;
      &lt;li&gt;Simon Marlow and Simon Peyton Jones. “Multicore garbage collection with local heaps.” ACM SIGPLAN Notices. Vol. 46. No. 11. ACM, 2011&lt;/li&gt;
      &lt;li&gt;Todd Anderson, “Optimizations in a private nursery-based garbage collector”, ISMM, 2010.&lt;/li&gt;
      &lt;li&gt;KC Sivaramakrishnan, Lukasz Ziarek, Suresh Jagannathan, “A Coherent and Managed Runtime for ML on the SCC”, MARC, 2012.&lt;/li&gt;
      &lt;li&gt;Lorenz Huelsbergen and Phil Winterbottom. “Very concurrent mark-&amp;amp;-sweep garbage collection without fine-grain synchronization.” ISMM 1998.&lt;/li&gt;
      &lt;li&gt;Scott Schneider, Christos D. Antonopoulos, and Dimitrios S. Nikolopoulos. “Scalable, locality-conscious multithreaded memory allocation.” ISMM 2006.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>(Monadic) Reflections on Concurrency</title>
   <link href="https://kcsrk.info/multicore/reflection/monads/effects/2017/06/13/monadic-reflections-on-concurrency/"/>
   <updated>2017-06-13T12:13:00+00:00</updated>
   <id>https://kcsrk.info/multicore/reflection/monads/effects/2017/06/13/monadic-reflections-on-concurrency</id>
   <content type="html">&lt;p&gt;We recently published a paper on &lt;a href=&quot;http://kcsrk.info/papers/system_effects_feb_18.pdf&quot;&gt;concurrent system programming with effect
handlers&lt;/a&gt;. In this paper, we show
that with the help of effect handlers, we could express in &lt;em&gt;direct-style&lt;/em&gt;,
various interactions of a concurrent program with OS services that typically
require callbacks. The question is what do we do about legacy code that uses
monadic concurrency libraries such as Lwt and Async. Surely a wholesale rewrite
of all Lwt and Async code is a no go. This post is an exploration of some ideas
to make Lwt and Async compatible with direct-style code.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;monadic-reflection&quot;&gt;Monadic Reflection&lt;/h2&gt;

&lt;p&gt;Andrzej Filinski introduced monadic reflection in his paper &lt;a href=&quot;http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.43.8213&amp;amp;rep=rep1&amp;amp;type=pdf&quot;&gt;Representing
Monads&lt;/a&gt;,
characterizing the relationship between monadic style and continuation-passing
style. Practically, in a language like multicore OCaml with native support for
delimited continuations, any monadic style program can also be written in
direct-style. Filinski introduces two operators to transform between the two
styles:&lt;/p&gt;

&lt;script src=&quot;http://gist-it.appspot.com/https://github.com/kayceesrk/reify_reflect_concurrency/blob/914c24ccfb4e438f17ac779404bf0418d421b450/rr_conc.ml?slice=420:426&quot;&gt;&lt;/script&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reify&lt;/code&gt; transforms a direct-style computation to a monadic one and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reflect&lt;/code&gt;
goes the other way. In multicore OCaml, we can implement monadic reflection for
&lt;em&gt;any&lt;/em&gt; monad as&lt;sup id=&quot;fnref:yallop&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:yallop&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;script src=&quot;http://gist-it.appspot.com/https://github.com/kayceesrk/reify_reflect_concurrency/blob/914c24ccfb4e438f17ac779404bf0418d421b450/rr_conc.ml?slice=427:440&quot;&gt;&lt;/script&gt;

&lt;p&gt;We introduce an effect &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;E&lt;/code&gt; which is parameterized with the monadic computation.
When this effect is performed, it returns the result of performing this monadic
computation. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reify&lt;/code&gt; wraps the direct-style computation with an effect handler
that handles &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;E m&lt;/code&gt; and binds the monadic computation &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m&lt;/code&gt; to the rest of the
direct-style computation. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reflect&lt;/code&gt; simply performs the given monadic
computation wrapped in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;E&lt;/code&gt;. The idea here is that whenever the monad does
anything interesting, we perform the effect &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;E&lt;/code&gt; which delegates the handling of
interesting monadic behavior to the effect handler.&lt;/p&gt;

&lt;h2 id=&quot;monadic-to-direct&quot;&gt;Monadic to Direct&lt;/h2&gt;

&lt;p&gt;We implement &lt;a href=&quot;https://benchmarksgame.alioth.debian.org/u64q/chameneosredux-description.html#chameneosredux&quot;&gt;chameneos-redux benchmark&lt;/a&gt;
from the computer language benchmarks game in direct-style and using concurrency
monad. The benchmark is intended to evaluate the cost of context switching
between tasks. The source code is available
&lt;a href=&quot;https://github.com/kayceesrk/reify_reflect_concurrency/blob/master/rr_conc.ml&quot;&gt;here&lt;/a&gt;
in a single-self contained file. We implement both versions as functors
(direct-style is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ChameneosD (S : SchedD) (M : MVarD)&lt;/code&gt; and monadic-style is
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ChameneosM (S : SchedM) (M : MVarM)&lt;/code&gt;) parameterized by a scheduler and an MVar
implementation. The signatures of direct and monadic style scheduler and MVars
are:&lt;/p&gt;

&lt;script src=&quot;http://gist-it.appspot.com/https://github.com/kayceesrk/reify_reflect_concurrency/blob/914c24ccfb4e438f17ac779404bf0418d421b450/rr_conc.ml?slice=2:42&quot;&gt;&lt;/script&gt;

&lt;p&gt;Using monadic reflection on the monadic scheduler &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SchedM&lt;/code&gt; and MVar &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MVarM&lt;/code&gt;
implementations, we can instantiate the direct-style functor &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ChameneosD&lt;/code&gt;:&lt;/p&gt;

&lt;script src=&quot;http://gist-it.appspot.com/https://github.com/kayceesrk/reify_reflect_concurrency/blob/914c24ccfb4e438f17ac779404bf0418d421b450/rr_conc.ml?slice=446:461&quot;&gt;&lt;/script&gt;

&lt;p&gt;We can even instantiate the direct-style functor &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ChameneosD&lt;/code&gt; with Lwt with no
extra effort:&lt;/p&gt;

&lt;script src=&quot;http://gist-it.appspot.com/https://github.com/kayceesrk/reify_reflect_concurrency/blob/914c24ccfb4e438f17ac779404bf0418d421b450/rr_conc.ml?slice=464:483&quot;&gt;&lt;/script&gt;

&lt;p&gt;Thus, monadic reflection lets you utilize Lwt and Async in direct-style.
Importantly, one gets back backtraces and the use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raise&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;try...with&lt;/code&gt;
for &lt;a href=&quot;https://ocsigen.org/lwt/dev/api/Lwt#2_Exceptionshandling&quot;&gt;exception handling&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;direct-to-monadic&quot;&gt;Direct to Monadic&lt;/h2&gt;

&lt;p&gt;Lwt and Async libraries provide strong guarantees on task interleavings. In
particular, both libraries provide &lt;em&gt;automatic mutual exclusion&lt;/em&gt; – context
switches between tasks only occur at bind points. In other words, any
non-monadic functions, such as calls to standard library functions, are
guaranteed not to context switch. With effect handlers, this is no longer the
case since effects are not tracked in the types in multicore OCaml.&lt;/p&gt;

&lt;p&gt;We can recover the type level marker with a shallow embedding:&lt;/p&gt;

&lt;script src=&quot;http://gist-it.appspot.com/https://github.com/kayceesrk/reify_reflect_concurrency/blob/914c24ccfb4e438f17ac779404bf0418d421b450/rr_conc.ml?slice=553:573&quot;&gt;&lt;/script&gt;

&lt;p&gt;And we can go back to direct-style using monadic reflection:&lt;/p&gt;

&lt;script src=&quot;http://gist-it.appspot.com/https://github.com/kayceesrk/reify_reflect_concurrency/blob/914c24ccfb4e438f17ac779404bf0418d421b450/rr_conc.ml?slice=577:592&quot;&gt;&lt;/script&gt;

&lt;h2 id=&quot;performance&quot;&gt;Performance&lt;/h2&gt;

&lt;p&gt;We compared the performance of different configurations for running
chameneos-redux for 1 million iterations:&lt;/p&gt;

&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/reflection_perf.png&quot; alt=&quot;Reflection Performance&quot; width=&quot;70%&quot; /&gt; &lt;/p&gt;

&lt;p&gt;The results show that monadic reflection has around 9% overhead on average over
the baseline monadic implementations. This is a small price to pay for the
advantage for programming in direct-style.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;We have been prototyping a multicore-capable I/O library for OCaml called
&lt;a href=&quot;https://github.com/kayceesrk/ocaml-aeio&quot;&gt;Aeio&lt;/a&gt;, with compatibility layer for
Lwt and Async built on top of this library. Monadic reflection and other
techniques can help resolve the schism between monadic libraries and
direct-style code.&lt;/p&gt;

&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h2&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:yallop&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Thanks to &lt;a href=&quot;https://www.cl.cam.ac.uk/~jdy22/&quot;&gt;Jeremy Yallop&lt;/a&gt; for introducing me to monadic reflection and &lt;a href=&quot;https://github.com/kayceesrk/effects-examples/blob/master/reify_reflect.ml&quot;&gt;contributing this implementation&lt;/a&gt;. &lt;a href=&quot;#fnref:yallop&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Building and Publishing an OCaml Package: Q1 2017</title>
   <link href="https://kcsrk.info/ocaml/opam/topkg/carcass/2017/03/05/building-and-publishing-an-OCaml-package/"/>
   <updated>2017-03-05T13:56:00+00:00</updated>
   <id>https://kcsrk.info/ocaml/opam/topkg/carcass/2017/03/05/building-and-publishing-an-OCaml-package</id>
   <content type="html">&lt;p&gt;One of the key indicators of maturity of a language ecosystem is the ease of
building, managing and publishing software packages in that language. OCaml
platform has made steady progress in the last few years to this end. While
&lt;a href=&quot;https://opam.ocaml.org/&quot;&gt;OPAM&lt;/a&gt; simplified package (and compiler) management,
the developing and publishing packages remained a constant pain point. This
situation has remarkably improved recently with the
&lt;a href=&quot;http://erratique.ch/software/topkg&quot;&gt;Topkg&lt;/a&gt; and
&lt;a href=&quot;https://github.com/dbuenzli/carcass&quot;&gt;Carcass&lt;/a&gt;. This post provides a short
overview of my workflow for building and publishing an OCaml package using Topkg
and Carcass.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Topkg is packager for distributing OCaml software. It provides an API for
describing rules for package builds and installs. Topkg-care provides the
command line tool &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;topkg&lt;/code&gt; with support for creating and linting the
distribution, publishing the distribution and its documentation on WWW, and
making the package available through OPAM. Carcass is a library and a command
line tool for defining and generating the directory structure for the OCaml
package. At the time of writing this post, carcass was unreleased.&lt;/p&gt;

&lt;h2 id=&quot;workflow&quot;&gt;Workflow&lt;/h2&gt;

&lt;p&gt;I recently released a package for &lt;a href=&quot;https://github.com/kayceesrk/mergeable-vector&quot;&gt;mergeable
vectors&lt;/a&gt; based on operational
transformation. The following describes my workflow to build and publish the
package.&lt;/p&gt;

&lt;h3 id=&quot;setup&quot;&gt;Setup&lt;/h3&gt;

&lt;p&gt;Install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;topkg-care&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;carcass&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ opam install topkg-care opam-publish
$ opam pin add -kgit carcass https://github.com/dbuenzli/carcass
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;develop&quot;&gt;Develop&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Create the directory structure
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  $ carcass body topkg/pkg mergeable_vector
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Init
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  $ cd mergeable_vector &amp;amp;&amp;amp; git init &amp;amp;&amp;amp; git add . &amp;amp;&amp;amp; git commit -m &quot;First commit.&quot;
  $ git remote add origin https://github.com/kayceesrk/mergeable-vector
  $ git push --set-upstream origin master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Develop: The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mergeable_vector/src&lt;/code&gt; directory has the source files. I use
&lt;a href=&quot;https://github.com/kayceesrk/mergeable-vector/blob/master/Makefile&quot;&gt;this Makefile&lt;/a&gt;
at the root of the package.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Test the package locally with OPAM
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  $ opam pin add mergeable_vector .
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;publish&quot;&gt;Publish&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Update the
&lt;a href=&quot;https://github.com/kayceesrk/mergeable-vector/blob/master/CHANGES.md&quot;&gt;CHANGES&lt;/a&gt; file for the new release.&lt;/li&gt;
  &lt;li&gt;Tag the release
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  $ topkg tag 0.1.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Build the distribution
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  $ topkg distrib
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Publish the distribution
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  $ topkg publish distrib
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;This makes a new release on &lt;a href=&quot;https://github.com/kayceesrk/mergeable-vector/releases&quot;&gt;Github&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Publish the doc
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  $ topkg publish doc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;This publishes the documentation on &lt;a href=&quot;http://kayceesrk.github.io/mergeable-vector/doc/&quot;&gt;Github&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Make an OPAM package info and submit it to OPAM repository at &lt;a href=&quot;https://opam.ocaml.org/&quot;&gt;opam.ocaml.org&lt;/a&gt;.
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  $ topkg opam pkg
  $ topkg opam submit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;This creates a Github &lt;a href=&quot;https://github.com/ocaml/opam-repository/pull/8623&quot;&gt;PR&lt;/a&gt;
to the &lt;a href=&quot;https://github.com/ocaml/opam-repository&quot;&gt;opam-repository&lt;/a&gt;. Once the
PR is merged, the package becomes available to the users.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Ezirmin : An easy interface to the Irmin library</title>
   <link href="https://kcsrk.info/ocaml/irmin/crdt/2017/02/15/an-easy-interface-to-irmin-library/"/>
   <updated>2017-02-15T13:46:00+00:00</updated>
   <id>https://kcsrk.info/ocaml/irmin/crdt/2017/02/15/an-easy-interface-to-irmin-library</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://github.com/kayceesrk/ezirmin&quot;&gt;Ezirmin&lt;/a&gt; is an easy interface over the
&lt;a href=&quot;https://github.com/mirage/irmin&quot;&gt;Irmin&lt;/a&gt;, a library database for building
persistent mergeable data structures based on the principles of Git. In this
post, I will primarily discuss the Ezirmin library, but also discuss some of the
finer technical details of mergeable data types implemented over Irmin.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h1 id=&quot;contents&quot;&gt;Contents&lt;/h1&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#contents&quot; id=&quot;markdown-toc-contents&quot;&gt;Contents&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#irmin-and-ezirmin&quot; id=&quot;markdown-toc-irmin-and-ezirmin&quot;&gt;Irmin and Ezirmin&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#quick-tour-of-ezirmin&quot; id=&quot;markdown-toc-quick-tour-of-ezirmin&quot;&gt;Quick tour of Ezirmin&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#merge-semantics&quot; id=&quot;markdown-toc-merge-semantics&quot;&gt;Merge semantics&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#working-with-history&quot; id=&quot;markdown-toc-working-with-history&quot;&gt;Working with history&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#reacting-to-changes&quot; id=&quot;markdown-toc-reacting-to-changes&quot;&gt;Reacting to changes&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#interaction-with-remotes&quot; id=&quot;markdown-toc-interaction-with-remotes&quot;&gt;Interaction with remotes&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#mergeable-persistent-data-types&quot; id=&quot;markdown-toc-mergeable-persistent-data-types&quot;&gt;Mergeable persistent data types&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#irmin-architecture&quot; id=&quot;markdown-toc-irmin-architecture&quot;&gt;Irmin Architecture&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#user-defined-merges&quot; id=&quot;markdown-toc-user-defined-merges&quot;&gt;User-defined merges&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#mergeable-counters&quot; id=&quot;markdown-toc-mergeable-counters&quot;&gt;Mergeable Counters&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#theory-of-merges&quot; id=&quot;markdown-toc-theory-of-merges&quot;&gt;Theory of merges&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#recursive-merges&quot; id=&quot;markdown-toc-recursive-merges&quot;&gt;Recursive merges&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#mergeable-logs&quot; id=&quot;markdown-toc-mergeable-logs&quot;&gt;Mergeable logs&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#efficient-mergeable-logs&quot; id=&quot;markdown-toc-efficient-mergeable-logs&quot;&gt;Efficient mergeable logs&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#mergeable-ropes&quot; id=&quot;markdown-toc-mergeable-ropes&quot;&gt;Mergeable ropes&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#next-steps&quot; id=&quot;markdown-toc-next-steps&quot;&gt;Next steps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;irmin-and-ezirmin&quot;&gt;Irmin and Ezirmin&lt;/h1&gt;

&lt;p&gt;Irmin is a library for manipulating persistent mergeable data structures
(including CRDTs) that follows the same principles of Git. In particular, it has
built-in support for snapshots, branches and reverts, and can compile to
multiple backends. Being written in pure OCaml, apps written using Irmin, as
well as running natively, can run in the browsers or be compiled to Unikernels.
A good introduction to the capabilities of Irmin can be found in the Irmin
&lt;a href=&quot;https://github.com/mirage/irmin/blob/master/README.md&quot;&gt;README&lt;/a&gt; file.&lt;/p&gt;

&lt;p&gt;One of the downsides to being extremely configurable is that the Irmin library
is not beginner friendly. In particular, the library tends to be rather functor
heavy, and even &lt;a href=&quot;https://github.com/mirage/irmin/blob/master/README.md#usage&quot;&gt;simple
uses&lt;/a&gt; require
multiple functor instantiations&lt;sup id=&quot;fnref:irmin&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:irmin&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. The primary goal of Ezirmin is to
provide a defuntorized interface to Irmin, specialized to useful defaults.
However, as I’ve continued to build Ezirmin, it has come to include a collection
of useful mergeable data types including counters, queues, ropes, logs, etc. I
will spend some time describing some of the interesting aspects of these data
structures.&lt;/p&gt;

&lt;h1 id=&quot;quick-tour-of-ezirmin&quot;&gt;Quick tour of Ezirmin&lt;/h1&gt;

&lt;p&gt;You can install the latest version of Ezirmin by&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone https://github.com/kayceesrk/ezirmin
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;ezirmin
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;opam pin add ezirmin &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Stable versions are also available through OPAM:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;opam &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;ezirmin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s fire up &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;utop&lt;/code&gt; and get started:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ezirmin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Infix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We’ll create a mergeable queue of strings using the Git file system backend
rooted at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp/ezirminq&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ezirmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;FS_queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Tc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* Mergeable queue of strings *)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt_main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/tmp/ezirminq&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bare&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;master&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;branch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abstr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m&lt;/code&gt; is the master branch of the repository. Ezirmin exposes a key value store,
where keys are hierarchical paths and values are whatever data types is stored in
the repo. In this case, the data type is a queue. Let’s push some elements into
the queue:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;push&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;home&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;todo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;buy milk&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;push&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;work&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;todo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;publish ezirmin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_list&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;home&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;todo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;buy milk&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The updates to the queue is saved in the Git repository at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp/ezirminq&lt;/code&gt;. In
another terminal,&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ezirmin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ezirmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;FS_queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Tc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* Mergeable queue of strings *)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Infix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt_main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/tmp/ezirminq&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bare&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;master&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;branch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abstr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pop&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;home&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;todo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;option&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;buy milk&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For concurrency control, use branches. In the first terminal,&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wip&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt_main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clone_force&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;wip&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;push&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wip&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;home&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;todo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;walk dog&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;push&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wip&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;home&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;todo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;take out trash&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The changes are not visible until the branches are merged.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_list&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;home&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;todo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;merge&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wip&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;into&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_list&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;home&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;todo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;walk dog&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;take out trash&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;merge-semantics&quot;&gt;Merge semantics&lt;/h2&gt;

&lt;p&gt;What should be the semantics of popping the queue at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;home/todo&lt;/code&gt; concurrently
at the master branch and wip branch? It is reasonable to ascribe exactly once
semantics to pop such that popping the same element on both branches and
subsequently merging the queues would lead to a merge conflict. However, a more
useful semantics is where we relax this invariant and allow elements to be
popped more than once on different branches. In particular, the merge operation
on the queue ensures that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;An element popped in one of the branches is not present after the merge.&lt;/li&gt;
  &lt;li&gt;Merges respect the program order in each of the branches.&lt;/li&gt;
  &lt;li&gt;Merges converge.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Hence, our merge queues are CRDTs.&lt;/p&gt;

&lt;h2 id=&quot;working-with-history&quot;&gt;Working with history&lt;/h2&gt;

&lt;p&gt;Irmin is fully compatible with Git. Hence, we can explore the history of the
operations using the git command line. In another terminal:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /tmp/ezirminq
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git lg
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; e75da48 - &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;4 minutes ago&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; push - Irmin xxxx.cam.ac.uk.[73126] &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;HEAD -&amp;gt; master, wip&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; 40ed32d - &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;4 minutes ago&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; push - Irmin xxxx.cam.ac.uk.[73126]
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; 6a56fb0 - &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;5 minutes ago&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; pop - Irmin xxxx.cam.ac.uk.[73221]
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; 6a2cc9a - &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;6 minutes ago&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; push - Irmin xxxx.cam.ac.uk.[73126]
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; 55f7fc8 - &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;6 minutes ago&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; push - Irmin xxxx.cam.ac.uk.[73126]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The Git log shows that there have been 4 pushes and 1 pop in this repository.
In addition to the data structures being mergeable, they are also persistent.
In particular, every object stored in Irmin has complete provenance. You can
also manipulate history using the Git command line.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git reset HEAD~2 &lt;span class=&quot;nt&quot;&gt;--hard&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git lg
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; e75da48 - &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;8 minutes ago&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; push - Irmin xxxx.cam.ac.uk.[73126] &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;wip&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; 40ed32d - &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;9 minutes ago&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; push - Irmin xxxx.cam.ac.uk.[73126]
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; 6a56fb0 - &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;9 minutes ago&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; pop - Irmin xxxx.cam.ac.uk.[73221] &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; 6a2cc9a - &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;10 minutes ago&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; push - Irmin xxxx.cam.ac.uk.[73126]
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; 55f7fc8 - &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;10 minutes ago&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; push - Irmin xxxx.cam.ac.uk.[73126]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Back in the first terminal:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_list&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;home&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;todo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since we rolled back the master to before the pushes were merged, we see an
empty list. Ezirmin also provides APIs for working with history
programmatically.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt_main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;repo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;init&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Books&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Ovine Supply Logistics&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;push_msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;push&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;begin&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;push_msg&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Baa&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;push_msg&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Baa&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;push_msg&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Black&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;push_msg&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Camel&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_list&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Baa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Baa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Black&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Camel&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Clearly this is wrong. Let’s fix this by reverting to earlier version:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m_1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;predecessors&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;repo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(** HEAD~1 version *)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_list&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m_1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Baa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Baa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Black&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;update_branch&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_list&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Baa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Baa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Black&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now that we’ve undone the error, we can do the right thing.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;push_msg&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Sheep&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_list&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Baa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Baa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Black&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Sheep&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;reacting-to-changes&quot;&gt;Reacting to changes&lt;/h2&gt;

&lt;p&gt;Ezirmin supports watching a particular key for updates and invoking a callback
function when there is one.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cb&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print_endline&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;callback: update to home/todo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;watch&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;home&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;todo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The code above installs a listener &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cb&lt;/code&gt; on the queue at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;home/todo&lt;/code&gt;, which is
run every time the queue is updated. This includes local &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;push&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pop&lt;/code&gt;
operations as well as updates due to merges.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;push&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;home&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;todo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hang pictures&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;home&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;todo&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;interaction-with-remotes&quot;&gt;Interaction with remotes&lt;/h2&gt;

&lt;p&gt;Unlike distributed data stores, where the updates are disseminated
transparently between the replicas, Ezirmin provides you the necessary building
blocks for building your own dissemination protocol. As with Git, Ezirmin
exposes the functionality to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;push&lt;/code&gt;&lt;sup id=&quot;fnref:push&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:push&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pull&lt;/code&gt; changes from remotes.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show_module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Sync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Sync&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;remote&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;remote_uri&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;remote&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pull&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;remote&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;branch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Merge&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Update&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Conflict&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`No_head&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Ok&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;push&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;remote&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;branch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Ok&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This design provides the flexibility to describe your own network layout, with
anti-entropy mechanisms built-in to the synchronization protocol. For example,
one might deploy the replicas in a hub-and-spoke model where each replica
accepts client writes locally and periodically publishes changes to the master
and also fetches any latest updates. The data structures provided by Ezirmin
are always mergeable and converge. Hence, the updates are never rejected. It is
important to note that even though we have a centralized master, this
deployment is still highly available. Even if the master is unavailable, the
other nodes can still accept client requests. The replicas may also be
connected in a peer-to-peer fashion without a centralized master for a more
resilient deployment.&lt;/p&gt;

&lt;h1 id=&quot;mergeable-persistent-data-types&quot;&gt;Mergeable persistent data types&lt;/h1&gt;

&lt;p&gt;Ezirmin is equipped with a &lt;a href=&quot;https://github.com/kayceesrk/ezirmin#whats-in-the-box&quot;&gt;growing
collection&lt;/a&gt; of mergeable
data types. The mergeable datatypes occupy a unique position in the space of
CRDTs. Given that we have the history, the design of mergeable datatypes is much
simpler. Additionally, this also leads to &lt;a href=&quot;http://gazagnaire.org/pub/FGM15.pdf&quot;&gt;richer
structures&lt;/a&gt; typically not found in CRDTs.
It is worth studying them in detail.&lt;/p&gt;

&lt;h2 id=&quot;irmin-architecture&quot;&gt;Irmin Architecture&lt;/h2&gt;

&lt;p&gt;Irmin provides a high-level key-value interface built over two lower level
heaps: a &lt;strong&gt;block store&lt;/strong&gt; and a &lt;strong&gt;tag store&lt;/strong&gt;. A block store is an append-only
content-addressable store that stores serialized values of application contents,
prefix-tree nodes, history meta-data, etc. Instead of using physical memory
address of blocks, the blocks are identified by the hash of their contents. As a
result block store enjoys very nice properties. Being content-addressed, we get
sharing for free: two blocks with the same content will have the have the same
hash. This not only applies for individual blocks, but also for
linked-structures. For example,&lt;/p&gt;

&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/linked_list.png&quot; alt=&quot;Hash list&quot; /&gt; &lt;/p&gt;

&lt;p&gt;The linked list above is uniquely identified by hash &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h0&lt;/code&gt; since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h0&lt;/code&gt; was
computed from the content &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; and the hash of the tail of the list &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h1&lt;/code&gt;. No
other list has hash &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h0&lt;/code&gt;. Changing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C&lt;/code&gt; in this list would result in a
different hash for the head of the list&lt;sup id=&quot;fnref:blockchain&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:blockchain&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. Moreover, since the block
store is append-only, all previous versions of a application-level data
structure is also available, and thus providing persistence. This also makes for
a nice concurrency story for multiple processes/threads operating on the block
store. The absence of mutations on block store mean that no additional
concurrency control mechanisms are necessary.&lt;/p&gt;

&lt;p&gt;The only mutable part of the Irmin architecture is the tag store, that maps
global names to blocks in the block store. The notion of branches are built on
top of the tag store. Cloning a branch creates a new tag that points to the same
block as the cloned branch.&lt;/p&gt;

&lt;h2 id=&quot;user-defined-merges&quot;&gt;User-defined merges&lt;/h2&gt;

&lt;p&gt;The real power of Irmin is due to the user-defined merges. Irmin expects the
developer to provide a 3-way merge function with the following signature:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;(** User-defined contents. *)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;merge&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;old&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Ok&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Conflict&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;(** 3-way merge. *)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Given the common ancestor &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;old&lt;/code&gt; and the two versions, merge function can either
return a successful merge or mark a conflict. It is up to the developer to ensure
that merges are commutative (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;merge old a b = merge old b a&lt;/code&gt;) and that the merge
captures the intent of the two branches. &lt;em&gt;If the merge function never conflicts,
we have CRDTs&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;mergeable-counters&quot;&gt;Mergeable Counters&lt;/h2&gt;

&lt;p&gt;The simplest mergeable data type is a counter with an increment and decrement
operations. Given that we have a 3-way merge function, the merge is intuitive:&lt;/p&gt;

&lt;script src=&quot;http://gist-it.appspot.com/https://github.com/kayceesrk/ezirmin/blob/125ecd3b8fbebbd501f218397b3c1f2ab12d13cf/src/ezirmin_counter.ml?slice=13:18&quot;&gt;&lt;/script&gt;

&lt;p&gt;Given the two new values for the counter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;t1&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;t2&lt;/code&gt;, and their lowest common
ancestor value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;old&lt;/code&gt;, the new value of the counter is the sum of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;old&lt;/code&gt; value
and the two deltas: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;old + (t1 - old) + (t2 - old) = t1 + t2 - old&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;theory-of-merges&quot;&gt;Theory of merges&lt;/h3&gt;

&lt;p&gt;While this definition is intuitive, the proof of why this strategy (i.e.,
computing deltas and applying to the common ancestor) is correct is quite
subtle. It happens to be the case that the patches (deltas) in this case,
integers under addition, form an &lt;a href=&quot;https://en.wikipedia.org/wiki/Abelian_group&quot;&gt;abelian
group&lt;/a&gt;. Judah Jacobson formalizes
&lt;a href=&quot;ftp://ftp.math.ucla.edu/pub/camreport/cam09-83.pdf&quot;&gt;patches for Darcs as inverse
semigroups&lt;/a&gt; and proves
convergence. Every abelian group is also an inverse semigroup. Hence, the above
strategy is correct. Merges can also be equivalently viewed as a &lt;a href=&quot;https://arxiv.org/pdf/1311.3903.pdf&quot;&gt;pushout in
category theory&lt;/a&gt;, leading to the same
result. I will have to save the discussion of the category theoretic reasoning
of Irmin merges for another time. But Liam O’Connor has written a concise
&lt;a href=&quot;http://liamoc.net/posts/2015-11-10-patch-theory.html&quot;&gt;post&lt;/a&gt; on the theory of patches
which is worth a read.&lt;/p&gt;

&lt;h3 id=&quot;recursive-merges&quot;&gt;Recursive merges&lt;/h3&gt;

&lt;p&gt;Since Ezirmin allows arbitrary branching and merging, the lowest common ancestor
need not be unique. One way to end up with multiple lowest common ancestors is
criss-cross merges. For example, consider the history graph below:&lt;/p&gt;

&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/criss_cross.png&quot; alt=&quot;Criss cross merge&quot; /&gt; &lt;/p&gt;

&lt;p&gt;The counter at some key in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; was initially &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;. The branch &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wip&lt;/code&gt; was
cloned at this point. The counter is incremented by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2&lt;/code&gt; at
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wip&lt;/code&gt;. At this point, both branches are merged into the other branch. The common
ancestor here is the initial state of counter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;. This results in counter value
of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3&lt;/code&gt; in both branches. Suppose there are further increments, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2&lt;/code&gt; at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt;
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;4&lt;/code&gt; at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wip&lt;/code&gt;, resulting in counter values &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;7&lt;/code&gt; respectively in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wip&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wip&lt;/code&gt; branch is now merged in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt;, there are two lowest common
ancestors: the commit with value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; at master and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2&lt;/code&gt; in wip. Since the 3-way
merge algorithm only work for a single common ancestor, the we adopt a recursive
merge strategy, where the lowest common ancestors are first merged resulting in
a internal commit with value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3&lt;/code&gt; (represented by a dotted circle). This commit
is now used as the common ancestor for merging, which results in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;9&lt;/code&gt; as the new
state of the counter. This matches the increments done in both branches. The
recursive merge strategy is also the default merge strategy for Git.&lt;/p&gt;

&lt;h2 id=&quot;mergeable-logs&quot;&gt;Mergeable logs&lt;/h2&gt;

&lt;p&gt;Another useful data type is &lt;a href=&quot;http://kcsrk.info/ezirmin/Ezirmin.Blob_log.html&quot;&gt;mergeable
logs&lt;/a&gt;, where each log message
is a string. The merge operation accumulates the logs in reverse chronological
order. To this end, each log entry is a pair of timestamp and message, and the
log itself is a list of entries. They are constructed using
&lt;a href=&quot;https://github.com/mirage/mirage-tc&quot;&gt;mirage-tc&lt;/a&gt;:&lt;/p&gt;

&lt;script src=&quot;http://gist-it.appspot.com/https://github.com/kayceesrk/ezirmin/blob/c2220aea1fd26daa90febc822f23f89205af3a69/src/ezirmin_blob_log.ml?slice=34:41&quot;&gt;&lt;/script&gt;

&lt;p&gt;The merge function extracts the newer entries from either branches, sorts them
and appends to the front of the old list.&lt;/p&gt;

&lt;script src=&quot;http://gist-it.appspot.com/https://github.com/kayceesrk/ezirmin/blob/c2220aea1fd26daa90febc822f23f89205af3a69/src/ezirmin_blob_log.ml?slice=48:66&quot;&gt;&lt;/script&gt;

&lt;p&gt;While this implementation is simple, it does not scale well. In particular, each
commit stores the entire log as a single serialized blob. This does not take
advantage of the fact that every commit can share the tail of the log with its
predecessor. Moreover, every append to the log needs to deserialize the entire
log, append the new entry and serialize the log again. Hence, append is an
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;O(n)&lt;/code&gt; operation, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt; is the size of the log. Merges are also worst case
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;O(n)&lt;/code&gt;. This is undesirable.&lt;/p&gt;

&lt;h3 id=&quot;efficient-mergeable-logs&quot;&gt;Efficient mergeable logs&lt;/h3&gt;

&lt;p&gt;We can implement a &lt;a href=&quot;http://kcsrk.info/ezirmin/Ezirmin.Log.html&quot;&gt;efficient logs&lt;/a&gt;
by taking advantage of the fact that every commit shares the tail of the log
with its predecessor.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;log_entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;c&quot;&gt;(** V.t is type of message. *)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;prev&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;option&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;(** K.t is the type of address in the block store. *)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Merges simply add a new node which points to the logs of merged branches,
resulting in a DAG that captures the causal history. The following sequence of
operations:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ezirmin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Infix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ezirmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Memory_log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Tc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt_main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;master&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt_main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;append&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;m0&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;append&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;m1&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;clone_force&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;wip&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;append&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;w0&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;append&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;m2&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;merge&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;into&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;append&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;w1&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;append&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;w2&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;append&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;m3&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;append&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;m4&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;results in the heap below.&lt;/p&gt;

&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/log.png&quot; alt=&quot;Merge log&quot; /&gt; &lt;/p&gt;

&lt;p&gt;Read traverses the log in reverse chronological order.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read_all&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;m4&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;m3&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;m2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;w0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;m1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;m0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This implementation has &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;O(1)&lt;/code&gt; appends and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;O(1)&lt;/code&gt; merges, resulting in much
better performance. The graph below compares the blob log implementation and
this linked implementation with file system backend by performing repeated
appends to the log and measuring the latency for append.&lt;/p&gt;

&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/perf_log.png&quot; alt=&quot;Perf log&quot; /&gt; &lt;/p&gt;

&lt;p&gt;Each point represents the average latency for the previous 100 appends. The
results show that the append latency for linked implementation remains
relatively constant while the blob implementation slows down considerably with
increasing number of appends. Additionally, the linked implementation also
supports efficient &lt;a href=&quot;http://kcsrk.info/ezirmin/Ezirmin.Log.html#VALread&quot;&gt;paginated
reads&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;mergeable-ropes&quot;&gt;Mergeable ropes&lt;/h2&gt;

&lt;p&gt;A rope data structure is used for efficiently storing and manipulating very long
strings. Ezirmin provides &lt;a href=&quot;http://kcsrk.info/ezirmin/Ezirmin.Rope.html&quot;&gt;mergeable
ropes&lt;/a&gt; where for &lt;a href=&quot;http://kcsrk.info/ezirmin/Ezirmin.Rope_content.html&quot;&gt;arbitrary
contents&lt;/a&gt;, but also
specialized for &lt;a href=&quot;http://kcsrk.info/ezirmin/Ezirmin.Rope_string.html&quot;&gt;strings&lt;/a&gt;.
Ropes automatically rebalance to maintain the invariant that the height of the
tree is proportional to the length of the contents. The crux of the merge
strategy is that given a common ancestor and the two trees to be merged,
the merge algorithm works out the smallest subtrees where the modification
occurred. If the modifications are on distinct subtrees, then the merge is
trivial.&lt;/p&gt;

&lt;p align=&quot;center&quot;&gt; &lt;img src=&quot;/assets/merge_rope.png&quot; alt=&quot;merge rope&quot; /&gt; &lt;/p&gt;

&lt;p&gt;If the modification is on the same subtree, then the algorithm delegates to
merge the contents. This problem has been well studied under the name of
&lt;a href=&quot;https://en.wikipedia.org/wiki/Operational_transformation&quot;&gt;operational
transformation&lt;/a&gt; (OT).
OT can be categorically explained in terms of pushouts.
Mergeable strings with insert, delete and replace operations are isomorphic to
counters with increment and decrement. We apply a similar strategy to merge
string.&lt;/p&gt;

&lt;script src=&quot;http://gist-it.appspot.com/https://github.com/kayceesrk/ezirmin/blob/c2220aea1fd26daa90febc822f23f89205af3a69/src/ezirmin_rope_string.ml?slice=193:206&quot;&gt;&lt;/script&gt;

&lt;p&gt;First we compute the diff between the common ancestor and the new tree using
&lt;a href=&quot;https://en.wikipedia.org/wiki/Wagner%E2%80%93Fischer_algorithm&quot;&gt;Wagner-Fischer
algorithm&lt;/a&gt;. Then
we transform one patch with respect to the other using standard OT definition
such that we can first apply one of the original patch to the common ancestor
and then apply the transformed patch of the other branch to get the result tree.&lt;/p&gt;

&lt;p&gt;For example,&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ezirmin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Infix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ezirmin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Memory_rope_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt_main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;master&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt_main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;make&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;abc&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Lwt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt_main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clone_force&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;w&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt_main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&apos;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* &quot;axc&quot; *)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;y&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&apos;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* &quot;aybc&quot; *)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;merge&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;into&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* &quot;ayxc&quot; *)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;merge&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;into&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt_main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;failwith&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;impossible&quot;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flush&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;|=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;m is &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ayxc&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Lwt_main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;failwith&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;impossible&quot;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flush&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;|=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;w is &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ayxc&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The combination of mergeable ropes with OT gets the best of both worlds.
Compared to a purely OT based implementation, diffs are only computed if updates
conflict at the leaves. The representation using ropes is also efficient in
terms of storage where multiple versions of the tree shares blocks. A purely
rope based implementation either has the option of storing individual characters
(atoms) at the leaves (and resolve conflicts based on some deterministic
mechanism such as timestamps or other deterministic strategies) or manifest the
conflict at the leaves to the user to get it resolved. A simple strategy might
be to present both of the conflicting strings, and ask the user to resolve it.
Hence, mergeable ropes + OT is strictly better than either of the approaches.&lt;/p&gt;

&lt;h1 id=&quot;next-steps&quot;&gt;Next steps&lt;/h1&gt;

&lt;p&gt;Ezirmin is open to comments and contributions. Next steps would be:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Implement more mergeable data types&lt;/li&gt;
  &lt;li&gt;Implement generic mergeable datatypes using &lt;a href=&quot;https://github.com/samoht/depyt&quot;&gt;depyt&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Explore the data types which admit conflicts. For example, a bank account with
non-negative balance does not form a CRDT with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;withdraw&lt;/code&gt; operation. However,
operations such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deposit&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;accrue_interest&lt;/code&gt; can be coordination-free.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 class=&quot;no_toc&quot; id=&quot;footnotes&quot;&gt;Footnotes&lt;/h1&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:irmin&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Things are indeed improving with a cleaner API in the &lt;a href=&quot;https://github.com/mirage/irmin/pull/397&quot;&gt;1.0 release&lt;/a&gt;. &lt;a href=&quot;#fnref:irmin&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:push&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Push is currently &lt;a href=&quot;https://github.com/mirage/irmin/issues/379&quot;&gt;broken&lt;/a&gt;. But given that Irmin is compatible with git, one can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git-push&lt;/code&gt; to publish changes. &lt;a href=&quot;#fnref:push&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:blockchain&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;The same principle underlies the irrefutability of &lt;a href=&quot;https://en.wikipedia.org/wiki/Blockchain_(database)&quot;&gt;blockchain&lt;/a&gt;. No block can be changed without reflecting the change in every subsequent block. &lt;a href=&quot;#fnref:blockchain&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Behavioural types</title>
   <link href="https://kcsrk.info/ocaml/types/2016/06/30/behavioural-types/"/>
   <updated>2016-06-30T09:31:00+00:00</updated>
   <id>https://kcsrk.info/ocaml/types/2016/06/30/behavioural-types</id>
   <content type="html">&lt;p&gt;Behavioural types such as session types, contracts and choreography describe the
behaviour of a software entity as a sequence of &lt;em&gt;operations&lt;/em&gt; on a resource such
as a communication channel, web service session or a file descriptor.
Behavioural types capture well-defined interactions, which are enforced
statically with the help of type system machinery. In this post, I will describe
a lightweight embedding of behavioural types in OCaml using polymorphic variants
through a series of examples. The complete source code for the examples is
available
&lt;a href=&quot;https://github.com/kayceesrk/code-snippets/blob/master/behavior.ml&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;!--_more--&gt;

&lt;p&gt;The idea of encoding behavioural types using polymorphic variants comes from
&lt;a href=&quot;http://www.di.unito.it/~padovani/Software/FuSe/FuSe.html&quot;&gt;FuSe&lt;/a&gt;, which is a
simple library implementation of binary sessions in OCaml. Similar to FuSe
linear use of resources is enforced through dynamic checks in the following
examples. We’ll raise &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LinearityViolation&lt;/code&gt; when linearity is violated.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;exception&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LinearityViolation&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;refs-that-explain-their-work&quot;&gt;Refs that explain their work&lt;/h2&gt;

&lt;p&gt;Let us define a ref type that is constrained not only by the type of value
that it can hold but also by the sequence of operations that can be performed
on it.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constraint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The phantom type variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;b&lt;/code&gt; constrained to be a polymorphic variant (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;b =
[&amp;gt;]&lt;/code&gt;) describes the sequence of permitted operations. For example, a reference
can only be read when the type presents the read capability &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[`Read of &apos;b]&lt;/code&gt;.
Here, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;b&lt;/code&gt; represents the behaviour of the continuation. Consequently, the
result of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read&lt;/code&gt; operation is a tuple consisting of the value read and a
reference whose type is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&apos;a,&apos;b) ref&lt;/code&gt;. It is useful to think of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read&lt;/code&gt;
operation as changing the type of the reference. The type for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;write&lt;/code&gt; is
similar.&lt;/p&gt;

&lt;p&gt;Associating behaviours with references is quite handy. For example, below is a
reference that holds an integer, which can only be written once following which
a single read is permitted:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_ref1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Stop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]])&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The behavioural types are also automatically inferred. For example,&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The inferred type says that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo1&lt;/code&gt; writes into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt; and then reads it. We can
apply &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo1&lt;/code&gt; on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my_ref1&lt;/code&gt; as their behaviours are compatible.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;res_ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_ref1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res_ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Stop&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Recursive behavioural types are obtained painlessly.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;foo2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The inferred types says that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo2&lt;/code&gt; repeatedly writes and then reads the given
reference. Incompatible references are rejected statically. For example,&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_ref2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Stop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]])&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_ref2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Stop&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abstr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_ref2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;This&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Stop&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;but&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;an&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;was&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;
       &lt;span class=&quot;nc&quot;&gt;These&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;two&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;variant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;types&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;have&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;no&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;intersection&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;whereas&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_ref3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_ref3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abstr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_ref3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;is accepted and runs forever. It is (sometimes) useful to write programs that
don’t always run forever such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo3&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo3&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;print_endline&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;done&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;foo3&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;which runs for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt; iterations, where it performs a write and a read in every
iteration but the last one where it just performs a read. Unfortunately, this
program does not type check:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;This&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;but&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;an&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;was&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;
       &lt;span class=&quot;nc&quot;&gt;These&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;two&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;variant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;types&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;have&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;no&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;intersection&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The problem is that the behaviour of the two branches are incompatible, and the
program is rightly rejected. We distinguish the branches in the type using:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;branch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;branch r f&lt;/code&gt; indicates branch selection in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt; where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; is a function that is
always of the form &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fun x -&amp;gt;  `Tag x&lt;/code&gt;. The fixed version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo3&lt;/code&gt; is:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo3&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;print_endline&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;done&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;branch&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Zero&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;branch&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Succ&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;foo3&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Succ&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Zero&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Observe that the inferred type captures the branching behaviour, and works as
expected:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_ref4&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo3&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_ref4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abstr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;implementation&quot;&gt;Implementation&lt;/h3&gt;

&lt;p&gt;The implementation is unremarkable except for the machinery to dynamically
enforce linearity.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;mutable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* For linearity *)&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;constraint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LinearityViolation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;false&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fresh&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fresh&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;branch&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fresh&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Behavioural types crucially depend on linear use of the resources. Since OCaml
does not have linear types, there is nothing that prevents writing the following
function that seemingly violates the behavioural contract.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Stop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]])&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
         &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
         &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Stop&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Stop&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;While the type of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt; says that it will be read only once, the function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo&lt;/code&gt;
reads it twice. This non-linear use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt; is caught dynamically; the second
read of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt; raises &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LinearityViolation&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;LinearityViolation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;polymorphic-references&quot;&gt;Polymorphic References&lt;/h2&gt;

&lt;p&gt;Since we can accurately track the behaviour of references, we can safely allow
differently typed values to be written and read from the reference. A reference
that holds a value of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;t&lt;/code&gt; can be read multiple times at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;t&lt;/code&gt; before being
written at type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;u&lt;/code&gt;. This protocol is captured by the following type:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PolyRef&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rw_prot&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;constraint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rw_prot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constraint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rw_prot&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As before, the reference holds values of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;a&lt;/code&gt; with the behaviour given by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;b&lt;/code&gt;.
The reference can either by read multiple times at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;a&lt;/code&gt; or written once at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;c&lt;/code&gt;
after which the reference holds values of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;c&lt;/code&gt;. The rest of the operations
are defined as usual:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PolyRef&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rw_prot&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rw_prot&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rw_prot&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rw_prot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rw_prot&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rw_prot&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;branch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rw_prot&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rw_prot&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rw_prot&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can now write interesting programs:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string_of_int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;int_of_string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rw_prot&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;rw_prot&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;rw_prot&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PolyRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Observe that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo&lt;/code&gt; reads &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt; as a integer, updates it as a string, reads it as
a string and then finally writing an integer into it. The inferred type
reflects this change from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int -&amp;gt; string -&amp;gt; int&lt;/code&gt;. The implementation of
polymorphic references uses the unsafe &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Obj.magic&lt;/code&gt; to coerce the contents.
However, the behavioural types ensure that accesses are safe.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PolyRef&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PolyRef&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rw_prot&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;constraint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rw_prot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;mutable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* For linearity *)&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;constraint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rw_prot&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;magic&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LinearityViolation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;false&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fresh&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;magic&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fresh&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;magic&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;branch&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fresh&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;file-descriptors&quot;&gt;File descriptors&lt;/h2&gt;

&lt;p&gt;We can utilise behavioural types to apply meaningful restrictions to operations
on file descriptors.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;File_descriptor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constraint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;openfile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Unix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open_flag&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Unix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_perm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Close&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;close&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mk_read_only&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Close&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mk_write_only&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Close&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open_stdin&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Close&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open_stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Close&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open_stderr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Close&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;File_descriptor&lt;/code&gt; module is a thin wrapper around the file descriptors from
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Unix&lt;/code&gt; module. The file descriptor obtained through openfile permits a subset
of operations to read, write and close. The precise set of capabilities is
dictated by the flags supplied. For example, with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;O_RDONLY&lt;/code&gt; the type of the
file descriptor obtained should be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;([`Close | `Read of &apos;a] as &apos;a) t&lt;/code&gt;. The
types of standard streams are also restricted. For example,&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open_stderr&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hello&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;hello&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Close&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abstr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open_stdin&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hello&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;This&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Close&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;but&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;an&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;was&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
       &lt;span class=&quot;nc&quot;&gt;The&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;variant&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;does&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allow&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;File descriptors can also be made read or write only.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
         &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;  &lt;span class=&quot;s2&quot;&gt;&quot;hello&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
         &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mk_read_only&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
         &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hello&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;This&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Close&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Read&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;but&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;an&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;was&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
       &lt;span class=&quot;nc&quot;&gt;The&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;variant&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;does&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;allow&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Write&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The implementation of the module is straightforward.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;File_descriptor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;File_descriptor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Unix&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_descr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;mutable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constraint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fresh&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LinearityViolation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;false&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open_stdin&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stdin&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open_stdout&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;open_stderr&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stderr&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;openfile&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;perm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;openfile&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;perm&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;mk&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;close&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;close&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buff&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ofs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buff&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ofs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fresh&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buff&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ofs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buff&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ofs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fresh&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mk_read_only&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fresh&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mk_write_only&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fresh&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;tracking-aliases&quot;&gt;Tracking Aliases&lt;/h2&gt;

&lt;p&gt;The final example I will discuss is alias tracking.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Alias&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constraint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;make&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`One&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dup&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Succ&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Succ&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;merge&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Succ&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`Succ&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;`One&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Alias&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Alias&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mutable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constraint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fresh&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LinearityViolation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;false&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;make&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;live&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dup&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fresh&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fresh&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;merge&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fresh&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The type variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;b&lt;/code&gt; tracks aliases as a depth in the aliasing tree. New
resources are initialised with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make&lt;/code&gt;, and the resultant resource has type
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&apos;a,[`One]) t&lt;/code&gt; indicating that there is just one reference to this resource.
Aliases are created explicitly with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dup&lt;/code&gt;, which destroys the original
reference and returns two new references, each one level deeper than the
original reference. Two references from the same level can be merged together
to obtain a reference at the next higher level, and in doing so destroying the
original references. All of this machinery is to ensure that the resource can
only be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;free&lt;/code&gt;d when there is a unique reference.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;make&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`One&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abstr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dup&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Succ&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`One&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abstr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Succ&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`One&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abstr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r11&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r12&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dup&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r11&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Succ&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Succ&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`One&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abstr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r12&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Succ&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Succ&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`One&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abstr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r21&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r22&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dup&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r21&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Succ&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Succ&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`One&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abstr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r22&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Succ&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Succ&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`One&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abstr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;merge&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r11&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r22&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Succ&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`One&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abstr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;merge&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r12&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r21&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Succ&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`One&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abstr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;utop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;merge&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Polymorphic variants are quite effective in encoding behavioural types.
However, the absence of linear types in OCaml makes us resort to dynamic tests
for linear use of resources. While it is possible to hide the resource under a
monad, combining the use of multiple resources would require monad
transformers, which is well known to be quite heavyweight in terms of
programmability. Perhaps an effect system would do the trick.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Lock-free programming for the masses</title>
   <link href="https://kcsrk.info/ocaml/multicore/2016/06/11/lock-free/"/>
   <updated>2016-06-11T09:08:00+00:00</updated>
   <id>https://kcsrk.info/ocaml/multicore/2016/06/11/lock-free</id>
   <content type="html">&lt;p&gt;Efficient concurrent programming libraries are essential for taking advantage of
fine-grained parallelism on multicore hardware. In this post, I will introduce
&lt;a href=&quot;https://github.com/ocamllabs/reagents&quot;&gt;&lt;em&gt;reagents&lt;/em&gt;&lt;/a&gt;, a composable, lock-free
concurrency library for expressing fine-grained parallel programs on &lt;a href=&quot;https://github.com/ocamllabs/ocaml-multicore/wiki&quot;&gt;Multicore
OCaml&lt;/a&gt;. Reagents offer a
high-level DSL for experts to specify efficient concurrency libraries, but also
allows the consumers of the libraries to extend them further without knowing the
details of the underlying implementation.&lt;/p&gt;

&lt;!--_more--&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Designing and implementing scalable concurrency libraries is an enormous
undertaking. Decades of research and industrial effort has led to
state-of-the-art concurrency libraries such as
&lt;a href=&quot;https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.htm://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html&quot;&gt;java.util.concurrent&lt;/a&gt;
(JUC) for the JVM and
&lt;a href=&quot;https://msdn.microsoft.com/en-us/library/dd460718(v=vs.110).aspx&quot;&gt;System.Collections.Concurrent&lt;/a&gt;
(SCC) for the .NET framework. These libraries are often written by experts and
have subtle invariants, which makes them hard to maintain and improve. Moreover,
it is hard for the library user to safely combine multiple atomic operations.
For example, while JUC and SCC provide atomic operations on stacks and queues,
such atomic operations cannot be combined into larger atomic operations.&lt;/p&gt;

&lt;p&gt;On the other hand software transactional memory (STM) offers
&lt;a href=&quot;http://research.microsoft.com/pubs/67418/2005-ppopp-composable.pdf&quot;&gt;composability&lt;/a&gt;,
but STM based data structures are generally less efficient than their lock-free
counterparts, especially when there is moderate to high levels of contention.
&lt;a href=&quot;https://github.com/aturon&quot;&gt;Aaron Turon&lt;/a&gt; introduced
&lt;a href=&quot;https://www.mpi-sws.org/~turon/reagents.pdf&quot;&gt;reagents&lt;/a&gt;, an expressive and
composable library which retains the performance and scalability of lock-free
programming. Reagents allow isolated atomic updates to shared state, as well as
message passing communication over channels. Furthermore, reagents provide a set
of combinators for sequential composition à la STM, parallel composition
à la &lt;a href=&quot;https://en.wikipedia.org/wiki/Join-calculus&quot;&gt;Join calculus&lt;/a&gt;, and
selective communication à la &lt;a href=&quot;https://en.wikipedia.org/wiki/Concurrent_ML&quot;&gt;Concurrent
ML&lt;/a&gt;, while being lock-free.
Reagents occupy this sweet-spot between expressivity and performance, and we
believe it could serve as a great default&lt;sup id=&quot;fnref:lib&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:lib&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; for writing fine-grained
concurrent programs in Multicore OCaml.&lt;/p&gt;

&lt;h2 id=&quot;combinators&quot;&gt;Combinators&lt;/h2&gt;

&lt;p&gt;The basic reagents combinators are presented below.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;(* channel communication *)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;swap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endpoint&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;(* shared memory *)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;upd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;(* sequential composition *)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;(* conjunction *)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;(* disjunction *)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;+&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;A reagent value with type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&apos;a,&apos;b) t&lt;/code&gt; represents an atomic transaction that
takes an input of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;a&lt;/code&gt; and returns a value of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;b&lt;/code&gt;. The basic atomic
operations are exchanging message on an endpoint of a channel through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swap&lt;/code&gt; and
updating a shared reference through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upd&lt;/code&gt;. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swap&lt;/code&gt; operation blocks the
calling thread until a matching swap operation is available on the dual
endpoint.&lt;/p&gt;

&lt;p&gt;The atomic reference update operation &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upd&lt;/code&gt;, takes a function which is applied
to the current value of the reference (of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;a&lt;/code&gt;) and the input value (of
type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;b&lt;/code&gt;), and is expected to return an optional pair of the new value for the
reference and a return value (of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;c&lt;/code&gt;). If the update function returns
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;None&lt;/code&gt;, then the invoking thread blocks until the reference is updated. Reagent
implementation takes care of the blocking and signalling necessary for thread
wake up.&lt;/p&gt;

&lt;p&gt;The most important feature of reagents is that it allows composition of reagent
transactions in sequence &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt; and in parallel &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;*&amp;gt;&lt;/code&gt;, and also to selectively
choose one of the available operations &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;+&amp;gt;&lt;/code&gt;. Furthermore, these combinators
being &lt;a href=&quot;http://www.cse.chalmers.se/~rjmh/afp-arrows.pdf&quot;&gt;arrows&lt;/a&gt;, enable
optimisations that cover the common case and help reagents achieve performance
commensurate to hand-written implementations. Reagents library also exposes
monadic combinators for convenience, at the cost of forgoing optimisation
opportunities.&lt;/p&gt;

&lt;h2 id=&quot;a-lock-free-stack&quot;&gt;A lock-free stack&lt;/h2&gt;

&lt;p&gt;The following is a reagent implementation of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Treiber_Stack&quot;&gt;Treiber lock-free
stack&lt;/a&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;R&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Reagent&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TreiberStack&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;push&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pop&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;try_pop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;push&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upd&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;try_pop&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upd&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;([]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pop&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upd&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;None&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We utilise a shared reference of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;a list ref&lt;/code&gt; to represent the stack and
use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upd&lt;/code&gt; operation to perform atomic operations on the stack. The important
take away from this snippet is that the code is no more complicated than a
sequential stack implementation. The logic for backoff, retry, blocking and
signalling are hidden behind the reagents implementation. In particular, the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pop&lt;/code&gt; operation blocks the calling thread until the stack is non-empty. Thus,
the experts can write efficient concurrency libraries using reagents while
preserving readability (and as a consequence maintainability) of code.&lt;/p&gt;

&lt;p&gt;Furthermore, since the stack interface is exposed as reagents, the individual
operations can be further composed. For example, given two Treiber stacks &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s1&lt;/code&gt;
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s2&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pop s1 &amp;gt;&amp;gt;&amp;gt; push s2&lt;/code&gt; transfers elements atomically between the stacks,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pop s1 &amp;lt;*&amp;gt; pop s2&lt;/code&gt; consumes elements atomically from both of the stacks, and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pop s1 &amp;lt;+&amp;gt; pop s2&lt;/code&gt; consumes an element from either of the stacks. Importantly,
the composition preserves the optimisations and blocking/signalling behaviours,
allowing the users of the library to arbitrarily combine and extend the
functionality without knowing about the underlying implementation.&lt;/p&gt;

&lt;h2 id=&quot;feeding-the-philosophers&quot;&gt;Feeding the philosophers&lt;/h2&gt;

&lt;p&gt;The parallel composition combinator provides an elegant way to solve the &lt;a href=&quot;https://en.wikipedia.org/wiki/Dining_philosophers_problem&quot;&gt;Dining
Philosophers
problem&lt;/a&gt;. The problem
imagines a set of philosophers seated around a circular table, forever
alternating between thinking and eating. Forks are placed between adjacent
philosophers, and each philosopher can only eat after obtaining both the left
and right forks. The goal is to design a solution where no philosopher will
starve. The problem highlights the issues of deadlock and fairness in concurrent
programming.&lt;/p&gt;

&lt;p&gt;One way to solve this problem is to model each fork as a pair of endpoints, one
for taking and another for dropping the fork.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fork&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endpoint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;take&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endpoint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mk_fork&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drop&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;take&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mk_chan&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;take&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drop&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;swap&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drop&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;take&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;swap&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;take&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now, the solution for a single round of eating can be implemented as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eat&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l_fork&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r_fork&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ignore&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;take&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l_fork&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;take&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r_fork&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;(* ...
   * eat
   * ... *)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;spawn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drop&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l_fork&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;spawn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@@&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drop&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r_fork&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;take l_fork &amp;lt;*&amp;gt; take r_fork&lt;/code&gt; to &lt;em&gt;atomically&lt;/em&gt; take both of the forks.
Reagents ensure that the protocol does not deadlock. After eating, we release
the forks by spawning lightweight threads. In the next round, the philosophers
race for the available forks. If the thread scheduler is fair, then the
protocol provides fairness among the philosophers. The complete solution is
available
&lt;a href=&quot;https://github.com/ocamllabs/reagents/blob/master/test/dining_philosophers.ml&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;implementation&quot;&gt;Implementation&lt;/h2&gt;

&lt;p&gt;The key idea behind the implementation is that the reagent transaction executes
in two phases. The first phase involves collecting all the compare-and-swap
(CAS) operations necessary for the transaction, and the second phase is invoking
a k-CAS operation (emulated in software). The failure to gather all the
available CASes constitutes a permanent failure, causing the thread to explore
other alternatives in the case of a selective communication or block otherwise.
The failure in the second phase means that there is active interference from
other concurrent threads, in which case the transaction is retried.&lt;/p&gt;

&lt;p&gt;Performance of the Reagents depends critically on having fine-grained control
over threads and schedulers for implementing backoff loops, blocking and
signalling. However, one of the main ideas of multicore OCaml is not to bake in
the thread scheduler into the compiler but rather describe them as libraries. To
this end, the reagents library is functorized over the following generic
scheduler interface:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Scheduler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;(* continuation *)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cont&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Suspend&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cont&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Resume&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cont&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The interface itself only describes the scheduler’s effects, whose behaviour is
defined by the
&lt;a href=&quot;http://kcsrk.info/ocaml/multicore/2015/05/20/effects-multicore/&quot;&gt;handlers&lt;/a&gt;.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;perform (Suspend f)&lt;/code&gt; applies &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; to the current continuation, and allows the
Reagent library to stash the thread on the unavailable resource’s wait queue.
The return type of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; is an option to handle the case when the resource might
have become available while suspending. If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;None&lt;/code&gt;, then the control
returns to the scheduler. Once the resource becomes available, the reagent
library performs the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Resume&lt;/code&gt; effect to resume the suspended thread.&lt;/p&gt;

&lt;h2 id=&quot;comparison-to-stm&quot;&gt;Comparison to STM&lt;/h2&gt;

&lt;p&gt;Reagents are less expressive than STM, which provides serializability. But in
return, Reagents provide stronger progress guarantee (lock-freedom) over STM
(obstruction-freedom)&lt;sup id=&quot;fnref:stm&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:stm&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. A reagent transaction operating more than once on
the same memory location will fail at runtime. Abstractly, this behaviour is
disallowed since it cannot be represented as a k-CAS operation. Due to this
restriction, the transaction &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pop s1 &amp;gt;&amp;gt;&amp;gt; push s1&lt;/code&gt; always fails, and prohibits
important patterns such as atomically pushing or popping multiple values from
the same stack. I am currently working on extending the reagents semantics to
relax this invariant. The resultant behaviour will be similar to a version of
snapshot isolation. While this is weaker than serializability semantics offered
by the STM, we will retain the benefit of lock-freedom.&lt;/p&gt;

&lt;h2 id=&quot;contribute&quot;&gt;Contribute!&lt;/h2&gt;

&lt;p&gt;Using the reagents library, we have implemented a collection of composable
concurrent data and synchronization structures such as stacks, queues, countdown
latches, reader-writer locks, condition variables, exchangers, atomic counters,
etc. There is great opportunity here to build a standard library for
fine-grained parallelism for Multicore OCaml, incorporating the latest
developments in lock-free data structures. There is still work to be done
optimising the implementation to remove allocations in the fast path, and
fine-tuning the reagents core.&lt;/p&gt;

&lt;p&gt;Contributions to the &lt;a href=&quot;https://github.com/ocamllabs/reagents&quot;&gt;library&lt;/a&gt; are most
welcome, and is a great way to contribute to the Multicore OCaml effort. Please
do file those issues and submit pull-requests.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:lib&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Reagents is just a library, and you can implement your own &lt;a href=&quot;https://en.wikipedia.org/wiki/Software_transactional_memory&quot;&gt;favourite&lt;/a&gt; &lt;a href=&quot;http://research.microsoft.com/en-us/projects/revisions/&quot;&gt;concurrent&lt;/a&gt; &lt;a href=&quot;http://www.kadix.ca/x10/doc/concepts/asyncfinishparallelism-1.html&quot;&gt;programming&lt;/a&gt; &lt;a href=&quot;https://en.wikipedia.org/wiki/Fork%E2%80%93join_model&quot;&gt;library&lt;/a&gt;. &lt;a href=&quot;#fnref:lib&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:stm&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;And then there are &lt;a href=&quot;http://www.acc.ncku.edu.tw/chinese/faculty/shulc/courses/adb/transactional-memory/notlockfree.pdf&quot;&gt;good arguments&lt;/a&gt; to why the semantics should be even weaker. &lt;a href=&quot;#fnref:stm&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Armed with Reason</title>
   <link href="https://kcsrk.info/reason/arm/2016/05/16/armed-with-reason/"/>
   <updated>2016-05-16T10:00:05+00:00</updated>
   <id>https://kcsrk.info/reason/arm/2016/05/16/armed-with-reason</id>
   <content type="html">&lt;p&gt;This is a short tutorial on how to build
&lt;a href=&quot;http://facebook.github.io/reason/&quot;&gt;Reason&lt;/a&gt; apps for an ARM target with the help
of Docker. I am using &lt;a href=&quot;https://blog.docker.com/2016/03/docker-for-mac-windows-beta/&quot;&gt;Docker for
Mac&lt;/a&gt;, which is
still under beta program. Using Docker for development has two important
advantages over traditional cross-compilation. First, the Reason toolchain comes
packaged as a Docker image and hence no local installation is necessary.
Secondly, cross-compilers are often tricky to get right. Docker for Mac comes
with multiarch support and hence removes the need for traditional
cross-compilation.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h1 id=&quot;setup&quot;&gt;Setup&lt;/h1&gt;

&lt;p&gt;I will be testing using a &lt;a href=&quot;https://en.wikipedia.org/wiki/Cubieboard&quot;&gt;Cubietruck&lt;/a&gt;
running Linaro Desktop. But these instructions should also work for
&lt;a href=&quot;https://www.raspbian.org/&quot;&gt;Raspbian&lt;/a&gt;, a Debian optimized for the Raspberry pi
hardware.&lt;/p&gt;

&lt;h1 id=&quot;build&quot;&gt;Build&lt;/h1&gt;

&lt;p&gt;First get the dockerfile for Reason toolchain and build the image.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; /tmp/reason_arm
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /tmp/reason_arm
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wget https://gist.githubusercontent.com/kayceesrk/dc37a6ffeeda2dea338550dd4e8ad7ec/raw/8e136b8b8170758bd5e9c0cacf70fed4f9ce3df1/Dockerfile
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker build &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; reason-arm .&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;All set! Let’s build a “Hello, World!” program.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; /tmp/reason_arm_hello
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /tmp/reason_arm_hello
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;print_endline &quot;Hello, Reason!&quot;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; hello.re
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;pwd&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;:/src reason-arm
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /src
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rebuild hello.native
^C&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The build artifacts are found in the host machines &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp/reason_arm_hello/_build&lt;/code&gt; directory.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;file _build/hello.native
_build/hello.native: ELF 32-bit LSB executable, ARM, version 1 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;SYSV&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, dynamically linked &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;uses shared libs&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;GNU/Linux 2.6.32, not stripped&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We can now transfer the file to the cubietruck and run it. My cubietruck’s IP
address is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.0.9&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;scp _build/hello.native linaro@192.168.0.9:
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ssh linaro@192.168.0.9
Welcome to Linaro 13.04 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;GNU/Linux 3.4.61+ armv7l&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; Documentation:  https://wiki.linaro.org/
Last login: Fri May 20 08:35:01 2016 from 192.168.0.3
linaro@cubietruck:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./hello.native
Hello, Reason!&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</content>
 </entry>
 
 <entry>
   <title>Profiling the stack</title>
   <link href="https://kcsrk.info/ocaml/profiling/2015/10/27/profiling-the-stack/"/>
   <updated>2015-10-27T17:29:30+00:00</updated>
   <id>https://kcsrk.info/ocaml/profiling/2015/10/27/profiling-the-stack</id>
   <content type="html">&lt;p&gt;In the &lt;a href=&quot;http://kcsrk.info/ocaml/profiling/2015/09/23/bytecode-allocation-profiler/&quot;&gt;last
post&lt;/a&gt;,
I described a &lt;em&gt;flat&lt;/em&gt; allocation profiler for OCaml 4.02 bytecode interpreter.
In this post, I’ll describe further developments which add support for call
stack information and better location information. Lets dive straight to the
usage:&lt;/p&gt;

&lt;!--more--&gt;

&lt;h1 id=&quot;enabling-stack-profiling&quot;&gt;Enabling stack profiling&lt;/h1&gt;

&lt;p&gt;Stack profiling is enabled by setting the environment variable
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CAML_PROFILE_STACK&lt;/code&gt; to the intended depth of stack. Suppose we would like to
attribute any allocation to the current function, we would set
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CAML_PROFILE_STACK=1&lt;/code&gt;. To do the same to the current function and its caller,
we would set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CAML_PROFILE_STACK=2&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CAML_PROFILE_STACK=&amp;lt;INFINITY&amp;gt;&lt;/code&gt; should
give you stack profile all the way down to the first function.&lt;/p&gt;

&lt;h2 id=&quot;why-should-i-care-about-the-stack-depth&quot;&gt;Why should I care about the stack depth?&lt;/h2&gt;

&lt;p&gt;Because it affects the program performance. Enabling stack profiling walks the
stack for &lt;strong&gt;every&lt;/strong&gt; allocation. This has the potential to severely affect the
program performance. Most often, with a flat profile, you’ve tracked the
offending allocation to some function in the standard library such as&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;File &lt;span class=&quot;s2&quot;&gt;&quot;bytes.ml&quot;&lt;/span&gt;, line 59, characters 7-81:
  C_CALL1 caml_create_string

File &lt;span class=&quot;s2&quot;&gt;&quot;src/bigstring.ml&quot;&lt;/span&gt;, line 98, characters 20-37:
  C_CALL1 caml_create_string&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And all you want is to find out the caller of that standard library function in
your code. A stack depth of a small number should provide you this information.
You might have to play around with the stack depth to identify what you are
looking for.&lt;/p&gt;

&lt;h1 id=&quot;profiling-n-queens&quot;&gt;Profiling N-queens&lt;/h1&gt;

&lt;p&gt;You can obtain and install the profiling enabled OCaml 4.02
&lt;a href=&quot;http://kcsrk.info/ocaml/profiling/2015/09/23/bytecode-allocation-profiler/#instructions&quot;&gt;here&lt;/a&gt;.
Let us obtain the flat profile first.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wget http://caml.inria.fr/pub/old_caml_site/Examples/oc/basics/queens.ml
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ocamlc &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; queens &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; queens.ml
&lt;span class=&quot;nv&quot;&gt;$ CAML_PROFILE_ALLOC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;queens.preprof ./queens
Chess boards&lt;span class=&quot;s1&quot;&gt;&apos;s size ? 8
The 8 queens problem has 92 solutions.

Do you want to see the solutions &amp;lt;n/y&amp;gt; ? n
$ ./tools/allocprof queens.preprof queens.prof
$ head -n10 queens.prof
Total: 77,863 words
Instr   Words   % of total      Location
-----   -----   ----------      --------
2488    31440   40.38%          file &quot;list.ml&quot;, line 55, characters 32-39
27681   31440   40.38%          file &quot;queens.ml&quot;, line 61, characters 46-52
27775   5895    7.57%           file &quot;queens.ml&quot;, line 38, characters 2-113
27759   4112    5.28%           file &quot;queens.ml&quot;, line 40, characters 33-41
27687   3930    5.05%           file &quot;queens.ml&quot;, line 61, characters 14-59
2403    86      0.11%           file &quot;pervasives.ml&quot;, line 490, characters 8-63
5391    44      0.06%           file &quot;list.ml&quot;, line 20, characters 15-29&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Observe that we now have the precise location information directly in the
profile, whereas
&lt;a href=&quot;http://kcsrk.info/ocaml/profiling/2015/09/23/bytecode-allocation-profiler&quot;&gt;earlier&lt;/a&gt;
one had to manually identify the source location using the instruction
information. In this profile, we see that most allocations were in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;list.ml:55&lt;/code&gt;, which is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List.map&lt;/code&gt; function. However, we cannot pin down the
source of these allocations in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;queens.ml&lt;/code&gt; from this profile since the profile
is flat. Let us now obtain the stack allocation profile, which will reveal the
source of these allocations in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;queens.ml&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ CAML_PROFILE_ALLOC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;queens.preprof &lt;span class=&quot;nv&quot;&gt;CAML_PROFILE_STACK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;10000 ./queens
Chess boards&lt;span class=&quot;s1&quot;&gt;&apos;s size ? 8
The 8 queens problem has 92 solutions.

Do you want to see the solutions &amp;lt;n/y&amp;gt; ? n
$ ./tools/allocprof queens.preprof queens.prof --sort-stack
$ head -n10 queens.prof
Total: 77,863 words
Instr   Current Cur %   Stack   Stack % Location
-----   ------- -----   -----   ------- --------
27836   0       0.00%   76911   98.78%  file &quot;queens.ml&quot;, line 100, characters 33-42
27549   0       0.00%   76870   98.72%  file &quot;queens.ml&quot;, line 85, characters 17-36
27466   0       0.00%   76473   98.21%  file &quot;queens.ml&quot;, line 45, characters 18-31
27715   0       0.00%   65117   83.63%  file &quot;queens.ml&quot;, line 62, characters 4-22
27694   0       0.00%   62880   80.76%  file &quot;queens.ml&quot;, line 61, characters 31-59
2487    0       0.00%   55020   70.66%  file &quot;list.ml&quot;, line 55, characters 32-39
2483    0       0.00%   31440   40.38%  file &quot;list.ml&quot;, line 55, characters 20-23&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;I’ve chosen a stack depth of 10000 to obtain the complete stack profile of the
program. The option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--sort-stack&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;allocprof&lt;/code&gt; sorts the results based on
the stack allocation profile. We can now clearly see the stack of functions
that perform most allocations. The line&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;27836   0       0.00%   76911   98.78%  file &lt;span class=&quot;s2&quot;&gt;&quot;queens.ml&quot;&lt;/span&gt;, line 100, characters 33-42&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;says that 98.78% of all allocations were performed by the function at
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;queens.ml:100&lt;/code&gt;, characters 33-42, and its callees. This isn’t surprising since
this function is the top-level &lt;a href=&quot;https://github.com/kayceesrk/code-snippets/blob/master/queens.ml#L100&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt;
function&lt;/a&gt;!
More interesting is the 98.21% of allocations on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;queens.ml:45&lt;/code&gt;. This is the
recursive call to the &lt;a href=&quot;https://github.com/kayceesrk/code-snippets/blob/master/queens.ml#L43&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;concmap&lt;/code&gt;
function&lt;/a&gt;,
which in turn invokes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List.map&lt;/code&gt; function on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;queens.ml:61&lt;/code&gt;. We’ve now
pinned down the source of the allocation in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;list.ml:55&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;queens.ml:61&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;caveats-and-conclusions&quot;&gt;Caveats and conclusions&lt;/h1&gt;

&lt;p&gt;Unlike stack profiles of C programs, OCaml’s stack profile does not include all
the functions in the call stack since many calls are in tail positions. Calls
to functions at tail position will not have a frame on the stack, and hence
will not be included in the profile.&lt;/p&gt;

&lt;p&gt;Please do submit issues and bug-fixes. Pull-requests are welcome! Also, here is
my trimmed down (yay \o/!), non-exhaustive wish list of features:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Dump the profile every few milliseconds to study the allocation behavior of
programs over time.&lt;/li&gt;
  &lt;li&gt;Save the &lt;a href=&quot;https://ocaml.org/meetings/ocaml/2013/proposals/profiling-memory.pdf&quot;&gt;location information in the object
header&lt;/a&gt;
and dump the heap at every GC to catch space leaks.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Thanks to &lt;a href=&quot;https://github.com/trevorsummerssmith&quot;&gt;trevorsummerssmith&lt;/a&gt; for the example. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>An Allocation Profiler for OCaml Bytecode Interpreter</title>
   <link href="https://kcsrk.info/ocaml/profiling/2015/09/23/bytecode-allocation-profiler/"/>
   <updated>2015-09-23T09:51:30+00:00</updated>
   <id>https://kcsrk.info/ocaml/profiling/2015/09/23/bytecode-allocation-profiler</id>
   <content type="html">&lt;p&gt;This post describes a simple flat allocation profiler for OCaml 4.02 bytecode
interpreter.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;OCaml is a strongly typed functional language with automatic memory management.
Automatic memory management alleviates the need to manually deal with memory
memory management, and by construction, avoids a large class of bugs. However,
abstractions are not free in OCaml. Unlike &lt;a href=&quot;http://mlton.org/&quot;&gt;MLton&lt;/a&gt;, a
whole-program optimizing Standard ML compiler, which I used to hack on in &lt;a href=&quot;http://multimlton.cs.purdue.edu/mML/Welcome.html&quot;&gt;an
earlier life&lt;/a&gt;, in OCaml, one
needs to be particularly aware of the cost of introducing abstractions such as
higher-order functions and modules. This is often at odds with desirable
programming patterns one tends to embrace in a higher-order modular functional
language. Writing performance sensitive code in OCaml remains a skill that is
acquired gradually through experience.&lt;/p&gt;

&lt;p&gt;There are of course, excellent
&lt;a href=&quot;https://janestreet.github.io/ocaml-perf-notes.html&quot;&gt;resources&lt;/a&gt;
&lt;a href=&quot;https://ocaml.org/learn/tutorials/performance_and_profiling.html&quot;&gt;available&lt;/a&gt;
to understand the performance implications of OCaml abstractions. However,
often times, I simply need a way to profile and uncover performance bottlenecks
in my program, before I can apply any targeted optimizations. Profiling along
the following three axes are particularly useful: &lt;em&gt;time&lt;/em&gt;, &lt;em&gt;counts&lt;/em&gt; and
&lt;em&gt;allocations&lt;/em&gt;. OCaml has &lt;a href=&quot;http://caml.inria.fr/pub/docs/manual-ocaml/profil.html&quot;&gt;good support for two of
these&lt;/a&gt;. While &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ocamlcp&lt;/code&gt;
with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ocamlprof&lt;/code&gt; gives you count profile, one can use the standard Unix
profiler &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gprof&lt;/code&gt; for time profiling. However, these do not necessarily help
with identifying the cost of abstractions, for which one needs an allocation
profiler&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;h1 id=&quot;the-state-of-allocation-profiling-in-ocaml&quot;&gt;The state of allocation profiling in OCaml&lt;/h1&gt;

&lt;p&gt;While allocation profiler is not part of the standard OCaml distribution,
several alternatives do exist. &lt;a href=&quot;http://memprof.typerex.org/&quot;&gt;Memprof&lt;/a&gt; from
&lt;a href=&quot;http://www.ocamlpro.com/&quot;&gt;OCamlPro&lt;/a&gt; provides &lt;em&gt;“non-intrusive memory profiler
for OCaml applications”&lt;/em&gt;, with a simple online version and a commercial version
with fine-grained tracing. Mark Shinwell has an &lt;a href=&quot;https://github.com/mshinwell/ocaml/tree/4.02-allocation-profiling&quot;&gt;allocation profiler for OCaml
4.02&lt;/a&gt; native
code programs generated by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ocamlopt&lt;/code&gt;. Unfortunately, neither of these options
were suitable for me as the &lt;a href=&quot;https://github.com/ocamllabs/ocaml-multicore&quot;&gt;Multicore
OCaml&lt;/a&gt; currently only supports
bytecode compilation, and has a
&lt;a href=&quot;http://www.lpw25.net/ocaml2014-abs.pdf&quot;&gt;markedly&lt;/a&gt;
&lt;a href=&quot;http://www.cl.cam.ac.uk/~sd601/papers/multicore_slides.pdf&quot;&gt;different&lt;/a&gt;
&lt;a href=&quot;https://www.youtube.com/watch?v=FzmQTC_X5R4&quot;&gt;GC&lt;/a&gt;. So I decided to implement my
own for the &lt;a href=&quot;https://github.com/kayceesrk/ocaml-multicore/tree/profile-alloc&quot;&gt;multicore
compiler&lt;/a&gt;.
Since the allocation profiler will be useful in general, I have also ported it
to &lt;a href=&quot;https://github.com/kayceesrk/ocaml/tree/4.02-profile-alloc&quot;&gt;OCaml 4.02&lt;/a&gt;.
This post talks about the vanilla OCaml allocation profiler.&lt;/p&gt;

&lt;h1 id=&quot;bytecode-allocation-profiler&quot;&gt;Bytecode allocation profiler&lt;/h1&gt;

&lt;p&gt;The idea of this allocation profiler is to record the allocations and associate
them with the position in the code where the corresponding block or closure was
allocated. In particular, we do not record the call stack that led to the
allocation point, which would have provided us a more accurate picture. One can
get pretty far with just the flat profile. Running the bytecode program under
the modified interpreter produces a profile, which is then analyzed offline.&lt;/p&gt;

&lt;p&gt;The bytecode interpreter of OCaml is remarkably simple, as is the patch for the
allocation profiler. In this section, I will detail the implementation of the
profiler. If you are interested in just using the profiler, do skip right to
the &lt;a href=&quot;#instructions&quot;&gt;instructions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When the bytecode is loaded by the interpreter in
&lt;a href=&quot;https://github.com/kayceesrk/ocaml/blob/ec9496b2485eee5be14e43d1d99b2b37a8d3b3da/byterun/fix_code.c#L50&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caml_load_code&lt;/code&gt;&lt;/a&gt;,
it allocates an array for the bytecode. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caml_start_code&lt;/code&gt; points to the start
of this array. The program counter
&lt;a href=&quot;https://github.com/kayceesrk/ocaml/blob/ec9496b2485eee5be14e43d1d99b2b37a8d3b3da/byterun/interp.c#L195&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pc&lt;/code&gt;&lt;/a&gt;
is a pointer into this array. We maintain a distinct code pointer
&lt;a href=&quot;https://github.com/kayceesrk/ocaml/blob/ec9496b2485eee5be14e43d1d99b2b37a8d3b3da/byterun/interp.c#L188&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;profile_pc&lt;/code&gt;&lt;/a&gt;
that always points to the instruction and never its operands. The offset of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;profile_pc&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caml_start_code&lt;/code&gt; uniquely identifies a instruction in the
bytecode executable. We will use this offset to record the allocation points.&lt;/p&gt;

&lt;p&gt;We allocate an array
&lt;a href=&quot;https://github.com/kayceesrk/ocaml/blob/ec9496b2485eee5be14e43d1d99b2b37a8d3b3da/byterun/startup.c#L418&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caml_profile_counts&lt;/code&gt;&lt;/a&gt;
of unsigned integers whose length is equal to the length of the code, into
which we will store the allocation counts. There are two main ways in which
OCaml allocates memory;
&lt;a href=&quot;https://github.com/kayceesrk/ocaml/blob/ec9496b2485eee5be14e43d1d99b2b37a8d3b3da/byterun/caml/memory.h#L71&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alloc_small&lt;/code&gt;&lt;/a&gt;
for allocating in minor heap, and
&lt;a href=&quot;https://github.com/kayceesrk/ocaml/blob/ec9496b2485eee5be14e43d1d99b2b37a8d3b3da/byterun/memory.c#L405&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caml_alloc_shr&lt;/code&gt;&lt;/a&gt;
for allocating in major heap. We modify both to record the allocations at a
given instruction. We modify
&lt;a href=&quot;https://github.com/kayceesrk/ocaml/blob/ec9496b2485eee5be14e43d1d99b2b37a8d3b3da/byterun/interp.c&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;interp.c&lt;/code&gt;&lt;/a&gt;
to update &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;profile_pc&lt;/code&gt; for instructions which potentially allocate. Allocations
for arrays and strings are performed in their corresponding C functions through
&lt;a href=&quot;https://github.com/kayceesrk/ocaml/blob/ec9496b2485eee5be14e43d1d99b2b37a8d3b3da/byterun/alloc.c#L30&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caml_alloc&lt;/code&gt;&lt;/a&gt;.
Such allocations are covered by recording the instruction in
&lt;a href=&quot;https://github.com/kayceesrk/ocaml/blob/ec9496b2485eee5be14e43d1d99b2b37a8d3b3da/byterun/interp.c#L69&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Setup_for_c_call&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caml_alloc_shr&lt;/code&gt; is also used by the GC for promoting live minor heap objects
to major heap at the end of a minor GC cycle. Allocations by GC is ignored by
resetting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;profile_pc&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NULL&lt;/code&gt; before minor collections. Hence, the profiler
only counts allocations by the mutator. Finally, the interpreter &lt;a href=&quot;https://github.com/kayceesrk/ocaml/blob/ec9496b2485eee5be14e43d1d99b2b37a8d3b3da/byterun/startup.c#L450&quot;&gt;outputs the
profile&lt;/a&gt;
at the end of execution of the program.&lt;/p&gt;

&lt;div id=&quot;instructions&quot;&gt; &lt;/div&gt;
&lt;p&gt;#Using the profiler&lt;/p&gt;

&lt;p&gt;In order to use the profiler, compile the OCaml programs with the bytecode
compiler &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ocamlc&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-g&lt;/code&gt; option to record the debugging information. This
will be used to interpret the profile. When using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ocamlbuild&lt;/code&gt; it is necessary
to compile and link with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-g&lt;/code&gt; (with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-cflag -g -lflag -g&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;First, get OCaml 4.02 with the allocation profiler, and build it using
&lt;a href=&quot;https://github.com/gasche/opam-compiler-conf&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opam-compiler-conf&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone https://github.com/kayceesrk/ocaml
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;ocaml
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git checkout 4.02-profile-alloc
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;opam compiler-conf configure
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make world.opt
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;opam compiler-conf &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Let us profile the &lt;a href=&quot;http://caml.inria.fr/pub/old_caml_site/Examples/oc/basics/queens.ml&quot;&gt;Eight
Queens&lt;/a&gt;
program. Profiling is enabled by setting the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CAML_PROFILE_ALLOC&lt;/code&gt; to the output
filename of the profile.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wget http://caml.inria.fr/pub/old_caml_site/Examples/oc/basics/queens.ml
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ocamlc &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; queens &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; queens.ml
&lt;span class=&quot;nv&quot;&gt;$ CAML_PROFILE_ALLOC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;queens.preprof ./queens
Chess boards&lt;span class=&quot;s1&quot;&gt;&apos;s size ? 8
The 8 queens problem has 92 solutions.

Do you want to see the solutions &amp;lt;n/y&amp;gt; ? n
$ ./tools/allocprof queens.preprof &amp;gt; queens.prof
$ head -n5 queens.prof
Total: 80,433 words
Instr   Words   % of total
-----   -----   ----------
2488    31440   39.09%
27681   31440   39.09%&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;allocprof&lt;/code&gt; is a small python script that post-processes the profile. The
post-processed profile shows the total number of words allocated, and is
followed by the instruction number, words allocated and the percentage of total
allocation that it represents. The instruction number can be linked back to the
source code by dumping the bytecode executable with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dumpobj&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./tools/dumpobj queens &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; queens.dumpobj
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vim queens.prof queens.dump queens.ml&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;img src=&quot;https://kcsrk.info/assets/queens-profile-alloc.png&quot; alt=&quot;Profiling 8 queens&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We can see that the program spent 39.09% of allocations for appending to lists
in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;queens.ml&lt;/code&gt; line 61. For the curious, the other 39.09% was spent in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List.map&lt;/code&gt; function.&lt;/p&gt;

&lt;h1 id=&quot;dealing-with-early-termination&quot;&gt;Dealing with early termination&lt;/h1&gt;

&lt;div id=&quot;earlytermination&quot;&gt; &lt;/div&gt;

&lt;p&gt;The profiler normally writes out the profile at the end of the standard program
termination, when the interpreter has run to completion. However, programs may
terminate early by explicitly invoking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exit&lt;/code&gt;. In such cases, the runtime does
not get a chance to output the profile. Hence, a function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;output_profile: unit
-&amp;gt; unit&lt;/code&gt; is provided to explicitly request the profile to be written out to the
filename provided in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CAML_PROFILE_ALLOC&lt;/code&gt;. The following example illustrates
the use case in a program that uses the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Async&lt;/code&gt; library:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;c&quot;&gt;(* foo.ml *)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Core&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Std&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Async&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Std&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hello!&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;(* Without this call, profile isn&apos;t written out *)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;output_profile&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;async_basic&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;foo&quot;&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;Command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Spec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Command&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The program is compiled and run as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ocamlbuild &lt;span class=&quot;nt&quot;&gt;-use-ocamlfind&lt;/span&gt; foo.byte &lt;span class=&quot;nt&quot;&gt;-package&lt;/span&gt; core &lt;span class=&quot;nt&quot;&gt;-package&lt;/span&gt; async &lt;span class=&quot;nt&quot;&gt;-tag&lt;/span&gt; thread &lt;span class=&quot;nt&quot;&gt;-tag&lt;/span&gt; debug
Finished, 3 targets &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0 cached&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;00:00:00.
&lt;span class=&quot;nv&quot;&gt;$ CAML_PROFILE_ALLOC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;foo.preprof ./foo.byte
Hello!
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls &lt;/span&gt;foo.preprof
foo.preprof&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Thanks to &lt;a href=&quot;https://github.com/trevorsummerssmith&quot;&gt;trevorsummerssmith&lt;/a&gt; for the
motivation and the example.&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;The allocation profiler has been quite useful for optimizing small programs. It
would be interesting to see whether it scales to larger ones. Also, here is my
(non-exhaustive) wish list of features:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Improve tooling. Avoid the need to manually search through text files.&lt;/li&gt;
  &lt;li&gt;Record stack allocation. This is especially important in multicore OCaml
  &lt;a href=&quot;http://kcsrk.info/#ocaml15&quot;&gt;since stacks are heap allocated&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Record the call stack information for allocations to get an informative profile.&lt;/li&gt;
  &lt;li&gt;Dump the profile every few milliseconds to study the allocation behavior of
  programs over time.&lt;/li&gt;
  &lt;li&gt;Save the &lt;a href=&quot;https://ocaml.org/meetings/ocaml/2013/proposals/profiling-memory.pdf&quot;&gt;location information in the object
  header&lt;/a&gt;
  and dump the heap at every GC to catch space leaks.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Profiling for time does give you the time that the program spends in garbage collection functions such as minor GC cycles and major GC slices, but are not helpful for pinpointing allocation bottlenecks. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Experiment with OCaml Multicore and Algebraic Effects</title>
   <link href="https://kcsrk.info/multicore/opam/ocaml/2015/09/10/ocaml-experimental-compilers/"/>
   <updated>2015-09-10T13:11:00+00:00</updated>
   <id>https://kcsrk.info/multicore/opam/ocaml/2015/09/10/ocaml-experimental-compilers</id>
   <content type="html">&lt;p&gt;I recently gave a talk on Algebraic Effects in OCaml at the &lt;a href=&quot;https://ocaml.org/meetings/ocaml/2015/&quot;&gt;OCaml Workshop
2015&lt;/a&gt;. The extended abstract and the
slides from the talk are available &lt;a href=&quot;http://kcsrk.info/#ocaml15&quot;&gt;here&lt;/a&gt;. The slides
should provide a gentle introduction to programming with algebraic effects and
handlers in OCaml. The examples from the talk (and many more!) are available
&lt;a href=&quot;https://github.com/kayceesrk/ocaml-eff-example&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Algebraic effects in OCaml are available as a part of the multicore OCaml. The
experimental compiler could easily be installed using the OCaml Labs opam
development repo.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;opam remote add ocamllabs &lt;span class=&quot;nt&quot;&gt;-k&lt;/span&gt; git https://github.com/ocamllabs/opam-repo-dev
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;opam switch 4.02.2+multicore&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you are interested in contributing, please do experiment with algebraic
effects, and report any inevitable bugs or feature requests to the multicore
OCaml &lt;a href=&quot;https://github.com/ocamllabs/ocaml-multicore/issues&quot;&gt;issue tracker&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We are also quite interested in hearing interesting applications of algebraic
effects such as the encoding of &lt;a href=&quot;https://github.com/kayceesrk/ocaml-eff-example/blob/master/reify_reflect.ml&quot;&gt;monadic
reflection&lt;/a&gt;
and &lt;a href=&quot;https://github.com/kayceesrk/ocaml-eff-example/blob/master/delimcc.ml&quot;&gt;one-shot multi-prompt delimited
control&lt;/a&gt;.
Feel free to submit pull requests with your examples.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Pearls of Algebraic Effects and Handlers</title>
   <link href="https://kcsrk.info/ocaml/multicore/effects/2015/05/27/more-effects/"/>
   <updated>2015-05-27T14:06:00+00:00</updated>
   <id>https://kcsrk.info/ocaml/multicore/effects/2015/05/27/more-effects</id>
   <content type="html">&lt;p&gt;In the &lt;a href=&quot;http://kcsrk.info/ocaml/multicore/2015/05/20/effects-multicore/&quot;&gt;previous
post&lt;/a&gt;, I
presented a simple cooperative multithreaded scheduler written using algebraic
effects and their handlers. Algebraic effects are of course useful for
expressing other forms of effectful computations. In this post, I will present
a series of simple examples to illustrate the utility of algebraic effects and
handlers in OCaml. Some of the examples presented here were borrowed from the
excellent paper on Eff programming language&lt;sup id=&quot;fnref:Eff&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:Eff&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. All of the examples
presented below are available
&lt;a href=&quot;https://github.com/kayceesrk/ocaml-eff-example&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;state&quot;&gt;State&lt;/h2&gt;

&lt;p&gt;We can use algebraic effects to model &lt;a href=&quot;https://github.com/kayceesrk/ocaml-eff-example/blob/master/state.ml&quot;&gt;stateful
computation&lt;/a&gt;,
with the ability to retrieve (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get&lt;/code&gt;) and update (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;put&lt;/code&gt;) the current state:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;STATE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;put&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;run&lt;/code&gt; runs a stateful computation with the given initial state.
Here is the implementation of the module &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;State&lt;/code&gt; which provides the desired
behaviour:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;State&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;STATE&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Put&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;put&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;perform&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Put&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Get&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;perform&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Get&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;comp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Put&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;continue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Get&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;continue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;comp&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;init&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The key idea here is that the handler converts the stateful computation to
functions that accept the state. For example, observe that if the function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt;
returns a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unit&lt;/code&gt; value (line 13), we return a function which accepts a state
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s&lt;/code&gt; and returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unit&lt;/code&gt;. The handler for effect &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Get&lt;/code&gt; (line 15) passes the current state &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s&lt;/code&gt;
to the continuation &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;k&lt;/code&gt;. The expression &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;continue k s&lt;/code&gt; returns a function that
accepts the current state and returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unit&lt;/code&gt;. Since fetching the current state
does not modify it, we apply this function to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s&lt;/code&gt;, the original state. Since
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Put&lt;/code&gt; modifies the state (line 14), the function returned by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;continue k ()&lt;/code&gt; is applied
to the new state &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s&apos;&lt;/code&gt;. We evaluate the computation by applying it to the initial
state &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init&lt;/code&gt; (line 16).&lt;/p&gt;

&lt;p&gt;Observe that the implementation of the handler for the stateful computation is
similar to the implementation of &lt;a href=&quot;https://wiki.haskell.org/State_Monad#Implementation&quot;&gt;State
monad&lt;/a&gt; in Haskell. Except
that in Haskell, you would have the stateful computation &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; have the type
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;State t ()&lt;/code&gt;, which says that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; is a stateful computation where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;t&lt;/code&gt; is the
type of state and  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt; the type of return value. Since multicore OCaml does
not have a effect system, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; simply has type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unit -&amp;gt; unit&lt;/code&gt; as opposed to
being explicitly tagged with the effects being performed. While the OCaml type
of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; under specifies the behaviour of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt;, it does allow you to combine various
kinds of effects directly, without the need for monad transformer
gymnastics&lt;sup id=&quot;fnref:Idris-eff&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:Idris-eff&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. For example, the following code snippet combines an int
and string typed state computations, each with its own handler:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;State&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;State&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;IS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;IS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;put&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;IS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;IS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;put&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;21&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;IS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;SS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;put&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;SS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;SS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;put&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;world&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;SS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;IS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;SS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;which prints:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;0
42
21
hello
world&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;

&lt;p&gt;We can expand upon our state example, to model &lt;a href=&quot;https://github.com/kayceesrk/ocaml-eff-example/blob/master/ref.ml&quot;&gt;ML style
references&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;State&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Univ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Univ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ref&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;perform&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Ref&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Read&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;perform&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Write&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;perform&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Write&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;comp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Ref&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Univ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;embed&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cont&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;continue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;cont&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inj&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Read&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prj&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;continue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;failwith&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Ref.run: Impossible -&amp;gt; ref not found&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Write&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;continue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inj&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;comp&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The idea is to represent the state as a list of universal typed values,
references as a record with inject and project functions to and from universal
type values, assign as appending a new value to the head of the state list, and
dereference as linear search through the list for a matching assignment. The
&lt;a href=&quot;https://blogs.janestreet.com/a-universal-type/#comment-163&quot;&gt;universal type
implementation&lt;/a&gt; is
due to Alan Frisch.&lt;/p&gt;

&lt;h2 id=&quot;transactions&quot;&gt;Transactions&lt;/h2&gt;

&lt;p&gt;We may handle lookup and update to implement
&lt;a href=&quot;https://github.com/kayceesrk/ocaml-eff-example/blob/master/transaction.ml&quot;&gt;transactions&lt;/a&gt;
that discards the updates to references in case an exception occurs:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;atomically&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;comp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;exception&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rb&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rb&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Update&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rb&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;old_v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;continue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;old_v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rb&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;comp&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Updating a reference builds up a rollback function that negates the effect of
the update. In case of an exception, the rollback function is evaluated before
re-raising the exception. For example, in the following code snippet:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;exception&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Res&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;atomically&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* T0 *)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;T0: %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;atomically&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;(* T1 *)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;21&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;T1: Before abort %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Res&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;T1: After abort %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Res&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;T0: T1 aborted with %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;T0: %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;the updates to reference &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt; by transaction &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T1&lt;/code&gt; are discarded on exception and
the program prints the following:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;T0: 10
T1: Before abort 21
T0: T1 aborted with 21
T0: 10&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;from-iterators-to-generators&quot;&gt;From Iterators to Generators&lt;/h2&gt;

&lt;p&gt;An iterator is a fold-function of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&apos;a -&amp;gt; unit) -&amp;gt; unit&lt;/code&gt;, that iterates a
client function over all the elements of a data structure. A generator is a
function of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unit -&amp;gt; &apos;a option&lt;/code&gt; that returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Some v&lt;/code&gt; each time the
function is invoked, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v&lt;/code&gt; is the &lt;em&gt;next-element&lt;/em&gt; in the data structure. The
function returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;None&lt;/code&gt; if the traversal is complete. Unlike an iterator, the
generator hands over control of the traversal to the client of the library.&lt;/p&gt;

&lt;p&gt;Gabriel Scherer’s insightful article on &lt;a href=&quot;http://gallium.inria.fr/blog/generators-iterators-control-and-continuations/&quot;&gt;generators, iterators, control and
continuations&lt;/a&gt;
nicely distinguish, motivate and provide implementation of different kinds of
iterators and generators for binary trees. While the iterator implementation is
obvious and straight-forward, the generator implementation requires translating
the code to CPS style and manually performing simplifications for efficient
traversal. Since algebraic effects handlers give us a handle to the
continuation, we can essentially &lt;a href=&quot;https://github.com/kayceesrk/ocaml-eff-example/blob/master/generator.ml&quot;&gt;&lt;em&gt;derive&lt;/em&gt; the generator implementation from
the
iterator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let us consider a binary tree with the following type:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Leaf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Node&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We can define an iterator that traverses the tree from left to right as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iter&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Leaf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Node&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iter&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iter&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;From this iterator, we derive the generator as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_gen&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Next&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;step&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;first_step&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;iter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;perform&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Next&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;nc&quot;&gt;None&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Next&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;step&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;continue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;step&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;first_step&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;At each step of the iteration, we perform the effect &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Next : a -&amp;gt; unit&lt;/code&gt; (line
7), which is handled by saving the continuation to a local reference and
returning the value (line 9 - 11). Since the effect handlers are provided with
the continuation, we are able to invert the control from the library to the
client of the library. This avoids the need to perform manual CPS translation.&lt;/p&gt;

&lt;h2 id=&quot;direct-style-asynchronous-io&quot;&gt;Direct-style asynchronous IO&lt;/h2&gt;

&lt;p&gt;Since the effect handler has access to the continuation, we can implement
minimal &lt;a href=&quot;https://github.com/kayceesrk/ocaml-eff-example/blob/master/aio.ml&quot;&gt;asynchronous IO in
direct-style&lt;/a&gt;
as opposed to the monadic style of asynchronous IO libraries such as Lwt and
Async. Our asynchronous IO library has the following interface:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AIO&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sig&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fork&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_descr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Unix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_descr&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sockaddr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Unix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sockaddr&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msg_flag&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Unix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg_flag&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;accept&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_descr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_descr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sockaddr&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recv&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_descr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msg_flag&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_descr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msg_flag&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Observe that the return type of the non-blocking function calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;accept&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recv&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;send&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sleep&lt;/code&gt; are the same as their blocking counterparts from
&lt;a href=&quot;http://caml.inria.fr/pub/docs/manual-ocaml/libref/Unix.html&quot;&gt;Unix&lt;/a&gt; module.&lt;/p&gt;

&lt;p&gt;The asynchronous IO implementation works as follows. For each blocking action,
if the action can be performed immediately, then it is. Otherwise, the thread
performing the blocking task is suspended and add to a pool of threads waiting
to perform IO:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;c&quot;&gt;(* Block until data is available to read on the socket. *)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Blk_read&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_descr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;(* Block until socket is writable. *)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Blk_write&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file_descr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;(* Sleep for given number of seconds. *)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Sleep&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;core&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Blk_read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;poll_rd&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;continue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Hashtbl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read_ht&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dequeue&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Blk_write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;poll_wr&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;continue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Hashtbl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;write_ht&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dequeue&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Sleep&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;continue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Hashtbl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sleep_ht&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Unix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gettimeofday&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;dequeue&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;accept&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;perform&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Blk_read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Unix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;accept&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recv&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pos&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;perform&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Blk_read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Unix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;recv&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pos&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bus&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pos&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;perform&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Blk_write&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nn&quot;&gt;Unix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bus&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pos&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The scheduler works by running all of the available threads until there are no
more threads to run. At this point, if there are threads that are waiting to
complete an IO operation, the scheduler invokes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;select()&lt;/code&gt; call and blocks
until one of the IO actions becomes available. The scheduler then resumes those
threads whose IO actions are now available:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;c&quot;&gt;(* When there are no threads to run, perform blocking io. *)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;perform_io&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rd_fds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Hashtbl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fold&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;acc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;acc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read_ht&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wr_fds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Hashtbl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fold&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;acc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;acc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;write_ht&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rdy_rd_fds&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rdy_wr_fds&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Unix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rd_fds&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wr_fds&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeout&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;resume&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ht&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;enqueue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Hashtbl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ht&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;nn&quot;&gt;Hashtbl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remove&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ht&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;resume&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ht&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;resume&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read_ht&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rdy_rd_fds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;resume&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;write_ht&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rdy_wr_fds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ignore&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wakeup&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Unix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gettimeofday&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;dequeue&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The
&lt;a href=&quot;https://github.com/kayceesrk/ocaml-eff-example/blob/master/aio.ml&quot;&gt;program&lt;/a&gt;
implements a simple echo server. The server listens on localhost port 9301. It
accepts multiple clients and echoes back to the client any data sent to the
server. This server is a direct-style reimplementation of the echo server found
&lt;a href=&quot;http://www.mega-nerd.com/erikd/Blog/CodeHacking/Ocaml/ocaml_select.html&quot;&gt;here&lt;/a&gt;,
which implements the echo server in CPS style:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;c&quot;&gt;(* Repeat what the client says until the client goes away. *)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;echo_server&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sock&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recv&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sock&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ignore&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sock&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;echo_server&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sock&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;string_of_sockaddr&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;echo_server : client (%s) disconnected.&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;%!&quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;close&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;close&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sock&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The echo server can be tested with a telnet client by starting the server and
on the same machine running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;telnet localhost 9301&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;The aim of the post is to illustrate the variety of alternative programming
paradigms that arise due to algebraic effects and handlers, and hopefully
kindle interest in reasoning and programming with effects and handlers in
OCaml. Algebraic effects and handlers support in OCaml is in active development
within the context of &lt;a href=&quot;https://github.com/ocamllabs/ocaml-multicore&quot;&gt;multicore
OCaml&lt;/a&gt;. When you find those
inevitable bugs, please report them to the &lt;a href=&quot;https://github.com/ocamllabs/ocaml-multicore/issues&quot;&gt;issue
tracker&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:Eff&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://arxiv.org/pdf/1203.1539v1.pdf&quot;&gt;Programming with Algebraic Effects and Handlers (pdf)&lt;/a&gt; &lt;a href=&quot;#fnref:Eff&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:Idris-eff&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://eb.host.cs.st-andrews.ac.uk/drafts/effects.pdf&quot;&gt;Programming and Reasoning with Algebraic Effects and Dependent Types (pdf)&lt;/a&gt; &lt;a href=&quot;#fnref:Idris-eff&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Effective Concurrency with Algebraic Effects</title>
   <link href="https://kcsrk.info/ocaml/multicore/2015/05/20/effects-multicore/"/>
   <updated>2015-05-20T14:04:00+00:00</updated>
   <id>https://kcsrk.info/ocaml/multicore/2015/05/20/effects-multicore</id>
   <content type="html">&lt;p&gt;Algebraic effects and handlers provide a modular abstraction for expressing
effectful computation, allowing the programmer to separate the expression of an
effectful computation from its implementation. In this post, I will present an
extension to OCaml for programming with linear algebraic effects, and
demonstrate its use in expressing concurrency primitives for &lt;a href=&quot;https://github.com/ocamllabs/ocaml-multicore&quot;&gt;multicore
OCaml&lt;/a&gt;. The design and
implementation of algebraic effects for multicore OCaml is due to &lt;a href=&quot;http://www.lpw25.net/&quot;&gt;Leo
White&lt;/a&gt;, &lt;a href=&quot;https://github.com/stedolan&quot;&gt;Stephen Dolan&lt;/a&gt; and
the multicore team at &lt;a href=&quot;http://www.cl.cam.ac.uk/projects/ocamllabs/&quot;&gt;OCaml
Labs&lt;/a&gt;.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Multicore-capable functional programming language implementations such as
&lt;a href=&quot;https://www.haskell.org/ghc/&quot;&gt;Glasgow Haskell Compiler&lt;/a&gt;,
&lt;a href=&quot;http://fsharp.org/&quot;&gt;F#&lt;/a&gt;, &lt;a href=&quot;http://manticore.cs.uchicago.edu/&quot;&gt;Manticore&lt;/a&gt; and
&lt;a href=&quot;https://github.com/kayceesrk/multiMLton&quot;&gt;MultiMLton&lt;/a&gt; expose one or more
libraries for expressing concurrent programs. The concurrent threads of
execution instantiated through the library are in turn multiplexed over the
available cores for speed up. A common theme among such runtimes is that the
primitives for concurrency along with the concurrent thread scheduler is baked
into the runtime system. Over time, the runtime system itself tends to become a
complex, monolithic piece of software, with extensive use of locks, condition
variables, timers, thread pools, and other arcana. As a result, it becomes
difficult to maintain existing concurrency libraries, let alone add new ones.
Such lack of malleability is particularly unfortunate as it prevents developers
from experimenting with custom concurrency libraries and scheduling strategies,
preventing innovation in the ecosystem. Our goal with this work is to provide a
minimal set of tools with which programmers can implement new concurrency
primitives and schedulers as OCaml libraries.&lt;/p&gt;

&lt;h2 id=&quot;a-taste-of-effects&quot;&gt;A Taste of Effects&lt;/h2&gt;

&lt;h3 id=&quot;a-simple-scheduler&quot;&gt;A Simple Scheduler&lt;/h3&gt;

&lt;p&gt;Let us illustrate the algebraic effect extension in multicore OCaml by
constructing a concurrent round-robin scheduler with the following interface:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;c&quot;&gt;(* Control operations on threads *)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fork&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;(* Runs the scheduler. *)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The basic tenet of programming with algebraic effects is that performing an
effectful computation is separate from its interpretation&lt;sup id=&quot;fnref:Eff&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:Eff&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.
In particular, the interpretation is dynamically chosen based on the context in
which an effect is performed. In our example, spawning a new thread and
yielding control to another are effectful actions, for which we declare the
following effects:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eff&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Fork&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eff&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Yield&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eff&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;a eff&lt;/code&gt; is the predefined extensible variant type for effects,
where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;a&lt;/code&gt; represents the return type of performing the effect. For
convenience, we introduce new syntax using which the same declarations are
expressed as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Fork&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Yield&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;unit&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Effects are performed using the primitive &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;perform&lt;/code&gt; of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;a eff -&amp;gt; &apos;a&lt;/code&gt;. We
define the functions &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fork&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yield&lt;/code&gt; as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fork&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;perform&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Fork&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;perform&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Yield&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;What is left is to provide an interpretation of what it means to perform
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fork&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yield&lt;/code&gt;. This interpretation is provided with the help of
&lt;em&gt;handlers&lt;/em&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run_q&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enqueue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;push&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run_q&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dequeue&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_empty&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run_q&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;continue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pop&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;run_q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spawn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dequeue&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;exception&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;print_string&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;dequeue&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Yield&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;enqueue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dequeue&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effect&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Fork&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;enqueue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spawn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;spawn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;spawn f&lt;/code&gt; (line 8) evaluates &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; in a new thread of control. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt;
may return normally with value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt; or exceptionally with an exception &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e&lt;/code&gt; or
effectfully with the effect performed along with the delimited
continuation&lt;sup id=&quot;fnref:Filinski94&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:Filinski94&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;k&lt;/code&gt;. In the pattern &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effect e k&lt;/code&gt;, if the
effect &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e&lt;/code&gt; has type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;a eff&lt;/code&gt;, then the delimited continuation &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;k&lt;/code&gt; has type
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&apos;a,&apos;b) continuation&lt;/code&gt;, i.e., the return type of the effect &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;a&lt;/code&gt; matches the
argument type of the continuation, and the return type of the delimited
continuation is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;b&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Observe that we represent the scheduler queue with a queue of delimited
continuations, with functions to manipulate the queue (lines 2–6). In the case
of normal or exceptional return, we pop the scheduler queue and resume the
resultant continuation using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;continue&lt;/code&gt; primitive (line 6). &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;continue k v&lt;/code&gt;
resumes the continuation &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;k : (&apos;a,&apos;b) continuation&lt;/code&gt; with value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v : &apos;a&lt;/code&gt; and
returns a value of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;b&lt;/code&gt;. In the case of effectful return with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Fork f&lt;/code&gt;
effect (lines 16–17), we enqueue the current continuation to the scheduler
queue and spawn a new thread of control for evaluating &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt;. In the case of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Yield&lt;/code&gt; effect (lines 14–15), we enqueue the current continuation, and resume
some other saved continuation from the scheduler queue.&lt;/p&gt;

&lt;h3 id=&quot;testing-the-scheduler&quot;&gt;Testing the scheduler&lt;/h3&gt;

&lt;p&gt;Lets write a simple concurrent program that utilises this scheduler, to create
a binary tree of tasks. The sources for this test are available
&lt;a href=&quot;https://github.com/kayceesrk/ocaml-eff-example&quot;&gt;here&lt;/a&gt;. The program
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;concurrent.ml&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;rec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;depth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Starting number %i&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;%!&quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;depth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;begin&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Forking number %i&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;%!&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;Sched&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fork&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;depth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Forking number %i&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;%!&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;Sched&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fork&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;depth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;begin&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Yielding in number %i&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;%!&quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;Sched&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Resumed number %i&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;%!&quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Finishing number %i&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;%!&quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Sched&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;generates a binary tree of depth 2, where the tasks are numbered as shown
below:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://kcsrk.info/assets/tree.png&quot; alt=&quot;Binary tree&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The program forks new tasks in a depth-first fashion and yields when it reaches
maximum depth, logging the actions along the way. To run the program, first
install multicore OCaml compiler, available from the &lt;a href=&quot;https://github.com/ocamllabs/opam-repo-dev&quot;&gt;OCaml Labs dev
repo&lt;/a&gt;. Once the compiler is
installed, the above test program can be compiled and run as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone https://github.com/kayceesrk/ocaml-eff-example
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;ocaml-eff-example
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./concurrent
Starting number 0
Forking number 1
Starting number 1
Forking number 3
Starting number 3
Yielding &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;number 3
Forking number 2
Starting number 2
Forking number 5
Starting number 5
Yielding &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;number 5
Forking number 4
Starting number 4
Yielding &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;number 4
Resumed number 3
Finishing number 3
Finishing number 0
Forking number 6
Starting number 6
Yielding &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;number 6
Resumed number 5
Finishing number 5
Finishing number 1
Resumed number 4
Finishing number 4
Finishing number 2
Resumed number 6
Finishing number 6&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The output illustrates how the tasks are forked and scheduled.&lt;/p&gt;

&lt;h2 id=&quot;implementation&quot;&gt;Implementation&lt;/h2&gt;

&lt;h3 id=&quot;fibers-for-concurrency&quot;&gt;Fibers for Concurrency&lt;/h3&gt;

&lt;p&gt;The main challenge in the implementation of algebraic effects is the efficient
management of delimited continuations. In multicore OCaml&lt;sup id=&quot;fnref:OW14&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:OW14&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;, the delimited
continuations are implemented using &lt;em&gt;fibers&lt;/em&gt;, which are small heap-allocated,
dynamically resized stacks. Fibers represent the unit of concurrency in the
runtime system.&lt;/p&gt;

&lt;p&gt;Our continuations are linear (one-shot)&lt;sup id=&quot;fnref:Bruggeman96&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:Bruggeman96&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;, in that once captured,
they may be resumed at most once. Capturing a one-shot continuation is fast,
since it involves only obtaining a pointer to the underlying fiber, and
requires no allocation. OCaml uses a calling convention without callee-save
registers, so capturing a one-shot continuation requires saving no more context
than that necessary for a normal function call.&lt;/p&gt;

&lt;p&gt;Since OCaml does not have linear types, we enforce the one-shot property at
runtime by raising an exception the second time a continuation is invoked. For
applications requiring true multi-shot continuations (such as probabilistic
programming&lt;sup id=&quot;fnref:Kiselyov09&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:Kiselyov09&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;), we envision providing an explicit operation to copy
a continuation.&lt;/p&gt;

&lt;p&gt;While continuation based concurrent functional programming runtimes such as
Manticore and MultiMLton use undelimited continuations, our continuations are
delimited. We believe delimited continuations enable complex nested and
hierarchical schedulers to be expressed more naturally due to the fact that
they introduce parent-child relationship between fibers similar to a function
invocation.&lt;/p&gt;

&lt;h3 id=&quot;running-on-multiple-cores&quot;&gt;Running on Multiple Cores&lt;/h3&gt;

&lt;p&gt;Multicore OCaml provides support for shared-memory parallel execution. The unit
of parallelism is a &lt;em&gt;domain&lt;/em&gt;, each running a separate system thread, with a
relatively small local heap and a single shared heap shared among all of the
domains. In order to distributed the fibers amongst the available domains, work
sharing/stealing schedulers are initiated on each of the domains. The multicore
runtime exposes to the programmer a small set of locking and signalling
primitives for achieving mutual exclusion and inter-domain communication.&lt;/p&gt;

&lt;p&gt;The multicore runtime has the invariant that there are no pointers between the
domain local heaps. However, the programmer utilising the effect library to
write schedulers need not be aware of this restriction as fibers are
transparently promoted from local to shared heap on demand. We will have to
save multicore-capable schedulers for another post.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:Eff&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://www.eff-lang.org/&quot;&gt;Eff&lt;/a&gt; &lt;a href=&quot;#fnref:Eff&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:Filinski94&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://www.diku.dk/hjemmesider/ansatte/andrzej/papers/RM-abstract.html&quot;&gt;Representing Monads&lt;/a&gt; &lt;a href=&quot;#fnref:Filinski94&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:OW14&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://ocaml.org/meetings/ocaml/2014/ocaml2014_1.pdf&quot;&gt;Multicore OCaml (pdf)&lt;/a&gt; &lt;a href=&quot;#fnref:OW14&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:Bruggeman96&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://www.cs.indiana.edu/~dyb/pubs/call1cc-abstract.html&quot;&gt;Representing Control in the presence of One-shot Continuations&lt;/a&gt; &lt;a href=&quot;#fnref:Bruggeman96&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:Kiselyov09&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://okmij.org/ftp/kakuritu/&quot;&gt;Embedded domain-specific language HANSEI for probabilistic models and (nested) inference&lt;/a&gt; &lt;a href=&quot;#fnref:Kiselyov09&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Opam Switch to Multicore OCaml</title>
   <link href="https://kcsrk.info/multicore/opam/ocaml/2015/03/25/opam-switch-to-multicore/"/>
   <updated>2015-03-25T18:15:00+00:00</updated>
   <id>https://kcsrk.info/multicore/opam/ocaml/2015/03/25/opam-switch-to-multicore</id>
   <content type="html">&lt;p&gt;OPAM has a great &lt;a href=&quot;https://opam.ocaml.org/doc/Usage.html#opamswitch&quot;&gt;compiler
switch&lt;/a&gt; feature that lets you
simultaneously host several OCaml installations, each with its own compiler
version and a set of installed packages. I wanted to use the power of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opam
switch&lt;/code&gt; for working with the experimental &lt;a href=&quot;https://github.com/ocamllabs/ocaml-multicore&quot;&gt;multicore
OCaml&lt;/a&gt; compiler. The key
advantage of doing this is that it lets you easily install packages from the
&lt;a href=&quot;http://opam.ocaml.org/&quot;&gt;OPAM repository&lt;/a&gt;, while sandboxing it from other OCaml
installations on your system. The post will show how to create OPAM compiler
switch for multicore OCaml.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;install-opam-compiler-conf&quot;&gt;Install opam-compiler-conf&lt;/h2&gt;

&lt;p&gt;The first step is to install Gabriel Scherer’s &lt;a href=&quot;https://github.com/gasche/opam-compiler-conf&quot;&gt;opam-compiler-conf
script&lt;/a&gt; which lets you do opam
switches on local installations:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone https://github.com/gasche/opam-compiler-conf
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;opam-compiler-conf
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; ~/.local/bin
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make &lt;span class=&quot;nv&quot;&gt;BINDIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~/.local/bin &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This installs the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opam-compiler-conf&lt;/code&gt; script under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.local/bin&lt;/code&gt;. Make sure
this directory is under your search path. Now, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$opam compiler-conf&lt;/code&gt; should
give you the list of available commands.&lt;/p&gt;

&lt;h2 id=&quot;build-multicore-ocaml-locally&quot;&gt;Build multicore OCaml locally&lt;/h2&gt;

&lt;p&gt;Typing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opam switch&lt;/code&gt; should list the compilers currently installed in your
system and those that are available. For instance, here is my setup:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;opam switch
system  C system  System compiler &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;4.02.1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
4.02.1  I 4.02.1  Official 4.02.1 release
4.02.0  I 4.02.0  Official 4.02.0 release
4.01.0  I 4.01.0  Official 4.01.0 release
&lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt;     &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; 3.11.2  Official 3.11.2 release
&lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt;     &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; 3.12.1  Official 3.12.1 release
&lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt;     &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; 4.00.0  Official 4.00.0 release
&lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt;     &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; 4.00.1  Official 4.00.1 release
&lt;span class=&quot;c&quot;&gt;# 66 more patched or experimental compilers, use &apos;--all&apos; to show&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can easily switch between the installations using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opam switch
[system-name]&lt;/code&gt;. Let us now install multicore OCaml as a new switch:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone https://github.com/ocamllabs/ocaml-multicore
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;ocaml-multicore
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;opam compiler-conf configure
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make world
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;opam compiler-conf &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;opam config &lt;span class=&quot;nb&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The multicore compiler is now installed and has been made the current compiler:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;opam switch
system                      I system                      System compiler &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;4.02.1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
4.02.1+local-git-multicore  C 4.02.1+local-git-multicore  Local checkout of 4.02.1 at /Users/kc/ocaml-multicore
4.02.1                      I 4.02.1                      Official 4.02.1 release
4.02.0                      I 4.02.0                      Official 4.02.0 release
4.01.0                      I 4.01.0                      Official 4.01.0 release
&lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt;                         &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; 3.11.2                      Official 3.11.2 release
&lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt;                         &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; 3.12.1                      Official 3.12.1 release
&lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt;                         &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; 4.00.0                      Official 4.00.0 release
&lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt;                         &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; 4.00.1                      Official 4.00.1 release
&lt;span class=&quot;c&quot;&gt;# 66 more patched or experimental compilers, use &apos;--all&apos; to show&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This can be confirmed by:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ocamlc &lt;span class=&quot;nt&quot;&gt;-version&lt;/span&gt;
4.02.1+multicore-dev0&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;which shows the current OCaml bytecode compiler version.&lt;/p&gt;

&lt;h2 id=&quot;working-with-the-local-switch&quot;&gt;Working with the local switch&lt;/h2&gt;

&lt;p&gt;Every time you change the compiler source, you need to rebuild the compiler and
reinstall the switch:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Changed compiler source...&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make world
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;opam compiler-conf reinstall&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The local installation can be removed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opam compiler-conf uninstall&lt;/code&gt;.&lt;/p&gt;
</content>
 </entry>
 

</feed>
