<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/default.xsl"?>
<fr:tree xmlns:fr="http://www.forester-notes.org" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:xml="http://www.w3.org/XML/1998/namespace" root="true" base-url="/">
  <fr:frontmatter>
    <fr:authors />
    <fr:uri>http://localhost/index/</fr:uri>
    <fr:display-uri>index</fr:display-uri>
    <fr:route>/index/</fr:route>
    <fr:title text="重庆森林">重庆森林</fr:title>
  </fr:frontmatter>
  <fr:mainmatter>
    <html:p>This is the <fr:link href="https://www.forester-notes.org/" type="external">forest</fr:link> of <fr:link href="/0001" type="external">Ilias Garnier</fr:link>. It acts as a core-dump of my brain: usefulness to third-parties would be purely incidental.
Those <fr:link href="/000O/" title="Articles" uri="http://localhost/000O/" display-uri="000O" type="local">articles</fr:link> should be readable. Use <html:code>ctrl-k</html:code> to search the rest.</html:p>
    <fr:tree show-metadata="false" expanded="false">
      <fr:frontmatter>
        <fr:authors />
        <fr:uri>http://localhost/000A/</fr:uri>
        <fr:display-uri>000A</fr:display-uri>
        <fr:route>/000A/</fr:route>
        <fr:title text="TODOs">TODOs</fr:title>
      </fr:frontmatter>
      <fr:mainmatter>
        <html:p>This is mostly a backlink accumulator for unfinished writing.</html:p>
        <html:p>
Other stuff:
<html:ul><html:li>Finish cleaning up the vlayout library, and then the vplot one. Would be cool to make drawing diagrams with arrows easy. Look at circuit layout algos? Could I use MCTS/MCGS for this?</html:li>
<html:li>Cleanup beamforming code and write an article out of it</html:li>
<html:li>HMM, split old page on wind power prediction using particle filters</html:li>
<html:li>Add a term indexing page</html:li>
<html:li>Look at discrimination trees</html:li>
<html:li>Plenty of other stuff on my old hard drives: exhaustive molecule generation, schreier-sims and so on.</html:li>
<html:li>The selection monad x memoizable choice tree monad =&gt; greedy algorithms, dynamic programming</html:li>
<html:li><fr:link href="/000M/" title="A category of weights and rewards" uri="http://localhost/000M/" display-uri="000M" type="local">A category of weights and rewards</fr:link></html:li>
<html:li>See <fr:link href="github.com/liamoc" type="external">Liam O'Connor</fr:link>'s forester plugins on syntax highlighting via nova</html:li></html:ul></html:p>
      </fr:mainmatter>
    </fr:tree>
    <html:p>
      <html:em>Ah! I've been through too much:-But, sweet Satan, I beg of you, a less blazing eye! and while waiting for the new little cowardly gestures yet to come, since you like an absence of descriptive or didactic skills in a writer, let me rip out these few ghastly pages from my notebook of the damned.</html:em>
    </html:p>
  </fr:mainmatter>
  <fr:backmatter>
    <fr:tree show-metadata="false" hidden-when-empty="true">
      <fr:frontmatter>
        <fr:authors />
        <fr:title text="References">References</fr:title>
      </fr:frontmatter>
      <fr:mainmatter />
    </fr:tree>
    <fr:tree show-metadata="false" hidden-when-empty="true">
      <fr:frontmatter>
        <fr:authors />
        <fr:title text="Context">Context</fr:title>
      </fr:frontmatter>
      <fr:mainmatter />
    </fr:tree>
    <fr:tree show-metadata="false" hidden-when-empty="true">
      <fr:frontmatter>
        <fr:authors />
        <fr:title text="Backlinks">Backlinks</fr:title>
      </fr:frontmatter>
      <fr:mainmatter />
    </fr:tree>
    <fr:tree show-metadata="false" hidden-when-empty="true">
      <fr:frontmatter>
        <fr:authors />
        <fr:title text="Related">Related</fr:title>
      </fr:frontmatter>
      <fr:mainmatter>
        <fr:tree show-metadata="true" expanded="false" toc="false" numbered="false">
          <fr:frontmatter>
            <fr:authors />
            <fr:uri>http://localhost/000O/</fr:uri>
            <fr:display-uri>000O</fr:display-uri>
            <fr:route>/000O/</fr:route>
            <fr:title text="重庆森林 › Articles"><fr:link href="/index/" title="重庆森林" uri="http://localhost/index/" display-uri="index" type="local">重庆森林</fr:link> › Articles</fr:title>
          </fr:frontmatter>
          <fr:mainmatter>
            <html:p>I'll post new notes and articles and backport old stuff here. This blog also got an <fr:link href="/000O/atom.xml" type="external">Atom feed</fr:link>.</html:p>
            <fr:tree show-metadata="true" expanded="false" toc="false" numbered="false">
              <fr:frontmatter>
                <fr:authors />
                <fr:date>
                  <fr:year>2026</fr:year>
                  <fr:month>1</fr:month>
                  <fr:day>12</fr:day>
                </fr:date>
                <fr:uri>http://localhost/001K/</fr:uri>
                <fr:display-uri>001K</fr:display-uri>
                <fr:route>/001K/</fr:route>
                <fr:title text="Compiling with continuations, continued">Compiling with continuations, continued</fr:title>
                <fr:taxon>article</fr:taxon>
              </fr:frontmatter>
              <fr:mainmatter><html:p>Reading notes and toy implementation for Andrew Kennedy's <fr:link href="/bib-ccc-kennedy/" title="Compiling with continuations, continued" uri="http://localhost/bib-ccc-kennedy/" display-uri="bib-ccc-kennedy" type="local">paper</fr:link>.
The paper introduces a continuation-based intermediate representation (IR) which simplifies and makes efficiently implementable some
classical optimizations (shrinking and inlining) and lends itself well to lowering to e.g. SSA representations.</html:p><html:p>The paper provides an abstract definition of the IR and its properties, defines a transformation from an ML-like language to the IR
and presents the optimizations as rewriting rules. Finally, a graph-based implementation is presented in a high-level fashion.</html:p><html:p>There's a flurry of work on the respective merits of various IRs such as SSA (with or without named blocks), CPS, ANF etc. In this page, we'll focus on fleshing out an implementation of Kennedy's ideas.</html:p>
  
  
  
  

<html:p><html:pre>#require "fmt";;</html:pre></html:p>

<fr:tree show-metadata="false"><fr:frontmatter><fr:authors /><fr:date><fr:year>2026</fr:year><fr:month>1</fr:month><fr:day>12</fr:day></fr:date><fr:title text="Source language">Source language</fr:title></fr:frontmatter><fr:mainmatter><html:p>Our source language is lambda-calculus with pairs and integers. The paper goes further (sums, let bindings, exceptions)
but we focus on the core idea.</html:p><html:p><html:pre>type expr =
  | Var of string
  | App of expr * expr
  | Lam of string * expr
  | Int of int
  | Pair of expr * expr
  | Fst of expr
  | Snd of expr
;;</html:pre></html:p><html:p>Let's see how to encode typical expressions.</html:p><html:p><html:pre>(* Example: [fun x -&gt; (x, x)] *)
let dup = Lam("x", Pair (Var "x", Var "x"));;</html:pre><html:pre>val dup : expr = Lam ("x", Pair (Var "x", Var "x"))
</html:pre></html:p><html:p>The definition of <html:code>pp_expr</html:code> is omitted, but we can use it to print stuff:</html:p><html:p><html:pre>let () = Format.printf "%a@." pp_expr dup;;</html:pre><html:pre>fun x -&gt; (x, x)</html:pre></html:p><html:p>We'll use the following expression as a tiny running example.</html:p><html:p><html:pre>let running_example =
   Lam ("f", Lam ("x", App (Var "f", Pair (Int 1, Var "x"))));;</html:pre></html:p><html:p>Or in readable form:</html:p><html:p><html:pre>let () = Format.printf "%a@." pp_expr running_example;;</html:pre><html:pre>fun f -&gt; fun x -&gt; f (1, x)</html:pre></html:p><html:p>All good. Let's look at the definition of the IR!</html:p></fr:mainmatter></fr:tree> 
<fr:tree show-metadata="false"><fr:frontmatter><fr:authors /><fr:date><fr:year>2026</fr:year><fr:month>1</fr:month><fr:day>12</fr:day></fr:date><fr:title text="Target language">Target language</fr:title></fr:frontmatter><fr:mainmatter><html:p>The target language has explicitly named continuations. We make regular variables (type <html:code>var</html:code>) and continuation variables (<html:code>kvar</html:code>) distinct at the type level.</html:p><html:p><html:pre>type var = Var of string
type kvar = KVar of string
;;</html:pre></html:p><html:p>Like with the CPS transform, the IR makes control flow explicit. All intermediate computations are bound to names.
Note that there is a specific syntactic class for values, which includes in particular lambda-abstractions. Those take
an additional continuation as a parameter (i.e. they never return). The <html:code>Kapp</html:code> constructor corresponds to calling
a continuation, while <html:code>Fapp (f, k, x)</html:code> calls a function with argument <html:code>x</html:code> and continuation <html:code>k</html:code>.
</html:p><html:p><html:pre>(* Expressions *)
type kexpr =
  (* let x = v in K *)
  | Let_val of { var : var; bound : kvalue; body : kexpr }

  (* let x = fst y in K *)
  | Let_fst of { var : var; bound : var; body : kexpr }

  (* let x = snd y in K *)
  | Let_snd of { var : var; bound : var; body : kexpr }

  (* let k x = K in L *)
  | Let_cont of { kvar : kvar; arg : var; fbody : kexpr; body : kexpr }

  (* k x *)
  | Kapp of kvar * var

  (* f k x *)
  | Fapp of var * kvar * var

(* Values *)
and kvalue =
  | Kv_int of int
  | Kv_pair of var * var
  (* \lambda  k. \lambda  x. K *)
  | Kv_lam of kvar * var * kexpr
;;</html:pre></html:p></fr:mainmatter></fr:tree>

<fr:tree show-metadata="false"><fr:frontmatter><fr:authors /><fr:date><fr:year>2026</fr:year><fr:month>1</fr:month><fr:day>12</fr:day></fr:date><fr:title text="Naive translation">Naive translation</fr:title></fr:frontmatter><fr:mainmatter><html:p>Taking our running example and trying to convert it by hand is a nice exercise (try it without looking!).</html:p><html:p>We proceed in a inside-out fashion. First the easy part: the innermost pair must be bound to a name. After the pair is evaluated, we proceed to the call of <html:code>f</html:code>.</html:p><html:p><html:pre>let f_pair =
  Let_val {
    var = Var "one";
    bound = Kv_int 1;
    body = Let_val {
      var = Var "pair";
      bound = Kv_pair (Var "one", Var "x");
      body = Fapp (Var "f", KVar "kinner", Var "pair")
    }
  }
;;</html:pre></html:p><html:p>Or in perhaps easier to read form:</html:p><html:p><html:pre>let () = Format.printf "%a@." pp_kexpr f_pair;;</html:pre><html:pre>let one = 1 in
let pair = (one, x) in
f kinner pair</html:pre></html:p><html:p>Note how we call a yet unbound function "f" with a yet unbound continuation "kinner". The variable "x" is free as well. Let's use <html:code>pair</html:code> to define the image of <html:code>fun x -&gt; f (1, x)</html:code>.</html:p><html:p><html:pre>let inner_lambda =
  Kv_lam (KVar "kinner", Var "x", f_pair)
;;</html:pre></html:p><html:p>This lambda is a value and has to be bound to a name as well.</html:p><html:p><html:pre>let inner =
  Let_val {
    var = Var "inner_lambda";
    bound = inner_lambda;
    body = Kapp (KVar "kouter", Var "inner_lambda")
  }
;;</html:pre></html:p><html:p><html:pre>let () = Format.printf "%a@." pp_kexpr inner;;</html:pre><html:pre>let inner_lambda = fun kinner x -&gt;
                     let one = 1 in
                     let pair = (one, x) in
                     f kinner pair in
kouter inner_lambda</html:pre></html:p><html:p>It remains to treat the outermost function. The last continuation is the "identity": it marks the end of the transformation.</html:p><html:p><html:pre>let outer =
  Let_val {
    var = Var "outer_lambda";
    bound = Kv_lam (KVar "kouter", Var "f", inner);
    body = Kapp (KVar "identity", Var "outer_lambda")
  }
;;</html:pre></html:p><html:p><html:pre>let () = Format.printf "%a@." pp_kexpr outer;;</html:pre><html:pre>let outer_lambda = fun kouter f -&gt;
                     let inner_lambda = fun kinner x -&gt;
                                          let one = 1 in
                                          let pair = (one, x) in
                                          f kinner pair in
                     kouter inner_lambda in
identity outer_lambda</html:pre></html:p><html:p><html:strong>This was rather cumbersome.</html:strong> We can automate this, but beforehand we need some tiny helpers.</html:p><html:p><html:pre>(* Fresh variable generation *)
let fresh f =
  let c = ref 0 in
  fun () -&gt;
    let v = !c in
    incr c ;
    Format.kasprintf f "%d" v

let kfresh = fresh (fun s -&gt; KVar ("k" ^ s))
let vfresh = fresh (fun s -&gt; Var ("x" ^ s))
;;</html:pre><html:pre>val fresh : (string -&gt; 'a) -&gt; unit -&gt; 'a = &lt;fun&gt;
val kfresh : unit -&gt; kvar = &lt;fun&gt;
val vfresh : unit -&gt; var = &lt;fun&gt;
</html:pre></html:p><html:p><html:pre>(* Convenient infix syntax to "bind" transformation-time continuation. *)
let ( let@ ) f m = f m;;</html:pre><html:pre>val ( let@ ) : ('a -&gt; 'b) -&gt; 'a -&gt; 'b = &lt;fun&gt;
</html:pre></html:p><html:p>Here comes the "naive" transformation. Look at its type: it takes an <html:code>expr</html:code> and returns a <html:code>kexpr</html:code>.
But there is an extra "transformation-time" continuation of type <html:code>var -&gt; expr</html:code> in the middle. It acts as an "accumulator" which encodes how to produce a <html:code>kexpr</html:code> when the input <html:code>expr</html:code>
has been transformed and the result of its evaluation bound a <html:code>var</html:code>.
</html:p><html:p><html:pre>let rec naive : expr -&gt; (var -&gt; kexpr) -&gt; kexpr =
 fun expr k -&gt;
  match expr with
  | Var x -&gt; k (Var x)
  | App (f, arg) -&gt;
      let@ fv = naive f in
      let@ argv = naive arg in
      let kvar = kfresh () in
      let arg = vfresh () in
      Let_cont { kvar; arg; fbody = k arg; body = Fapp (fv, kvar, argv) }
  | Lam (arg, body) -&gt;
      let var = vfresh () in
      let kvar = kfresh () in
      let body =
        let@ xv = naive body in
        Kapp (kvar, xv)
      in
      Let_val { var; bound = Kv_lam (kvar, Var arg, body); body = k var }
  | Int i -&gt;
      let var = vfresh () in
      Let_val { var; bound = Kv_int i; body = k var }
  | Pair (l, r) -&gt;
      let@ lv = naive l in
      let@ rv = naive r in
      let var = vfresh () in
      Let_val { var; bound = Kv_pair (lv, rv); body = k var }
  | Fst p -&gt;
      let@ pv = naive p in
      let var = vfresh () in
      Let_fst { var; bound = pv; body = k var }
  | Snd p -&gt;
      let@ pv = naive p in
      let var = vfresh () in
      Let_snd { var; bound = pv; body = k var }

let run_naive : expr -&gt; kexpr =
 fun expr -&gt; naive expr (fun exprv -&gt; Kapp (KVar "id", exprv))
;;</html:pre><html:pre>val naive : expr -&gt; (var -&gt; kexpr) -&gt; kexpr = &lt;fun&gt;
val run_naive : expr -&gt; kexpr = &lt;fun&gt;
</html:pre></html:p><html:p>Let's apply this to our example!</html:p><html:p><html:pre>let () = Format.printf "%a@." pp_kexpr (run_naive running_example);;</html:pre><html:pre>let x0 = fun k0 f -&gt;
           let x1 = fun k1 x -&gt;
                      let x2 = 1 in
                      let x3 = (x2, x) in
                      let k2 x4 =
                        k1 x4
                      in
                      f k2 x3 in
           k0 x1 in
id x0</html:pre></html:p><html:p>Up to <fr:tex display="inline"><![CDATA[\alpha ]]></fr:tex>-conversion, this is <html:strong>almost</html:strong> identical to our hand-rolled transform. Except that the naive transformation introduced a tiny <fr:tex display="inline"><![CDATA[\eta ]]></fr:tex>-expanded continuation <html:code>let k2 x4 = k1 x4</html:code>!
We don't want that.</html:p></fr:mainmatter></fr:tree> 
<fr:tree show-metadata="false"><fr:frontmatter><fr:authors /><fr:date><fr:year>2026</fr:year><fr:month>1</fr:month><fr:day>12</fr:day></fr:date><fr:uri>http://localhost/kennedy-ccc-optimizing/</fr:uri><fr:display-uri>kennedy-ccc-optimizing</fr:display-uri><fr:route>/kennedy-ccc-optimizing/</fr:route><fr:title text="Smarter translation">Smarter translation</fr:title></fr:frontmatter><fr:mainmatter><html:p>The optimizing translation, as its name suggests, is smarter about transforming expressions in tail position and avoids introducing those dummy <fr:tex display="inline"><![CDATA[\eta ]]></fr:tex>-expanded forms.</html:p><html:p><html:pre>let rec optimizing : expr -&gt; (var -&gt; kexpr) -&gt; kexpr =
 fun expr k -&gt;
  match expr with
  | Var x -&gt; k (Var x)
  | App (f, arg) -&gt;
      let@ fv = optimizing f in
      let@ argv = optimizing arg in
      let kvar = kfresh () in
      let arg = vfresh () in
      Let_cont { kvar; arg; fbody = k arg; body = Fapp (fv, kvar, argv) }
  | Lam (arg, body) -&gt;
      (* [fun arg -&gt; body]@k = letval v = fun ark k0 -&gt; [body][fun bv -&gt; k0 bv] in k v *)
      let var = vfresh () in
      let kvar = kfresh () in
      let body = optimizing_tailcall body kvar in
      Let_val { var; bound = Kv_lam (kvar, Var arg, body); body = k var }
  | Int i -&gt;
      let var = vfresh () in
      Let_val { var; bound = Kv_int i; body = k var }
  | Pair (l, r) -&gt;
      let@ lv = optimizing l in
      let@ rv = optimizing r in
      let var = vfresh () in
      Let_val { var; bound = Kv_pair (lv, rv); body = k var }
  | Fst p -&gt;
      let@ pv = optimizing p in
      let var = vfresh () in
      Let_fst { var; bound = pv; body = k var }
  | Snd p -&gt;
      let@ pv = optimizing p in
      let var = vfresh () in
      Let_snd { var; bound = pv; body = k var }

and optimizing_tailcall : expr -&gt; kvar -&gt; kexpr =
 fun expr kv -&gt;
  match expr with
  | Var x -&gt; Kapp (kv, Var x)
  | Int i -&gt;
      let var = vfresh () in
      Let_val { var; bound = Kv_int i; body = Kapp (kv, var) }
  | App (f, arg) -&gt;
      let@ fv = optimizing f in
      let@ argv = optimizing arg in
      Fapp (fv, kv, argv)
  | Lam (arg, body) -&gt;
      let var = vfresh () in
      let kvar = kfresh () in
      Let_val
        { var;
          bound = Kv_lam (kvar, Var arg, optimizing_tailcall body kvar);
          body = Kapp (kv, var)
        }
  | Pair (l, r) -&gt;
      let@ lv = optimizing l in
      let@ rv = optimizing r in
      let var = vfresh () in
      Let_val { var; bound = Kv_pair (lv, rv); body = Kapp (kv, var) }
  | Fst p -&gt;
      let@ pv = optimizing p in
      let var = vfresh () in
      Let_fst { var; bound = pv; body = Kapp (kv, var) }
  | Snd p -&gt;
      let@ pv = optimizing p in
      let var = vfresh () in
      Let_snd { var; bound = pv; body = Kapp (kv, var) }

let run_optimizing : expr -&gt; kexpr =
 fun expr -&gt; optimizing expr (fun exprv -&gt; Kapp (KVar "id", exprv))
;;</html:pre><html:pre>val optimizing : expr -&gt; (var -&gt; kexpr) -&gt; kexpr = &lt;fun&gt;
val optimizing_tailcall : expr -&gt; kvar -&gt; kexpr = &lt;fun&gt;
val run_optimizing : expr -&gt; kexpr = &lt;fun&gt;
</html:pre></html:p><html:p>Let's apply this again to our example.</html:p><html:p><html:pre>let () = Format.printf "%a@." pp_kexpr (run_optimizing running_example);;</html:pre><html:pre>let x5 = fun k3 f -&gt;
           let x6 = fun k4 x -&gt;
                      let x7 = 1 in
                      let x8 = (x7, x) in
                      f k4 x8 in
           k3 x6 in
id x5</html:pre></html:p><html:p>Much better!</html:p></fr:mainmatter></fr:tree> 
<fr:tree show-metadata="false"><fr:frontmatter><fr:authors /><fr:date><fr:year>2026</fr:year><fr:month>1</fr:month><fr:day>12</fr:day></fr:date><fr:title text="Optimizing by rewriting on a graph-like IR">Optimizing by rewriting on a graph-like IR</fr:title></fr:frontmatter><fr:mainmatter><html:p>We have seen how to efficiently translate <html:em>to</html:em> the IR but not how to perform optimizations <html:em>on</html:em> IR terms. The author argues that
the purely functional representation is ill-suited for rewriting purposes and suggests using a graph-based, mutable
term representation combined with a union-find data structure to represent binding constructs. Besides some useful
figures, an actual implementation is not shown. We remedy this.</html:p><html:p>The first key ingredient is a representation for variable binders and variable occurrences. Prescriptions from the paper:
<html:ul><html:li>All occurrences for a variable should be linked in a doubly-linked (circular) list, for efficient iteration.</html:li>
<html:li>Those occurrences should also be organized in a union-find data structure, whose representative element should store a pointer to the <html:em>binding construct</html:em>
for that variable. This allows constant-time access to the binder from any variable.</html:li>
<html:li>The binder should point to the canonical occurrence, if any.</html:li></html:ul>
These might seem like weird prescriptions, but together they allow near-O(1) substitution of a variable for another one! An especially important operation in a IR
where all intermediate computations are named, and the basis of many optimizations. It also allows to know in constant time whether a binder is dead or not.
</html:p><html:p>We start with the representation of binders and variable occurrences. Note that the type of binders and
occurrences is parameterized by <html:code>'expr</html:code> which represents the type of expressions, to be defined later.
This is a way to break a mutually recursive definition.</html:p><html:p><html:pre>type 'expr cell = {
  mutable repr : 'expr uf_node;
  mutable next : 'expr cell;
  mutable prev : 'expr cell;
}
and 'expr uf_node = Root of 'expr binder | Node of 'expr cell
and 'expr binder = {
  var : string;
  mutable binding : 'expr option;
  mutable repr_cell : 'expr cell option;
};;</html:pre></html:p><html:p>Let's unpack this definition. We have three types, defined in a mutually recursive fashion.
<html:ul><html:li>A <html:code>'expr cell</html:code> encode variable occurrences, organized in a doubly linked circular list for convenient iteration.</html:li>
<html:li><html:code>'expr uf_node</html:code> are union-find nodes. All occurrences for a given <html:code>binder</html:code> are in the same class, the canonical representative being the <html:code>binder</html:code>.</html:li>
<html:li>A <html:code>'expr binder</html:code> contain the name of the variable, a pointer to the binding <html:strong>expression</html:strong> (i.e. the actual AST node)
and a backpointer to the representative cell. This backpointer is initialized "late", via a wrapper
<html:code>make_binder</html:code> which ensures correctness.</html:li></html:ul></html:p><html:p><html:pre>(* Initializes a [binder] named [var] and gives it to the callback [f] *)
let make_binder : type a. var:string -&gt; (a binder -&gt; a) -&gt; a =
  fun ~var f -&gt;
  let uninitialized = { var; binding = None; repr_cell = None } in
  let expr = f uninitialized in
  uninitialized.binding &lt;- Some expr ;
  expr

(* [repr cell] returns the binder to which the occurrence is attached. *)
let repr : type expr. expr cell -&gt; expr binder =
 fun cell -&gt;
  let rec loop cell acc =
    match cell.repr with
    | Node cell' -&gt; loop cell' (cell :: acc)
    | Root binder as repr -&gt;
        List.iter (fun c -&gt; c.repr &lt;- repr) acc ;
        binder
  in
  loop cell []
;;</html:pre><html:pre>val make_binder : var:string -&gt; ('a binder -&gt; 'a) -&gt; 'a = &lt;fun&gt;
val repr : 'expr cell -&gt; 'expr binder = &lt;fun&gt;
</html:pre></html:p><html:p><html:code>make_occurrence</html:code> creates a fresh variable occurrence associated to a binder. If there is no occurrence,
the a singleton cell is created and set as being the union-find canonical representative. If not, the fresh
cell is inserted into the doubly linked list of occurrences.</html:p><html:p><html:pre>let insert_fresh_after cell binder =
  (* assert that cell is in same binder eq. class *)
  assert (repr cell == binder) ;
  let repr_cell = Option.get binder.repr_cell in
  let rec fresh = { repr = Node repr_cell; next = fresh; prev = fresh } in
  let next = cell.next in
  fresh.prev &lt;- cell ;
  fresh.next &lt;- next ;
  next.prev &lt;- fresh ;
  cell.next &lt;- fresh ;
  fresh

let make_occurrence : 'expr binder -&gt; 'expr cell =
 fun binder -&gt;
  match binder.repr_cell with
  | None -&gt;
      let rec occurrence =
        { repr = Root binder; next = occurrence; prev = occurrence }
      in
      binder.repr_cell &lt;- Some occurrence ;
      occurrence
  | Some repr_occ -&gt; insert_fresh_after repr_occ binder
;;</html:pre></html:p><html:p>We can now define substitution <html:code>subst x y</html:code>, which substitutes <html:code>y</html:code> by <html:code>x</html:code>.
It proceeds as follows:
<html:ul><html:li>If <html:code>y</html:code> is dead (no occurrences), there's nothing to do.</html:li>
<html:li>Otherwise, we merge the lists of cells for <html:code>x</html:code> and <html:code>y</html:code> and let the representative cell for <html:code>y</html:code>
point to that for <html:code>x</html:code>.</html:li></html:ul>
Note that it is assumed in the implementation that <html:code>x</html:code> is not dead: this can be easily relaxed.
Note also that out of laziness, I didn't bother implementing the classical rank-based union computation - this also could be easily
added. As such, the implementation presented here is not near-constant time.
</html:p><html:p><html:pre>let unsafe_merge_dll (repr1 : _ cell) (repr2 : _ cell) =
  let next1 = repr1.next in
  let prev2 = repr2.prev in
  repr1.next &lt;- repr2 ;
  repr2.prev &lt;- repr1 ;
  next1.prev &lt;- prev2 ;
  prev2.next &lt;- next1

let subst (x : _ binder) (y : _ binder) =
  assert (x != y) ;
  begin
    match (x.repr_cell, y.repr_cell) with
    | (_, None) -&gt; ()
    | (None, _) -&gt; assert false
    | (Some x_repr_cell, Some y_repr_cell) -&gt;
        (* Invariant: the binder is what it should *)
        assert (repr y_repr_cell == y) ;
        assert (repr x_repr_cell == x) ;
        unsafe_merge_dll x_repr_cell y_repr_cell ;
        (* Reconnect representative cell to binding class of [x] *)
        (* TODO: use rank-based UF merge *)
        y_repr_cell.repr &lt;- x_repr_cell.repr
  end
;;</html:pre><html:pre>val unsafe_merge_dll : 'a cell -&gt; 'a cell -&gt; unit = &lt;fun&gt;
val subst : 'a binder -&gt; 'a binder -&gt; unit = &lt;fun&gt;
</html:pre></html:p><html:p>That's it for the core variable handling! We define a pair of extra helpful functions.</html:p><html:p><html:pre>let get_name : 'expr binder -&gt; string = fun binder -&gt; binder.var
let is_dead binder = Option.is_none binder.repr_cell
let retrieve_binder : 'expr cell -&gt; 'expr =
 fun var -&gt;
  let binder = repr var in
  Option.get binder.binding
;;</html:pre><html:pre>val get_name : 'expr binder -&gt; string = &lt;fun&gt;
val is_dead : 'a binder -&gt; bool = &lt;fun&gt;
val retrieve_binder : 'expr cell -&gt; 'expr = &lt;fun&gt;
</html:pre></html:p><html:p>We pack those definitions under a generative module whose signature is:</html:p><html:p><html:pre>module type Var = sig
  type 'expr t
  type 'expr binder

  val make_binder : var:string -&gt; ('a binder -&gt; 'a) -&gt; 'a
  val make_occurrence : 'expr binder -&gt; 'expr t
  val get_name : 'a binder -&gt; string
  val subst : 'a binder -&gt; 'a binder -&gt; unit
  val is_dead : 'a binder -&gt; bool
  val repr : 'expr t -&gt; 'expr binder
  val retrieve_binder : 'expr t -&gt; 'expr
end
;;</html:pre></html:p><html:p>(We could have directly implemented that module but the REPL does not allow for piecewise module definitions).</html:p><html:p><html:pre>module Make_var () : Var =
struct
  type 'expr t = 'expr cell
  type nonrec 'expr binder = 'expr binder
  let make_binder = make_binder
  let make_occurrence = make_occurrence
  let get_name = get_name
  let subst = subst
  let is_dead = is_dead
  let repr = repr
  let retrieve_binder = retrieve_binder
end;;</html:pre><html:pre>module Make_var : () -&gt; Var
</html:pre></html:p><html:p>Let's instantiate this module for regular and continuation variables.</html:p><html:p><html:pre>module Var = Make_var ()
module KVar = Make_var ()
;;</html:pre></html:p><html:p>We can now define the graph-like IR! The main difference, besides relying on the variable representation above, is that terms are mutable and that each expression contains a pointer to its enclosing expression
for easier rewriting. We have to let go the mutually recursive definition of <html:code>kexpr</html:code> and <html:code>kvalue</html:code>, whose type constraints will be encoded as dynamic checks.</html:p><html:p>A side note: the reliance of parent pointers makes the sharing of identical sub-expressions impossible.
This is not much of an issue for the purpose of compiling and optimizing but it could be a show-stopper
in the setting of e.g. program synthesis.</html:p><html:p><html:pre>type kexpr_desc =
  | Let_val of { var : var_binder; bound : kexpr; body : kexpr }
  | Let_fst of { var : var_binder; bound : var; body : kexpr }
  | Let_snd of { var : var_binder; bound : var; body : kexpr }
  | Let_cont of { kvar : kvar_binder;
                  var : var_binder;
                  fbody : kexpr;
                  body : kexpr }
  | Kapp of kvar * var
  | Fapp of var * kvar * var
  | Kv_int of int
  | Kv_pair of var * var
  | Kv_lam of kvar_binder * var_binder * kexpr

and kexpr = { mutable desc : kexpr_desc; mutable parent : kexpr option }
and var_binder = kexpr Var.binder
and kvar_binder = kexpr KVar.binder
and var = kexpr Var.t
and kvar = kexpr KVar.t
;;</html:pre></html:p><html:p>The presence of forward and backpointers makes constructing expressions not entirely trivial. We
make good use of the <html:code>Var</html:code> interface to provide a bunch of smart constructors taking care of
proper initialization.</html:p><html:p><html:pre>let make_var = Var.make_occurrence
let make_kvar = KVar.make_occurrence
let make desc = { desc; parent = None }
let is_value kexpr =
  match kexpr.desc with Kv_int _ | Kv_pair _ | Kv_lam _ -&gt; true | _ -&gt; false;;</html:pre><html:pre>val make_var : 'a Var.binder -&gt; 'a Var.t = &lt;fun&gt;
val make_kvar : 'a KVar.binder -&gt; 'a KVar.t = &lt;fun&gt;
val make : kexpr_desc -&gt; kexpr = &lt;fun&gt;
val is_value : kexpr -&gt; bool = &lt;fun&gt;
</html:pre></html:p><html:p>Let's unpack the definition of <html:code>let_val</html:code>. We see that the <html:code>Let_val</html:code> constructor takes
a <html:code>binder</html:code> as argument. We allocate this <html:code>binder</html:code> via <html:code>Var.make_binder</html:code>. In the scope
of the callback, where the binder is in scope, we evaluate the <html:code>body</html:code> of the construct.</html:p><html:p>Something that we must take proper care of is the initialization of parent pointers: the convention is
that this initialization is left to use-time of the sub-expressions.</html:p><html:p><html:pre>let let_val ~(var : string) (bound : kexpr) (body : var_binder -&gt; kexpr) =
  (* Since we had to collapse the mutually recursive [expr] and [value]
     types into one, we defer what was a statically checked invariant
     to a dynamically checked one. *)
  assert (is_value bound) ;
  Var.make_binder ~var (fun var -&gt;
      let body = body var in
      assert (Option.is_none bound.parent) ;
      assert (Option.is_none body.parent) ;
      let root = make (Let_val { var; bound; body }) in
      let some_root = Some root in
      bound.parent &lt;- some_root ;
      body.parent &lt;- some_root ;
      root)
;;</html:pre><html:pre>val let_val : var:string -&gt; kexpr -&gt; (var_binder -&gt; kexpr) -&gt; kexpr = &lt;fun&gt;
</html:pre></html:p><html:p>The other constructs follow the same pattern.</html:p><html:p><html:pre>let let_fst ~(var : string) (bound : var) (body : var_binder -&gt; kexpr) =
  Var.make_binder ~var @@ fun var -&gt;
  let body = body var in
  let root = make @@ Let_fst { var; bound; body } in
  assert (Option.is_none body.parent) ;
  let some_root = Some root in
  body.parent &lt;- some_root ;
  root

let let_snd ~(var : string) (bound : var) (body : var_binder -&gt; kexpr) =
  Var.make_binder ~var @@ fun var -&gt;
  let body = body var in
  let root = make @@ Let_snd { var; bound; body } in
  assert (Option.is_none body.parent) ;
  let some_root = Some root in
  body.parent &lt;- some_root ;
  root

let let_cont ~(kvar : string) ~(var : string) (cont : var_binder -&gt; kexpr)
    (body : kvar_binder -&gt; kexpr) =
  KVar.make_binder ~var:kvar @@ fun kvar -&gt;
  Var.make_binder ~var @@ fun var -&gt;
  let fbody = cont var in
  let body = body kvar in
  let root = make @@ Let_cont { kvar; var; fbody; body } in
  assert (Option.is_none fbody.parent) ;
  assert (Option.is_none body.parent) ;
  let some_root = Some root in
  fbody.parent &lt;- some_root ;
  body.parent &lt;- some_root ;
  root

let kapp kv v = make (Kapp (kv, v))
let fapp fv k x = make (Fapp (fv, k, x))
let int i = make (Kv_int i)
let pair l r = make (Kv_pair (l, r))

let lam ~kvar ~var body =
  KVar.make_binder ~var:kvar @@ fun kvar -&gt;
  Var.make_binder ~var @@ fun var -&gt; make (Kv_lam (kvar, var, body kvar var))
;;</html:pre><html:pre>val let_fst : var:string -&gt; var -&gt; (var_binder -&gt; kexpr) -&gt; kexpr = &lt;fun&gt;
val let_snd : var:string -&gt; var -&gt; (var_binder -&gt; kexpr) -&gt; kexpr = &lt;fun&gt;
val let_cont :
  kvar:string -&gt;
  var:string -&gt; (var_binder -&gt; kexpr) -&gt; (kvar_binder -&gt; kexpr) -&gt; kexpr =
  &lt;fun&gt;
val kapp : kvar -&gt; var -&gt; kexpr = &lt;fun&gt;
val fapp : var -&gt; kvar -&gt; var -&gt; kexpr = &lt;fun&gt;
val int : int -&gt; kexpr = &lt;fun&gt;
val pair : var -&gt; var -&gt; kexpr = &lt;fun&gt;
val lam :
  kvar:string -&gt; var:string -&gt; (kvar_binder -&gt; var_binder -&gt; kexpr) -&gt; kexpr =
  &lt;fun&gt;
</html:pre></html:p><html:p>Now that we can construct expressions, time to revisit conversion from the source language to the IR.
We use the <fr:link href="/kennedy-ccc-optimizing/" title="Compiling with continuations, continued › Smarter translation" uri="http://localhost/kennedy-ccc-optimizing/" display-uri="kennedy-ccc-optimizing" type="local">optimizing</fr:link> translation. We just need to adjoin an environment mapping regular
variable names to <html:code>binder</html:code>s and use the combinators defined above rather than straight constructors.</html:p><html:p><html:pre>module Env = Map.Make (String)

(* Scope representation: a map from names to binders. *)
type env = var_binder Env.t

let get_var (env : env) (v : string) : var_binder = Env.find v env
let kfresh = fresh (fun s -&gt; s)
let vfresh = fresh (fun s -&gt; s)
;;</html:pre></html:p><html:p><html:pre>let rec optimizing : env -&gt; expr -&gt; (var_binder -&gt; kexpr) -&gt; kexpr =
 fun env expr k -&gt;
  match expr with
  | Var x -&gt; k (get_var env x)
  | App (f, arg) -&gt;
      let@ fv = optimizing env f in
      let@ argv = optimizing env arg in
      let kvar = kfresh () in
      let var = vfresh () in
      let_cont ~kvar ~var k (fun kv -&gt;
          fapp (make_var fv) (make_kvar kv) (make_var argv))
  | Lam (arg, body) -&gt;
      (* [fun arg -&gt; body]@k = letval v = fun ark k0 -&gt; [body][fun bv -&gt; k0 bv] in k v *)
      let var = vfresh () in
      let kvar = kfresh () in
      let_val
        ~var
        (lam ~kvar ~var:arg (fun kv v -&gt;
             let env = Env.add arg v env in
             optimizing_tailcall env body kv))
        k
  | Int i -&gt;
      let var = vfresh () in
      let_val ~var (int i) k
  | Pair (l, r) -&gt;
      let@ lv = optimizing env l in
      let@ rv = optimizing env r in
      let var = vfresh () in
      let_val ~var (pair (make_var lv) (make_var rv)) k
  | Fst p -&gt;
      let@ pv = optimizing env p in
      let var = vfresh () in
      let_fst ~var (make_var pv) k
  | Snd p -&gt;
      let@ pv = optimizing env p in
      let var = vfresh () in
      let_snd ~var (make_var pv) k

and optimizing_tailcall : env -&gt; expr -&gt; kvar_binder -&gt; kexpr =
 fun env expr kv -&gt;
  match expr with
  | Var x -&gt; kapp (make_kvar kv) (make_var (get_var env x))
  | Int i -&gt;
      let var = vfresh () in
      let_val ~var (int i) (fun v -&gt; kapp (make_kvar kv) (make_var v))
  | App (f, arg) -&gt;
      let@ fv = optimizing env f in
      let@ argv = optimizing env arg in
      fapp (make_var fv) (make_kvar kv) (make_var argv)
  | Lam (arg, body) -&gt;
      let var = vfresh () in
      let kvar = kfresh () in
      let_val
        ~var
        (lam ~kvar ~var:arg (fun kv v -&gt;
             let env = Env.add arg v env in
             optimizing_tailcall env body kv))
        (fun v -&gt; kapp (make_kvar kv) (make_var v))
  | Pair (l, r) -&gt;
      let@ lv = optimizing env l in
      let@ rv = optimizing env r in
      let var = vfresh () in
      let_val
        ~var
        (pair (make_var lv) (make_var rv))
        (fun v -&gt; kapp (make_kvar kv) (make_var v))
  | Fst p -&gt;
      let@ pv = optimizing env p in
      let var = vfresh () in
      let_fst ~var (make_var pv) (fun v -&gt; kapp (make_kvar kv) (make_var v))
  | Snd p -&gt;
      let@ pv = optimizing env p in
      let var = vfresh () in
      let_snd ~var (make_var pv) (fun v -&gt; kapp (make_kvar kv) (make_var v))

let run_optimizing : expr -&gt; kexpr =
 fun expr -&gt;
  KVar.make_binder ~var:"id" @@ fun id -&gt;
  let env = Env.empty in
  optimizing env expr (fun exprv -&gt; kapp (make_kvar id) (make_var exprv))
;;</html:pre></html:p><html:p>We conclude this page by implementing an optimization example presented in the article.
This example is a "shrinking reduction", corresponding to the elimination rules for pairs.
In essence, if we project out a variable which is statically bound to a pair, we may replace
the projection by the corresponding pair component. The rewriting rule is the following, where
<html:code>C</html:code> ranges over contexts:
<html:pre>
letval x = (x1, x2) in  --&gt;    letval x = (x1, x2) in
C{let y = fst x in K}          C{K[x1/y]}
</html:pre>
Let's implement this. We define a type of shrinking reductions (we restrict to the example above).
A value <html:code>Beta_proj_fst { letval_pair; letproj }</html:code> corresponds to the left hand side of the rule
above, where <html:code>letval_pair</html:code> is the full expression and <html:code>letproj</html:code> is the subexpression being
eliminated.
</html:p><html:p><html:pre>type shrinking_reduction =
  | Beta_proj_fst of { letval_pair : kexpr; letproj : kexpr }
;;</html:pre></html:p><html:p>Performing the reduction boils down to performing the substitution. This makes the
<html:code>let y = fst x in ...</html:code> binding dead, allowing us to erase it.</html:p><html:p><html:pre>let proj_fst pair =
  match pair.desc with Kv_pair (fst, _) -&gt; fst | _ -&gt; assert false

let perform_reduction : shrinking_reduction -&gt; unit = function
  | Beta_proj_fst { letval_pair; letproj } -&gt;
      begin match (letval_pair.desc, letproj.desc) with
      | (Let_val { var = x; bound = pair; body = _ },
         Let_fst { var; bound; body = k }) -&gt;
          assert (Var.repr bound == x) ;
          let x1_binder = Var.repr (proj_fst pair) in
          (* Perform substitution *)
          Var.subst x1_binder var ;
          (* Erase now useless binding *)
          (* invariant: k record is uniquely owned and is going to become unreachable *)
          k.parent &lt;- None ;
          letproj.desc &lt;- k.desc
      | _ -&gt; assert false
    end
;;</html:pre><html:pre>val proj_fst : kexpr -&gt; var = &lt;fun&gt;
val perform_reduction : shrinking_reduction -&gt; unit = &lt;fun&gt;
</html:pre></html:p><html:p>That's it for the optimization itself! It remains to <html:em>find</html:em> such redexes in the program. We
use a generic iterator over the AST, to which we pass a function which scans for redexes and accumulates
them in a queue.</html:p><html:p><html:pre>let rec iter kexpr ~f =
  f kexpr ;
  begin
    match kexpr.desc with
    | Let_val { var = _; bound; body } -&gt;
        iter bound ~f ;
        iter body ~f
    | Let_fst { var = _; bound = _; body } -&gt; iter body ~f
    | Let_snd { var = _; bound = _; body } -&gt; iter body ~f
    | Let_cont { kvar = _; var = _; fbody; body } -&gt;
        iter fbody ~f ;
        iter body ~f
    | Kapp _ -&gt; ()
    | Fapp _ -&gt; ()
    | Kv_int _ -&gt; ()
    | Kv_pair _ -&gt; ()
    | Kv_lam (_, _, body) -&gt; iter body ~f
  end

let is_kv_pair kexpr = match kexpr.desc with Kv_pair _ -&gt; true | _ -&gt; false

let scan_reduction kexpr queue =
  iter kexpr ~f:(fun expr -&gt;
      match expr.desc with
      | Let_fst { var = _; bound; body = _ } -&gt;
          (* [bound] is a variable, find its binder. *)
          let binder_expr = Var.retrieve_binder bound in
          begin match binder_expr.desc with
            | Let_val { var = binder_var; bound = bound'; body = _ }
              when is_kv_pair bound' -&gt;
                assert (Var.repr bound == binder_var) ;
                Queue.add
                  (Beta_proj_fst { letval_pair = binder_expr;
                                   letproj = expr })
                  queue
            | _ -&gt; ()
          end
      | _ -&gt; ())
;;</html:pre><html:pre>val iter : kexpr -&gt; f:(kexpr -&gt; 'a) -&gt; unit = &lt;fun&gt;
val is_kv_pair : kexpr -&gt; bool = &lt;fun&gt;
val scan_reduction : kexpr -&gt; shrinking_reduction Queue.t -&gt; unit = &lt;fun&gt;
</html:pre></html:p><html:p>Let's apply this to some example!</html:p><html:p><html:pre>let example =
  lam ~kvar:"k" ~var:"x" @@ fun k x -&gt;
  let_val ~var:"p" (pair (make_var x) (make_var x)) @@ fun p -&gt;
  let_fst ~var:"z" (make_var p) @@ fun z -&gt;
  let_val ~var:"w" (pair (make_var p) (make_var z)) @@ fun w -&gt;
  let_val ~var:"t" (pair (make_var w) (make_var x)) @@ fun t -&gt;
  kapp (make_kvar k) (make_var t)

let () = Format.printf "%a@." pp_kexpr example;;</html:pre><html:pre>fun k x -&gt;
  let p = (x, x) in
  let z = fst p in
  let w = (p, z) in
  let t = (w, x) in
  k t</html:pre></html:p><html:p>Scanning for the redex bound to <html:code>z</html:code>:</html:p><html:p><html:pre>let queue = Queue.create ()
let () = scan_reduction example queue
let () = Format.printf "queue length: %d@." (Queue.length queue);;</html:pre><html:pre>val queue : shrinking_reduction Queue.t = &lt;abstr&gt;
</html:pre><html:pre>queue length: 1</html:pre></html:p><html:p>Performing the optimization:</html:p><html:p><html:pre>Queue.iter perform_reduction queue;;</html:pre><html:pre>- : unit = ()
</html:pre></html:p><html:p>Printing the result:</html:p><html:p><html:pre>let () = Format.printf "%a@." pp_kexpr example;;</html:pre><html:pre>fun k x -&gt;
  let p = (x, x) in
  let w = (p, x) in
  let t = (w, x) in
  k t</html:pre></html:p></fr:mainmatter></fr:tree> 
<fr:tree show-metadata="false"><fr:frontmatter><fr:authors /><fr:date><fr:year>2026</fr:year><fr:month>1</fr:month><fr:day>12</fr:day></fr:date><fr:title text="Conclusion">Conclusion</fr:title></fr:frontmatter><fr:mainmatter><html:p>That was a lot of work, and we only considered a portion of the ideas covered in the paper.
Some things we skipped:
<html:ul><html:li>Algebraic datatypes (we only covered products)</html:li>
<html:li>Handling exceptions via double-barrelled CPS</html:li>
<html:li>Recursion</html:li>
<html:li>Other shrinking reductions</html:li>
<html:li>Contification</html:li></html:ul>
However I think we covered the heart of the paper. The items above are nontrivial but not too hard once
the core structure is pinned down. Very nice paper!
</html:p></fr:mainmatter></fr:tree>


</fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="true" expanded="false" toc="false" numbered="false">
              <fr:frontmatter>
                <fr:authors />
                <fr:date>
                  <fr:year>2025</fr:year>
                  <fr:month>12</fr:month>
                  <fr:day>14</fr:day>
                </fr:date>
                <fr:uri>http://localhost/0019/</fr:uri>
                <fr:display-uri>0019</fr:display-uri>
                <fr:route>/0019/</fr:route>
                <fr:title text="Backtracking parser combinators">Backtracking parser combinators</fr:title>
                <fr:taxon>article</fr:taxon>
              </fr:frontmatter>
              <fr:mainmatter><html:p>Reasonable languages are <fr:link href="https://en.wikipedia.org/wiki/Canonical_LR_parser" type="external">LR(1)</fr:link>. Parsing them is best done using tools like <fr:link href="https://gallium.inria.fr/~fpottier/menhir/" type="external">menhir</fr:link>. Out of this convenient class of grammars, one has to resort to other means: manually writing the parser, or using parser combinators.
</html:p><fr:tree show-metadata="false"><fr:frontmatter><fr:authors /><fr:date><fr:year>2025</fr:year><fr:month>12</fr:month><fr:day>15</fr:day></fr:date><fr:uri>http://localhost/001A/</fr:uri><fr:display-uri>001A</fr:display-uri><fr:route>/001A/</fr:route><fr:title text="Parsing as state monads on streams">Parsing as state monads on streams</fr:title></fr:frontmatter><fr:mainmatter><html:p>
We'll assume fixed a type of <fr:tex display="inline"><![CDATA[S]]></fr:tex> of symbols.
Parsing means consuming part of a stream of symbols and producing a value of a given type, together with the rest of the stream.
A stream can be seen as a function <fr:tex display="inline"><![CDATA[S^\N ]]></fr:tex>.
The "parsing functor" <fr:tex display="inline"><![CDATA[P]]></fr:tex> is
<fr:tex display="block"><![CDATA[
P(A) = S^\N  \rightarrow  A \times  S^\N 
]]></fr:tex>
We recognize a thinly veiled state monad. We may also need to handle failure: to this end, compose the state monad with some error monad.
<fr:tex display="block"><![CDATA[
P(A) = S^\N  \rightarrow  (A + Error) \times  S^\N 
]]></fr:tex></html:p></fr:mainmatter></fr:tree><html:p>(In this article we'll take <fr:tex display="inline"><![CDATA[Error = 1]]></fr:tex>.) Let's implement this, see how it falls short of our goals and the how <fr:link href="/000J/" title="Codensity monad" uri="http://localhost/000J/" display-uri="000J" type="local">codensity monad</fr:link> of <fr:tex display="inline"><![CDATA[P]]></fr:tex> saves the day.</html:p>
  
  
  
  

<fr:tree show-metadata="false"><fr:frontmatter><fr:authors /><fr:date><fr:year>2025</fr:year><fr:month>12</fr:month><fr:day>14</fr:day></fr:date><fr:title text="State-monad based parsing combinators">State-monad based parsing combinators</fr:title></fr:frontmatter><fr:mainmatter><html:p><html:pre>#require "fmt";;</html:pre></html:p><html:p>For simplicity, we will take symbols to be characters and streams to be sequences of characters.</html:p><html:p><html:pre>type symbol = char
type stream = char Seq.t

(* Note the call to [memoize]: in order to implement backtracking, we want our streams
   to be persistent. We must be able to reprocess a chunk of the stream as many times
   as it takes. *)
let of_string : string -&gt; stream = fun str -&gt; String.to_seq str |&gt; Seq.memoize;;</html:pre></html:p><html:p>
Our basic implementation (hinting that there will be a non-basic one) will be a state monad
over streams composed with an option monad for errors. We start of with basic monadic primitives:
<html:code>bind</html:code>, <html:code>return</html:code> and <html:code>run</html:code>.
</html:p><html:p><html:pre>(* ['a t] is the type of parsers yielding a value of type ['a] *)
type 'a t = stream -&gt; 'a option * stream

(* Monadic composition of parsers.
   Note the straightforward handling of errors. *)
let bind : 'a t -&gt; ('a -&gt; 'b t) -&gt; 'b t =
  fun m f stream -&gt;
  match m stream with
  | (None, _) as fail -&gt; fail
  | (Some x, rest) -&gt; f x rest

let return x = fun stream -&gt; (Some x, stream)

(* Running a monadic computation. *)
let run (p : 'a t) (str : string) = fst @@ p (of_string str)
;;</html:pre></html:p><html:p>We add some basic way of expressing failure. </html:p><html:p><html:pre>let fail () : 'a t = fun stream -&gt; (None, stream);;</html:pre></html:p><html:p>Now, we can define some basic parsing combinators!</html:p><html:p><html:pre>(* A convenient syntax for [bind]. Recall that [let* x = m in b]
   is equivalent to [bind m (fun x -&gt; b)]. *)
let (let*) = bind

(* [exact sym] matches exactly the symbol [sym], or fails. *)
let exact sym : unit t =
  fun stream -&gt;
  match Seq.uncons stream with
  | None -&gt; (None, stream)
  | Some (x, rest) -&gt;
    if Char.equal x sym then
      (Some (), rest)
    else
      (None, rest)

(* [try_bind m f on_error] is used as a building block for backtracking.
   When [m] evaluates to a failure, [f] is called with the stream as it was
   before computing [m]. *)
let try_bind : 'a t -&gt; ('a -&gt; 'b t) -&gt; (unit -&gt; 'b t) -&gt; 'b t =
  fun m f on_error stream -&gt;
  match m stream with
  | (None, _) -&gt; on_error () stream
  | (Some x, rest) -&gt; f x rest

(* [first_of [p_1; ...; pk]] tries to parse the stream with each parser in the given list,
   in order. *)
let rec first_of : 'a t list -&gt; 'a t =
  fun cases -&gt;
  match cases with
  | [] -&gt; fail ()
  | p :: rest -&gt;
    try_bind p return (fun () -&gt; first_of rest)
;;</html:pre><html:pre>val ( let* ) : 'a t -&gt; ('a -&gt; 'b t) -&gt; 'b t = &lt;fun&gt;
val exact : Char.t -&gt; unit t = &lt;fun&gt;
val try_bind : 'a t -&gt; ('a -&gt; 'b t) -&gt; (unit -&gt; 'b t) -&gt; 'b t = &lt;fun&gt;
val first_of : 'a t list -&gt; 'a t = &lt;fun&gt;
</html:pre></html:p></fr:mainmatter></fr:tree>

<fr:tree show-metadata="false"><fr:frontmatter><fr:authors /><fr:date><fr:year>2025</fr:year><fr:month>12</fr:month><fr:day>14</fr:day></fr:date><fr:title text="Some simple examples and a failure">Some simple examples and a failure</fr:title></fr:frontmatter><fr:mainmatter><html:p><html:pre>let print = function
  | None -&gt; print_endline "failure"
  | Some _ -&gt; print_endline "success!"

(* Matches "ab" *)
let match_ab =
  let* () = exact 'a' in
  exact 'b'

let () = print (run match_ab "ab");;</html:pre><html:pre>success!</html:pre></html:p><html:p><html:pre>let () = print (run match_ab "ac");;</html:pre><html:pre>failure</html:pre></html:p><html:p>Now let's try a more complicated example, involving backtracking.</html:p><html:p><html:pre>let match_abxx =
  let* () = match_ab in
  let* () = exact 'x' in
  exact 'x'

let match_ab_or_abxx =
  first_of [match_ab; match_abxx]

let parser =
  let* () = match_ab_or_abxx in
  exact '.'

let () = print (run parser "abxx.");;</html:pre><html:pre>failure</html:pre></html:p><html:p>What gives?
<html:ol><html:li>the parser <html:code>match_ab</html:code> successfully matches the prefix of the stream</html:li>
<html:li>the next expected symbol is <html:code>'.'</html:code>, however the rest of the stream contains <html:code>"xx."</html:code></html:li>
<html:li>but since <html:code>match_ab</html:code> succeeded, it can't act as a backtracking point anymore!</html:li></html:ol>
The root of the issue is that we'd like <html:code>try_bind m f on_error</html:code> to act as a backtracking point for its whole continuation, rather
than just the computation corresponding to <html:code>m</html:code>. Using the <fr:link href="/000J/" title="Codensity monad" uri="http://localhost/000J/" display-uri="000J" type="local">codensity</fr:link> monad of a well-chosen functor allows to express
this pattern.
</html:p></fr:mainmatter></fr:tree> 
<fr:tree show-metadata="false"><fr:frontmatter><fr:authors /><fr:date><fr:year>2025</fr:year><fr:month>7</fr:month><fr:day>16</fr:day></fr:date><fr:uri>http://localhost/000J/</fr:uri><fr:display-uri>000J</fr:display-uri><fr:route>/000J/</fr:route><fr:title text="Codensity monad">Codensity monad</fr:title><fr:taxon>Definition</fr:taxon></fr:frontmatter><fr:mainmatter><html:p>The <html:em>codensity monad</html:em> of a functor is formally defined as its <fr:link href="https://en.wikipedia.org/wiki/Kan_extension" type="external">right Kan extension</fr:link> along itself, when it exists. In programming terms, assuming a (category-theoretic) functor is represented as a type constructor <fr:tex display="inline"><![CDATA[F : \ast  \rightarrow  \ast ]]></fr:tex>, its codensity monad is <fr:tex display="inline"><![CDATA[Codensity_F(A) = \forall  X. (A \rightarrow  F(X)) \rightarrow  F(X)]]></fr:tex>. In code:</html:p>
  
  
  
  
<html:p><html:pre>module Codensity (F : sig type 'a t val return : 'a -&gt; 'a t end) =
struct
  type 'a t = { call : 'b. ('a -&gt; 'b F.t) -&gt; 'b F.t }

  let bind : type a b. a t -&gt; (a -&gt; b t) -&gt; b t =
    fun m f -&gt;
    { call = (fun k -&gt; m.call (fun xm -&gt; (f xm).call k)) }

  let return : type a. a -&gt; a t =
    fun x -&gt; { call = (fun k -&gt; k x) }

  let run : 'a t -&gt; 'a F.t = fun m -&gt; m.call F.return
end</html:pre></html:p>

<html:p>A particularly useful trick is to use a functor of the form <fr:tex display="inline"><![CDATA[F'(X) = S \rightarrow  F(X)]]></fr:tex>. Typically, <fr:tex display="inline"><![CDATA[S]]></fr:tex> would be some kind of state or monoid. Since we're programming in CPS, the state can always stay in 'parameter' position!</html:p><html:p>Some good resources about the codensity monad for programming are:
<html:ul><html:li><fr:link href="https://www.cs.ox.ac.uk/ralf.hinze/Kan.pdf" type="external">Kan Extensions for Program Optimisation Or: Art and Dan Explain an Old Trick (Ralf Hinze)</fr:link></html:li>
<html:li><fr:link href="https://janis-voigtlaender.eu/papers/AsymptoticImprovementOfComputationsOverFreeMonads.pdf" type="external">Asymptotic Improvement of Computations over Free Monads (Janis Voigtlander)</fr:link></html:li></html:ul></html:p></fr:mainmatter></fr:tree>

<fr:tree show-metadata="false"><fr:frontmatter><fr:authors /><fr:date><fr:year>2025</fr:year><fr:month>12</fr:month><fr:day>14</fr:day></fr:date><fr:title text="Codensity monad-based parsing combinators">Codensity monad-based parsing combinators</fr:title></fr:frontmatter><fr:mainmatter><html:p>To which functor should we apply the codensity construction? In order to properly implement backtracking,

<html:blockquote><html:strong>backtracking points must be able to modify the continuation of their context</html:strong> when a failure occurs.
</html:blockquote>

Failure will hence be <html:em>handled</html:em> by passing an extra continuation (an "error continuation state") along the stream
(here in first position):
<fr:tex display="block"><![CDATA[
F(X) = (S^\N  \rightarrow  X+Error) \rightarrow  S^\N  \rightarrow  X+Error
]]></fr:tex>
Yielding:
<fr:tex display="block"><![CDATA[
Codensity_{F}(A) = \forall  X. (A \rightarrow  F(X)) \rightarrow  F(X)
]]></fr:tex>
It is worth emphasizing again that the error continuation should be seen as part of the state, same as the stream.
This type might be reminiscent of a <fr:link href="https://www.sciencedirect.com/science/article/pii/S1571066104809745" type="external">double-barrelled</fr:link>
CPS transformation but the monad above is more expressive as the 'main' continuation can modify its own error continuation.
</html:p><html:p><html:pre>type error = unit

module M = Codensity(struct
  type 'a t = (stream -&gt; 'a option) -&gt; stream -&gt; 'a option

  let return x = fun _kerr _stream -&gt; Some x
end);;</html:pre><html:pre>type error = unit
module M :
  sig
    type 'a t = {
      call :
        'b.
          ('a -&gt; (stream -&gt; 'b option) -&gt; stream -&gt; 'b option) -&gt;
          (stream -&gt; 'b option) -&gt; stream -&gt; 'b option;
    }
    val bind : 'a t -&gt; ('a -&gt; 'b t) -&gt; 'b t
    val return : 'a -&gt; 'a t
    val run : 'a t -&gt; (stream -&gt; 'a option) -&gt; stream -&gt; 'a option
  end
</html:pre></html:p><html:p>Let's reimplement our parsing primitive. Bear extra attention to <html:code>try_bind</html:code>!</html:p><html:p><html:pre>open M

let ( let* ) = bind

let try_bind : type a b. a t -&gt; (a -&gt; b t) -&gt; (error -&gt; b t) -&gt; b t =
 fun m f ferr -&gt;
  { call =
      (fun k kerr stream -&gt;
        (* We override [kerr] with [on_error].
           Observe how [on_error] resumes with the whole [stream]. *)
        let on_error = fun _stream -&gt; (ferr ()).call k kerr stream in
        m.call (fun x kerr stream -&gt;
          (f x).call k kerr stream
        ) on_error stream)
  }

let fail () = { call = (fun _k kerr stream -&gt; kerr stream) }

let exact tok : _ t =
  { call =
      (fun k kerr stream -&gt;
        match Seq.uncons stream with
        | None -&gt; kerr stream
        | Some (tok', rest) -&gt; (
            match Char.equal tok tok' with
            | false -&gt; kerr stream
            | true -&gt; k () kerr rest))
  }

let first_of (parsers : _ t list) : _ t =
  let rec loop parsers =
    match parsers with
    | [] -&gt; fail ()
    | p :: rest -&gt; try_bind p return (fun _err -&gt; loop rest)
  in
  loop parsers
;;</html:pre></html:p><html:p><html:pre>let print = function
  | None -&gt; print_endline "failure"
  | Some _ -&gt; print_endline "success!"

let run p (str : string) = run p (fun _ -&gt; None) (String.to_seq str)

(* Matches "ab" *)
let match_ab =
  let* () = exact 'a' in
  exact 'b'

let () = print (run match_ab "ab");;</html:pre><html:pre>success!</html:pre></html:p><html:p><html:pre>let () = print (run match_ab "ac");;</html:pre><html:pre>failure</html:pre></html:p><html:p>Let's retry the example involving backtracking.</html:p><html:p><html:pre>let match_abxx =
  let* () = match_ab in
  let* () = exact 'x' in
  exact 'x'

let match_ab_or_abxx =
  first_of [match_ab; match_abxx]

let parser =
  let* () = match_ab_or_abxx in
  exact '.'

let () = print (run parser "abxx.");;</html:pre><html:pre>success!</html:pre></html:p><html:p>
Some remarks/ideas
<html:ul><html:li>The idea above is fairly general and doesn't apply just to parsers. <html:code>try_bind</html:code> is a limited form of effect handler (our continuations are not delimited though).</html:li>
<html:li>To make this reasonably performant, one may need to defunctionalize the implementation, or perhaps use the flambda compiler with unboxing
annotations? In any case, one would need a better representation of streams.</html:li>
<html:li>In the basic example given here, the error continuation never uses its input stream meaningfully but it would be useful e.g. to continue parsing despite errors.</html:li>
<html:li>The error type could be made more interesting that <html:code>unit</html:code>. In that case, the error continuation could take an extra argument corresponding to the error.</html:li>
<html:li>Rather than <html:code>first_of</html:code>, we could handle non-determinism by enumerating all valid parses.</html:li>
<html:li>Or we may want to optimize for some given cost function. In this setting, can we contrast the codensity-based approach vs selection monads?</html:li></html:ul></html:p></fr:mainmatter></fr:tree> 

</fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="true" expanded="false" toc="false" numbered="false">
              <fr:frontmatter>
                <fr:authors />
                <fr:date>
                  <fr:year>2025</fr:year>
                  <fr:month>12</fr:month>
                  <fr:day>5</fr:day>
                </fr:date>
                <fr:uri>http://localhost/0018/</fr:uri>
                <fr:display-uri>0018</fr:display-uri>
                <fr:route>/0018/</fr:route>
                <fr:title text="Functional machine calculus">Functional machine calculus</fr:title>
                <fr:taxon>article</fr:taxon>
              </fr:frontmatter>
              <fr:mainmatter><html:p><html:strong>Links:</html:strong>
<html:ul><html:li>The functional machine calculus <fr:link href="https://arxiv.org/abs/2212.08177" type="external">I</fr:link>, <fr:link href="https://arxiv.org/abs/2211.13140" type="external">II</fr:link>, <fr:link href="https://arxiv.org/abs/2510.07851" type="external">III</fr:link></html:li>
<html:li><fr:link href="https://arxiv.org/abs/2405.10801" type="external">The relational machine calculus</fr:link> (Barrett et al.)</html:li></html:ul></html:p><html:p>
The functional machine calculus (FMC): a stack-based model of computation that allows to faithfully represent effectful and higher-order computation.
<html:ul><html:li>FMC may serve as a compilation target for effectful <fr:tex display="inline"><![CDATA[\lambda ]]></fr:tex>-calculi;</html:li>
<html:li>FMC are closely related to their denotations as string diagrams in appropriate categories.






<fr:tree show-metadata="true" expanded="false" toc="false" numbered="false"><fr:frontmatter><fr:authors /><fr:date><fr:year>2025</fr:year><fr:month>12</fr:month><fr:day>5</fr:day></fr:date><fr:title text="TODO: FMC semantics"><fr:link href="/000A/" title="TODOs" uri="http://localhost/000A/" display-uri="000A" type="local">TODO</fr:link>: FMC semantics</fr:title></fr:frontmatter><fr:mainmatter /></fr:tree></html:li></html:ul></html:p><html:p>FMC syntax features variables, sequencing, pushing onto a named stack and popping
off a named stack, binding the result to a variable. Stack names are dubbed "locations",
variables ranging over locations are denoted <fr:tex display="inline"><![CDATA[\ell ]]></fr:tex>. The term "location" hints at the use of the stacks to implement effectful constructs such as mutable references.
<fr:tex display="block"><![CDATA[
\begin {array}{lclr}
 e, e_i & ::= & x & \text {variable} \\
        & |   & e_1 ; e_2 & \text {sequencing} \\
        & |   & [e_1]_{\ell }.e_2 & \text {push $e_1$ on stack $\ell $ and evaluate $e_2$} \\
        & |   & \langle  x \rangle _{\ell }.e & \text {pop from stack $\ell $, bind to $x$ and evaluate $e$} \\
        & |   & \ast  & \text {no-op}
\end {array}
]]></fr:tex>
Capture-avoiding substitution on expressions is denoted <fr:tex display="inline"><![CDATA[e\{e'/x\}]]></fr:tex>.
We postulate a "main" location: when location variables are elided, push and pop refer to that one. Extra locations may be used to encode other state-like effects.
Operational semantics is given by transforming stacks (we only use the main location for simplicity). A stack <fr:tex display="inline"><![CDATA[S]]></fr:tex> is just a sequence of expressions, with the
top of the stack written on the right. The one-step evaluation relation is denoted <fr:tex display="inline"><![CDATA[\rightarrow ]]></fr:tex>. Stacks will be denoted <fr:tex display="inline"><![CDATA[S \equiv  e_1 \rhd  \ldots  \rhd  e_k]]></fr:tex>.

<fr:tex display="block"><![CDATA[
[e_1].e_2, S \rightarrow  e_2, S \rhd  e_1
]]></fr:tex>
Popping triggers a capture-avoiding substitution.
<fr:tex display="block"><![CDATA[
\langle  x \rangle .e, S \rhd  e' \rightarrow  e\{e'/x\}, S
]]></fr:tex>
We elude sequencing and no-op rules.
</html:p><html:p><html:strong>Question</html:strong>: can we implement a VM for the FMC using an environment rather than substitutions?</html:p><html:p>We extend the FMC with string literals and concatenation <fr:tex display="inline"><![CDATA[\cdot ]]></fr:tex> to have non-trivial computations.</html:p><fr:tex display="block"><![CDATA[
concat, S \rhd  s_1 \rhd  s_2 \rightarrow  \ast , S \rhd  (s_1 \cdot  s_2)
]]></fr:tex><html:p>Let's code this.</html:p>
  
  
  
  

<html:p><html:pre>#require "ppx_deriving.show";;</html:pre></html:p>
<html:p><html:pre>#require "fmt";;</html:pre></html:p>

We directly represent sequential composition as list of instructions.
<html:p><html:pre>module Syntax =
struct
  type literal = string
  [@@deriving show { with_path = false }]

  (* The type of instructions *)
  type instr =
    | Var of string (* Variable *)
    | Push of t (* Push code onto stack *)
    | Pop of string (* Pop from stack, bind to var *)
    | Lit of literal (* Push literal to stack *)
    | Concat (* String concatenation *)
  [@@deriving show { with_path = false }]

  (* An FMC program is a list of instructions *)
  and t = instr list
  [@@deriving show { with_path = false }]
end;;</html:pre></html:p>
The target machine uses De Bruijn indices instead of named variables.
<html:p><html:pre>module Code =
struct
  type literal = Syntax.literal
  [@@deriving show { with_path = false }]

  (* Continuation is made explicit as last arg of each instruction. *)
  type t =
    | Var of int * t (* De Bruijn index and continuation *)
    | Push of t * t
    | Pop of t
    | Lit of literal * t
    | Concat of t
    | Nil
  [@@deriving show { with_path = false }]

  type scope = string list
  [@@deriving show { with_path = false }]

  let rec from_instr : Syntax.instr -&gt; scope -&gt; (scope -&gt; t) -&gt; t =
    fun instr scope k -&gt;
      match instr with
      | Var s -&gt;
        begin match List.find_index (fun s' -&gt; String.equal s s') scope with
        | None -&gt; failwith ("unbound variable " ^ s)
        | Some i -&gt; Var (i, k scope)
        end
      | Push t -&gt;
        Push (from_syn t scope, k scope)
      | Pop name -&gt;
        Pop (k (name :: scope))
      | Lit l -&gt;
        Lit (l, k scope)
      | Concat -&gt;
        Concat (k scope)
  and from_syn : Syntax.t -&gt; scope -&gt; t =
    fun syn scope -&gt;
      match syn with
      | [] -&gt; Nil
      | instr :: rest -&gt;
        from_instr instr scope (fun scope -&gt; from_syn rest scope)
end;;</html:pre></html:p>

Evaluation implements subtitution using an explicit environment. The resulting machine is reminiscent of
the <fr:link href="https://en.wikipedia.org/wiki/SECD_machine" type="external">SECD machine</fr:link>.
<html:p><html:pre>module Eval =
struct
  (* The type of environments. *)
  type env = value list [@@deriving show]
  (* A closure is a piece of code in a given environment *)
  and closure = env * Code.t [@@deriving show]
  (* A value is either a closure or a literal *)
  and value =
    | Vclos of closure
    | Vlit of Code.literal
  [@@deriving show]

  (* The [stack] type models the main stack of the FMC. *)
  type stack = value Dynarray.t
  let empty_stack () = Dynarray.create ()
  let push : stack -&gt; value -&gt; unit = Dynarray.add_last
  let pop : stack -&gt; value = Dynarray.pop_last
  let pp_stack = Fmt.using Dynarray.to_seq (Fmt.Dump.seq pp_value)

  (* The [kstack] type corresponds to a stack of continuations. *)
  type kstack = closure list

  (* Evaluation: execute each instruction, updating the stack and/or
     environment, and move to the next continuation.
     Main correctness question: correctly handling the environment. *)
  let rec eval : Code.t -&gt; env -&gt; stack -&gt; kstack -&gt; stack =
    fun code env stack kstack -&gt;
      match code with
      | Code.Var (i, k) -&gt;
          let v = List.nth env i in
          begin
            match v with
            | Vlit lit -&gt;
                push stack v ;
                eval k env stack kstack
            | Vclos (env', code') -&gt;
                (* Push current cont. to kstack and install closure. *)
                eval code' env' stack ((env, k) :: kstack)
          end
      | Nil -&gt; begin
          match kstack with
          | [] -&gt;
              (* Execution terminates *)
              stack
          | (env', code) :: rest -&gt; eval code env' stack rest
        end
      | Push (Var (i, Nil), k) -&gt;
          (* This clause is not strictly required but I conjecture that it is
             sufficient to ensure that literals are canonically represented
             by values of the form [Vlit] on the stack, rather than trivial
             closures over a variable. *)
          let v = List.nth env i in
          push stack v ;
          eval k env stack kstack
      | Push (code, k) -&gt;
          push stack (Vclos (env, code)) ;
          eval k env stack kstack
      | Pop k -&gt;
          let v = pop stack in
          eval k (v :: env) stack kstack
      | Lit (lit, k) -&gt;
          push stack (Vlit lit) ;
          eval k env stack kstack
      | Concat k -&gt;
          let v2 = pop stack in
          let v1 = pop stack in
          begin
            match (v1, v2) with
            | (Vlit s1, Vlit s2) -&gt;
                (* Conjecture: in a well-typed program, literals on the stack
                   are of the form [Vlit]. *)
                push stack (Vlit (String.cat s1 s2)) ;
                eval k env stack kstack
            | _ -&gt; failwith "ill-typed program"
          end
end;;</html:pre></html:p>

<html:p>Let's play around with some examples. In <fr:link href="https://arxiv.org/abs/2211.13140" type="external">The functional machine calculus II</fr:link>, a translation from the call-by-value <fr:tex display="inline"><![CDATA[\lambda ]]></fr:tex>-calculus to the FMC is given.
<fr:tex display="block"><![CDATA[
\begin {array}{lllr}
\llbracket  x \rrbracket  & = & [x].\ast  \\
\llbracket  \lambda  x. M \rrbracket  & = & [\langle  x \rangle . \llbracket  M \rrbracket ].\ast  \\
\llbracket  M ~ N \rrbracket  & = & \llbracket  N \rrbracket  ; \llbracket  M \rrbracket  ; \langle  x \rangle  . x & \text {($x$ fresh)}\\
\end {array}
]]></fr:tex></html:p>

<html:p>In code:</html:p>

<html:p><html:pre>type lc =
  | Var of string
  | Lam of string * lc
  | App of lc * lc
  | Lit of Syntax.literal
  | Concat of lc * lc

(* fresh variable generator *)
let fresh : unit -&gt; string =
  let c = ref 0 in
  fun () -&gt;
    incr c;
    "v" ^ (string_of_int !c)

(* Convenience constructors *)
let lambda (f : lc -&gt; lc) = let v = fresh () in Lam (v, f (Var v))
let app (f : lc) (arg : lc) = App (f, arg)
let lit s : lc = Lit s
let concat l r = Concat (l, r)

(* Conversion from lambda-calculus to FMC *)
let rec to_fmc_aux : lc -&gt; Syntax.t -&gt; Syntax.t =
 fun term k -&gt;
  let open Syntax in
  match term with
  | Var s -&gt; Push [Var s] :: k
  | Lam (s, body) -&gt; Push (Pop s :: to_fmc_aux body []) :: k
  | App (f, arg) -&gt;
     let var = fresh () in
     to_fmc_aux arg (to_fmc_aux f (Pop var :: Var var :: k))
  | Lit l -&gt; Lit l :: k
  | Concat (lhs, rhs) -&gt;
     to_fmc_aux rhs (to_fmc_aux lhs (Concat :: k))

let to_fmc term = to_fmc_aux term [] ;;</html:pre></html:p>

Let's print some basic examples.
<html:p><html:pre>let print_fmc fmc = print_endline (Syntax.show fmc);;</html:pre></html:p>

<html:p><html:pre>let print_lambda lc = print_fmc (to_fmc lc);;</html:pre></html:p>

<html:p><html:pre>print_lambda @@ lambda (fun x -&gt; x);;</html:pre><html:pre>[(Push [(Pop "v1"); (Push [(Var "v1")])])]</html:pre></html:p>

<html:p><html:pre>print_lambda @@ lambda (fun fst -&gt; lambda (fun snd -&gt; snd));;</html:pre><html:pre>[(Push [(Pop "v2"); (Push [(Pop "v3"); (Push [(Var "v3")])])])]</html:pre></html:p>

<html:p><html:pre>print_lambda @@ app (app (lambda (fun fst -&gt; lambda (fun snd -&gt; snd))) (lit "fst")) (lit "snd");;</html:pre><html:pre>[(Lit "snd"); (Lit "fst");
  (Push [(Pop "v4"); (Push [(Pop "v5"); (Push [(Var "v5")])])]); (Pop "v7");
  (Var "v7"); (Pop "v6"); (Var "v6")]</html:pre></html:p>

Now let's evaluate stuff.
<html:p><html:pre>(* Evaluate a lambda term and return the FMC stack *)
let eval_lambda lc =
  let stack = Eval.empty_stack () in
  let code = Code.from_syn (to_fmc lc) [] in
  Eval.eval code [] stack []
;;</html:pre><html:pre>val eval_lambda : lc -&gt; Eval.stack = &lt;fun&gt;
</html:pre></html:p>

We expect this to evalaute to the string <html:code>"snd"</html:code>.
<html:p><html:pre>let stack = eval_lambda @@ app (app (lambda (fun fst -&gt; lambda (fun snd -&gt; snd))) (lit "fst")) (lit "snd");;</html:pre></html:p>

<html:p><html:pre>print_endline (Fmt.to_to_string Eval.pp_stack stack);;</html:pre><html:pre>[(Eval.Vlit "snd")]</html:pre></html:p>

Now a lambda which concatenates a string with itself, featuring non-linearity.
<html:p><html:pre>let stack = eval_lambda @@ (app (lambda (fun s -&gt;  concat s s)) (lit "str_"));;</html:pre></html:p>

<html:p><html:pre>print_endline (Fmt.to_to_string Eval.pp_stack stack);;</html:pre><html:pre>[(Eval.Vlit "str_str_")]</html:pre></html:p>

Remarks/going further:
<html:ul><html:li>We could use GADTs to encode the stack typing discipline described in the paper, in the style of what the <fr:link href="https://gitlab.com/tezos/tezos/-/blob/686ec7e8ef47ee3bc8778e05fa1a1631148bfb6c/src/proto_alpha/lib_protocol/script_typed_ir.ml#L441" type="external">Michelson interpreter</fr:link> does</html:li>
<html:li>State-like effects can be handled with extra stacks (one stack per 'location'/reference). If my understanding in correct this means that the number of stacks may dynamically grow (e.g. when one allocates new references.)</html:li>
<html:li>Control: the extension is described in the third paper and seems straightforward, though the description makes it look like rather inefficent (basically, a <html:code>switch</html:code> would be executing pieces of code conditionally for each branch until finding the right one rather than actually jumping).</html:li></html:ul>



</fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="true" expanded="false" toc="false" numbered="false">
              <fr:frontmatter>
                <fr:authors />
                <fr:date>
                  <fr:year>2025</fr:year>
                  <fr:month>11</fr:month>
                  <fr:day>8</fr:day>
                </fr:date>
                <fr:uri>http://localhost/000P/</fr:uri>
                <fr:display-uri>000P</fr:display-uri>
                <fr:route>/000P/</fr:route>
                <fr:title text="A plugin system for Forester">A plugin system for Forester</fr:title>
                <fr:taxon>article</fr:taxon>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>
Forester is a great tool but I have found writing code snippets frustrating, as those are not evaluated nor type-checked. I just prototyped a plugin feature which allows essentially mapping Forester values through an external program. I got a plugin connected to an OCaml toplevel instance. At the time of writing the code is on my <fr:link href="https://github.com/igarnier" type="external">github</fr:link>. I have the following needs:

<html:ul><html:li>Intersplice text and pieces of code to be evaluated, following the usual literate programming practice.</html:li>
<html:li>Maintain simultaneously distinct states for a given plugin.</html:li>
<html:li>Ideally, integrate extra artifacts (images, etc) produced by the plugin. This is not done.</html:li></html:ul>

I tried to be minimally invasive but my patch certainly requires a lot of discussion before being mergeable. I plan to dogfood it on my own forest for the time being. A demonstration is in order.
</html:p>
                <html:p><html:p><html:pre>let x = 1+1;;</html:pre><html:pre>val x : int = 2
</html:pre></html:p>

We note that the code is not highlighted. This could be a future feature. Let's carry on with our computation.

<html:p><html:pre>x + 3;;</html:pre><html:pre>- : int = 5
</html:pre></html:p></html:p>
                <html:p>
The Forester code looks like this:

<html:pre><![CDATA[\alloc\plugin/ocamldemo
\put\plugin/ocamldemo{\plugin{ocaml}}

\get\plugin/ocamldemo{}{let x = 1+1;;}

We note that the code is not highlighted. This could be a future feature. Let's carry on with our computation.

\get\plugin/ocamldemo{}{x + 3;;}]]></html:pre></html:p>
                <html:p>
Plugin initialization happens at <html:pre><![CDATA[\plugin{ocaml}]]></html:pre> The resulting (stateful) plugin value is attached to the key
<html:pre><![CDATA[\plugin/ocamldemo]]></html:pre>

In this case, initialization is nontrivial: the toplevel needs to be compiled in bytecode, so it leaves in its own server, in a separate executable from Forester. When the plugin is initialized, the server is launched and the Forester-side of the plugin acts as a client, pushing phrases and getting the outcome as well as the catpured stdout. Each plugin instance gets its own server, hence its own toplevel. The OCaml toplevel is very stateful so having one process per plugin instance takes a lot of problems away.
</html:p>
                <html:p>
Each call to the plugin takes two arguments. The first one is used to pass plugin options, as text content. The second one takes the code to execute.




By default, stdout and topevel output are captured:
<html:pre><![CDATA[\get\plugin/ocamldemo{}{Format.printf "stdout message"; 42 ;;}]]></html:pre>

<html:p><html:pre>Format.printf "stdout message"; 42 ;;</html:pre><html:pre>- : int = 42
</html:pre><html:pre>stdout message</html:pre></html:p>

Sometimes however we don't want one or the other. One can pass a comma-separated list of options
as first argument: "no-stdout" disables standard output capture, "no-echo" disables the
toplevel echo.

<html:pre><![CDATA[\get\plugin/ocamldemo{no-stdout}{Format.printf "stdout message"; 42 ;;}]]></html:pre>

<html:p><html:pre>Format.printf "stdout message"; 42 ;;</html:pre><html:pre>- : int = 42
</html:pre></html:p></html:p>
                <html:p>Some items that needs improving/future features:

<html:ul><html:li>general: the command <html:code>forester new</html:code> re-evaluates everything, do we really need to run the plugins or can't we just run in 'dummy' mode? Or cache result of evaluation as artifacts, perhaps? The latter requires tracking depenencies across calls to a given plugin instance, which is nontrivial.</html:li>
<html:li>general: come up with a plugin protocol that would allow to exchange artifacts produced by the plugin (encompassing what the latex feature does)</html:li>
<html:li>general: allow to pass optional parameters at plugin initialization and use time</html:li>
<html:li>ocaml: use native toplevel instead of bytecode one</html:li>
<html:li>ocaml: syntax highlighting</html:li>
<html:li>ocaml: handle newlines and other special characters in string literals</html:li></html:ul>

I discovered this <fr:link href="https://todo.sr.ht/~jonsterling/forester/87" type="external">RFC</fr:link> after implementing the plugin. Worth reading in depth.

</html:p>
              </fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="true" expanded="false" toc="false" numbered="false">
              <fr:frontmatter>
                <fr:authors />
                <fr:date>
                  <fr:year>2025</fr:year>
                  <fr:month>7</fr:month>
                  <fr:day>13</fr:day>
                </fr:date>
                <fr:uri>http://localhost/000D/</fr:uri>
                <fr:display-uri>000D</fr:display-uri>
                <fr:route>/000D/</fr:route>
                <fr:title text="Monadic Monte Carlo tree search">Monadic Monte Carlo tree search</fr:title>
                <fr:taxon>article</fr:taxon>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>
Monte Carlo tree search (MCTS for short) is a heuristic method to solve <fr:link href="https://en.wikipedia.org/wiki/Markov_decision_process" type="external">markov decision process</fr:link> (MDPs).
</html:p>
                <fr:tree show-metadata="false">
                  <fr:frontmatter>
                    <fr:authors />
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>7</fr:month>
                      <fr:day>13</fr:day>
                    </fr:date>
                    <fr:uri>http://localhost/000F/</fr:uri>
                    <fr:display-uri>000F</fr:display-uri>
                    <fr:route>/000F/</fr:route>
                    <fr:title text="Markov decision processes">Markov decision processes</fr:title>
                    <fr:taxon>Definition</fr:taxon>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p><fr:link href="https://en.wikipedia.org/wiki/Markov_decision_process" type="external">Markov decision processes</fr:link> (MDPs) are models of an agent that moves probabilistically from state to state by taking actions, and gets rewards at each state it visits. MDPs are the canonical setting of reinforcement learning (RL). Solving an MDP means finding a <html:em>policy</html:em>, i.e. a function which at every state gives an optimal action to take so that the expected reward is maximized.
</html:p>
                    <html:p>A monadic interface to describe (non-probabilistic) MDPs is the following:


  <fr:resource hash="eef6832fea89f6cb37ca9dd2e8f462eb"><fr:resource-content><html:img src="/eef6832fea89f6cb37ca9dd2e8f462eb.svg" /></fr:resource-content><fr:resource-source type="latex" part="preamble"><![CDATA[
  \usepackage{tikz, tikz-cd, mathtools, amssymb, stmaryrd, listings}
 \usepackage[all]{xy}
 \usetikzlibrary{matrix,arrows}
 \usetikzlibrary{backgrounds,fit,positioning,calc,shapes}
 \usetikzlibrary{decorations.pathreplacing}
 \usetikzlibrary{decorations.pathmorphing}
 \usetikzlibrary{decorations.markings}

 \lstset{
  language=[Objective]Caml,
  columns=[c]fixed,
  % basicstyle=\small\ttfamily,
  % keywordstyle=\bfseries,
  keywordstyle={\bfseries},
  morekeywords={begin, end, if, then, else, match, fun, function, let, rec, and}
  deletekeywords=value
  upquote=true,
  commentstyle=,
  breaklines=false,
  showstringspaces=false,
  stringstyle=\color{blue},
  literate={'"'}{\textquotesingle "\textquotesingle}3
 }
]]></fr:resource-source><fr:resource-source type="latex" part="body"><![CDATA[
   \begin{lstlisting}{ObjectiveCaml}
   
module type MDP = sig
   type 'a t
   val return : 'a -> 'a t
   val bind : 'a t -> ('a -> 'b t) -> 'b t
   val choices : 'a array -> 'a t
   val reward : float -> unit t
end

   \end{lstlisting}
  ]]></fr:resource-source></fr:resource></html:p>
                    <html:p><html:code>return</html:code> and <html:code>bind</html:code> are the usual monadic constructs, while <html:code>choices</html:code> is the set of actions available at that program point and <html:code>reward</html:code> attributes a (nonnegative) reward to the trace in which it occurs.</html:p>
                  </fr:mainmatter>
                </fr:tree>
                <html:p>MCTS implements this interface by representing computations as lazily expanded choice trees where local exploration decisions are guided by <fr:link href="/000E/" title="Multi-armed bandits" uri="http://localhost/000E/" display-uri="000E" type="local">multi-armed bandits</fr:link>. We will explain each of these techniques before coalescing them into an implementation for MCTS. Before, a toy motivating example is in order.
</html:p>
                <fr:tree show-metadata="false">
                  <fr:frontmatter>
                    <fr:authors />
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>7</fr:month>
                      <fr:day>14</fr:day>
                    </fr:date>
                    <fr:uri>http://localhost/000G/</fr:uri>
                    <fr:display-uri>000G</fr:display-uri>
                    <fr:route>/000G/</fr:route>
                    <fr:title text="Monadic MCTS">Monadic MCTS</fr:title>
                    <fr:taxon>Example</fr:taxon>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>Assume given an <fr:link href="/000D/" title="Monadic Monte Carlo tree search" uri="http://localhost/000D/" display-uri="000D" type="local">MCTS</fr:link> implementation of the <fr:link href="/000F/" title="Markov decision processes" uri="http://localhost/000F/" display-uri="000F" type="local"><html:code>MDP</html:code> interface</fr:link>: <html:code>module Mcts : MDP</html:code></html:p>
                    <html:p>Consider the following type for arithmetic expressions featuring holes.


  <fr:resource hash="7d9cac86a4ae07ba442fb41e97456e5f"><fr:resource-content><html:img src="/7d9cac86a4ae07ba442fb41e97456e5f.svg" /></fr:resource-content><fr:resource-source type="latex" part="preamble"><![CDATA[
  \usepackage{tikz, tikz-cd, mathtools, amssymb, stmaryrd, listings}
 \usepackage[all]{xy}
 \usetikzlibrary{matrix,arrows}
 \usetikzlibrary{backgrounds,fit,positioning,calc,shapes}
 \usetikzlibrary{decorations.pathreplacing}
 \usetikzlibrary{decorations.pathmorphing}
 \usetikzlibrary{decorations.markings}

 \lstset{
  language=[Objective]Caml,
  columns=[c]fixed,
  % basicstyle=\small\ttfamily,
  % keywordstyle=\bfseries,
  keywordstyle={\bfseries},
  morekeywords={begin, end, if, then, else, match, fun, function, let, rec, and}
  deletekeywords=value
  upquote=true,
  commentstyle=,
  breaklines=false,
  showstringspaces=false,
  stringstyle=\color{blue},
  literate={'"'}{\textquotesingle "\textquotesingle}3
 }
]]></fr:resource-source><fr:resource-source type="latex" part="body"><![CDATA[
   \begin{lstlisting}{ObjectiveCaml}
   
type expr = Add of expr * expr
          | Mul of expr * expr
          | Const of int
          | Hole

   \end{lstlisting}
  ]]></fr:resource-source></fr:resource></html:p>
                    <html:p>We implement a function that non-deterministically evaluates such expressions by filling holes. <html:code>eval</html:code> takes an expression and returns a computation in the type <html:code>Mcts.t</html:code> which yields the result of the evaluation and the generated expression.


  <fr:resource hash="56d3162c521507f3c1243ae699a1e0bb"><fr:resource-content><html:img src="/56d3162c521507f3c1243ae699a1e0bb.svg" /></fr:resource-content><fr:resource-source type="latex" part="preamble"><![CDATA[
  \usepackage{tikz, tikz-cd, mathtools, amssymb, stmaryrd, listings}
 \usepackage[all]{xy}
 \usetikzlibrary{matrix,arrows}
 \usetikzlibrary{backgrounds,fit,positioning,calc,shapes}
 \usetikzlibrary{decorations.pathreplacing}
 \usetikzlibrary{decorations.pathmorphing}
 \usetikzlibrary{decorations.markings}

 \lstset{
  language=[Objective]Caml,
  columns=[c]fixed,
  % basicstyle=\small\ttfamily,
  % keywordstyle=\bfseries,
  keywordstyle={\bfseries},
  morekeywords={begin, end, if, then, else, match, fun, function, let, rec, and}
  deletekeywords=value
  upquote=true,
  commentstyle=,
  breaklines=false,
  showstringspaces=false,
  stringstyle=\color{blue},
  literate={'"'}{\textquotesingle "\textquotesingle}3
 }
]]></fr:resource-source><fr:resource-source type="latex" part="body"><![CDATA[
   \begin{lstlisting}{ObjectiveCaml}
   
let rec eval : expr -> (int * expr) Mcts.t =
 fun expr ->
  match expr with
  | Add (e1, e2) ->
      let* (v1, e1') = eval e1 in
      let* (v2, e2') = eval e2 in
      return (v1 + v2, Add (e1', e2'))
  | Mul (e1, e2) ->
      let* (v1, e1') = eval e1 in
      let* (v2, e2') = eval e2 in
      return (v1 * v2, Mul (e1', e2'))
  | Const i -> return (i, expr)
  | Hole ->
      let* choice =
        Mcts.choices [| Add (Hole, Hole);
                        Mul (Hole, Hole);
                        Const 1;
                        Const 2 |]
      in
      eval choice

   \end{lstlisting}
  ]]></fr:resource-source></fr:resource></html:p>
                    <html:p>The function <html:code>eval</html:code> describes the simultaneous evaluation and generation of an arithmetic expression. Observe how a hole is filled: we call <html:code>Mcts.choices</html:code> to describe possible options and proceed with the evaluation on the outcome. The <html:code>MDP</html:code> interface allows us to guide the evalation/generation process to produce expressions satisfying some constraints. For instance, the following <html:code>query</html:code> function takes an integer and returns a computation which produces an expression <html:code>e</html:code> whose evaluation matches the <html:code>target</html:code>.


  <fr:resource hash="4401ea850f26caa9ffbe224fd4109d02"><fr:resource-content><html:img src="/4401ea850f26caa9ffbe224fd4109d02.svg" /></fr:resource-content><fr:resource-source type="latex" part="preamble"><![CDATA[
  \usepackage{tikz, tikz-cd, mathtools, amssymb, stmaryrd, listings}
 \usepackage[all]{xy}
 \usetikzlibrary{matrix,arrows}
 \usetikzlibrary{backgrounds,fit,positioning,calc,shapes}
 \usetikzlibrary{decorations.pathreplacing}
 \usetikzlibrary{decorations.pathmorphing}
 \usetikzlibrary{decorations.markings}

 \lstset{
  language=[Objective]Caml,
  columns=[c]fixed,
  % basicstyle=\small\ttfamily,
  % keywordstyle=\bfseries,
  keywordstyle={\bfseries},
  morekeywords={begin, end, if, then, else, match, fun, function, let, rec, and}
  deletekeywords=value
  upquote=true,
  commentstyle=,
  breaklines=false,
  showstringspaces=false,
  stringstyle=\color{blue},
  literate={'"'}{\textquotesingle "\textquotesingle}3
 }
]]></fr:resource-source><fr:resource-source type="latex" part="body"><![CDATA[
   \begin{lstlisting}{ObjectiveCaml}
   
let query (target : int) =
  let* (v, e) = eval Hole in
  let score = exp ~-.(float_of_int (abs (v - target))) in
  let* () = Mcts.reward score in
  return (v, e)

   \end{lstlisting}
  ]]></fr:resource-source></fr:resource></html:p>
                    <html:p>This is achieved by assigning a reward which penalizes bad answers: the reward is of the form <fr:tex display="block"><![CDATA[e^{-|v - target|}]]></fr:tex></html:p>
                  </fr:mainmatter>
                </fr:tree>
                <html:p>The core of the implementation is a representation of the choice tree.</html:p>
                <fr:tree show-metadata="false">
                  <fr:frontmatter>
                    <fr:authors />
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>7</fr:month>
                      <fr:day>14</fr:day>
                    </fr:date>
                    <fr:uri>http://localhost/000I/</fr:uri>
                    <fr:display-uri>000I</fr:display-uri>
                    <fr:route>/000I/</fr:route>
                    <fr:title text="Memoizable choice tree monad">Memoizable choice tree monad</fr:title>
                    <fr:taxon>Definition</fr:taxon>
                  </fr:frontmatter>
                  <fr:mainmatter><html:p>
We're concerned with implementing the following signature, corresponding to a monad for finite non-determinism. (Note however than much of what is written here applies to more general signatures.)
</html:p>
  <fr:resource hash="15cc6880b8528de3b410a3f4f3d46c60"><fr:resource-content><html:img src="/15cc6880b8528de3b410a3f4f3d46c60.svg" /></fr:resource-content><fr:resource-source type="latex" part="preamble"><![CDATA[
  \usepackage{tikz, tikz-cd, mathtools, amssymb, stmaryrd, listings}
 \usepackage[all]{xy}
 \usetikzlibrary{matrix,arrows}
 \usetikzlibrary{backgrounds,fit,positioning,calc,shapes}
 \usetikzlibrary{decorations.pathreplacing}
 \usetikzlibrary{decorations.pathmorphing}
 \usetikzlibrary{decorations.markings}

 \lstset{
  language=[Objective]Caml,
  columns=[c]fixed,
  % basicstyle=\small\ttfamily,
  % keywordstyle=\bfseries,
  keywordstyle={\bfseries},
  morekeywords={begin, end, if, then, else, match, fun, function, let, rec, and}
  deletekeywords=value
  upquote=true,
  commentstyle=,
  breaklines=false,
  showstringspaces=false,
  stringstyle=\color{blue},
  literate={'"'}{\textquotesingle "\textquotesingle}3
 }
]]></fr:resource-source><fr:resource-source type="latex" part="body"><![CDATA[
   \begin{lstlisting}{ObjectiveCaml}
   
module type M = sig
  type 'a t
  val bind : 'a t -> ('a -> 'b t) -> 'b t
  val return : 'a -> 'a t
  val choices : 'a array -> 'a t
end

   \end{lstlisting}
  ]]></fr:resource-source></fr:resource>
<html:p>
A free monadic implementation as given by <html:code>Free</html:code> below just reflects the monadic opereations in a GADT. This is fine for some applications, but it makes memoizing choices nontrivial: the callbacks to be memoized are inside <html:code>bind</html:code> nodes while the choices are in <html:code>choices</html:code> nodes.
</html:p>
  <fr:resource hash="2c1109686e5f9f3db122ea158057261c"><fr:resource-content><html:img src="/2c1109686e5f9f3db122ea158057261c.svg" /></fr:resource-content><fr:resource-source type="latex" part="preamble"><![CDATA[
  \usepackage{tikz, tikz-cd, mathtools, amssymb, stmaryrd, listings}
 \usepackage[all]{xy}
 \usetikzlibrary{matrix,arrows}
 \usetikzlibrary{backgrounds,fit,positioning,calc,shapes}
 \usetikzlibrary{decorations.pathreplacing}
 \usetikzlibrary{decorations.pathmorphing}
 \usetikzlibrary{decorations.markings}

 \lstset{
  language=[Objective]Caml,
  columns=[c]fixed,
  % basicstyle=\small\ttfamily,
  % keywordstyle=\bfseries,
  keywordstyle={\bfseries},
  morekeywords={begin, end, if, then, else, match, fun, function, let, rec, and}
  deletekeywords=value
  upquote=true,
  commentstyle=,
  breaklines=false,
  showstringspaces=false,
  stringstyle=\color{blue},
  literate={'"'}{\textquotesingle "\textquotesingle}3
 }
]]></fr:resource-source><fr:resource-source type="latex" part="body"><![CDATA[
   \begin{lstlisting}{ObjectiveCaml}
   
module Free =
struct
  type _ t =
    | Choices : 'a array -> 'a t
    | Bind : 'a t * ('a -> 'b t) -> 'b t
    | Return : 'a -> 'a t

  let bind m f = Bind (m, f)
  let return x = Return x
  let choices arr = Choices arr
end

   \end{lstlisting}
  ]]></fr:resource-source></fr:resource>
<html:p>If <html:code>bind</html:code> nodes were always associated to the right as in <html:code>bind (choices ...) (fun x -&gt; bind (choices ...) ...)</html:code>, then we could easily memoize. We can enforce this by constraining the structure of the trees to be flat, as in:</html:p>
  <fr:resource hash="00fda6f3b9a3955d7edcd781439464e0"><fr:resource-content><html:img src="/00fda6f3b9a3955d7edcd781439464e0.svg" /></fr:resource-content><fr:resource-source type="latex" part="preamble"><![CDATA[
  \usepackage{tikz, tikz-cd, mathtools, amssymb, stmaryrd, listings}
 \usepackage[all]{xy}
 \usetikzlibrary{matrix,arrows}
 \usetikzlibrary{backgrounds,fit,positioning,calc,shapes}
 \usetikzlibrary{decorations.pathreplacing}
 \usetikzlibrary{decorations.pathmorphing}
 \usetikzlibrary{decorations.markings}

 \lstset{
  language=[Objective]Caml,
  columns=[c]fixed,
  % basicstyle=\small\ttfamily,
  % keywordstyle=\bfseries,
  keywordstyle={\bfseries},
  morekeywords={begin, end, if, then, else, match, fun, function, let, rec, and}
  deletekeywords=value
  upquote=true,
  commentstyle=,
  breaklines=false,
  showstringspaces=false,
  stringstyle=\color{blue},
  literate={'"'}{\textquotesingle "\textquotesingle}3
 }
]]></fr:resource-source><fr:resource-source type="latex" part="body"><![CDATA[
   \begin{lstlisting}{ObjectiveCaml}
   
type 'a op = Choices of 'a array

type _ flat =
   | Bind : 'a op * ('a -> 'b flat) -> 'b flat
   | Return : 'a -> 'a flat

   \end{lstlisting}
  ]]></fr:resource-source></fr:resource>
<html:p>But this is overly constraining for users. We can alleviate this issue by applying the <fr:link href="/000J/" title="Codensity monad" uri="http://localhost/000J/" display-uri="000J" type="local"><html:code>Codensity</html:code></fr:link> construction to the type above. Rather than using an explicit <html:code>Bind</html:code> node to chain computations, we use continuation-passing style combined with a definition of trees which are always explicitly flattened.</html:p>
  <fr:resource hash="174943e45ffcf5d726d1f3d59ca85cf6"><fr:resource-content><html:img src="/174943e45ffcf5d726d1f3d59ca85cf6.svg" /></fr:resource-content><fr:resource-source type="latex" part="preamble"><![CDATA[
  \usepackage{tikz, tikz-cd, mathtools, amssymb, stmaryrd, listings}
 \usepackage[all]{xy}
 \usetikzlibrary{matrix,arrows}
 \usetikzlibrary{backgrounds,fit,positioning,calc,shapes}
 \usetikzlibrary{decorations.pathreplacing}
 \usetikzlibrary{decorations.pathmorphing}
 \usetikzlibrary{decorations.markings}

 \lstset{
  language=[Objective]Caml,
  columns=[c]fixed,
  % basicstyle=\small\ttfamily,
  % keywordstyle=\bfseries,
  keywordstyle={\bfseries},
  morekeywords={begin, end, if, then, else, match, fun, function, let, rec, and}
  deletekeywords=value
  upquote=true,
  commentstyle=,
  breaklines=false,
  showstringspaces=false,
  stringstyle=\color{blue},
  literate={'"'}{\textquotesingle "\textquotesingle}3
 }
]]></fr:resource-source><fr:resource-source type="latex" part="body"><![CDATA[
   \begin{lstlisting}{ObjectiveCaml}
   
module Codensity =
struct
  type _ tree =
    | Choices : 'a array * ('a -> 'b tree) -> 'b tree
    | Return : 'a -> 'a tree

  type 'a codensity = {
    call : 'b. ('a -> 'b tree) -> 'b tree
  }

  type 'a t = 'a codensity

  let choices arr =
    { call = (fun k -> Choices (arr, k)) }
  let bind m f =
    { call = (fun k ->
        m.call (fun xm -> (f xm).call k)) }
  let return x =
    { call = (fun k -> k x) }
end

   \end{lstlisting}
  ]]></fr:resource-source></fr:resource>
<html:p>One can obtain a tree from a <fr:link href="/000J/" title="Codensity monad" uri="http://localhost/000J/" display-uri="000J" type="local">codensity</fr:link> computation by <html:em>running it</html:em>:


  <fr:resource hash="0dca0935b9f8cdbd62686d0f8b6cc271"><fr:resource-content><html:img src="/0dca0935b9f8cdbd62686d0f8b6cc271.svg" /></fr:resource-content><fr:resource-source type="latex" part="preamble"><![CDATA[
  \usepackage{tikz, tikz-cd, mathtools, amssymb, stmaryrd, listings}
 \usepackage[all]{xy}
 \usetikzlibrary{matrix,arrows}
 \usetikzlibrary{backgrounds,fit,positioning,calc,shapes}
 \usetikzlibrary{decorations.pathreplacing}
 \usetikzlibrary{decorations.pathmorphing}
 \usetikzlibrary{decorations.markings}

 \lstset{
  language=[Objective]Caml,
  columns=[c]fixed,
  % basicstyle=\small\ttfamily,
  % keywordstyle=\bfseries,
  keywordstyle={\bfseries},
  morekeywords={begin, end, if, then, else, match, fun, function, let, rec, and}
  deletekeywords=value
  upquote=true,
  commentstyle=,
  breaklines=false,
  showstringspaces=false,
  stringstyle=\color{blue},
  literate={'"'}{\textquotesingle "\textquotesingle}3
 }
]]></fr:resource-source><fr:resource-source type="latex" part="body"><![CDATA[
   \begin{lstlisting}{ObjectiveCaml}
   
let run_codensity : type a. a t -> a tree =
  fun m -> m.call (fun x -> Return x)

   \end{lstlisting}
  ]]></fr:resource-source></fr:resource></html:p><html:p>
And once a tree is obtained, one may explore it. For instance, random sampling from
a tree is a simple recursive function:


  <fr:resource hash="4e8abac3d48922a671445d442d69841d"><fr:resource-content><html:img src="/4e8abac3d48922a671445d442d69841d.svg" /></fr:resource-content><fr:resource-source type="latex" part="preamble"><![CDATA[
  \usepackage{tikz, tikz-cd, mathtools, amssymb, stmaryrd, listings}
 \usepackage[all]{xy}
 \usetikzlibrary{matrix,arrows}
 \usetikzlibrary{backgrounds,fit,positioning,calc,shapes}
 \usetikzlibrary{decorations.pathreplacing}
 \usetikzlibrary{decorations.pathmorphing}
 \usetikzlibrary{decorations.markings}

 \lstset{
  language=[Objective]Caml,
  columns=[c]fixed,
  % basicstyle=\small\ttfamily,
  % keywordstyle=\bfseries,
  keywordstyle={\bfseries},
  morekeywords={begin, end, if, then, else, match, fun, function, let, rec, and}
  deletekeywords=value
  upquote=true,
  commentstyle=,
  breaklines=false,
  showstringspaces=false,
  stringstyle=\color{blue},
  literate={'"'}{\textquotesingle "\textquotesingle}3
 }
]]></fr:resource-source><fr:resource-source type="latex" part="body"><![CDATA[
   \begin{lstlisting}{ObjectiveCaml}
   
let rec monte_carlo_run : type a. Random.State.t -> a tree -> a =
  fun rng -> function
    | Choices (arr, callback) ->
      let i = Random.State.int rng (Array.length arr) in
      monte_carlo_run rng (callback arr.(i))
    | Return x -> x

   \end{lstlisting}
  ]]></fr:resource-source></fr:resource></html:p><html:p>However, this will reallocate already explored trees. Memoization can make the structure more computationally efficient. We elide the definitions identical to that of the <html:code>Codensity</html:code> module.


  <fr:resource hash="75b2e1d99f1ca743a451b22cb7aaff7a"><fr:resource-content><html:img src="/75b2e1d99f1ca743a451b22cb7aaff7a.svg" /></fr:resource-content><fr:resource-source type="latex" part="preamble"><![CDATA[
  \usepackage{tikz, tikz-cd, mathtools, amssymb, stmaryrd, listings}
 \usepackage[all]{xy}
 \usetikzlibrary{matrix,arrows}
 \usetikzlibrary{backgrounds,fit,positioning,calc,shapes}
 \usetikzlibrary{decorations.pathreplacing}
 \usetikzlibrary{decorations.pathmorphing}
 \usetikzlibrary{decorations.markings}

 \lstset{
  language=[Objective]Caml,
  columns=[c]fixed,
  % basicstyle=\small\ttfamily,
  % keywordstyle=\bfseries,
  keywordstyle={\bfseries},
  morekeywords={begin, end, if, then, else, match, fun, function, let, rec, and}
  deletekeywords=value
  upquote=true,
  commentstyle=,
  breaklines=false,
  showstringspaces=false,
  stringstyle=\color{blue},
  literate={'"'}{\textquotesingle "\textquotesingle}3
 }
]]></fr:resource-source><fr:resource-source type="latex" part="body"><![CDATA[
   \begin{lstlisting}{ObjectiveCaml}
   
module MemoCodensity =
struct
  type _ tree =
    | Choices : 'a array * 'b tree Lazy.t array -> 'b tree
    | Return : 'a -> 'a tree

  type 'a codensity = {
    call : 'b. ('a -> 'b tree) -> 'b tree
  }

  type 'a t = 'a codensity

  let init_choices arr k =
    let subtrees = Array.map (fun c -> Lazy.from_fun (fun () -> k c)) arr in
    Choices (arr, subtrees)

  let choices arr =
    { call = (fun k -> init_choices arr k) }

  let bind m f = ...
  let return x = ...
  let run_codensity (m : 'a t) = ...

  let rec monte_carlo_run : type a. Random.State.t -> a tree -> a =
    fun rng -> function
      | Choices (_, subtrees) ->
        let i = Random.State.int rng (Array.length subtrees) in
        monte_carlo_run rng (Lazy.force subtrees.(i))
      | Return x -> x
end

   \end{lstlisting}
  ]]></fr:resource-source></fr:resource></html:p></fr:mainmatter>
                </fr:tree>
                <html:p>
MCTS uses multi-armed bandits as local decision-making units in nodes of a choice trees.</html:p>
                <fr:tree show-metadata="false">
                  <fr:frontmatter>
                    <fr:authors />
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>7</fr:month>
                      <fr:day>13</fr:day>
                    </fr:date>
                    <fr:uri>http://localhost/000E/</fr:uri>
                    <fr:display-uri>000E</fr:display-uri>
                    <fr:route>/000E/</fr:route>
                    <fr:title text="Multi-armed bandits">Multi-armed bandits</fr:title>
                    <fr:taxon>Definition</fr:taxon>
                  </fr:frontmatter>
                  <fr:mainmatter><html:p><fr:link href="https://en.wikipedia.org/wiki/Multi-armed_bandit" type="external">Multi-armed bandits</fr:link> (MAB) are a foundational model of decision-making under uncertainty. In such models, we have:

<html:ul><html:li><fr:tex display="inline"><![CDATA[K]]></fr:tex> actions (so-called <html:em>arms</html:em>)</html:li>
<html:li>an unknown family of reward distributions <fr:tex display="inline"><![CDATA[\rho _i \in  Pr(\mathbb {R}_{\ge  0})]]></fr:tex> (assumed to have finite mean)</html:li>
<html:li><fr:tex display="inline"><![CDATA[T]]></fr:tex> <html:em>trials</html:em></html:li></html:ul>

At each trial <fr:tex display="inline"><![CDATA[t \in  [1;T]]]></fr:tex> we select an action <fr:tex display="inline"><![CDATA[k_t \in  [1;K]]]></fr:tex> and get a reward sampled from the distribution associated to <fr:tex display="inline"><![CDATA[k_t]]></fr:tex>, i.e. <fr:tex display="inline"><![CDATA[\rho _{k_t}]]></fr:tex>. An optimal strategy on average is to select the arm corresponding to the distribution with maximal mean. The goal is to devise a strategy to select actions so as to minimize <html:em>regret</html:em>, i.e. the difference between the obtained reward and that obtained via the optimal strategy.
</html:p><html:p>Some algorithms to solve the MAB problem are <fr:tex display="inline"><![CDATA[\epsilon ]]></fr:tex>-greedy bandits, <fr:link href="/000L/" title="UCB1 algorithm" uri="http://localhost/000L/" display-uri="000L" type="local">UCB1</fr:link>, etc.</html:p><html:p>Algorithms to solve the MAB problem share a common interface. We distinguish two kinds of states:
<html:ul><html:li><html:code>Ready</html:code>: when in a ready state, the bandit may <html:code>select</html:code> an <html:code>Action</html:code>, and transition in a <html:em>Waiting</html:em> state.</html:li>
<html:li><html:code>Waiting</html:code>: when in a waiting state, the bandit may receive a <html:code>Reward</html:code> and <html:code>update</html:code> its internal statistics, moving back to a <html:em>Ready</html:em> state.</html:li></html:ul></html:p>
   
   <html:img width="400px" src="/bafkrmico7mm5hsm7vyxy4ldqikmh3uv6mtzmd56iiai7xa26qeqdmjsnqu.svg" />
<html:p>
This translates in the following interface:


  <fr:resource hash="0e457ff7ad8bd01800aa82bf4b101d16"><fr:resource-content><html:img src="/0e457ff7ad8bd01800aa82bf4b101d16.svg" /></fr:resource-content><fr:resource-source type="latex" part="preamble"><![CDATA[
  \usepackage{tikz, tikz-cd, mathtools, amssymb, stmaryrd, listings}
 \usepackage[all]{xy}
 \usetikzlibrary{matrix,arrows}
 \usetikzlibrary{backgrounds,fit,positioning,calc,shapes}
 \usetikzlibrary{decorations.pathreplacing}
 \usetikzlibrary{decorations.pathmorphing}
 \usetikzlibrary{decorations.markings}

 \lstset{
  language=[Objective]Caml,
  columns=[c]fixed,
  % basicstyle=\small\ttfamily,
  % keywordstyle=\bfseries,
  keywordstyle={\bfseries},
  morekeywords={begin, end, if, then, else, match, fun, function, let, rec, and}
  deletekeywords=value
  upquote=true,
  commentstyle=,
  breaklines=false,
  showstringspaces=false,
  stringstyle=\color{blue},
  literate={'"'}{\textquotesingle "\textquotesingle}3
 }
]]></fr:resource-source><fr:resource-source type="latex" part="body"><![CDATA[
   \begin{lstlisting}{ObjectiveCaml}
   
module Int_bandit : sig
  type ready
  type waiting
  type action = int
  type reward = float

  val init : int -> ready
  val select : ready -> action * waiting
  val set_reward : waiting -> reward -> ready
end

   \end{lstlisting}
  ]]></fr:resource-source></fr:resource></html:p><html:p>
In practice, one may want to decompose the <html:code>waiting</html:code> state as <html:code>ready * action</html:code> as we typically just need to remember the last action taken.
</html:p></fr:mainmatter>
                </fr:tree>
                <html:p>
The MCTS tree is defined by adjoining bandits to choices nodes in a codensity-based <fr:link href="/000I/" title="Memoizable choice tree monad" uri="http://localhost/000I/" display-uri="000I" type="local">memoizable tree</fr:link> monad. An implementation could look as follows:

  <fr:resource hash="849bc84516fa1fed22f8d2c8c747b595"><fr:resource-content><html:img src="/849bc84516fa1fed22f8d2c8c747b595.svg" /></fr:resource-content><fr:resource-source type="latex" part="preamble"><![CDATA[
  \usepackage{tikz, tikz-cd, mathtools, amssymb, stmaryrd, listings}
 \usepackage[all]{xy}
 \usetikzlibrary{matrix,arrows}
 \usetikzlibrary{backgrounds,fit,positioning,calc,shapes}
 \usetikzlibrary{decorations.pathreplacing}
 \usetikzlibrary{decorations.pathmorphing}
 \usetikzlibrary{decorations.markings}

 \lstset{
  language=[Objective]Caml,
  columns=[c]fixed,
  % basicstyle=\small\ttfamily,
  % keywordstyle=\bfseries,
  keywordstyle={\bfseries},
  morekeywords={begin, end, if, then, else, match, fun, function, let, rec, and}
  deletekeywords=value
  upquote=true,
  commentstyle=,
  breaklines=false,
  showstringspaces=false,
  stringstyle=\color{blue},
  literate={'"'}{\textquotesingle "\textquotesingle}3
 }
]]></fr:resource-source><fr:resource-source type="latex" part="body"><![CDATA[
   \begin{lstlisting}{ObjectiveCaml}
   
type _ tree =
  | Choices : {
      bandit : Int_bandit.t;
      choices : 'a array;
      subtrees : 'b tree Lazy.t;
    } -> 'b tree
  | Reward : {
      reward : float;
      subtree : unit -> 'a tree
    } -> 'a tree
  | Return : 'a -> 'a tree

   \end{lstlisting}
  ]]></fr:resource-source></fr:resource></html:p>
                <html:p>However we don


  <fr:resource hash="1b5a2e7d414f344f5686db4c4aa88955"><fr:resource-content><html:img src="/1b5a2e7d414f344f5686db4c4aa88955.svg" /></fr:resource-content><fr:resource-source type="latex" part="preamble"><![CDATA[
  \usepackage{tikz, tikz-cd, mathtools, amssymb, stmaryrd, listings}
 \usepackage[all]{xy}
 \usetikzlibrary{matrix,arrows}
 \usetikzlibrary{backgrounds,fit,positioning,calc,shapes}
 \usetikzlibrary{decorations.pathreplacing}
 \usetikzlibrary{decorations.pathmorphing}
 \usetikzlibrary{decorations.markings}

 \lstset{
  language=[Objective]Caml,
  columns=[c]fixed,
  % basicstyle=\small\ttfamily,
  % keywordstyle=\bfseries,
  keywordstyle={\bfseries},
  morekeywords={begin, end, if, then, else, match, fun, function, let, rec, and}
  deletekeywords=value
  upquote=true,
  commentstyle=,
  breaklines=false,
  showstringspaces=false,
  stringstyle=\color{blue},
  literate={'"'}{\textquotesingle "\textquotesingle}3
 }
]]></fr:resource-source><fr:resource-source type="latex" part="body"><![CDATA[
   \begin{lstlisting}{ObjectiveCaml}
   
module Mcts =
struct
  type _ tree =
    | Choices : {
        bandit : Int_bandit.t;
        choices : 'a array;
        subtrees : 'b tree Lazy.t;
      } -> 'b tree
    | Reward : {
        reward : float;
        subtree : unit -> 'a tree
      } -> 'a tree
    | Return : 'a -> 'a tree

  type 'a codensity = {
    call : 'b. ('a -> 'b tree) -> 'b tree
  }

  let init_choices choices k =
    let subtrees =
        Array.map (fun c -> Lazy.from_fun (fun () -> k c)) choices
    in
    let arity = Array.length choices in
    Choices { bandit = Int_bandit.init arity; choices; subtrees }

  let choices arr = ...
  let reward r =
    { call = (fun k -> Reward { reward = r; subtree = ka })}
  let bind m f = ...
  let return x = ...
  let run_codensity = ...
end

   \end{lstlisting}
  ]]></fr:resource-source></fr:resource>


MCTS explores such trees by iterating the following three phases:

<html:ol><html:li><html:strong>selection</html:strong>: starting at the root, recursively let bandit select actions until an unexplored subtree is encountered;</html:li>
<html:li><html:strong>rollout</html:strong>: Monte Carlo estimation of the reward associated to the chosen actions</html:li>
<html:li><html:strong>backup</html:strong>: assign reward estimate to bandits</html:li></html:ol>

MCTS does not prescribe when to stop iterating these three phases: one may for instance inspect how the internal statistics of the bandits evolve and decide to stop when their reward estimate is good enough.

An example might clarify what these three phases are.
</html:p>
                <fr:tree show-metadata="false">
                  <fr:frontmatter>
                    <fr:authors />
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>7</fr:month>
                      <fr:day>14</fr:day>
                    </fr:date>
                    <fr:uri>http://localhost/000H/</fr:uri>
                    <fr:display-uri>000H</fr:display-uri>
                    <fr:route>/000H/</fr:route>
                    <fr:title text="MCTS exploration">MCTS exploration</fr:title>
                    <fr:taxon>Example</fr:taxon>
                  </fr:frontmatter>
                  <fr:mainmatter><html:p>We consider a simple example of <fr:link href="/000F/" title="Markov decision processes" uri="http://localhost/000F/" display-uri="000F" type="local">MDP</fr:link> and how it solved by <fr:link href="/000D/" title="Monadic Monte Carlo tree search" uri="http://localhost/000D/" display-uri="000D" type="local">MCTS</fr:link>. We assume given an <fr:link href="/000D/" title="Monadic Monte Carlo tree search" uri="http://localhost/000D/" display-uri="000D" type="local">MCTS</fr:link> implementation of the <fr:link href="/000F/" title="Markov decision processes" uri="http://localhost/000F/" display-uri="000F" type="local"><html:code>MDP</html:code> interface</fr:link>: <html:code>module Mcts : MDP</html:code> and use <html:code>let*</html:code> as a notation for <html:code>Mcts.bind</html:code>.
</html:p>
  <fr:resource hash="70db1b1f258390c0feb080d7033e6efe"><fr:resource-content><html:img src="/70db1b1f258390c0feb080d7033e6efe.svg" /></fr:resource-content><fr:resource-source type="latex" part="preamble"><![CDATA[
  \usepackage{tikz, tikz-cd, mathtools, amssymb, stmaryrd, listings}
 \usepackage[all]{xy}
 \usetikzlibrary{matrix,arrows}
 \usetikzlibrary{backgrounds,fit,positioning,calc,shapes}
 \usetikzlibrary{decorations.pathreplacing}
 \usetikzlibrary{decorations.pathmorphing}
 \usetikzlibrary{decorations.markings}

 \lstset{
  language=[Objective]Caml,
  columns=[c]fixed,
  % basicstyle=\small\ttfamily,
  % keywordstyle=\bfseries,
  keywordstyle={\bfseries},
  morekeywords={begin, end, if, then, else, match, fun, function, let, rec, and}
  deletekeywords=value
  upquote=true,
  commentstyle=,
  breaklines=false,
  showstringspaces=false,
  stringstyle=\color{blue},
  literate={'"'}{\textquotesingle "\textquotesingle}3
 }
]]></fr:resource-source><fr:resource-source type="latex" part="body"><![CDATA[
   \begin{lstlisting}{ObjectiveCaml}
   
let* w = Mcts.choices [|0; 1|] in
let* x = Mcts.choices [|2; 3|] in
let* y = Mcts.choices [|4; 5|] in
let* z = Mcts.choices [|6; 7|] in
let sum = w + x + y + z in
let* () = Mcts.reward (float_of_int sum) in
return sum

   \end{lstlisting}
  ]]></fr:resource-source></fr:resource>
<html:p>The example is set up so that at depth <html:code>0</html:code>, actions are <html:code>0, 1</html:code>; at depth <html:code>1</html:code>, actions are <html:code>2, 3</html:code>, etc. Initially, the tree only contains a root node with unexplored choices corresponding to actions <html:code>0</html:code> and <html:code>1</html:code>. The root node contains a bandit which is <html:code>ready</html:code> to take an action.</html:p>
   
   <html:img width="400px" src="/bafkrmiezq65xjp3ojzsfjpqxubfepbissy7bl2wspzrcaq5knni5snnofy.png" />
<html:p>We enter the <html:strong>selection</html:strong> phase. The bandit at the root selects action <html:code>0</html:code> and enters a <html:code>waiting</html:code> state. The subtree corresponding to this action was not explored: we unfolded a new node, containing a new bandit.</html:p>
   
   <html:img width="400px" src="/bafkrmifvjsvaiemgzsjymnbtk4245q7l7g23mvj67zyglxaiu4lrbaqhgi.png" />
<html:p>Since the subtree was not explored, we switch from the <html:strong>selection</html:strong> to the <html:strong>rollout</html:strong> phase, where we must estimate the reward of the choice performed by the root bandit. In basic MCTS, we randomly explore the tree until a leaf and accumulate the reward on the path. Other value estimation techniques exist, e.g. using a neural network as in AlphaGo.</html:p>
   
   <html:img width="400px" src="/bafkrmierbyshrtl2ken5bpvwkg3q4cngst4rkfeub653hm2yosx2ylq4vy.png" />
<html:p>We got a reward of <html:code>13</html:code>. We enter the <html:strong>backup</html:strong> phase, where we assign the reward to all bandits that took a decision in this round. Since this was the first round, only the bandit at the root gets the reward.</html:p>
   
   <html:img width="400px" src="/bafkrmifcgwpnh6wqtxv2ojyalza5q2uf5urait3xtyk52ti6sqekry2nia.png" />
<html:p>This completes the first round. We move back to a state in which the tree is ready for the next round.</html:p>
   
   <html:img width="400px" src="/bafkrmibgsx7y6jwxk5a67mjzmntok5u5ggriejdc5x2hzwvifmy5kn23c4.png" />
<html:p>The next animation displays the next two phases.</html:p>
   
   <html:img width="400px" src="/bafkrmih2qrfzao5qnqkub7ngwrp4qt3sbtnlokokpo4lebu2ts5eenu3wi.gif" />
</fr:mainmatter>
                </fr:tree>
              </fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="true" expanded="false" toc="false" numbered="false">
              <fr:frontmatter>
                <fr:authors />
                <fr:date>
                  <fr:year>2021</fr:year>
                  <fr:month>1</fr:month>
                  <fr:day>24</fr:day>
                </fr:date>
                <fr:uri>http://localhost/000S/</fr:uri>
                <fr:display-uri>000S</fr:display-uri>
                <fr:route>/000S/</fr:route>
                <fr:title text="Automatic differentiation">Automatic differentiation</fr:title>
                <fr:taxon>article</fr:taxon>
              </fr:frontmatter>
              <fr:mainmatter>
                <fr:tree show-metadata="false">
                  <fr:frontmatter>
                    <fr:authors />
                    <fr:date>
                      <fr:year>2021</fr:year>
                      <fr:month>1</fr:month>
                      <fr:day>24</fr:day>
                    </fr:date>
                    <fr:title text="Composing jacobians">Composing jacobians</fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>
Given a (sufficiently differentiable, etc) function <fr:tex display="inline"><![CDATA[f : \mathbb {R}^m \rightarrow  \mathbb {R}^n]]></fr:tex>, its jacobian has the following type:
<fr:tex display="block"><![CDATA[
J(f) : \mathbb {R}^m \rightarrow  Lin(\mathbb {R}^m,\mathbb {R}^n)
]]></fr:tex>
where <fr:tex display="inline"><![CDATA[Lin(A,B)]]></fr:tex> denotes the space of linear maps (matrices) from <fr:tex display="inline"><![CDATA[A]]></fr:tex> to <fr:tex display="inline"><![CDATA[B]]></fr:tex>.

The goal of AD is to compute (exactly) the jacobian matrix of a function explicitly
constructed as a composition of functions with known jacobians.

The chain rule for jacobians gives us a neat formula for sequential composition:
given <fr:tex display="inline"><![CDATA[g : \mathbb {R}^l \rightarrow  \mathbb {R}^m]]></fr:tex>, <fr:tex display="inline"><![CDATA[f : \mathbb {R}^m \rightarrow  \mathbb {R}^n]]></fr:tex>, we have
<fr:tex display="block"><![CDATA[
J(f \circ  g) = x \mapsto  J(f)(g(x)) J(g)(x)
]]></fr:tex>
Nothing special so far. Note that in order to evaluate the jacobians along the chain,
we need first to evaluate <fr:tex display="inline"><![CDATA[g(x)]]></fr:tex> and <fr:tex display="inline"><![CDATA[f (g (x))]]></fr:tex>. We could stop here
and we would have a correct algorithm for computing jacobians.
</html:p>
                    <html:p>
The <html:em>real</html:em> point of AD however is to take advantage of the sparsity of some
of these jacobians. This sparsity arises when we consider parallel composition
of functions, as obtained by taking eg <fr:tex display="inline"><![CDATA[f : \mathbb {R}^m \rightarrow  \mathbb {R}^{m'}]]></fr:tex> <fr:tex display="inline"><![CDATA[g : \mathbb {R}^n \rightarrow  \mathbb {R}^{n'}]]></fr:tex>
to the function <fr:tex display="inline"><![CDATA[\langle  f, g\rangle  : \mathbb {R}^{m + n} \rightarrow  \mathbb {R}^{m' + n'}]]></fr:tex> with the obvious
definition. The jacobian of this last function has the following shape:
<fr:tex display="block"><![CDATA[
J(\langle  f, g \rangle ) = \left ( \begin {array}{ll} J(f) & 0 \\ 0 & J(g) \end {array} \right )
]]></fr:tex>
We want to take advantage of this sparsity to perform the global jacobian
computation faster. Another instance where sparsity enters the picture is when
data is duplicated. The jacobian of the diagonal operator <fr:tex display="inline"><![CDATA[\Delta _n: \mathbb {R}^n \rightarrow  \mathbb {R}^{n+n}]]></fr:tex>;
defined by <fr:tex display="inline"><![CDATA[\Delta _n : x \mapsto  (x,x)]]></fr:tex>, is
<fr:tex display="block"><![CDATA[
J(\Delta _n)(-) =\left ( \begin {array}{ll} I \\ I \end {array} \right )
]]></fr:tex>
with <fr:tex display="inline"><![CDATA[I]]></fr:tex> the identity matrix.
</html:p>
                    <html:p>
Let's be pendantic about it and rewrite a small example in
pointfree format:
<fr:tex display="block"><![CDATA[
\begin {array}{lll}
  h & : & \mathbb {R} \rightarrow  \mathbb {R} \\
  h(y) & = & sin(y) \times  y + y \times  y \\
  & = & + \circ  \langle  \times  \circ  \langle  sin, id \rangle  \circ  \Delta _1, \times   \circ  \Delta _1 \rangle  \circ  \Delta _1
\end {array}
]]></fr:tex>
Interpreting elements of this decomposition as arrows in a suitable monoidal category
(<html:em>which</html:em> category? is another interesting question) yields the following string
diagram.
</html:p>
                    <html:figure><html:img width="250px" src="/bafkrmiewiv2wc7hjgohigs7rhi427qwo4lholo7em6joer3nclsgs2lth4.png" />
 <html:figcaption>String diagrammatic depiction of <fr:tex display="inline"><![CDATA[h]]></fr:tex></html:figcaption></html:figure>
                    <html:p>
This corresponds to a mathematically grounded notion of <html:em>computational graph</html:em>.
Algorithmic differentiation is typically performed directly on such graphs, where
sparsity is manifest and can be easily taken advantage of.
We're left with two problems:
<html:ul><html:li>generate these graphs from the source expressions (this is not hard);</html:li>
<html:li>perform the jacobian computation taking advantage of the sparsity of the graph.</html:li></html:ul></html:p>
                    <html:p>
The second problem can be stated as follows: given a computational graph, what is the schedule for evaluating
the jacobian that minimizes the amount of work (eg measured in basic arithmetic operations)?
As often with interesting problems, this is NP-complete (see <fr:link href="https://dl.acm.org/doi/10.5555/3114201.3114717" type="external">this paper</fr:link>).
</html:p>
                    <html:p>
Empirically, the functions people want to differentiate map a
high-dimensional domain to a lower-dimensional range (neural networks are
typical in this respect). For these functions, an evaluation strategy that
works well in practice consists in evaluating the product of jacobians
left-to-right. This is sometimes called backpropagation, or reverse-mode AD.
</html:p>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false">
                  <fr:frontmatter>
                    <fr:authors />
                    <fr:date>
                      <fr:year>2021</fr:year>
                      <fr:month>1</fr:month>
                      <fr:day>24</fr:day>
                    </fr:date>
                    <fr:title text="Backpropagation">Backpropagation</fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>
We present backpropagation as an algorithm computing the partial derivatives of a chosen output of the graph
(a DAG really) with respect to all inputs of the graph <html:em>simultaneously</html:em>, by working inductively on the graph and by case
analysis on the kind of nodes. We distinguish two such kinds:
<html:ul><html:li>nodes with <html:em>fan-out</html:em>, which map one input to several outputs
  (in our syntax this corresponds just to <fr:tex display="inline"><![CDATA[\Delta ]]></fr:tex> nodes);</html:li>
<html:li>nodes with <html:em>fan-in</html:em>, which map several inputs to one output.</html:li></html:ul></html:p>
                    <html:p>
We assume that the graph has been evaluated forward, ie
each node is associated to an evaluated jacobian matrix at the point of interest.
We will thus abuse notation and let <fr:tex display="inline"><![CDATA[J(f)]]></fr:tex> denote <fr:tex display="inline"><![CDATA[J(f)(x)]]></fr:tex>, leaving
the evaluation point <fr:tex display="inline"><![CDATA[x]]></fr:tex> implicit.
</html:p>
                    <html:p>
The state of the algorithm at each step consists, for the node under consideration,
of partial derivatives of the chosen "global" output with respect to the each
output of the node (i.e. outgoing edges of the node).
</html:p>
                    <html:p>
The dotted edges in the illustrative diagrams below hint at the fact that each
considered graph may be embedded in a larger one.
</html:p>
                    <html:p><html:strong>Base step.</html:strong> The initial step is to consider the output edge with respect to which we wish
to differentiate the inputs of the graph. This corresponds to some ``dangling''
edge of some arbitrary node.

<html:figure><html:img width="70px" src="/bafkrmih4muaeum5vhi2u65fuh4xr7re3galnxw6ud2ixc6uoveax2c6qem.png" />
 <html:figcaption>A dangling edge</html:figcaption></html:figure>
We must assign to this edge the partial derivative of the output with respect to <fr:tex display="inline"><![CDATA[\ldots ]]></fr:tex> itself, ie the <fr:tex display="inline"><![CDATA[n \times  n]]></fr:tex> identity matrix.
</html:p>
                    <html:p><html:strong>Nodes with fan-in.</html:strong> We consider the case of a node with fan-in as depicted below
(the dimensions have been indicated on the edges). This diagram represents
a node <fr:tex display="inline"><![CDATA[h]]></fr:tex> with two inputs from nodes <fr:tex display="inline"><![CDATA[f]]></fr:tex>and <fr:tex display="inline"><![CDATA[g]]></fr:tex>. The boxed node <fr:tex display="inline"><![CDATA[G]]></fr:tex> represents an
arbitrary subgraph that is connected to <fr:tex display="inline"><![CDATA[h]]></fr:tex>. <fr:tex display="inline"><![CDATA[G]]></fr:tex> has a terminal output of dimension
<fr:tex display="inline"><![CDATA[o]]></fr:tex>.
</html:p>
                    <html:figure><html:img width="250px" src="/bafkrmifw7mu53zjfjxyczreibgfvcmtl7bqdj6kdm62tsor4v3isp4cluy.png" />
 <html:figcaption>A node with fan-in</html:figcaption></html:figure>
                    <html:p>
Our <html:em>induction hypothesis</html:em> is that <fr:tex display="inline"><![CDATA[J(G)]]></fr:tex> has been computed, ie we have
the partial derivatives of <fr:tex display="inline"><![CDATA[G]]></fr:tex> with respect to the <html:em>output</html:em> of <fr:tex display="inline"><![CDATA[h]]></fr:tex>.
We want to compute the partial derivatives of <fr:tex display="inline"><![CDATA[h \circ  G]]></fr:tex>
with respect to the outputs of the direct ancestors of <fr:tex display="inline"><![CDATA[h]]></fr:tex>, namely <fr:tex display="inline"><![CDATA[f]]></fr:tex> and <fr:tex display="inline"><![CDATA[g]]></fr:tex>.

That's straightforward: simply compute <fr:tex display="inline"><![CDATA[A_h = J(h) J(G)]]></fr:tex>. <fr:tex display="inline"><![CDATA[A_h]]></fr:tex> is a matrix with
<fr:tex display="inline"><![CDATA[\ell  + n]]></fr:tex> columns: the first <fr:tex display="inline"><![CDATA[\ell ]]></fr:tex> columns correspond to the partial derivatives
of <fr:tex display="inline"><![CDATA[h \circ  G]]></fr:tex> with respect to the output of <fr:tex display="inline"><![CDATA[f]]></fr:tex> and the last <fr:tex display="inline"><![CDATA[n]]></fr:tex> columns are
the counterpart for <fr:tex display="inline"><![CDATA[g]]></fr:tex>.
</html:p>
                    <html:p><html:strong>Nodes with fan-out.</html:strong> It remains to consider the case of the <fr:tex display="inline"><![CDATA[\Delta ]]></fr:tex> nodes.
Let's take the simple case of a node <fr:tex display="inline"><![CDATA[\Delta _n : \mathbb {R}^n \rightarrow  \mathbb {R}^{n+n}]]></fr:tex>.
</html:p>
                    <html:figure><html:img height="250px" src="/bafkrmic5vusmws4xwwlljzuejecdnowh2hx5s3foihm3exv6onijr45eka.png" />
 <html:figcaption>A node with fan-out</html:figcaption></html:figure>
                    <html:p>
By induction hypothesis, we have the partial derivatives of <fr:tex display="inline"><![CDATA[G]]></fr:tex> with respect
to each outgoing edge of <fr:tex display="inline"><![CDATA[\Delta ]]></fr:tex>: concretely, the first outgoing edge
is associated to the <fr:tex display="inline"><![CDATA[n]]></fr:tex> first columns of <fr:tex display="inline"><![CDATA[J(G)]]></fr:tex> and the second outgoing edge
to the <fr:tex display="inline"><![CDATA[n]]></fr:tex> last columns of <fr:tex display="inline"><![CDATA[J(G)]]></fr:tex>.
</html:p>
                    <html:p>
Looking at the definition of <fr:tex display="inline"><![CDATA[J(\Delta _n)]]></fr:tex>, one obtains that the partial
derivative of the the composition of <fr:tex display="inline"><![CDATA[\Delta _n]]></fr:tex> with <fr:tex display="inline"><![CDATA[G]]></fr:tex> is obtained
as the <html:em>sum</html:em> of the <fr:tex display="inline"><![CDATA[n]]></fr:tex> first columns of <fr:tex display="inline"><![CDATA[J(G)]]></fr:tex> with the <fr:tex display="inline"><![CDATA[n]]></fr:tex> last
columns of <fr:tex display="inline"><![CDATA[J(G)]]></fr:tex>.
</html:p>
                    <html:p>
We notice something interesting: in order to evaluate a <fr:tex display="inline"><![CDATA[\Delta _n]]></fr:tex> node,
we <html:strong>must</html:strong> evaluate all its children! These acts as "rendez-vous" points
during the backpropagation procedure.
</html:p>
                    <html:p><html:strong>That's it!?</html:strong>

The algorithm above is quite simple but contains the essence of backpropagation.
Still, there's a big gap between this description and a practical implementation.
Let's name a few.
<html:ul><html:li>In practice, the <fr:tex display="inline"><![CDATA[\Delta _n]]></fr:tex> nodes need not be explicitly represented
  in the graph. Nodes have a fan-in and a fan-out. This makes it slightly
  more complicated to schedule node evaluation: one needs to proceed in
  reverse topological order to ensure that each node is evaluated
  only once, and only when all its successors have been evaluated.</html:li>
<html:li>Some practical details matter for performance: for nodes with
  fan-out <fr:tex display="inline"><![CDATA[> 1]]></fr:tex>, one can sum the contributions of their successors into
  an accumliator that needs to be allocated only once. This yields an
  algorithm that is rather imperative in nature but quite efficient.</html:li>
<html:li>There's value in making the computation incremental,
  ie reevaluate functions and jacobians as lazily as reasonably possible.
  This allows eg recomputing gradients efficiently when only changing
  part of a high-dimensional input.</html:li></html:ul></html:p>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false">
                  <fr:frontmatter>
                    <fr:authors />
                    <fr:date>
                      <fr:year>2021</fr:year>
                      <fr:month>1</fr:month>
                      <fr:day>24</fr:day>
                    </fr:date>
                    <fr:title text="Toy implementation">Toy implementation</fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
  
  
  
  

<html:p>
A toy implementation of the above is not so long to write,
let's give it a try.

We must start with some fairly boring linear algebra.
</html:p>

<html:p><html:pre>(* Matrices in column-major format.
   n.b.: [float array array] is not a very
   good datatype for matrices. *)
type matrix = { c : int; r : int; data : float array array }
type vector = float array

(* Basic accessors *)
let cols m = m.c
let rows m = m.r

(* Creating matrices. *)
let empty () = { c = 0; r = 0; data = [||] }
let zeros ~c ~r = { c; r; data = Array.make_matrix c r 0.0 }
let identity n =
  let id = Array.make_matrix n n 0. in
  for i = 0 to n - 1 do
    id.(i).(i) &lt;- 1.
  done ;
  { c = n; r = n; data = id }

(* pointwise matrix addition *)
let matrix_add m1 m2 =
  { c = m1.c; r = m1.r;
    data = Array.map2 (Array.map2 ( +. )) m1.data m2.data }

(* Matrix multiplication *)
let mm m1 m2 =
  assert (cols m1 = rows m2) ;
  let result = Array.make_matrix (cols m2) (rows m1) 0.0 in
  for c = 0 to cols m2 - 1 do
    for r = 0 to rows m1 - 1 do
      let acc = ref 0.0 in
      for k = 0 to cols m1 - 1 do
        acc := !acc +. (m2.data.(c).(k) *. m1.data.(k).(r))
      done ;
      result.(c).(r) &lt;- !acc
    done
  done ;
  let r = rows m1 in
  let c = cols m2 in
  { c; r; data = result }

(* Submatrix of [m] containing the columns in the
   inclusive range [c;c+dim-1]. Columns are indexed from 0. *)
let sub_cols m c dim =
  let data = Array.sub m.data c dim in
  { c = dim; r = m.r; data };;</html:pre><html:pre>type matrix = { c : int; r : int; data : float array array; }
type vector = float array
val cols : matrix -&gt; int = &lt;fun&gt;
val rows : matrix -&gt; int = &lt;fun&gt;
val empty : unit -&gt; matrix = &lt;fun&gt;
val zeros : c:int -&gt; r:int -&gt; matrix = &lt;fun&gt;
val identity : int -&gt; matrix = &lt;fun&gt;
val matrix_add : matrix -&gt; matrix -&gt; matrix = &lt;fun&gt;
val mm : matrix -&gt; matrix -&gt; matrix = &lt;fun&gt;
val sub_cols : matrix -&gt; int -&gt; int -&gt; matrix = &lt;fun&gt;
</html:pre></html:p>

<html:p>
Let's define the type of a node. We'll take the route of nodes with
fan-in and fan-out (so no explicit <fr:tex display="inline"><![CDATA[\Delta ]]></fr:tex>).
</html:p>

<html:p><html:pre>type node =
  { transfer : vector -&gt; vector;  (** Forward evaluation *)
    jacobian : vector -&gt; matrix;  (** Jacobian *)
    mutable value : vector;       (** Current value of the node *)
    mutable accumulator : matrix; (** Accumulator *)
    back : node array;            (** Nodes upstream *)
    uid : int                     (** unique id *)
  };;</html:pre></html:p>

<html:p>
Most fields should be obvious, except <html:code>uid</html:code>.
We will use it to tag nodes so that the following relationship holds:
<html:figure><html:code>n1.uid &lt;= n2.uid</html:code> <fr:tex display="inline"><![CDATA[\Rightarrow ]]></fr:tex> there exists a topological
ordering of the graph where <html:code>n1</html:code> is before <html:code>n2</html:code>.
</html:figure></html:p>

<html:p>
We'll use the following to generate strictly increasing uids.
</html:p>

<html:p><html:pre>let gen =
  let c = ref 0 in
  fun () -&gt;
    let v = !c in
    incr c ;
    v
;;</html:pre><html:pre>val gen : unit -&gt; int = &lt;fun&gt;
</html:pre></html:p>

<html:p>
Let's define a generic function to compose nodes together.
The <html:code>back</html:code> argument corresponds to the nodes on which
the newly created node depends for its inputs.
</html:p>

<html:p><html:pre>let create ~back ~transfer ~jacobian =
  { transfer;
    jacobian;
    value = [||];
    accumulator = empty ();
    back;
    uid = gen ()
  }
;;</html:pre><html:pre>val create :
  back:node array -&gt;
  transfer:(vector -&gt; vector) -&gt; jacobian:(vector -&gt; matrix) -&gt; node = &lt;fun&gt;
</html:pre></html:p>

<html:p>
As a first example, here's how to create a node for
the <fr:tex display="inline"><![CDATA[\sin ]]></fr:tex> function.
</html:p>

<html:p><html:pre>let sin x =
  create
    ~back:[| x |]
    ~transfer:(fun v -&gt; [| sin v.(0) |])
    ~jacobian:(fun v -&gt; { c = 1; r = 1; data = [| [| cos v.(0) |] |] })
;;</html:pre><html:pre>val sin : node -&gt; node = &lt;fun&gt;
</html:pre></html:p>

<html:p>
A graph would be useless without some way to specify its
inputs. We'll do so using the (quite hackish) <html:code>input</html:code> node:
</html:p>

<html:p><html:pre>let input () =
  let value = ref 0.0 in
  let node =
    create
      ~back:[||]
      ~transfer:(fun _v -&gt; [| !value |])
      ~jacobian:(fun v -&gt; zeros ~c:0 ~r:(Array.length v))
  in
  let set x = value := x in
  (node, set)
;;</html:pre><html:pre>val input : unit -&gt; node * (float -&gt; unit) = &lt;fun&gt;
</html:pre></html:p>

<html:p>
This function returns a node and a "setter" function.
Note that the jacobian is empty: it has <fr:tex display="inline"><![CDATA[0]]></fr:tex> columns
(because the <html:code>input</html:code> node has no backward nodes)
but we must still specify that it has the right number of
rows, so that the linear algebra routines are happy.
</html:p>

<html:p>
We'll first implement code to evaluate the graph <html:em>forward</html:em>.
The following helper function gathers all values of the
direct ancestors (elements of <html:code>node.back</html:code>) of
the given node and concatenates them into a vector:
</html:p>

<html:p><html:pre>let get_backward_values node =
  Array.map (fun node -&gt; node.value) node.back
  |&gt; Array.to_list
  |&gt; Array.concat
;;</html:pre><html:pre>val get_backward_values : node -&gt; float array = &lt;fun&gt;
</html:pre></html:p>

<html:p>
Evaluating the graph forward is triggered by querying the
value of a node using the <html:code>eval</html:code> function.
</html:p>

<html:p><html:pre>let rec eval_loop node =
  Array.iter eval_loop node.back ;
  let inputs = get_backward_values node in
  node.value &lt;- node.transfer inputs

let eval node = eval_loop node ; node.value
;;</html:pre><html:pre>val eval_loop : node -&gt; unit = &lt;fun&gt;
val eval : node -&gt; vector = &lt;fun&gt;
</html:pre></html:p>

<html:p>
Upon calling <html:code>eval</html:code>, the auxilliary <html:code>eval_loop</html:code>
function will first evaluate all ancestors recursively. After it
returns, all values of direct ancestors have been recomputed and
the <html:code>node.transfer</html:code> function is called on the now valid
inputs contained in these ancestors.

Let's try our forward evaluation code out:
</html:p>

<html:p><html:pre>(* test forward evaluation for a scalar function *)
let () =
  (* Create graph *)
  let (x, set_x) = input () in
  let graph = sin (sin x) in
  (* Dummy inputs *)
  let inputs = Array.init 100 (fun i -&gt; float_of_int i *. 0.1) in
  (* Assert forward evaluation matches direct-style code *)
  assert (
    Array.for_all
      (fun x -&gt;
        set_x x ;
        let res = eval graph in
        res.(0) = Stdlib.(sin (sin x)))
      inputs ) ;
  Format.printf "Success!@."
;;</html:pre><html:pre>Success!</html:pre></html:p>

<html:p>Let's carry on with differentiation.</html:p>

<html:p>In order to ensure that we process nodes in the good order, we'll
need a form of priority queues. When processing a node, we'll place
its direct ancestors in this queue. Nodes will be taken from the queue
by decreasing uid. The invariant on uids will thus ensure that
a node cannot be processed before all its (transitive) successors
are processed first.</html:p>

<html:p>For nodes with fan-out <fr:tex display="inline"><![CDATA[> 1]]></fr:tex>, this ensures that the accumulator
contains <html:em>all</html:em> jacobian contributions of its direct children.</html:p>

<html:p>We'll use a quick to implement priority queue: a sorted list.</html:p>

<html:p><html:pre>(* List of nodes sorted by decreasing uid *)
let rec insert x l =
  match l with
  | [] -&gt; [x]
  | y :: tl -&gt;
      if y.uid = x.uid then l
      else if y.uid &gt; x.uid then y :: insert x tl
      else x :: l
;;</html:pre><html:pre>val insert : node -&gt; node list -&gt; node list = &lt;fun&gt;
</html:pre></html:p>

<html:p>
We can now implement backpropagation. The algorithm takes
as parameter a node corresponding to the <html:code>output</html:code> variable,
with respect to which all partial derivatives at the roots will
be computed (these roots corresponding to <html:code>input</html:code> nodes).
</html:p>

<html:p>
The first step is to initialize the graph:
<html:ol><html:li>ensure that all nodes upstream of <html:code>output</html:code> have up-to-date values
  by calling <html:code>eval_loop</html:code>;</html:li>
<html:li>allocate suitably dimensioned accumulators;</html:li>
<html:li>initialize the accumulator of <html:code>output</html:code>
  with the identity matrix.</html:li></html:ol></html:p>

<html:p>
The accumulator at each <html:code>node</html:code> must store the jacobian
corresponding to the downstream part of the graph, which is a function from
the outputs of <html:code>node</html:code> to <html:code>output</html:code>.
The function <html:code>allocate_accumulators</html:code> takes care of
recursively initializing all accumulators of nodes upstream of <html:code>output</html:code>.
</html:p>

<html:p><html:pre>let rec allocate_accumulators node output_dim =
  node.accumulator &lt;- zeros ~c:(Array.length node.value) ~r:output_dim ;
  Array.iter (fun node -&gt;
     allocate_accumulators node output_dim) node.back
;;</html:pre><html:pre>val allocate_accumulators : node -&gt; int -&gt; unit = &lt;fun&gt;
</html:pre></html:p>

<html:p>
We can now move to the core loop of backpropagation. At this point,
most of it has already been explaind: no point in commenting further.
</html:p>

<html:p><html:pre>let rec backprop_loop node prioqueue =
  let ja = node.jacobian (get_backward_values node) in
  let acc = node.accumulator in
  let start_col = ref 0 in
  let queue = ref prioqueue in
  for i = 0 to Array.length node.back - 1 do
    let back = node.back.(i) in
    let odim = Array.length back.value in
    (* Accumulate slice of the product in [back] *)
    let prod = mm acc (sub_cols ja !start_col odim) in
    back.accumulator &lt;- matrix_add back.accumulator prod ;
    queue := insert back !queue ;
    start_col := !start_col + odim
  done ;
  backprop_queue !queue

and backprop_queue prioqueue =
  match prioqueue with [] -&gt; () | node :: tl -&gt; backprop_loop node tl
;;</html:pre><html:pre>val backprop_loop : node -&gt; node list -&gt; unit = &lt;fun&gt;
val backprop_queue : node list -&gt; unit = &lt;fun&gt;
</html:pre></html:p>

<html:p>
The entrypoint for backpropagation proceeds to the initialization,
as described above, before calling the loop with an empty queue.
</html:p>

<html:p><html:pre>let backprop node =
  eval_loop node ;
  let output_dim = Array.length node.value in
  allocate_accumulators node output_dim ;
  node.accumulator &lt;- identity output_dim ;
  backprop_loop node []
;;</html:pre><html:pre>val backprop : node -&gt; unit = &lt;fun&gt;
</html:pre></html:p>

<html:p>
Finally! Let's try it out on a simple example:
</html:p>

<html:p><html:pre>(* test backward evaluation for a scalar function *)
let () =
  let (var, set_var) = input () in
  let graph = sin (sin var) in
  let inputs = Array.init 100 (fun i -&gt; float_of_int i *. 0.1) in
  assert (
    Array.for_all
      (fun x -&gt;
        set_var x ;
        backprop graph ;
        let derivative = var.accumulator.data.(0).(0) in
        derivative = Stdlib.(cos x *. cos (sin x)))
      inputs ) ;
  Format.printf "Success!@."
;;</html:pre><html:pre></html:pre><html:pre>Success!</html:pre></html:p>

<html:p>
let's try a more
complicated example. We'll need some more node constructors:
</html:p>

<html:p><html:pre>let ( + ) x y =
  create
    ~back:[| x; y |]
    ~transfer:(fun v -&gt; [| v.(0) +. v.(1) |])
    ~jacobian:(fun _v -&gt;
      { c = 2; r = 1; data = [| [| 1.0 |]; [| 1.0 |] |] })

let ( * ) x y =
  create
    ~back:[| x; y |]
    ~transfer:(fun v -&gt; [| v.(0) *. v.(1) |])
    ~jacobian:(fun v -&gt;
      { c = 2; r = 1; data = [| [| v.(1) |]; [| v.(0) |] |] })

let pair x y =
  create
    ~back:[| x; y |]
    ~transfer:(fun v -&gt; [| v.(0); v.(1) |])
    ~jacobian:(fun _v -&gt;
      { c = 2; r = 2; data = [| [| 1.; 0.0 |]; [| 0.0; 1.0 |] |] })
;;</html:pre><html:pre>val ( + ) : node -&gt; node -&gt; node = &lt;fun&gt;
val ( * ) : node -&gt; node -&gt; node = &lt;fun&gt;
val pair : node -&gt; node -&gt; node = &lt;fun&gt;
</html:pre></html:p>

<html:p>
Now, for the final example: I crafted a function from <fr:tex display="inline"><![CDATA[\mathbb {R}^2]]></fr:tex> to
<fr:tex display="inline"><![CDATA[\mathbb {R}^2]]></fr:tex> and I compared the outcome of our algorithm with
a symbolic solution painstakingly copied from Wolfram alpha.
</html:p>

<html:p><html:pre>let approx_eq (f1 : float) (f2 : float) = abs_float (f1 -. f2) &lt; 0.0001

let actual_jacobian x y =
  let open Stdlib in (* needed because we shadowed the original defs *)
  [| [| cos ((x +. sin y) *. sin (x *. y))
        *. (sin (x *. y) +. (y *. (x +. sin y) *. cos (x *. y)));
        (y *. y *. sin (x +. sin x))
        +. (x *. y *. y *. (cos x +. 1.) *. cos (x +. sin x))
     |];
     [| cos ((x +. sin y) *. sin (x *. y))
        *. ((x *. (x +. sin y) *. cos (x *. y)) +. (cos y *. sin (x *. y)));
        2. *. x *. y *. sin (x +. sin x)
     |]
  |]

(* test backward evaluation for a vector function *)
let success =
  let (v1, set_v1) = input () in
  let (v2, set_v2) = input () in
  let graph =
    let graph1 = sin ((v1 + sin v2) * sin (v1 * v2)) in
    let graph2 = v1 * v2 * v2 * sin (v1 + sin v1) in
    pair graph1 graph2
  in
  let inputs1 = List.init 100 (fun i -&gt; float_of_int i *. 0.1) in
  let inputs2 = List.init 100 (fun i -&gt; 50. +. (float_of_int i *. 0.1)) in
  List.for_all2
    (fun x y -&gt;
      set_v1 x ;
      set_v2 y ;
      backprop graph ;
      let ja = actual_jacobian x y in
      let dv1_dx = v1.accumulator.data.(0).(0) in
      let dv1_dy = v1.accumulator.data.(0).(1) in
      let dv2_dx = v2.accumulator.data.(0).(0) in
      let dv2_dy = v2.accumulator.data.(0).(1) in
      (approx_eq ja.(0).(0) dv1_dx) &amp;&amp;
      (approx_eq ja.(0).(1) dv1_dy) &amp;&amp;
      (approx_eq ja.(1).(0) dv2_dx) &amp;&amp;
      (approx_eq ja.(1).(1) dv2_dy))
    inputs1
    inputs2
;;</html:pre><html:pre>val approx_eq : float -&gt; float -&gt; bool = &lt;fun&gt;
val actual_jacobian : float -&gt; float -&gt; float array array = &lt;fun&gt;
val success : bool = true
</html:pre></html:p>

<html:p>
That's it!
</html:p></fr:mainmatter>
                </fr:tree>
              </fr:mainmatter>
            </fr:tree>
          </fr:mainmatter>
        </fr:tree>
      </fr:mainmatter>
    </fr:tree>
    <fr:tree show-metadata="false" hidden-when-empty="true">
      <fr:frontmatter>
        <fr:authors />
        <fr:title text="Contributions">Contributions</fr:title>
      </fr:frontmatter>
      <fr:mainmatter />
    </fr:tree>
  </fr:backmatter>
</fr:tree>
