<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Blueberry Wren Thoughts</title>
    <subtitle>The bloggings of Wren</subtitle>
    <link rel="self" type="application/atom+xml" href="https://blueberrywren.dev/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://blueberrywren.dev"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-05-14T00:00:00+00:00</updated>
    <id>https://blueberrywren.dev/atom.xml</id>
    <entry xml:lang="en">
        <title>Flat&#x2F;Non-higher-order construction of ANF via mutable holes</title>
        <published>2026-05-14T00:00:00+00:00</published>
        <updated>2026-05-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/anf-mutable/"/>
        <id>https://blueberrywren.dev/blog/anf-mutable/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/anf-mutable/">&lt;h1 id=&quot;flat-non-higher-order-construction-of-anf-via-mutable-holes&quot;&gt;Flat&#x2F;Non-higher-order  construction of ANF via mutable holes&lt;&#x2F;h1&gt;
&lt;p&gt;This post will describe an algorithm for constructing an ANF&#x2F;similar IR from a functional-like base language with no closure usage,
and with no related excess space requirements. This algorithm is as far as I know not new, and has apparently been known in
imperative compilation for a while. However, I admittedly have no source for this, nor
have I seen it described for functional-like languages.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to Ryan Brewer and rpjohnst for their inspiration on this.&lt;&#x2F;p&gt;
&lt;p&gt;If you are only interested in code, please skip to Implementation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;&#x2F;h2&gt;
&lt;p&gt;First, let us describe our input and output languages. Our input language will look like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;ml &lt;&#x2F;span&gt;&lt;span&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  | Let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;string &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;ml &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;ml
&lt;&#x2F;span&gt;&lt;span&gt;  | Name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;string
&lt;&#x2F;span&gt;&lt;span&gt;  | Int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int
&lt;&#x2F;span&gt;&lt;span&gt;  | Add &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;ml &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;ml
&lt;&#x2F;span&gt;&lt;span&gt;  | Print &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;ml
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is meant to echo some simple functional programming language, and contains all the elements needed to demonstrate the algorithm.&lt;&#x2F;p&gt;
&lt;p&gt;Our output language will look like a lexically-scoped flat ANF-style construction, with all lets at the toplevel.
The goal is to convert from our input &lt;code&gt;ml&lt;&#x2F;code&gt; to this language.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;base &lt;&#x2F;span&gt;&lt;span&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  | Name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;string
&lt;&#x2F;span&gt;&lt;span&gt;  | Add &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;string &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;string
&lt;&#x2F;span&gt;&lt;span&gt;  | Int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int
&lt;&#x2F;span&gt;&lt;span&gt;  | Print &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;string
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;anf &lt;&#x2F;span&gt;&lt;span&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  | Let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;string &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;base &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;anf
&lt;&#x2F;span&gt;&lt;span&gt;  | Done &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;string
&lt;&#x2F;span&gt;&lt;span&gt;  | Hole &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;anf option ref
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The notable addition is the &lt;code&gt;Hole&lt;&#x2F;code&gt; constructor in &lt;code&gt;anf&lt;&#x2F;code&gt;, the purpose of which will be described now.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-premise&quot;&gt;The premise&lt;&#x2F;h2&gt;
&lt;p&gt;Imagine we are trying to convert the term&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;  y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When we arrive at the body of &lt;code&gt;x&lt;&#x2F;code&gt;, we have a conundrum. We need to put the conversion of &lt;code&gt;y&lt;&#x2F;code&gt; before &lt;code&gt;x&lt;&#x2F;code&gt;,
so that using &lt;code&gt;y&lt;&#x2F;code&gt; is well-scoped. Hence, we must convert &lt;code&gt;y&lt;&#x2F;code&gt; before we can continue. How do we use this conversion, though?
&lt;code&gt;x&lt;&#x2F;code&gt;&#x27;s content needs to be put in the &lt;code&gt;anf&lt;&#x2F;code&gt; field of &lt;code&gt;y&lt;&#x2F;code&gt;&#x27;s &lt;code&gt;Let&lt;&#x2F;code&gt;, so it&#x27;s not clear how to both convert &lt;code&gt;y&lt;&#x2F;code&gt; before &lt;code&gt;x&lt;&#x2F;code&gt; and
to use &lt;code&gt;x&lt;&#x2F;code&gt;&#x27;s finished conversion in &lt;code&gt;y&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;One &quot;traditional&quot; method of solving this is via continuations, where &lt;code&gt;y&lt;&#x2F;code&gt; is passed a closure representing &quot;what to do next&quot;, after it
converts its body. We can then put &lt;code&gt;x&lt;&#x2F;code&gt;&#x27;s content in that closure, which will be invoked later. This has two main flaws:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It uses excess space. A conversion of a term will allocate ~2x the memory &quot;needed&quot;; it must allocate for the ANF construction itself, and for the closures needed during the construction.&lt;&#x2F;li&gt;
&lt;li&gt;It is slower, due to the aforementioned closure allocation and application.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This method resolves these.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-algorithm&quot;&gt;The algorithm&lt;&#x2F;h2&gt;
&lt;p&gt;Recall that we left a &lt;code&gt;Hole of anf option ref&lt;&#x2F;code&gt; field in our &lt;code&gt;anf&lt;&#x2F;code&gt; type. I will denote a hole like this: &lt;code&gt;[·]&lt;&#x2F;code&gt;.
The central idea is that our conversion of any given &lt;code&gt;ml&lt;&#x2F;code&gt; fragment will return:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The fragment itself.&lt;&#x2F;li&gt;
&lt;li&gt;A name we can use to refer to what was bound in the fragment (In the conversion of addition&#x2F;similar with nested content, names must be conjured.)&lt;&#x2F;li&gt;
&lt;li&gt;The reference created by the hole, so that it may be filled.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;val &lt;&#x2F;span&gt;&lt;span&gt;convert : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;ml &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;anf &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;string &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;anf option ref&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Consider this simplified example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt; x
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When we convert &lt;code&gt;x&lt;&#x2F;code&gt;, this signals for the conversion of &lt;code&gt;y&lt;&#x2F;code&gt;. There are two steps to converting a &lt;code&gt;let&lt;&#x2F;code&gt; - we
must first convert the &quot;head&quot; (&lt;code&gt;2&lt;&#x2F;code&gt;), and then the &quot;body&quot; (&lt;code&gt;y&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;Converting the &lt;code&gt;head&lt;&#x2F;code&gt; will result in something of form&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in 
&lt;&#x2F;span&gt;&lt;span&gt;[·]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that the hole is left to be filled later. This way, the conversion of &lt;code&gt;y&lt;&#x2F;code&gt;&#x27;s head need know nothing about its environment.
We represent this in code via the &lt;code&gt;Hole&lt;&#x2F;code&gt; constructor, which contains a reference to a fragment that either may be empty (&lt;code&gt;None&lt;&#x2F;code&gt;)
or filled (&lt;code&gt;Some ...&lt;&#x2F;code&gt;).
The conversion of the body can then proceed by first generating the expected addition, binding it to &lt;code&gt;nm&lt;&#x2F;code&gt; so it may be referenced later:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;nm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;[·]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We now need to get this fragment into the proper lexical scope. We can do this by plugging it into the hole left by the conversion of the head:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;[
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;nm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;  [·]
&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, returning this fragment, the name bound (&lt;code&gt;y&lt;&#x2F;code&gt;), and the reference to the inner hole, we can continue converting &lt;code&gt;x&lt;&#x2F;code&gt;;
First, convert the head, using the name returned by the conversion of &lt;code&gt;y&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; nm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;[·]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, the body:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;nm2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;[·]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Plug:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; nm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;[
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;nm2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;  [·]
&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And finally plug it into the hole returned by &lt;code&gt;y&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;[
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;nm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;  [
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; nm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;    [
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;nm2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;      [·]
&lt;&#x2F;span&gt;&lt;span&gt;    ]
&lt;&#x2F;span&gt;&lt;span&gt;  ]
&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We are left with a final hole we can plug with &lt;code&gt;Done&lt;&#x2F;code&gt; to be explicit about the end of a control flow path.
One disadvantage of this strategy is that it does generate many unneeded names. Most of these can be avoided by carefully special
casing certain &lt;code&gt;lets&lt;&#x2F;code&gt;, and the rest can be eliminated via a simple folding pass.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;implementation&quot;&gt;Implementation&lt;&#x2F;h2&gt;
&lt;p&gt;Below is a sample implementation of this algorithm, in OCaml.&lt;&#x2F;p&gt;
&lt;details&gt;
&lt;summary&gt;
  The implementation can be unfolded here.
&lt;&#x2F;summary&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;ml &lt;&#x2F;span&gt;&lt;span&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  | Let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;string &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;ml &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;ml
&lt;&#x2F;span&gt;&lt;span&gt;  | Name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;string
&lt;&#x2F;span&gt;&lt;span&gt;  | Int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int
&lt;&#x2F;span&gt;&lt;span&gt;  | Add &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;ml &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;ml
&lt;&#x2F;span&gt;&lt;span&gt;  | Print &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;ml
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* Suffix with &amp;#39; to dodge OCaml annoyances. *)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;base &lt;&#x2F;span&gt;&lt;span&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  | Name&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;string
&lt;&#x2F;span&gt;&lt;span&gt;  | Add&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;string &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;string
&lt;&#x2F;span&gt;&lt;span&gt;  | Int&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int
&lt;&#x2F;span&gt;&lt;span&gt;  | Print&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;string
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;anf &lt;&#x2F;span&gt;&lt;span&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  | Let&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;string &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;base &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;anf
&lt;&#x2F;span&gt;&lt;span&gt;  | Done&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;string
&lt;&#x2F;span&gt;&lt;span&gt;  | Hole&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;anf option ref
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;fresh_name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;counter &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= ref &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;fun &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    incr counter;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;nm&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span&gt; string_of_int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;counter
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* A helper to make an anf fragment of form
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;   let new_name = base in
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;   [·]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt; *)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;make_let_hole &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;base &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: base&lt;&#x2F;span&gt;&lt;span&gt;) : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;(anf * string * anf option ref) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; fresh_name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;r &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= ref &lt;&#x2F;span&gt;&lt;span&gt;None &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;  (Let&amp;#39; (name, base, Hole&amp;#39; r), name, r)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let rec &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;convert &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;ml &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: ml&lt;&#x2F;span&gt;&lt;span&gt;) : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;(anf * string * anf option ref) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; ml &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;with
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Name &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;nm &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* Bind to a new name, and return.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;                   A case that can be eliminated in most cases.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;                   *)
&lt;&#x2F;span&gt;&lt;span&gt;    make_let_hole (Name&amp;#39; nm)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Int &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;i &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    make_let_hole (Int&amp;#39; i)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Add (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* First, we convert `a` and `b` *)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(a_anf, a_name, a_hole) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; convert a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(b_anf, b_name, b_hole) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; convert b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* We chose a left-to-right evaluation order, so we
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;       want to put `a` before `b`. Hence, plug `b`&amp;#39;s fragment
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;       into the hole provided by `a`.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;       *)
&lt;&#x2F;span&gt;&lt;span&gt;    a_hole &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;:= &lt;&#x2F;span&gt;&lt;span&gt;Some b_anf;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* Then, we need a fragment for the addition itself. *)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(add_anf, add_name, add_hole) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;      make_let_hole (Add&amp;#39; (a_name, b_name))
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* We put this in `b`&amp;#39;s hole. *)
&lt;&#x2F;span&gt;&lt;span&gt;    b_hole &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;:= &lt;&#x2F;span&gt;&lt;span&gt;Some add_anf;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* Finally, we return the whole expression.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;       Everything is contained within `a_anf`.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;       If the user wishes to refer to the result of this conversion,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;       they should use add_name.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;       If they wish to plug something into it,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;       they should use add_hole.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;       *)
&lt;&#x2F;span&gt;&lt;span&gt;    (a_anf, add_name, add_hole)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Print &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;body &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* Print is similar. *)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(body_anf, body_name, body_hole) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; convert body &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(print_anf, print_name, print_hole) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;      make_let_hole (Print&amp;#39; body_name)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;    body_hole &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;:= &lt;&#x2F;span&gt;&lt;span&gt;Some print_anf;
&lt;&#x2F;span&gt;&lt;span&gt;    (body_anf, print_name, print_hole)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Let (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;head&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;body&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(head_anf, head_name, head_hole) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; convert head &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;(body_anf, body_name, body_hole) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; convert body &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* We need to bind this let before body to ensure it is
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;       properly lexically scoped.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;       *)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;let_anf &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;Let&amp;#39; (name, Name&amp;#39; head_name, body_anf) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* Then fill it as expected. *)
&lt;&#x2F;span&gt;&lt;span&gt;    head_hole &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;:= &lt;&#x2F;span&gt;&lt;span&gt;Some let_anf;
&lt;&#x2F;span&gt;&lt;span&gt;    (head_anf, body_name, body_hole)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;details&gt;
&lt;p&gt;I recommend toying with the conversion yourself, using &lt;code&gt;utop&lt;&#x2F;code&gt; or similar.
In the following, I will &quot;clean up&quot; the output slightly, as to not make it unreadable.&lt;&#x2F;p&gt;
&lt;p&gt;If we use our first example term:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span&gt;utop # &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;term &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;Let(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;x&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, Let(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;y&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, Int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, Add (Name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;y&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, Int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)), Add (Name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;x&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, Int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;));;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;val &lt;&#x2F;span&gt;&lt;span&gt;term : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;ml &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  Let (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;&amp;quot;x&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, Let (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;&amp;quot;y&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, Int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, Add (Name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;&amp;quot;y&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, Int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)), Add (Name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;&amp;quot;x&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, Int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;utop # convert term;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* Cleaned up: *)
&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;nm1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; nm1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;nm2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;nm3 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;nm4 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; nm2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt; nm3 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; nm4 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;nm5 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;nm6 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;3 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;nm7 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; nm5 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt; nm6 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;Hole [·]
&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;nm7&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;empty reference&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can then plug the returned hole, as described.
Via some inspection, we can verify this is indeed correct, and conforms to our ANF-like form, as expected.&lt;&#x2F;p&gt;
&lt;p&gt;As mentioned earlier, the large amount of duplicate names can be mitigated through strategies such as
special casing &lt;code&gt;let _ = &amp;lt;direct base&amp;gt;&lt;&#x2F;code&gt; and folding passes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;properties&quot;&gt;Properties&lt;&#x2F;h2&gt;
&lt;p&gt;Clearly, the algorithm does not use closures, or any indirect jumps. It does not allocate any more than needed for the representation of
the output program; there is no excessive closure allocation. I do not currently have a good way to test performance on real-world large inputs,
but I have no reason to believe it would not perform better than an equivalent higher-order version.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;future-work&quot;&gt;Future work&lt;&#x2F;h2&gt;
&lt;p&gt;I believe this method should be extendable to CPS as well, although I have not tried as of the moment. The &quot;usual&quot; higher-order CPS
conversion described in e.g. &quot;Compiling with continuations, continued&quot; looks quite similar to the higher-order presentation
of ANF conversion, so I would be interested in whether it can be similarly massaged into a mutable form.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Type safe interpreters</title>
        <published>2026-01-17T00:00:00+00:00</published>
        <updated>2026-01-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/type-safe-interpreters/"/>
        <id>https://blueberrywren.dev/blog/type-safe-interpreters/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/type-safe-interpreters/">&lt;p&gt;It is well known that most software has bugs&lt;sup&gt;&lt;i&gt;[Citation needed]&lt;&#x2F;i&gt;&lt;&#x2F;sup&gt;.
It is also well known that interpreters are mostly software&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. One issue that one might
run into in an interpreter is &lt;em&gt;type safety&lt;&#x2F;em&gt;: It may very well be possible for your
typed language&#x27;s interpreter to nevertheless end up in a state where it is asked
to evaluate &lt;code&gt;1 + &quot;hi!&quot;&lt;&#x2F;code&gt;. What can we do about that?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gadts-generalized-adts&quot;&gt;GADTs: Generalized ADTs&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;GADTs are a technique for increasing type safety in a program, by &quot;indexing&quot; a constructor by a type.
One of the canonical examples for this is an &lt;code&gt;Option&lt;&#x2F;code&gt;-like. Imagine we wanted a type-safe way to ensure
that in some cases, we could always extract the value inside. One way of doing this is to add an extra
type parameter, and use that to mark whether something is inside. We will use OCaml for this demonstration.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* Dummy constructors; we are only using these for their types *)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;yes &lt;&#x2F;span&gt;&lt;span&gt;= Yes
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;no &lt;&#x2F;span&gt;&lt;span&gt;= No
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;(_, _) maybe &lt;&#x2F;span&gt;&lt;span&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;      |  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^ &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;regular &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;&amp;quot;information inside&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^ &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;marker &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;whether the information exists 
&lt;&#x2F;span&gt;&lt;span&gt;  | Nothing : (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;no&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;maybe
&lt;&#x2F;span&gt;&lt;span&gt;  | Just : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;yes&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;maybe
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that we have used a different syntax than usual. Normally, we put a type parameter in the constructor,
like &lt;code&gt;type &#x27;a list&lt;&#x2F;code&gt;, and then use that throughout (&lt;code&gt;&#x27;a * &#x27;a list&lt;&#x2F;code&gt;). However, as we are changing that type
in the &quot;return&quot; of the constructor, we need a syntax that allows us to change that. &lt;code&gt;_&lt;&#x2F;code&gt; marks a type parameter
we &quot;don&#x27;t need to name&quot; (as we always specify it), and in this case, we always specify both. Then, we
add our elements before a &lt;code&gt;-&amp;gt;&lt;&#x2F;code&gt;, mimicking a function. The general form of this in OCaml is &lt;code&gt;t1 * t2 * ... * tn -&amp;gt; t&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now, if we have something of type &lt;code&gt;(yes, &#x27;a) maybe&lt;&#x2F;code&gt;, we know it contains a value! The only other way a &lt;code&gt;maybe&lt;&#x2F;code&gt; can be
formed is via &lt;code&gt;Nothing&lt;&#x2F;code&gt;, but that gives it type &lt;code&gt;(no, &#x27;a) maybe&lt;&#x2F;code&gt;, so it&#x27;d be type-incorrect. This means we
can write a function like&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;get &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: (yes, &amp;#39;a) maybe&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;with
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Just &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; a
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and have it be total; there is no missing case, because the missing case is a type error. Note that when writing a
function like &lt;code&gt;or_else : (_, &#x27;a) maybe -&amp;gt; &#x27;a -&amp;gt; &#x27;a&lt;&#x2F;code&gt;, we need to use this interesting piece of syntax:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;or_else &lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;type m. (m, &amp;#39;a) maybe -&amp;gt; &amp;#39;a -&amp;gt; &amp;#39;a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= fun &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;x def &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;with
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Just &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; a
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Nothing -&amp;gt; def
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is as otherwise OCaml&#x27;s normal type inference can get in our way and infer the wrong type, leading to a type error.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-4-1&quot;&gt;&lt;a href=&quot;#fn-4&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;type-safe-interpreters&quot;&gt;Type safe interpreters&lt;&#x2F;h2&gt;
&lt;p&gt;How does this allow us to get a more type-safe interpreter, though? Well, let&#x27;s start by introducing our expression
type:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;_ expr &lt;&#x2F;span&gt;&lt;span&gt;=
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We&#x27;ve added space for a type parameter. What should integers and booleans look like? Maybe we should paramaterize our expressions
by the type they &quot;evaluate to&quot; - that way, when we have a &lt;code&gt;&#x27;a expr&lt;&#x2F;code&gt;, we know that it&#x27;ll evaluate to something
of type &lt;code&gt;&#x27;a&lt;&#x2F;code&gt;. Hence:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Lit : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; expr
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Bool : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt; expr
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, we want to add a case for &lt;code&gt;Add&lt;&#x2F;code&gt; and &lt;code&gt;Negate&lt;&#x2F;code&gt;. Naturally, we shouldn&#x27;t be able to add two booleans, so let&#x27;s restrict it
to only taking in &lt;code&gt;int expr&lt;&#x2F;code&gt;s, and similar for negate. We also know that these should return integers, too.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Add : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; expr
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Negate : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; expr
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We&#x27;ve already added type safety! It&#x27;s impossible to write &lt;code&gt;Add (Bool true, Lit 5)&lt;&#x2F;code&gt;, because &lt;code&gt;Add&lt;&#x2F;code&gt; expects a &lt;code&gt;int expr&lt;&#x2F;code&gt;,
but &lt;code&gt;Bool true&lt;&#x2F;code&gt; is a &lt;code&gt;bool expr&lt;&#x2F;code&gt;. Let&#x27;s keep going: &lt;code&gt;&amp;lt;=&lt;&#x2F;code&gt; (or &lt;code&gt;Leq&lt;&#x2F;code&gt;) should take two integers and return a boolean,
and &lt;code&gt;If&lt;&#x2F;code&gt; should take a boolean as its first argument, but anything for its second and third.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Leq : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt; expr
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;If : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &amp;#39;a expr
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that we can still use generic parameters, like &lt;code&gt;&#x27;a&lt;&#x2F;code&gt; here - we just need to think about when it makes sense to do so,
to get the type safety we want.&lt;&#x2F;p&gt;
&lt;p&gt;Now for functions. What should a function look like here? One way of implementing them is with a &quot;Higher-order abstract syntax&quot;(HOAS)&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; approach,
where we use the functions of the host language to make functions in the interpreted language. In that case, we should
take a function as the argument to our constructor, but when what is our result type? That function type! We&#x27;ll
need to know it later to safely write &lt;code&gt;Apply&lt;&#x2F;code&gt;, so we &quot;store&quot; it in the type now. We also want the function
to take and return an &lt;code&gt;_ expr&lt;&#x2F;code&gt;, so we can do constructions like &lt;code&gt;Lam (fun x -&amp;gt; Add(x,x))&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Lam : (&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a expr&lt;&#x2F;span&gt;&lt;span&gt; -&amp;gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b expr&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (&amp;#39;a expr -&amp;gt; &amp;#39;b expr) expr
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that the function is not an &lt;code&gt;expr&lt;&#x2F;code&gt; at first, as otherwise we would have no way to construct it in the first
place. (Remember, this is how we make functions.)&lt;&#x2F;p&gt;
&lt;p&gt;Then &lt;code&gt;Apply&lt;&#x2F;code&gt;. It should take in a function, and a value, and then return the function applied to the value.
This hence translates as:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Apply : (&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a expr&lt;&#x2F;span&gt;&lt;span&gt; -&amp;gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b expr&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a expr&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &amp;#39;b expr
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As a finale, we&#x27;ll add pairs and projections. I won&#x27;t elaborate on these, hoping that it&#x27;s becoming obvious how
they work.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Pair : &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; (&amp;#39;a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;b) expr
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Fst : (&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt; * &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &amp;#39;a expr
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Snd : (&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt; * &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &amp;#39;b expr
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;details&gt;&lt;summary&gt;All of the above in one code block&lt;&#x2F;summary&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;_ expr &lt;&#x2F;span&gt;&lt;span&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  | Lit : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int expr
&lt;&#x2F;span&gt;&lt;span&gt;  | Bool : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;bool expr
&lt;&#x2F;span&gt;&lt;span&gt;  | Add : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int expr
&lt;&#x2F;span&gt;&lt;span&gt;  | Negate : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int expr
&lt;&#x2F;span&gt;&lt;span&gt;  | Leq : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;bool expr
&lt;&#x2F;span&gt;&lt;span&gt;  | If : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;bool expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a expr
&lt;&#x2F;span&gt;&lt;span&gt;  | Lam : (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;b expr&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;b expr&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;expr
&lt;&#x2F;span&gt;&lt;span&gt;  | Apply : (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;b expr&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;b expr
&lt;&#x2F;span&gt;&lt;span&gt;  | Pair : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;b expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;b&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;expr
&lt;&#x2F;span&gt;&lt;span&gt;  | Fst : (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;b&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a expr
&lt;&#x2F;span&gt;&lt;span&gt;  | Snd : (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;b&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;b expr
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;details&gt;
&lt;h2 id=&quot;examples&quot;&gt;Examples&lt;&#x2F;h2&gt;
&lt;p&gt;Now let&#x27;s look at some examples and their types.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span&gt;utop # Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;utop # Bool &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt; expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;Bool &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;utop # Add (Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;, Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;);;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;Add (Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;, Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;utop # Lam (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;fun &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;f &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; f);;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; : (&amp;#39;a expr -&amp;gt; &amp;#39;a expr) expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;Lam &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;fun&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;utop # Apply (Lam (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;fun &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;x &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; Add(x,x)), Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;);;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;Apply (Lam &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;fun&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;, Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;utop # Lam (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;fun &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; If (b, Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;, Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;));;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; : (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt; expr -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; expr) expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;Lam &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;fun&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We have that a construction like &lt;code&gt;Lam (fun b -&amp;gt; If (b, b, Lit 6))&lt;&#x2F;code&gt; is not just an error, but a &lt;em&gt;type error&lt;&#x2F;em&gt;!
This means it&#x27;s caught at compile time!&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span&gt;utop # Lam (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;fun &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; If (b, b, Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;));;
&lt;&#x2F;span&gt;&lt;span&gt;                               &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^^^^^
&lt;&#x2F;span&gt;&lt;span&gt;Error: This constructor has &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; expr
&lt;&#x2F;span&gt;&lt;span&gt;       but an expression was expected of &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt; expr
&lt;&#x2F;span&gt;&lt;span&gt;       Type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;not&lt;&#x2F;span&gt;&lt;span&gt; compatible &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;with type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;bool
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;the-actual-evaluator&quot;&gt;The actual evaluator&lt;&#x2F;h2&gt;
&lt;p&gt;From here, the evaluator itself is very simple. We just write the interpretation of our language, as usual:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let rec &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;eval &lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;type t. t expr -&amp;gt; t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= fun &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;x &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;with
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Lit &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; a
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Bool &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; b
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Add (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; eval a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt; eval b
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Negate &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span&gt;(eval a)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Leq (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (eval a) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;lt;= &lt;&#x2F;span&gt;&lt;span&gt;(eval b)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;If (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;cond&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;l&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(eval cond) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;then &lt;&#x2F;span&gt;&lt;span&gt;(eval l) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;(eval r))
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Lam &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;f &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;fun &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;x &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; f x)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Apply (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; eval ((eval f) x)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Pair (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (eval a, eval b)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Fst &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; fst (eval a)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Snd &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; snd (eval a);;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;Lam&lt;&#x2F;code&gt; and &lt;code&gt;Apply&lt;&#x2F;code&gt; cases are interesting. In the former, we need to return a &lt;em&gt;function&lt;&#x2F;em&gt; of type &lt;code&gt;&#x27;a expr -&amp;gt; &#x27;b expr&lt;&#x2F;code&gt;.
We can start by introducing a function &lt;code&gt;fun x -&amp;gt;&lt;&#x2F;code&gt;, but we have &lt;code&gt;f : &#x27;a expr -&amp;gt; &#x27;b expr&lt;&#x2F;code&gt;, so we just apply it.
In the latter, we need to &lt;code&gt;eval f&lt;&#x2F;code&gt; to get a function &lt;code&gt;&#x27;a expr -&amp;gt; &#x27;b expr&lt;&#x2F;code&gt; from &lt;code&gt;f&lt;&#x2F;code&gt;, which is of type
&lt;code&gt;(&#x27;a expr -&amp;gt; &#x27;b expr) expr&lt;&#x2F;code&gt;. We can then pass it &lt;code&gt;x&lt;&#x2F;code&gt;, which is of type &lt;code&gt;&#x27;a expr&lt;&#x2F;code&gt; to get a &lt;code&gt;&#x27;b expr&lt;&#x2F;code&gt;, which
we must then evaluate again to get a &lt;code&gt;&#x27;b&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now we can run the above examples.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span&gt;utop # eval (Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;);;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;utop # eval (Bool &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;);;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;utop # eval (Add (Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;, Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;));;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;9
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;utop # eval (Lam (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;fun &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;f &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; f));;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; : &amp;#39;_weak1 expr -&amp;gt; &amp;#39;_weak1 expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;fun&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* The `_weak1` is due to an internal OCaml limitation, called the &amp;quot;value restriction&amp;quot;. *)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;utop # eval (Apply (Lam (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;fun &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;x &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; Add(x,x)), Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;));;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;10
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;utop # eval (Lam (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;fun &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; If (b, Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;, Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;)), Bool &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;);;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt; expr -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;fun&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* Note that this gives us a function returning `int expr`. We&amp;#39;d need to either use `Apply`, like below,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;   or `eval` to get an `int` out of it.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;*)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;utop # eval (Apply (Lam (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;fun &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; If (b, Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;, Lit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;)), Bool &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;));;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Remember, all of the above is completely type safe! We have succesfully constructed an interpreter that can never
type error.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-do-you-apply-this&quot;&gt;How do you apply this?&lt;&#x2F;h2&gt;
&lt;p&gt;In short, it can be hard. One way is to have a &quot;base&quot; language that&#x27;s parsed, and then have your typechecker produce
a representation like the above that you then know is type correct. However, this does prevent typechecker bugs
from sneaking through, which was our entire goal!&lt;&#x2F;p&gt;
&lt;p&gt;To some extent, this is kicking the bucket down the road - you are now relying that your &quot;host language&quot;&#x27;s typechecker
is correct. However, this is a numbers game; if you&#x27;re writing in OCaml or Haskell or similar, the chances of that
are very very high unless you&#x27;re using extremely weird features.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;aside-denotional-semantics&quot;&gt;Aside: Denotional semantics&lt;&#x2F;h2&gt;
&lt;p&gt;The astute may have noted that this is essentially a version of denotional semantics. We&#x27;re interpreting into the
type-safe domain of the host language to ensure that the types always line up (as they must, for the interpretation
to succeed, and the typechecker of the host language ensures that).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;all-code&quot;&gt;All code&lt;&#x2F;h2&gt;
&lt;details&gt;&lt;summary&gt;All the code in one block, for pasting.&lt;&#x2F;summary&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;_ expr &lt;&#x2F;span&gt;&lt;span&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;  | Lit : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int expr
&lt;&#x2F;span&gt;&lt;span&gt;  | Bool : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;bool expr
&lt;&#x2F;span&gt;&lt;span&gt;  | Add : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int expr
&lt;&#x2F;span&gt;&lt;span&gt;  | Negate : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int expr
&lt;&#x2F;span&gt;&lt;span&gt;  | Leq : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;bool expr
&lt;&#x2F;span&gt;&lt;span&gt;  | If : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;bool expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a expr
&lt;&#x2F;span&gt;&lt;span&gt;  | Lam : (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;b expr&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;b expr&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;expr
&lt;&#x2F;span&gt;&lt;span&gt;  | Apply : (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;b expr&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;b expr
&lt;&#x2F;span&gt;&lt;span&gt;  | Pair : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a expr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;b expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;b&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;expr
&lt;&#x2F;span&gt;&lt;span&gt;  | Fst : (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;b&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a expr
&lt;&#x2F;span&gt;&lt;span&gt;  | Snd : (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;b&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;expr &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;&amp;#39;b expr&lt;&#x2F;span&gt;&lt;span&gt;;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let rec &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;eval &lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;type t. t expr -&amp;gt; t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= fun &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;x &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;with
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Lit &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; a
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Bool &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; b
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Add (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; eval a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt; eval b
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Negate &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span&gt;(eval a)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Leq (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (eval a) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;lt;= &lt;&#x2F;span&gt;&lt;span&gt;(eval b)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;If (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;cond&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;l&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(eval cond) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;then &lt;&#x2F;span&gt;&lt;span&gt;(eval l) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;(eval r))
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Lam &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;f &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;fun &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;x &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; f x)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Apply (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; eval ((eval f) x)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Pair (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; (eval a, eval b)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Fst &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; fst (eval a)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Snd &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; snd (eval a);;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;details&gt;
&lt;footer class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;No, I won&#x27;t do the same joke twice. Most of the time. &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;I am not going into what &quot;ADT&quot; stands for, as it&#x27;s a whole nother debate. &lt;a href=&quot;#fr-2-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-4&quot;&gt;
&lt;p&gt;It may for example eagerly infer &lt;code&gt;(yes, &#x27;a) maybe -&amp;gt; (yes, &#x27;a) maybe&lt;&#x2F;code&gt;, which is a type error, as we also want to handle the &lt;code&gt;(no, &#x27;a) maybe&lt;&#x2F;code&gt; &lt;code&gt;Nothing&lt;&#x2F;code&gt; case. &lt;a href=&quot;#fr-4-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;Higher-order abstract syntax. A bit too in-depth to explore in full right now, but worth exploring. &lt;a href=&quot;#fr-3-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;footer&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Axiom J in Homotopy Type Theory (HoTT)</title>
        <published>2026-01-01T00:00:00+00:00</published>
        <updated>2026-01-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/cubical-j/"/>
        <id>https://blueberrywren.dev/blog/cubical-j/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/cubical-j/">&lt;h2 id=&quot;preface&quot;&gt;Preface&lt;&#x2F;h2&gt;
&lt;p&gt;Happy new years!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;notation&quot;&gt;Notation&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;∀&lt;&#x2F;code&gt; may be used in place of a Pi-type in some cases. A nested &lt;code&gt;Π (a b : A). ...&lt;&#x2F;code&gt; (or sim. for &lt;code&gt;Σ&lt;&#x2F;code&gt;) represents &lt;code&gt;Π (a : A). Π (b : A). ...&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;j&quot;&gt;J&lt;&#x2F;h3&gt;
&lt;p&gt;Axiom J is the following:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;Given:
&lt;&#x2F;span&gt;&lt;span&gt;A : Type
&lt;&#x2F;span&gt;&lt;span&gt;x y : A
&lt;&#x2F;span&gt;&lt;span&gt;P : Π (a b : A). a = b -&amp;gt; Type
&lt;&#x2F;span&gt;&lt;span&gt;with
&lt;&#x2F;span&gt;&lt;span&gt;P x x refl
&lt;&#x2F;span&gt;&lt;span&gt;and
&lt;&#x2F;span&gt;&lt;span&gt;eq : x = y
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;we can conclude
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;P x y eq
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;where &lt;code&gt;refl : ∀x. x = x&lt;&#x2F;code&gt;. In short, for any property &lt;code&gt;P&lt;&#x2F;code&gt;, if &lt;code&gt;P&lt;&#x2F;code&gt; is true for &lt;code&gt;x x refl&lt;&#x2F;code&gt;,
and we know that &lt;code&gt;eq : x = y&lt;&#x2F;code&gt;, then &lt;code&gt;P&lt;&#x2F;code&gt; is true for &lt;code&gt;x y eq&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In a non-cubical context, this is obvious - the only proof of &lt;code&gt;x = y&lt;&#x2F;code&gt; for any &lt;code&gt;x&lt;&#x2F;code&gt; and &lt;code&gt;y&lt;&#x2F;code&gt; is &lt;code&gt;refl&lt;&#x2F;code&gt;, so it&#x27;s close to a no-op. However, in HoTT, where there may
be many proofs of &lt;code&gt;x = y&lt;&#x2F;code&gt;, Axiom J is slightly less obvious. Why can we conclude that &lt;code&gt;P&lt;&#x2F;code&gt; is true for any path if we are only given that
it is true at &lt;code&gt;refl&lt;&#x2F;code&gt;?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why&quot;&gt;Why?&lt;&#x2F;h2&gt;
&lt;p&gt;First, let&#x27;s curry &lt;code&gt;P&lt;&#x2F;code&gt;, turning the initial arguments from a Pi-type to a Sigma-type:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;P : Π (a b : A). a = b -&amp;gt; Type
&lt;&#x2F;span&gt;&lt;span&gt;==&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;P : (Σ(a : A). Σ(b : A). a = b) -&amp;gt; Type
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And rewrite the above accordingly.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;Given:
&lt;&#x2F;span&gt;&lt;span&gt;A : Type
&lt;&#x2F;span&gt;&lt;span&gt;x y : A
&lt;&#x2F;span&gt;&lt;span&gt;P : (Σ(a : A). Σ(b : A). a = b) -&amp;gt; Type
&lt;&#x2F;span&gt;&lt;span&gt;with
&lt;&#x2F;span&gt;&lt;span&gt;P (x, x, refl)
&lt;&#x2F;span&gt;&lt;span&gt;and
&lt;&#x2F;span&gt;&lt;span&gt;eq : x = y
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;we can conclude
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;P (x, y, eq)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We will first apply the principle that if &lt;code&gt;a = b&lt;&#x2F;code&gt;, then &lt;code&gt;P a -&amp;gt; P b&lt;&#x2F;code&gt;, generally called something like &lt;code&gt;subst&lt;&#x2F;code&gt;itution. We can use &lt;code&gt;P (x, x, refl)&lt;&#x2F;code&gt; as our &quot;&lt;code&gt;P a&lt;&#x2F;code&gt;&quot;. We then aim to show that:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;Given:
&lt;&#x2F;span&gt;&lt;span&gt;eq : x = y
&lt;&#x2F;span&gt;&lt;span&gt;then
&lt;&#x2F;span&gt;&lt;span&gt;(x, x, refl) = (x, y, eq)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The first element is obvious - clearly &lt;code&gt;x = x&lt;&#x2F;code&gt;. Now we have to show that &lt;code&gt;(x, refl) = (y, eq)&lt;&#x2F;code&gt;.
This seems impossible! We do &lt;em&gt;not&lt;&#x2F;em&gt; have that &lt;code&gt;refl = eq&lt;&#x2F;code&gt;, due to the nature of HoTT.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s approach this by analysing the type of &lt;code&gt;(x, refl)&lt;&#x2F;code&gt; and &lt;code&gt;(y, eq)&lt;&#x2F;code&gt; (it&#x27;s the same for both; otherwise the equality above wouldn&#x27;t make sense).&lt;&#x2F;p&gt;
&lt;p&gt;Looking at the type of &lt;code&gt;P&lt;&#x2F;code&gt; above, we can conclude that&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;(x, refl) : Σ(b : A). x = b
&lt;&#x2F;span&gt;&lt;span&gt;                      ^ note the `x` here we got from 
&lt;&#x2F;span&gt;&lt;span&gt;                        the first element of the tuple
&lt;&#x2F;span&gt;&lt;span&gt;and then necessarily
&lt;&#x2F;span&gt;&lt;span&gt;(y, eq)   : Σ(b : A). x = b
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now for the trick. While we do &lt;em&gt;not&lt;&#x2F;em&gt; have that &lt;code&gt;refl = eq&lt;&#x2F;code&gt;, we don&#x27;t actually need it!
It turns out that we can prove that any element of &lt;code&gt;Σ(b : A). x = b&lt;&#x2F;code&gt; is equal to any other element of &lt;code&gt;Σ(b : A). x = b&lt;&#x2F;code&gt;, irregardless of
the proof of equality used - in other words, &lt;code&gt;Σ(b : A). x = b&lt;&#x2F;code&gt; only has one inhabitant. This property (only having one inhabitant) is called &quot;contractibility&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;A &quot;proper&quot; proof of this requires some careful thinking
(One can be found &lt;a href=&quot;https:&#x2F;&#x2F;1lab.dev&#x2F;1Lab.Path.html#34069&quot;&gt;here as &lt;code&gt;Singleton-contract&lt;&#x2F;code&gt;, in Cubical Agda, courtesy of the 1lab&lt;&#x2F;a&gt;,
and it&#x27;s Lemma 3.11.8 in the HoTT book, at time of writing.), but I&#x27;ll give an informal one here.&lt;&#x2F;p&gt;
&lt;p&gt;Consider what &lt;code&gt;Σ(b : A). x = b&lt;&#x2F;code&gt; &lt;em&gt;means&lt;&#x2F;em&gt;. One way of interpreting it is like it&#x27;s a subset - that
&quot;&lt;code&gt;Σ(b : A). x = b&lt;&#x2F;code&gt; is the type of things that are elements of &lt;code&gt;A&lt;&#x2F;code&gt; equal to &lt;code&gt;x&lt;&#x2F;code&gt;&quot;.
However, there&#x27;s only one of those! Namely, &lt;code&gt;x&lt;&#x2F;code&gt; itself. If we chose anything else, we wouldn&#x27;t have &lt;code&gt;x = b&lt;&#x2F;code&gt; in the first place.
This means that our choice of equality doesn&#x27;t matter at all - when we consider the tuple as a whole, there can only be one inhabitant.
Hence, as we already have that &lt;code&gt;x = y&lt;&#x2F;code&gt;, we have &lt;code&gt;(x, refl) = (x, eq) = (y, eq)&lt;&#x2F;code&gt;, completing our proof.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tldr&quot;&gt;TLDR&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;J : Π (A : Type) 
&lt;&#x2F;span&gt;&lt;span&gt;      (x y : A)
&lt;&#x2F;span&gt;&lt;span&gt;      (eq : x = y)
&lt;&#x2F;span&gt;&lt;span&gt;      (P : Π(a b : A). x = y -&amp;gt; Type).
&lt;&#x2F;span&gt;&lt;span&gt;         P x x refl 
&lt;&#x2F;span&gt;&lt;span&gt;      -&amp;gt; P x y eq
&lt;&#x2F;span&gt;&lt;span&gt;Goal : P x y eq
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Consider the equivalent &quot;curried&quot; version, so curry &lt;code&gt;P&lt;&#x2F;code&gt;:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;J : Π (A : Type) 
&lt;&#x2F;span&gt;&lt;span&gt;      (x y : A)
&lt;&#x2F;span&gt;&lt;span&gt;      (eq : x = y)
&lt;&#x2F;span&gt;&lt;span&gt;      (P : (Σ(a : A). Σ(b : A). a = b) -&amp;gt; Type).
&lt;&#x2F;span&gt;&lt;span&gt;         P (x, x, refl)
&lt;&#x2F;span&gt;&lt;span&gt;      -&amp;gt; P (x, y, eq)
&lt;&#x2F;span&gt;&lt;span&gt;Goal : P (x, y, eq)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Use &lt;code&gt;subst : a = b -&amp;gt; P a -&amp;gt; P b&lt;&#x2F;code&gt;:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;Goal : (x, x, refl) = (x, y, eq)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;Use that &lt;code&gt;Π x a b. a = b -&amp;gt; (x, a) = (x, b)&lt;&#x2F;code&gt; (with &lt;code&gt;a = (x, refl)&lt;&#x2F;code&gt; and &lt;code&gt;b = (y, eq)&lt;&#x2F;code&gt;:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;Goal : (x, refl) = (y, eq)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;Use that &lt;code&gt;Σ(b : A). x = b&lt;&#x2F;code&gt; is contractible (&lt;code&gt;Π (one two : Σ(b : A). x = b)). one = two&lt;&#x2F;code&gt;):&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;Done!
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A handwavy &quot;proof term&quot; may look like (ommitting some &quot;obvious&quot; arguments, as one may do with implicit arguments in Agda):&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;Given:
&lt;&#x2F;span&gt;&lt;span&gt;subst : Π P a b. a = b -&amp;gt; P a -&amp;gt; P b
&lt;&#x2F;span&gt;&lt;span&gt;subst-fst : Π x y p q. (x , p) = (x , q) -&amp;gt; x = y -&amp;gt; (x , p) = (y , q)
&lt;&#x2F;span&gt;&lt;span&gt;pair-snd-eq : Π x a b. a = b -&amp;gt; (x , a) = (x , b)
&lt;&#x2F;span&gt;&lt;span&gt;singleton-contractible : Π x (one two : Σ(b : A). x = b)). one = two
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;We have:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;J : Π (A : Type) 
&lt;&#x2F;span&gt;&lt;span&gt;      (x y : A)
&lt;&#x2F;span&gt;&lt;span&gt;      (eq : x = y)
&lt;&#x2F;span&gt;&lt;span&gt;      (P : (Σ(a : A). Σ(b : A). a = b) -&amp;gt; Type).
&lt;&#x2F;span&gt;&lt;span&gt;         P x x refl 
&lt;&#x2F;span&gt;&lt;span&gt;      -&amp;gt; P x y eq
&lt;&#x2F;span&gt;&lt;span&gt;J A x y eq P Pxxrefl = 
&lt;&#x2F;span&gt;&lt;span&gt;  subst  (pair-snd-eq singleton-contractible) Pxxrefl
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Written in Pure Sea</title>
        <published>2025-12-19T00:00:00+00:00</published>
        <updated>2025-12-19T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/pure-sea/"/>
        <id>https://blueberrywren.dev/blog/pure-sea/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/pure-sea/">&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣴⣶⠾⠿⠿⠯⣷⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
&lt;&#x2F;span&gt;&lt;span&gt;⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⣾⠛⠁⠀⠀⠀⠀⠀⠀⠈⢻⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
&lt;&#x2F;span&gt;&lt;span&gt;⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⠿⠁⠀⠀⠀⢀⣤⣾⣟⣛⣛⣶⣬⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
&lt;&#x2F;span&gt;&lt;span&gt;⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⠟⠃⠀⠀⠀⠀⠀⣾⣿⠟⠉⠉⠉⠉⠛⠿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
&lt;&#x2F;span&gt;&lt;span&gt;⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⡟⠋⠀⠀⠀⠀⠀⠀⠀⣿⡏⣤⠀⠀__&#x2F;\웃_⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
&lt;&#x2F;span&gt;&lt;span&gt;⠀⠀⠀⠀⠀⠀⠀⣠⡿⠛⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⣷⡍⠀⠀\____&#x2F;⠀⠀⠀⢀⣀⣀⣤⣤⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀ 
&lt;&#x2F;span&gt;&lt;span&gt;⠀⠀⠀⠀⠀⣠⣼⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠷⣤⣤⣠⣤⣤⡤⡶⣶⢿⠟⠹⠿⠄⣿⣿⠏⠀⣀⣤⡦⠀⠀⠀⠀⣀⡄
&lt;&#x2F;span&gt;&lt;span&gt;⢀⣄⣠⣶⣿⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠓⠚⠋⠉⠀⠀⠀⠀⠀⠀⠈⠛⡛⡻⠿⠿⠙⠓⢒⣺⡿⠋⠁
&lt;&#x2F;span&gt;&lt;span&gt;⠉⠉⠉⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠁⠀
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I don&#x27;t have great C legs.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Horrible answers to &quot;What is a type?&quot;</title>
        <published>2025-11-17T00:00:00+00:00</published>
        <updated>2025-11-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/horrible-types/"/>
        <id>https://blueberrywren.dev/blog/horrible-types/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/horrible-types/">&lt;ul&gt;
&lt;li&gt;A set.&lt;&#x2F;li&gt;
&lt;li&gt;Absolutely not a set.&lt;&#x2F;li&gt;
&lt;li&gt;An element of a category.&lt;&#x2F;li&gt;
&lt;li&gt;A proposition.&lt;&#x2F;li&gt;
&lt;li&gt;A chosen fixed point of a generating function.&lt;&#x2F;li&gt;
&lt;li&gt;The initial algebra&#x2F;final coalgebra of a generating endofunctor over a reasonable base category (say, &lt;code&gt;Set&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;A metaphorical representation of bytes.&lt;&#x2F;li&gt;
&lt;li&gt;A membership function &lt;code&gt;UNIV → bool&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;That thing you put after the &lt;code&gt;:&lt;&#x2F;code&gt; to make the computer stop yelling at you :(&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;as any&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Propaganda made up by Big Typechecker to make us complacent.&lt;&#x2F;li&gt;
&lt;li&gt;Nerd shit.&lt;&#x2F;li&gt;
&lt;li&gt;The archetype of person that you tend to feel attracted to romantically.&lt;&#x2F;li&gt;
&lt;li&gt;A metal plate with a glyph, used for printing ink onto paper.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Opinion piece: On Zig (and the design choices within)</title>
        <published>2025-10-14T00:00:00+00:00</published>
        <updated>2025-10-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/on-zig/"/>
        <id>https://blueberrywren.dev/blog/on-zig/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/on-zig/">&lt;p&gt;(From someone who has spent far too much time thinking about the designs of programming languages)&lt;&#x2F;p&gt;
&lt;p&gt;This post is split up into a few sections. I would also like to preface this post with:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;This is a little bit of a rant. I believe it presents some very reasonable points about Zig as a language, but it&#x27;s not going to be
perfect or completely objective. It is an opinion piece, and you&#x27;re free to ignore it if you want.&lt;&#x2F;li&gt;
&lt;li&gt;Existing memory safe languages are not perfect. Rust will be used as an example quite a bit, as from what is currently available, it embodies closer to what I think is reasonable in a programming language. However, there is still much room for improvement in this space.&lt;&#x2F;li&gt;
&lt;li&gt;All of the following is ultimately my opinion. If you disagree, you are welcome to find me somewhere on the internet and ask me more.&lt;&#x2F;li&gt;
&lt;li&gt;I bear no grudge or ill will against anyone who contributes to, works on, or is otherwise involved in the Zig community. The following are things I have noted about the language, not the people behind it. If you enjoy Zig, go and write it, and make cool stuff - I am not the programming language police.&lt;&#x2F;li&gt;
&lt;li&gt;Exception to the above: I have one gripe about the Zig community. This gripe &quot;targets&quot; no one person in particular; rather, larger trends.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;ideological-differences&quot;&gt;Ideological differences&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;memory&quot;&gt;Memory&lt;&#x2F;h3&gt;
&lt;p&gt;First, and very much foremost, Zig is not memory safe. This is, in my opinion, the most
egregious thing in this post, by a very large margin. Moreso, Zig does not make any attempt to
be memory safe -
it can catch some things at runtime, with specific allocators, but so can C these days. Indeed, there
are some cases, like use-after-realloc, that &lt;code&gt;asan&lt;&#x2F;code&gt; can catch and Zig cannot.&lt;&#x2F;p&gt;
&lt;p&gt;A language in the modern day that does not make an attempt at memory safety is, in my opinion, not reasonable. It has been shown that in some areas, up to 70% of security bugs are due to memory safety issues (&lt;a href=&quot;https:&#x2F;&#x2F;www.chromium.org&#x2F;Home&#x2F;chromium-security&#x2F;memory-safety&#x2F;&quot;&gt;Source&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;I subscribe to the idea that the user must be constrained. It is perhaps harsh to say, but for large and complex programs, I believe that there are very few programmers who will write memory-correct code nine times out of ten. When writing code with others, that goes down. I personally do not believe I fit into that category.&lt;&#x2F;p&gt;
&lt;p&gt;The fact that Zig allows the user to write faulty software is supported by various somewhat informal, but still useful, statistics. Notably, the following statistic disregard duplicates, and unreported errors. However, general trends are still of note.&lt;&#x2F;p&gt;
&lt;p&gt;UPDATE: Someone has done a much more thorough analysis of crashes in JS runtimes! Thank you to the authors of the &lt;a href=&quot;https:&#x2F;&#x2F;js-segfault-compare.sigmasd.workers.dev&#x2F;&quot;&gt;Javascript Runtime Segfault Tracker&lt;&#x2F;a&gt;, which demonstrates my point very effectively. To quote the person who sent me this: &quot;it&#x27;s a log scale. i&#x27;ll let you guess which runtime is responsible for that.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;For posterity, I leave my own analysis below:&lt;&#x2F;p&gt;
&lt;details&gt;&lt;summary&gt;Here are some:&lt;&#x2F;summary&gt;
&lt;ol&gt;
&lt;li&gt;The Rust compiler has had a lifetime 59,780 issues reported. Of these, 4,158 contain one of &quot;crash&quot;, &quot;segmentation fault&quot;, or &quot;segfault&quot;.&lt;&#x2F;li&gt;
&lt;li&gt;The Zig compiler has had a lifetime 13,269 issues reported. Of these, 2,260 contain one of &quot;crash&quot;, &quot;segmentation fault&quot;, or &quot;segfault&quot;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This means that, roughly:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;7% of lifetime issues reported in the Rust compiler are crashes.&lt;&#x2F;li&gt;
&lt;li&gt;17% of lifetime issues reported in the Zig compiler are crashes.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Not ideal.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The Node&#x2F;v8 JS runtime, written partially itself in JS and partially in C++, has had a lifetime 19,631 issues reported, 1,710 of which contain one of the above keywords.&lt;&#x2F;li&gt;
&lt;li&gt;The Deno JS runtime, written primarily in Rust, has had a lifetime 13,422 issues reported, 552 of which contain one of the above keywords.&lt;&#x2F;li&gt;
&lt;li&gt;The Bun JS runtime, written in Zig, has had a lifetime 13,828 issues reported, 3676 of which contain one of the above keywords.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Again, this roughly means:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;8.7% of lifetime issues reported in Node are crashes.&lt;&#x2F;li&gt;
&lt;li&gt;4.1% of lifetime issues reported in Deno are crashes.&lt;&#x2F;li&gt;
&lt;li&gt;26.5% (!!!) of lifetime issues reported in Bun are crashes.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Also not great. Again, these statistics are slightly off at best simply due to the nature of their collection, but the trends do not lie.&lt;&#x2F;p&gt;
&lt;&#x2F;details&gt;
&lt;p&gt;If you&#x27;re not reading the above: It can be summarized as &quot;Pretty bad.&quot;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;philosophy&quot;&gt;Philosophy&lt;&#x2F;h3&gt;
&lt;p&gt;At one point, this part of the article contained a runthrough of the &lt;code&gt;zig zen&lt;&#x2F;code&gt;, and my opinions on each bullet point. I have decided that that is not a constructive discussion of Zig. It suffices for me to say that I do not believe Zig particularly embodies its own zen.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;practical&quot;&gt;Practical&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;comptime&quot;&gt;Comptime&lt;&#x2F;h3&gt;
&lt;p&gt;Zig does generics in an odd way. I believe this is the best way of putting it.
This post is not meant to be, nor will it contain, a proper explanation of Zig&#x27;s &lt;code&gt;comptime&lt;&#x2F;code&gt;
capabilities, so I refer the reader to the wider internet there. However, doing generics
with &quot;normal&quot; code means that there are multiple ways to write the same generic function.
There is no standardization between different libraries, different styles of writing code, and
different users of Zig. Every person can do generics in their own special way.&lt;&#x2F;p&gt;
&lt;p&gt;This obviously has slightly dire effects on readability. In practice, most Zig users are reasonable enough
to stick to some &quot;common patterns&quot; of doing generics and similar, but it is widely known that if the user is giving the ability to do something, it will be done. I believe that generics are important enough they should be first class.&lt;&#x2F;p&gt;
&lt;p&gt;Arguments can be made that Zig&#x27;s comptime is also useful for other things, not just generics. Some examples I have been given are conditional compilation, and variadic functions. Beyond these, I am yet to see a convincing motivating example that &lt;em&gt;requires&lt;&#x2F;em&gt; the machinery that Zig provides. Every such example can, in my experience, be solved with less powerful (and hence, for the most part, less confusing) machinery.&lt;&#x2F;p&gt;
&lt;p&gt;As a result, I am inclined to believe that Zig&#x27;s comptime is a very large and all-encompassing feature that ultimately brings very little to the table that smaller features cannot.&lt;&#x2F;p&gt;
&lt;p&gt;I am personally a proponent of a good macro system, but I will readily admit people can also go overboard with one of those.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;casting&quot;&gt;Casting&lt;&#x2F;h3&gt;
&lt;p&gt;Zig&#x27;s casting is a bit cumbersome. To cast a float to a specific int width, for example, must be done with &lt;code&gt;@as(i32, @intFromFloat(flt))&lt;&#x2F;code&gt;. Bit of a mouthful. Inference can help here (For example if a variable is already known to be a &lt;code&gt;i32&lt;&#x2F;code&gt;, the outer cast is not needed), but I would think that with Zig&#x27;s comptime abilities, this could be made a bit nicer. Luckily, it is common Zig practice to annotate everything if possible, so this does come up slightly less in practice. It is still a bit bulky however.&lt;&#x2F;p&gt;
&lt;p&gt;Float to int casting additionally can invoke undefined behavior if the float is outside the integer&#x27;s range. I personally prefer truncating semantics, with perhaps a specialized method (&lt;code&gt;intFromFloatUnsafe&lt;&#x2F;code&gt;?) for UB semantics. That&#x27;s more of a personal preference though.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;semantics&quot;&gt;Semantics&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;result-location-semantics-rls&quot;&gt;Result location semantics (RLS)&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;ziglang.org&#x2F;documentation&#x2F;0.15.1&#x2F;#Result-Location-Semantics&quot;&gt;See here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Result location semantics are in theory a quite nice idea. Knowing predictably where things are going to be placed in memory is, of course, good for any systems-adjacent language! In practice, there are several choices within RLS that I find counterintuitive. Take the following example, where we attempt to swap two struct members in place:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; std &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= @&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;std&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; What &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    a: i32,
&lt;&#x2F;span&gt;&lt;span&gt;    b: i32,
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() void {
&lt;&#x2F;span&gt;&lt;span&gt;    var x: What &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;.{ .a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, .b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;    x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; What { .a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; x.b, .b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; x.a };
&lt;&#x2F;span&gt;&lt;span&gt;    std.log.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;info&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;x: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, .{x});
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    var y: What &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;.{ .a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, .b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;    y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;.{ .a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; y.b, .b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; y.a };
&lt;&#x2F;span&gt;&lt;span&gt;    std.log.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;info&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;y: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, .{y});
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This outputs the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;info: x: .{ .a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, .b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;info: y: .{ .a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, .b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I will note that the equivalent C can only be written in the former style, and it prints the former.&lt;&#x2F;p&gt;
&lt;p&gt;The only difference between the latter and the former is whether the type name is present. This is intended behavior! Indeed, this very example is given in the Zig reference, a fact that I find odd. Why give a warning against something when you could just fix it? Zig does not have move or copy constructors; I do not think there is very much reason for the latter to ever behave the way it does. One extra register is all you ever need, even for an arbitrary parallel move! (&lt;a href=&quot;https:&#x2F;&#x2F;compiler.club&#x2F;parallel-moves&#x2F;&quot;&gt;Source&lt;&#x2F;a&gt;.)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;pointer-reference-optimization&quot;&gt;Pointer reference optimization&lt;&#x2F;h3&gt;
&lt;p&gt;In its previous form, PRO has been removed from Zig. There was a long period where this would print &lt;code&gt;5&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; std &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= @&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;std&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;AAAA &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    foo: [100]u32,
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;kindabad&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;: AAAA, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;: *AAAA) void {
&lt;&#x2F;span&gt;&lt;span&gt;  b.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;.foo[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  std.debug.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;unideal: {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, .{ a.foo[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] });
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;void {
&lt;&#x2F;span&gt;&lt;span&gt;    var f: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;AAAA &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; undefined;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    f.foo[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;kindabad&lt;&#x2F;span&gt;&lt;span&gt;(f, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;f);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As Zig would correctly, per PRO at the time, but incorrectly per common sense, pass &lt;code&gt;a&lt;&#x2F;code&gt; as a reference.&lt;&#x2F;p&gt;
&lt;p&gt;This is actually mildly unfortunate. It&#x27;s a very interesting optimization, and being able to guarantee behavior around optimization of parameter passing would also be quite beneficial. Unfortunately, Zig simply does not have the level of control needed to do it. Aliasing is freely allowed, and in order to make PRO work, it cannot be. Rust can, and in many cases does, do this! It&#x27;s a shame Zig has to miss out.&lt;&#x2F;p&gt;
&lt;p&gt;There is current work to make PRO work in the case of pure functions (&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ziglang&#x2F;zig&#x2F;issues&#x2F;5973#issuecomment-2380332493&quot;&gt;Source&lt;&#x2F;a&gt;), so I remain hopeful that it will return in some form eventually.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;misc-improvable-things&quot;&gt;Misc. Improvable things&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;speed&quot;&gt;Speed&lt;&#x2F;h3&gt;
&lt;p&gt;The Zig compiler is not particularly fast. The LLVM backend even more so; compared to Clang, (which has the home field advantage, but can still be quite slow), and by my measurements, Clang is consistently between 3-10x faster. A new Zig backend has been written to help fix this; by similar measurements, it is consistently faster than Clang by 1.5-2x, and much faster than the Zig LLVM backend. While these numbers are nothing to scoff at, I believe there is more room for improvement, and I would like to see where it goes. Zig is a simpler language than C when comptime is not involved, and I would be excited to see that reflected in the benchmarks. It is also possible that Zig could use LLVM more efficiently, but I cannot comment on this without digging into the internals of the compiler.&lt;&#x2F;p&gt;
&lt;p&gt;Of course, all of this is quite reasonable. The Zig compiler has had far, far fewer man-hours put into it, and this of course reflects in aspects of the compiler that simply take a lot of time, such as these. I look forward to seeing what can be done in the future.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tooling&quot;&gt;Tooling&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;build-system&quot;&gt;Build system&lt;&#x2F;h4&gt;
&lt;p&gt;The Zig build system is a little confusing. It is very neat to be able to write build system code in the language itself, and this is a feature I believe more languages should have. Unfortunately, it is as of current not well documented enough to justify its own complexity. This of course can be improved, and I hope it is.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;language-server&quot;&gt;Language server&lt;&#x2F;h4&gt;
&lt;p&gt;Zig currently does not have a &quot;first class&quot; language server. The &quot;Zig Language Server&quot;, or ZLS, is unofficial; It does not have real compiler integration, so it is unfortunately limited in some ways. The creator of Zig apparently does not use a language server while programming, so I do slightly understand why it is not a priority, but I personally believe tools like a good language server are quite essential to wider&#x2F;popular usage. Here are some quotes I have heard from people who have used it far more than I:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&quot;Deeply horrid&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&quot;It is one of the worst LSPs I have ever used&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&quot;Don&#x27;t get me started&quot;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Apparently it is very limited when &lt;code&gt;comptime&lt;&#x2F;code&gt; comes into play, and cannot handle compound types like 2D arrays.&lt;&#x2F;p&gt;
&lt;p&gt;I cannot offer much firsthand experience however.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;debug-mode&quot;&gt;Debug mode&lt;&#x2F;h3&gt;
&lt;p&gt;There are always more errors to be caught. I particularly recently noticed that Zig cannot currently catch use-after-realloc errors, like the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; std &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= @&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;std&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;void {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; allocator &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; std.heap.page_allocator;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    var buffer &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; try allocator.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;alloc&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    buffer[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; new_buffer &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; try allocator.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;realloc&lt;&#x2F;span&gt;&lt;span&gt;(buffer, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;&#x2F;&#x2F; Should be caught!
&lt;&#x2F;span&gt;&lt;span&gt;    buffer[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;99&lt;&#x2F;span&gt;&lt;span&gt;; 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    allocator.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;free&lt;&#x2F;span&gt;&lt;span&gt;(new_buffer);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Address sanitizer with Clang can catch this, so theoretically Zig should be able to catch it (perhaps with a similar system) too.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;misc-improvable-things-that-won-t-be-improved-for-reasons-beyond-me&quot;&gt;Misc. Improvable things that won&#x27;t be improved for reasons beyond me&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;behavior-around-undefined&quot;&gt;Behavior around &lt;code&gt;undefined&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;debug-mode-1&quot;&gt;Debug mode&lt;&#x2F;h4&gt;
&lt;p&gt;Apparently, it is desired that comparisons with &lt;code&gt;undefined&lt;&#x2F;code&gt; panic. This seems reasonable to me. However, the issue for this has been open &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ziglang&#x2F;zig&#x2F;issues&#x2F;63&quot;&gt;for almost ten years&lt;&#x2F;a&gt;, which makes me worry that it might be a while still until it is finished.&lt;&#x2F;p&gt;
&lt;p&gt;This panics in &lt;code&gt;Debug&lt;&#x2F;code&gt; and &lt;code&gt;ReleaseSafe&lt;&#x2F;code&gt; modes, however, so it does at least work in some cases.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() void {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; x: &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; undefined;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h4 id=&quot;safety&quot;&gt;Safety&lt;&#x2F;h4&gt;
&lt;p&gt;According to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ziglang&#x2F;zig&#x2F;issues&#x2F;21915&quot;&gt;this issue&lt;&#x2F;a&gt;, it is &quot;not a goal of the Zig compiler&quot; to catch issues like the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;pub &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;() void {
&lt;&#x2F;span&gt;&lt;span&gt;    var buf: []&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;u8 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; undefined;
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;&#x2F;&#x2F; Very not allowed!
&lt;&#x2F;span&gt;&lt;span&gt;    buf[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This just seems silly to me. Catching something like this, in the simple case, should be just one pass over the AST; why not do it?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tabs-and-syntax&quot;&gt;Tabs and syntax&lt;&#x2F;h3&gt;
&lt;p&gt;Zig simply doesn&#x27;t allow tabs in comments and strings? &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ziglang&#x2F;zig-spec&#x2F;issues&#x2F;38&quot;&gt;This issue&lt;&#x2F;a&gt; explains more, but the justification of &quot;it (a tab) is ambiguous (in) how it should be rendered&quot;, I do not quite agree with.&lt;&#x2F;p&gt;
&lt;p&gt;Strings make some sense; you can still write &lt;code&gt;\t&lt;&#x2F;code&gt; for a tab, and they do indeed make output ambiguous. However, they&#x27;re still allowed in indentation! This means that in commenting out code, you can take a program from valid to invalid. &lt;code&gt;zig fmt&lt;&#x2F;code&gt; does reify tabs into spaces, but if your editor is misconfigured and you&#x27;re not running &lt;code&gt;zig fmt&lt;&#x2F;code&gt; constantly?&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;tabs.zig:5:36: error: comment contains invalid byte: &amp;#39;\t&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&#x2F;        const str: *const [1:0]u8 = &amp;quot;w&amp;quot;;
&lt;&#x2F;span&gt;&lt;span&gt;  ^~~~~~~~~~~
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Very odd.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly, the following will not compile:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;gt;=&lt;&#x2F;span&gt;&lt;span&gt;b) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;because the whitespace isn&#x27;t correct. Zig doesn&#x27;t have warnings, so this is always a compile error.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;iteration&quot;&gt;Iteration&lt;&#x2F;h3&gt;
&lt;p&gt;Zig does not have a way to iterate through a slice or similar in any way except one-at-a-time forwards. Anything else? You&#x27;re using a &lt;code&gt;while&lt;&#x2F;code&gt; loop, and you&#x27;ll enjoy it. Zig blanket bans proposals to change the language, so despite issues like &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ziglang&#x2F;zig&#x2F;issues&#x2F;21814&quot;&gt;this one&lt;&#x2F;a&gt;, I doubt this will happen any time soon.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;warnings&quot;&gt;Warnings&lt;&#x2F;h3&gt;
&lt;p&gt;Zig doesn&#x27;t have &#x27;em. Everything is an error. In practice, this mostly manifests through reasonably harmless things like &quot;unused variable&quot; notices becoming errors, which is reasonably annoying when just trying to spitball.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;my-only-note-on-the-community&quot;&gt;My only note on the community&lt;&#x2F;h2&gt;
&lt;p&gt;For the most part, the community is about par for the course for programming language communities; that is to say, quite nice. However, I have had some reasonably negative interactions that I feel are somewhat of a general trend. They usually proceed like the following:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;I ask a question about solving something in Zig. Often, given my background, it is about adapting my more functional-esque thinking to Zig.&lt;&#x2F;li&gt;
&lt;li&gt;Someone chimes in with a half-solution that does not actually address my problem.&lt;&#x2F;li&gt;
&lt;li&gt;I attempt to communicate this to them, which often involves explaining the features I would use in &amp;lt;insert other language&amp;gt;.&lt;&#x2F;li&gt;
&lt;li&gt;They insist that these features are not needed, but do not elaborate on how one would solve the problem without them.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This is unpleasant, and while it&#x27;s not a particularly uncommon thing to see in programming language communities, Zig seems to have a bit of a bad case of it. I suspect it is due to Zig&#x27;s fairly minimalistic nature; it lacks a lot of features that one would otherwise use to solve problems. Of course, this is the appeal for many, but still. It is made worse when said topic is something one is particularly knowledgeable about, and the people you are conversing with believe they can solve the issue without that knowledge.&lt;&#x2F;p&gt;
&lt;p&gt;I do not believe that a few bad apples necessarily spoil the whole barrel here, but they definitely sour it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;&#x2F;h2&gt;
&lt;p&gt;I find Zig interesting, with an unfortunately negative connotation. I believe the goal of a C-like memory unsafe language &quot;for the modern day&quot;, while interesting at first glance, ignores many of the issues that make C a problem in said modern day. Much of Zig seems to me like &quot;wishful thinking&quot;; if every programmer was 150% smarter and more capable, perhaps it would work. Alas, they are not; myself included.&lt;&#x2F;p&gt;
&lt;p&gt;I believe that modern concerns of memory safety and correctness require modern solutions; not performing patchwork fixes over the core issue.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Isabelle&#x2F;HOL: The various rule methods</title>
        <published>2025-09-19T00:00:00+00:00</published>
        <updated>2025-09-19T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/isabelle-rule-musings/"/>
        <id>https://blueberrywren.dev/blog/isabelle-rule-musings/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/isabelle-rule-musings/">&lt;p&gt;The following is adapted from the &lt;a href=&quot;https:&#x2F;&#x2F;isabelle.in.tum.de&#x2F;dist&#x2F;Isabelle2025&#x2F;doc&#x2F;tutorial.pdf&quot;&gt;Isabelle&#x2F;HOL 2025 tutorial&lt;&#x2F;a&gt;, particularly 5.2 and onwards. It will explain much more thoroughly than I can.&lt;&#x2F;p&gt;
&lt;p&gt;I also make no promise that the following is entirely 100% correct. It is ultimately my understanding, but I have run it past several others, and to the best of our knowledge it is correct.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;notes&quot;&gt;Notes&lt;&#x2F;h1&gt;
&lt;p&gt;These rule methods can be used in many different ways. While some general principles are mentioned below, if the prerequisits are met,
every rule can theoretically be used with every rule method. Many of these various combinations will not be beneficial to proving a given
goal, and hence it is useful to know how the rule methods interact with rules and proof states in order to select the correct pairing.&lt;&#x2F;p&gt;
&lt;p&gt;In that vein, the same rule will be interpreted differently by these different rule methods. Read more for how they work, and hence why.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;rule-erule-drule-and-frule-informally&quot;&gt;&lt;code&gt;rule&lt;&#x2F;code&gt;, &lt;code&gt;erule&lt;&#x2F;code&gt;, &lt;code&gt;drule&lt;&#x2F;code&gt;, and &lt;code&gt;frule&lt;&#x2F;code&gt;, informally&lt;&#x2F;h1&gt;
&lt;p&gt;We use &lt;code&gt;P&lt;&#x2F;code&gt;, &lt;code&gt;Q&lt;&#x2F;code&gt;, and &lt;code&gt;R&lt;&#x2F;code&gt; as arbitrary assumptions and goals throughout.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rule&quot;&gt;&lt;code&gt;rule&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Consider the introduction rule &lt;code&gt;conjI&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P   Q
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;----- conjI
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt; ∧ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we have a goal of form &lt;code&gt;R ==&amp;gt; P ∧ Q&lt;&#x2F;code&gt;, from &lt;code&gt;conjI&lt;&#x2F;code&gt; we can infer that it is sufficent to seperately prove &lt;code&gt;P&lt;&#x2F;code&gt; and &lt;code&gt;Q&lt;&#x2F;code&gt;. Indeed, performing &lt;code&gt;apply (rule conjI)&lt;&#x2F;code&gt; on a goal of this shape will result in two goals:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;. &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;. &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;which can be then proven seperately. &lt;code&gt;rule&lt;&#x2F;code&gt; is for backwards-reasoning; here we can see that as moving &quot;backwards up&quot; the introduction rule (Starting with the bottom, and ending with the top.) It is therefore useful for introduction rules, as demonstrated.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;erule&quot;&gt;&lt;code&gt;erule&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;erule&lt;&#x2F;code&gt; is designed to function with elimination rules. Take for example the elimination rule for disjunction:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt; ∨ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span&gt;     (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R&lt;&#x2F;span&gt;&lt;span&gt;)    (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;-------------------------------- disjE
&lt;&#x2F;span&gt;&lt;span&gt;              &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(Informally, to prove something about a disjunction, we must handle both possible cases.)&lt;&#x2F;p&gt;
&lt;p&gt;If we have a goal of the form:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt; ∨ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;we can perform &lt;code&gt;apply (erule disjE)&lt;&#x2F;code&gt; to transform this into two goals:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;. &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;. &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;where we must handle each possible case of the disjunction. &lt;code&gt;erule&lt;&#x2F;code&gt; is a bit of both backwards and forwards reasoning. In the above elimination rule, we can see that we need three assumptions to prove &lt;code&gt;R&lt;&#x2F;code&gt; --- we already have &lt;code&gt;P ∨ Q&lt;&#x2F;code&gt;, so it is sufficient to then only additionally prove &lt;code&gt;P ==&amp;gt; R&lt;&#x2F;code&gt; and &lt;code&gt;Q ==&amp;gt; R&lt;&#x2F;code&gt;, which are exactly the goals &lt;code&gt;erule&lt;&#x2F;code&gt; gives us.&lt;&#x2F;p&gt;
&lt;p&gt;Notable: &lt;code&gt;erule&lt;&#x2F;code&gt; deletes the already-held assumption, as it is &quot;rarely useful&quot; (quoting the Isabelle&#x2F;HOL tutorial). See below&#x27;s note for more.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;note-on-rule-vs-erule&quot;&gt;Note on &lt;code&gt;rule&lt;&#x2F;code&gt; vs &lt;code&gt;erule&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;As mentioned, &lt;code&gt;erule&lt;&#x2F;code&gt; deliberately deletes the already-held assumptions when using an elimination rule. Above, we could see that &lt;code&gt;P ∨ Q&lt;&#x2F;code&gt; was not present in the generated goals, as it was already assumed. By instead using &lt;code&gt;rule&lt;&#x2F;code&gt;, we can keep the original goal in our assumptions as follows. If we apply the principles from the &lt;code&gt;rule&lt;&#x2F;code&gt; section to &lt;code&gt;disjE&lt;&#x2F;code&gt;, we would get:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt; ∨ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;apply (rule disjE)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;⟦ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt; ∨ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span&gt; ⟧ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt; ∨ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q
&lt;&#x2F;span&gt;&lt;span&gt;⟦ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt; ∨ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt; ⟧ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R
&lt;&#x2F;span&gt;&lt;span&gt;⟦ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt; ∨ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span&gt; ⟧ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;i.e., &lt;code&gt;rule&lt;&#x2F;code&gt;, as expected, replaces the goal R with the goals sufficent to prove it. In this case, however, the first goal is trivial, and in the latter two, &lt;code&gt;P ∨ Q&lt;&#x2F;code&gt; holds little worth, as we know either &lt;code&gt;P&lt;&#x2F;code&gt; or &lt;code&gt;Q&lt;&#x2F;code&gt;. This is why &lt;code&gt;erule&lt;&#x2F;code&gt; automatically discharges the first goal and deletes the already-held assumption.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;drule&quot;&gt;&lt;code&gt;drule&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;For the sake of example, recall (one of) the conjunction elimination rules:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt; ∧ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;----- conjunct1
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This rule is more specifically called a &quot;destruction&quot; rule, as it takes apart (destroys) the original term (here the conjunction) and concludes with one of its subterms. The &lt;code&gt;d&lt;&#x2F;code&gt; in &lt;code&gt;drule&lt;&#x2F;code&gt; therefore stands for &lt;code&gt;destruction&lt;&#x2F;code&gt; or &lt;code&gt;destroy&lt;&#x2F;code&gt;. Destruction rules are used for forwards-reasoning, as you move &quot;forwards down&quot; the rule.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;apply (drule conjunct1)&lt;&#x2F;code&gt; hence replaces an assumption of form &lt;code&gt;P ∧ Q&lt;&#x2F;code&gt; with one of &lt;code&gt;P&lt;&#x2F;code&gt;, deleting the original &lt;code&gt;P ∧ Q&lt;&#x2F;code&gt; assumption.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt; ∧ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;apply (drule conjunct1)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;frule&quot;&gt;&lt;code&gt;frule&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;frule&lt;&#x2F;code&gt; functions the same as &lt;code&gt;drule&lt;&#x2F;code&gt;, but does not delete the original premise. The &lt;code&gt;f&lt;&#x2F;code&gt; stands for &lt;code&gt;forwards&lt;&#x2F;code&gt;, as it is used for forwards-reasoning.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt; ∧ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;apply (frule conjunct1)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;⟦ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt; ∧ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt; ⟧ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;useful-related-tools&quot;&gt;Useful related tools&lt;&#x2F;h2&gt;
&lt;p&gt;For all the above rule methods, &lt;code&gt;[of P₁ P₂ ... Pₙ]&lt;&#x2F;code&gt; can be used to explicitly instantiate them instead of using the &lt;code&gt;rule_tac&lt;&#x2F;code&gt; family (which is explained below). This instantiates left-to-right by occurence, so with&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span&gt;thm conjI (* ⟦&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span&gt;⟧ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; ?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt; ∧ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span&gt; *)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;conjI [of A B]&lt;&#x2F;code&gt; will result in the instantiation &lt;code&gt;⟦A; B⟧ ==&amp;gt; A ∧ B&lt;&#x2F;code&gt;, from where the rule will proceed.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt; ∧ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Isabelle&lt;&#x2F;span&gt;&lt;span&gt; can solve this on its own, but for the sake &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of&lt;&#x2F;span&gt;&lt;span&gt; example&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.
&lt;&#x2F;span&gt;&lt;span&gt;apply (rule conjI [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A B&lt;&#x2F;span&gt;&lt;span&gt;])
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;. &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;. &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Notably, &lt;code&gt;[of ...]&lt;&#x2F;code&gt; does still work with the &lt;code&gt;_tac&lt;&#x2F;code&gt; family, but there is (as far as I know) no reason to use it over &lt;code&gt;_tac&lt;&#x2F;code&gt;&#x27;s explicit instantiation. Speaking of:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-tac-suffixes&quot;&gt;The &lt;code&gt;_tac&lt;&#x2F;code&gt; suffixes&lt;&#x2F;h2&gt;
&lt;p&gt;For each of the above,  there is a corresponding &lt;code&gt;_tac&lt;&#x2F;code&gt; (standing for tactic): &lt;code&gt;rule_tac&lt;&#x2F;code&gt;, &lt;code&gt;drule_tac&lt;&#x2F;code&gt;, etc. These &lt;code&gt;_tac&lt;&#x2F;code&gt;s are slightly more powerful than their &lt;code&gt;_tac&lt;&#x2F;code&gt;less equivalents. Firstly, each allows for the various premises to be explicitly instantiated by name. For example, with the &lt;code&gt;conjI&lt;&#x2F;code&gt; rule, one could explicitly write&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span&gt;thm conjI (* ⟦&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span&gt;⟧ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; ?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt; ∧ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span&gt; *)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt; ⋀ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;apply (rule_tac &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt; and &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt; conjI)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;. &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;. &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This allows the rule to refer to meta-forall-bound variables, which most commonly arise when performing induction or similar. For a goal of form:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt; n
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;with some &lt;code&gt;n :: nat&lt;&#x2F;code&gt; mentioned in &lt;code&gt;P&lt;&#x2F;code&gt;, performing &lt;code&gt;apply (induction n)&lt;&#x2F;code&gt; will generate the goals&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P 0 
&lt;&#x2F;span&gt;&lt;span&gt;⋀ nat&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;. &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt; nat &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Suc&lt;&#x2F;span&gt;&lt;span&gt; nat) (* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Variable&lt;&#x2F;span&gt;&lt;span&gt; naming may differ&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; *)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;nat&lt;&#x2F;code&gt; is a meta-forall bound variable. This functions as expected; during the induction step of an inductive proof, we must prove that for any &lt;code&gt;nat&lt;&#x2F;code&gt;, &lt;code&gt;P nat ==&amp;gt; P (Suc nat)&lt;&#x2F;code&gt;. Because it is meta-forall bound, &lt;code&gt;rule&lt;&#x2F;code&gt; and friends cannot refer to &lt;code&gt;nat&lt;&#x2F;code&gt; directly using &lt;code&gt;[of ...]&lt;&#x2F;code&gt; (Although, automatic unification can work). Instead, we must use &lt;code&gt;rule_tac&lt;&#x2F;code&gt; and friends to refer to it. I am not quite sure why this is, but I presume it is due to internal complexities around the meta-forall.&lt;&#x2F;p&gt;
&lt;details&gt;&lt;summary&gt;A small artificial example of this difference, if the above is not clear.&lt;&#x2F;summary&gt;
&lt;p&gt;Recall that &lt;code&gt;[of ...]&lt;&#x2F;code&gt; can be used to explicitly instantiate:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span&gt;lemma without_forall&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;A ∧ B ==&amp;gt; A&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  apply (erule conjE [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;]) (* succeeds *)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;lemma with_forall&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;⋀ a b. a ∧ b ==&amp;gt; a&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  apply (erule conjE [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of&lt;&#x2F;span&gt;&lt;span&gt; a]) (* fails *)
&lt;&#x2F;span&gt;&lt;span&gt;  apply (erule_tac &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt; conjE) (* succeeds *)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;These lemmas are otherwise equivalent; only their presentation differs.&lt;&#x2F;p&gt;
&lt;&#x2F;details&gt;
&lt;p&gt;In general, these &lt;code&gt;_tac&lt;&#x2F;code&gt; methods have the form&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span&gt;rule_tac v₁ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; t₁ and v₂ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; t₂ and &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt; and vₙ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; tₙ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;RULE
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;where &lt;code&gt;vₙ&lt;&#x2F;code&gt; is a variable occuring in &lt;code&gt;RULE&lt;&#x2F;code&gt;, and &lt;code&gt;tₙ&lt;&#x2F;code&gt; is a locally bound variable or assumption. Any combination of zero or more of the variables occuring in &lt;code&gt;RULE&lt;&#x2F;code&gt; may be used, in any order.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;_tac&lt;&#x2F;code&gt; methods have an additional advantage, which is that they can be told to refer to a specific goal. If we have goals of the form&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;. &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt; ∧ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;. &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt; ∧ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;==&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;R
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;erule conjE&lt;&#x2F;code&gt; and friends will by default refer to the first goal. Using &lt;code&gt;erule_tac [i] conjE&lt;&#x2F;code&gt;, we can refer to the &lt;code&gt;ith&lt;&#x2F;code&gt; goal (1-indexed.) When combining this with specifying variables, the goal specifier comes first. (i.e., &lt;code&gt;apply (erule_tac [1] P=a in conjE)&lt;&#x2F;code&gt;.)&lt;&#x2F;p&gt;
&lt;h1 id=&quot;rule-erule-drule-and-frule-more-formally&quot;&gt;&lt;code&gt;rule&lt;&#x2F;code&gt;, &lt;code&gt;erule&lt;&#x2F;code&gt;, &lt;code&gt;drule&lt;&#x2F;code&gt;, and &lt;code&gt;frule&lt;&#x2F;code&gt;, (more) formally&lt;&#x2F;h1&gt;
&lt;p&gt;This section is almost entirely copied from the aformentioned Isabelle&#x2F;HOL tutorial.&lt;&#x2F;p&gt;
&lt;p&gt;Given an arbitrary rule R of the form:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt;₁ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;P&lt;&#x2F;span&gt;&lt;span&gt;₂ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;... &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Pₙ
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;------------  R
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Q
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For elimination rules, &lt;code&gt;P₁&lt;&#x2F;code&gt; is referred to as the &quot;Major premise&quot;. This will usually be the object being eliminated. In &lt;code&gt;disjE&lt;&#x2F;code&gt; for example, it is &lt;code&gt;P ∨ Q&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Method &lt;code&gt;rule&lt;&#x2F;code&gt; unifies &lt;code&gt;Q&lt;&#x2F;code&gt; with the current subgoal, and replaces it with the &lt;code&gt;n&lt;&#x2F;code&gt; subgoals &lt;code&gt;P₁ ... Pₙ&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Method &lt;code&gt;erule&lt;&#x2F;code&gt; unifies &lt;code&gt;Q&lt;&#x2F;code&gt; with the current subgoal, and &lt;code&gt;P₁&lt;&#x2F;code&gt; with the first suitable assumption. The subgoal is then replaced with the &lt;code&gt;n - 1&lt;&#x2F;code&gt; subgoals &lt;code&gt;P₂ ... Pₙ&lt;&#x2F;code&gt;, and the assumption &lt;code&gt;P₁&lt;&#x2F;code&gt; is deleted.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Method &lt;code&gt;drule&lt;&#x2F;code&gt; unifies &lt;code&gt;P₁&lt;&#x2F;code&gt; with the first suitable assumption, which it then deletes. It then adds the &lt;code&gt;n - 1&lt;&#x2F;code&gt; subgoals &lt;code&gt;P₂ ... Pₙ&lt;&#x2F;code&gt;, and the original subgoal gains the assumption &lt;code&gt;Q&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Method &lt;code&gt;frule&lt;&#x2F;code&gt; is like &lt;code&gt;drule&lt;&#x2F;code&gt;, but it does not delete &lt;code&gt;P₁&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Crafting a dependent typechecker, part 1</title>
        <published>2025-07-19T00:00:00+00:00</published>
        <updated>2025-07-19T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/dependent-p1/"/>
        <id>https://blueberrywren.dev/blog/dependent-p1/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/dependent-p1/">&lt;p&gt;This series is intended to give an interested layperson some idea of what goes on behind-the-scenes in a dependent typechecker, and how they might implement one of their own.&lt;&#x2F;p&gt;
&lt;p&gt;I personally hold the belief that dependent languages (or similar) will eventually be the future of programming, so knowing this information seems worthwhile to me. One may also simply be interested for the sake of it, or may be interested in implementing their own dependent language.&lt;&#x2F;p&gt;
&lt;p&gt;This series does assume a small base amount of knowledge around dependent programming languages. There are many tutorials out there far better than I could provide, so I will refer the reader to the wider internet if they are curious. (Return here afterwards, though!).&lt;&#x2F;p&gt;
&lt;p&gt;Additionally, the code snippets will be in OCaml, although a Haskell or Rust version may be made available at a later date.&lt;&#x2F;p&gt;
&lt;p&gt;The technique we will implement in this series can most succinctly be described as &quot;Bidirectional typechecking, utilizing Normalization by Evaluation&quot;. I do not expect the reader to understand that sentence for at least a little while ;).&lt;&#x2F;p&gt;
&lt;p&gt;All code snippets will be collated at the end of each page, so scroll all the way down if you&#x27;re only interested in that.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;&#x2F;h2&gt;
&lt;p&gt;The following are resources I highly recommend for exploring this topic on your own.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;András Kovacs&#x27; &quot;Elaboration Zoo&quot;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;AndrasKovacs&#x2F;elaboration-zoo&quot;&gt;found here&lt;&#x2F;a&gt;. It was a primary source of inspiration for this series.&lt;&#x2F;li&gt;
&lt;li&gt;&quot;A tutorial implementation of a dependently typed lambda calculus&quot;, by Andres Löh, Conor McBride, and Wouter Swierstra; &lt;a href=&quot;https:&#x2F;&#x2F;www.andres-loeh.de&#x2F;LambdaPi&#x2F;LambdaPi.pdf&quot;&gt;found here&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&quot;Checking Dependent Types with Normalization by Evaluation: A Tutorial&quot;, by David Christiansen, &lt;a href=&quot;https:&#x2F;&#x2F;davidchristiansen.dk&#x2F;tutorials&#x2F;nbe&#x2F;&quot;&gt;found here&lt;&#x2F;a&gt;, for the more lisp-minded.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;the-fundamental-operation-of-typechecking&quot;&gt;The fundamental operation of typechecking&lt;&#x2F;h2&gt;
&lt;p&gt;If you have implemented a typechecker before, you may have come to the realization that deciding when two things are the same is a very large component of typechecking. Whether it be simply checking that two arguments to &lt;code&gt;+&lt;&#x2F;code&gt; are both integers, or larger problems with polymorphism, the arguable core of typechecking is deciding equality.&lt;&#x2F;p&gt;
&lt;p&gt;In a dependent language, our types can (and often do) contain expressions that must be evaluated. Therefore, in order to explore how we check equality in the presence of evaluation, we will first start by considering how we do this for a very simple language - integer arithmetic. Take two expressions:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;17 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;4 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;4 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;4 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;3
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;How might we decide whether these are equal? The obvious solution is to evaluate them. Indeed, (sparing the reader the derivation), we can see they both evaluate to &lt;code&gt;36&lt;&#x2F;code&gt;, and so they are equal.&lt;&#x2F;p&gt;
&lt;p&gt;Let us now introduce a small extension: Variables with a known value, using &quot;let&quot;. We will refer to the variables themselves as &quot;bound variables&quot;, as they are bound by the &quot;let&quot;. In this case, they are additionally bound to a value. Terms containing only bound variables are referred to &quot;closed&quot; terms - this alludes to, for example, closed and open systems in the real world. Getting back to evaluation, we could simply substitute the computed value:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;: x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;13 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;39
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;substitute&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;: (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;13 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;39
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then evaluate. (In this case, our result is 117.) However, what if the variable occurs multiple times? The following is a little bad, but not awful:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;: x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;substitute&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;: (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But what if &lt;code&gt;x&lt;&#x2F;code&gt; was the following?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;8 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;3 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;14 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;8 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;14 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;3 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;18 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;3 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;6 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;12 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;4 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;6 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;18 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;14 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;3 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;4 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;3 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;12 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;18 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;4 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Duplicating that would clearly not be ideal!&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps we could compute &lt;code&gt;x&lt;&#x2F;code&gt; in advance, and then substitute that result in. This is much better:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;evaluate and substitute&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;61&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;61 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;61&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;5
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(In fact, there is yet another optimization to do: What if we don&#x27;t need to compute it at all, say because it&#x27;s not used? We will explore this possibility later.)&lt;&#x2F;p&gt;
&lt;p&gt;A simple OCaml interpretation of the terms of this language may be the following.
(sidetrack: A &quot;term&quot; is some element of a language. Above, we have the language of (restricted) integer arithmetic, and our terms are expressions of said. Hence, we call our OCaml interpretation of this language &lt;code&gt;term&lt;&#x2F;code&gt;.)&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;variable &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;string
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term &lt;&#x2F;span&gt;&lt;span&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;    | Literal &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int 
&lt;&#x2F;span&gt;&lt;span&gt;    | Name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;variable 
&lt;&#x2F;span&gt;&lt;span&gt;    | Mul &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term 
&lt;&#x2F;span&gt;&lt;span&gt;    | Exp &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term 
&lt;&#x2F;span&gt;&lt;span&gt;    | Add &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term 
&lt;&#x2F;span&gt;&lt;span&gt;    | Sub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term 
&lt;&#x2F;span&gt;&lt;span&gt;    | Let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;variable &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term 
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* let x = ...; ... *)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We then must make an environment that associates, or &quot;binds&quot;, our names to terms. &lt;code&gt;Let&lt;&#x2F;code&gt; is often called a &quot;binder&quot; because it functions as the source of this binding. We will make our context a list of pairs &lt;code&gt;(variable name, term)&lt;&#x2F;code&gt;, and will reimpliement the lookup function for example&#x27;s sake, although a suitable function is available as &lt;code&gt;List.assoc&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;environment &lt;&#x2F;span&gt;&lt;span&gt;= (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;variable &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;list
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let rec &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;lookup &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;env &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: environment&lt;&#x2F;span&gt;&lt;span&gt;) (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;name &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: variable&lt;&#x2F;span&gt;&lt;span&gt;) : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; env &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;with
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* See note below. *)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;[] &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; failwith (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;Variable &amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span&gt; name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot; not found.&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;nm&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;) :: &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;rest &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; nm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;then
&lt;&#x2F;span&gt;&lt;span&gt;            value
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;else
&lt;&#x2F;span&gt;&lt;span&gt;            lookup rest name
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note: In this series, we will not be considering the possibility that a name is used without being previously defined in some way. This is an error, and can be handled via normal means, e.g. a suitable error message.&lt;&#x2F;p&gt;
&lt;p&gt;We now note something curious: Our lookup function need not return a fully computed value! It could return &lt;code&gt;7 + 2&lt;&#x2F;code&gt;, which we would have to further evaluate before we could do anything with. It would be possible of course to manually insert invariants ensuring that this is not the case, but we could still accidentally violate them.&lt;&#x2F;p&gt;
&lt;p&gt;Here we hit one of the most important distinctions in our exploration of dependent typechecking.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;terms-vs-values&quot;&gt;Terms vs. Values&lt;&#x2F;h2&gt;
&lt;p&gt;A &quot;term&quot;, as previously seen, is any element of a chosen language. Above, this was (some subset of) integer arithmetic. We could also consider the language of OCaml programs, of which the above examples would be terms. However, two terms are not always easy to compare. We may need to evaluate one, or both, and we don&#x27;t know whether that will be needed until we start comparing them.&lt;&#x2F;p&gt;
&lt;p&gt;Instead, what if we defined another type that was guaranteed to be reduced to some suitable level? For this simple case, we could restrict this to contain only fully evaluated terms (i.e., integers). We&#x27;ll call these &quot;values&quot;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;value &lt;&#x2F;span&gt;&lt;span&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;    | VLiteral &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We prefix these constructors with &lt;code&gt;V&lt;&#x2F;code&gt; to ensure they&#x27;re distinct, and to remind us that they construct values. Then, we could modify our environment and lookup function to only deal with values:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- type&lt;&#x2F;span&gt;&lt;span&gt; environment &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;(variable &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; term) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;list
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+ type&lt;&#x2F;span&gt;&lt;span&gt; environment &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;(variable &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; value) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;list
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- let rec &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;lookup &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;env &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: environment&lt;&#x2F;span&gt;&lt;span&gt;) (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;name &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: variable&lt;&#x2F;span&gt;&lt;span&gt;) : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+ let rec &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;lookup &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;env &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: environment&lt;&#x2F;span&gt;&lt;span&gt;) (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;name &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: variable&lt;&#x2F;span&gt;&lt;span&gt;) : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;value &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and now we know that &lt;code&gt;lookup&lt;&#x2F;code&gt; will always return something we can handle immediately, with no further processing.&lt;&#x2F;p&gt;
&lt;p&gt;In the general case, we call this &quot;suitably-reduced&quot; constraint a &quot;normal form&quot;. We can say that &lt;code&gt;value&lt;&#x2F;code&gt; contains only elements of &lt;code&gt;term&lt;&#x2F;code&gt; in this chosen normal form.&lt;&#x2F;p&gt;
&lt;p&gt;Now we can finish our little evaluator. We do a slight hack to perform arithmetic inside values; if our value type contained more than just the constructor &lt;code&gt;VLiteral&lt;&#x2F;code&gt;, we would have to consider how to handle that case. This is something we will cover soon.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* OCaml does not have integer exponentiation by default. Definition omitted. *)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;pow &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: int&lt;&#x2F;span&gt;&lt;span&gt;) (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: int&lt;&#x2F;span&gt;&lt;span&gt;) : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; ...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let rec &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;do_op &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;op &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: int -&amp;gt; int -&amp;gt; int&lt;&#x2F;span&gt;&lt;span&gt;) (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: value&lt;&#x2F;span&gt;&lt;span&gt;) (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: value&lt;&#x2F;span&gt;&lt;span&gt;) : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;value &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* Hack: This is only valid because we know our value type has one constructor, VLiteral. *)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;VLiteral va &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;VLiteral vb &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;    VLiteral (op va vb)
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let rec &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;eval &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;env &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: environment&lt;&#x2F;span&gt;&lt;span&gt;) (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;tm &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: term&lt;&#x2F;span&gt;&lt;span&gt;) : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;value &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; tm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;with
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Literal &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;i &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; VLiteral i
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Name &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;nm &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; lookup env nm
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Mul (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; do_op ( &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; ) (eval env a) (eval env b)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Exp (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; do_op pow   (eval env a) (eval env b)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Add (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; do_op ( &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt; ) (eval env a) (eval env b)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Sub (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; do_op ( &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; ) (eval env a) (eval env b)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Let (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;nm&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;rest&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;result &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; eval env def &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;new_env &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;(nm, result) :: env &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;        eval new_env rest
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In the &lt;code&gt;Let&lt;&#x2F;code&gt; case, we compute the definition first, then extend our environment with the new name and value before computing the rest of the expression.&lt;&#x2F;p&gt;
&lt;p&gt;We then, by returning a &lt;code&gt;value&lt;&#x2F;code&gt;, have a guarantee that whatever comes out of &lt;code&gt;eval&lt;&#x2F;code&gt; is as simple as we want it to be.&lt;&#x2F;p&gt;
&lt;p&gt;Comparing for equality is then very simple: We use &lt;code&gt;eval&lt;&#x2F;code&gt; to evaluate our terms into values, then because our values are in a nice normal form, we have the guarantee that we can compare them easily, with no further evaluation needed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap up&lt;&#x2F;h2&gt;
&lt;p&gt;So far we have covered:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Languages and terms.&lt;&#x2F;li&gt;
&lt;li&gt;Simple evaluation strategies for let bound variables &amp;amp; closed terms.&lt;&#x2F;li&gt;
&lt;li&gt;Values and normal forms.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;In the next part, we will explore how to take these concepts and apply them to something much closer to a &quot;real&quot; programming language, with &lt;code&gt;lambda&lt;&#x2F;code&gt; expressions and application, which will require the introduction of a &quot;closure&quot;. From there, we can explore how to deal with open terms, containing free variables, and onwards to dependent types.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;code&quot;&gt;Code&lt;&#x2F;h2&gt;
&lt;details&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;variable &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;string
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term &lt;&#x2F;span&gt;&lt;span&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;    | Literal &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int 
&lt;&#x2F;span&gt;&lt;span&gt;    | Name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;variable 
&lt;&#x2F;span&gt;&lt;span&gt;    | Mul &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term 
&lt;&#x2F;span&gt;&lt;span&gt;    | Exp &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term 
&lt;&#x2F;span&gt;&lt;span&gt;    | Add &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term 
&lt;&#x2F;span&gt;&lt;span&gt;    | Sub &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term 
&lt;&#x2F;span&gt;&lt;span&gt;    | Let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;variable &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;term 
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* let x = ...; ...*)
&lt;&#x2F;span&gt;&lt;span&gt;      
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;value &lt;&#x2F;span&gt;&lt;span&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;    | VLiteral &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;of &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int
&lt;&#x2F;span&gt;&lt;span&gt;      
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;environment &lt;&#x2F;span&gt;&lt;span&gt;= (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;variable &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;list
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let rec &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;lookup &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;env &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: environment&lt;&#x2F;span&gt;&lt;span&gt;) (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;name &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: variable&lt;&#x2F;span&gt;&lt;span&gt;) : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;value &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; env &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;with
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* See note below. *)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;[] &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; failwith (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;Variable &amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span&gt; name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;^ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot; not found.&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;nm&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;) :: &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;rest &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; nm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;then
&lt;&#x2F;span&gt;&lt;span&gt;            value
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;else
&lt;&#x2F;span&gt;&lt;span&gt;            lookup rest name
&lt;&#x2F;span&gt;&lt;span&gt;      
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* OCaml does not have integer exponentiation by default. Definition omitted. *)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;pow &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: int&lt;&#x2F;span&gt;&lt;span&gt;) (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: int&lt;&#x2F;span&gt;&lt;span&gt;) : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; ...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let rec &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;do_op &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;op &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: int -&amp;gt; int -&amp;gt; int&lt;&#x2F;span&gt;&lt;span&gt;) (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: value&lt;&#x2F;span&gt;&lt;span&gt;) (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: value&lt;&#x2F;span&gt;&lt;span&gt;) : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;value &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;(* Hack: This is only valid because we know our value type has one constructor, VLiteral. *)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;VLiteral va &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;VLiteral vb &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;    VLiteral (op va vb)
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let rec &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;eval &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;env &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: environment&lt;&#x2F;span&gt;&lt;span&gt;) (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;tm &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;: term&lt;&#x2F;span&gt;&lt;span&gt;) : &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;value &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; tm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;with
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Literal &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;i &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; VLiteral i
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Name &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;nm &lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; lookup env nm
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Mul (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; do_op ( &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; ) (eval env a) (eval env b)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Exp (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; do_op pow   (eval env a) (eval env b)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Add (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; do_op ( &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt; ) (eval env a) (eval env b)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Sub (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; do_op ( &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; ) (eval env a) (eval env b)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;Let (&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;nm&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;rest&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;result &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; eval env def &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;new_env &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;(nm, result) :: env &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in
&lt;&#x2F;span&gt;&lt;span&gt;        eval new_env rest
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;details&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Debruijn indexes and levels, and why they&#x27;re handy</title>
        <published>2025-05-26T00:00:00+00:00</published>
        <updated>2025-05-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/debruijn-explanation/"/>
        <id>https://blueberrywren.dev/blog/debruijn-explanation/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/debruijn-explanation/">&lt;script&gt;
 function r(str) {
while (str.charAt(0) == &#x27; &#x27;) {
  	str = str.slice(1);
  }
  return str;
}

function get_args(str) {
 	str = r(str);
  if (str == &quot;&quot;) {
  	return [&quot;&quot;, []]
  }
  else if (str.charAt(0) == &#x27;.&#x27;) {
  	return [str.slice(1), []];
  }
  let [rest, l] = get_args(str.slice(1));
  return [rest, [str.charAt(0)].concat(l)];
}

function parse_app(str) {
	str = r(str);
  if (str == &quot;&quot;) {
  	return [&quot;&quot;, []];
  }
  else if (str.charAt(0) == &#x27;(&#x27;) {
  	let [rest, l] = parse(str.slice(1));
    let [rest1, k] = parse_app(rest);
    return [rest1, [l].concat(k)];
  }
  else if (str.charAt(0) == &#x27;)&#x27;) {
  	return [str.slice(1), []]
  } else {
  	let c = str.charAt(0);
    let [rest, l] = parse_app(str.slice(1));
    return [rest, [c].concat(l)];
  }
}

function parse(str) {
	str = r(str);
  if (str == &quot;&quot;) {
  	return [&quot;&quot;, {}]
  }
  else if (str.charAt(0) == &#x27;\\&#x27;) {
  	let [rest, a] = get_args(str.slice(1));
    let [rest1, bd] = parse_app(rest);
    return [rest1, {args : a, bd}]
  } else {
  	return parse_app(str);
  }
}

function iso(x) {
return typeof x === &#x27;object&#x27; &amp;&amp; !Array.isArray(x) &amp;&amp; x !== null;
}

function islist(x) {
return (x.constructor.name == &quot;Array&quot;)
}

function helper(args, p) {
let r = [];
for (let l of p) {
  if (iso(l)) {
  	r.push(debru_h(args, l));
  } else if (islist(l)) {
  	r.push(helper(args, l));
  }
  else {
    	r.push(args.indexOf(l));
  }
  }
  return r;
}

function debru_h(arg, p) {
	let args = p.args.reverse().concat(arg);
 	return {l : p.args.length, bd : helper(args, p.bd)};
}

function debru(p) {
	let [_, bd] = p;
 	return debru_h([], bd);
}

function printer(p) {
	if (iso(p)) {
  	let rest = p.bd;
    return &quot;(&quot; + &quot;λ &quot;.repeat(p.l) + printer(rest) + &quot;)&quot;;
  }
  else if (islist(p)) {
  	k = &quot;&quot;;
  	for (let e of p) {
    	k += &quot; &quot; + printer(e);
    }
    return &quot;(&quot; + k.slice(1) + &quot;)&quot;;
  }
  else {
   	return p;
  }
}
&lt;&#x2F;script&gt;
&lt;h2 id=&quot;assumed-knowledge&quot;&gt;Assumed knowledge&lt;&#x2F;h2&gt;
&lt;p&gt;At least a familiarity with the lambda calculus, including how it is evaluated. Some base knowledge of programming languages is also assumed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;The problem&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s look at a little imaginary term, in some lambda-calculus-like language. For future note, we call the lambda a &quot;binder&quot;, as it binds a variable. There are other types of binders, e.g. &lt;code&gt;let&lt;&#x2F;code&gt;, but we will only consider lambdas for the moment.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span&gt;λ f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; (λ y f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; (f y)) f
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can perform what&#x27;s called &quot;beta reduction&quot; on this term — essentially, function application, applying &lt;code&gt;f&lt;&#x2F;code&gt; to the lambda.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span&gt;λ f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; (λ y f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; (f y)) (f)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;substitute [y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;:=&lt;&#x2F;span&gt;&lt;span&gt; f] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt; λ y f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; (f y)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;λ f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; (λ f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; f f)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Uh oh. We&#x27;ve accidentally captured a variable! Instead of &lt;code&gt;f&lt;&#x2F;code&gt; referring to the outer &lt;code&gt;f&lt;&#x2F;code&gt;, now it refers to the inner &lt;code&gt;f&lt;&#x2F;code&gt;. This is &quot;the capture problem&quot;, and it is quite annoying. Generally to avoid this, we need to rename &lt;em&gt;everything&lt;&#x2F;em&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; in our &quot;substituted&quot; term to names that are free (do not occur) in the &quot;subsitutee&quot; so nothing is accidentally captured. What if we could introduce a notation that avoids this?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;presenting-de-bruijn-indexes&quot;&gt;Presenting: De Bruijn Indexes!&lt;&#x2F;h2&gt;
&lt;p&gt;De Bruijn indexes are a naming scheme where:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We use natural numbers to refer to lambdas, and&lt;&#x2F;li&gt;
&lt;li&gt;Zero refers to the &quot;most recent&quot; lambda; one refers to the second most recent, etc.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Let&#x27;s rewrite that term above using this system:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span&gt;λ (λ λ (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0 1&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here&#x27;s some ascii art showing what refers to what:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span&gt; λ   (λ   λ   (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0   1&lt;&#x2F;span&gt;&lt;span&gt;))   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0
&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;|    |    \&lt;&#x2F;span&gt;&lt;span&gt;———&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&#x2F;   |     |
&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;|    |            |     |
&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;|    \&lt;&#x2F;span&gt;&lt;span&gt;————————————&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&#x2F;     |
&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;\&lt;&#x2F;span&gt;&lt;span&gt;———————————————————————&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, how does this help us with our substitution problem? Surely if we naively subtitute we will still have binding issues - and indeed we do:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span&gt;λ (λ λ (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0 1&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;λ (λ (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0 0&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;No good!&lt;&#x2F;p&gt;
&lt;p&gt;What De Bruijn indexes allow us to do is simply avoid capturing. The rule is simple: Every time we go past a binder when substituting, we increment every free variable&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; in our substituted term by one, to avoid the new binder. Just once, we decrement every free varible in the substitutee, to account for the removal of the binder:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span&gt; λ (λ λ (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1 2&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0
&lt;&#x2F;span&gt;&lt;span&gt; ^  ^ ^
&lt;&#x2F;span&gt;&lt;span&gt; a  b c
&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt; λ (λ (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1 1&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt; ^  ^  ^ ^ 
&lt;&#x2F;span&gt;&lt;span&gt; a  b  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;| \&lt;&#x2F;span&gt;&lt;span&gt; decremented by one
&lt;&#x2F;span&gt;&lt;span&gt;       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;|
&lt;&#x2F;span&gt;&lt;span&gt;       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;\&lt;&#x2F;span&gt;&lt;span&gt; incremented by one when we passed &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e6db74;&quot;&gt;&amp;quot;through&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; lambda c
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we&#x27;re cool! Everything works as expected, and it takes much less work (and is much more predictable!).&lt;&#x2F;p&gt;
&lt;p&gt;At the bottom of this post there&#x27;s a little widget that can convert terms to de Bruijn for you, if you want to play around!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;presenting-de-bruijn-levels&quot;&gt;Presenting: De Bruijn levels!&lt;&#x2F;h2&gt;
&lt;p&gt;De Bruijn levels work similar to De Bruijn indexes, in that we use numbers to refer to binders. However, in De Bruijn levels, the lowest number refers to the &lt;em&gt;least&lt;&#x2F;em&gt; recently bound item.&lt;&#x2F;p&gt;
&lt;p&gt;Recall that:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Named&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;   λ f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; (λ y f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; (f y)) f
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Indexes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; λ (λ λ (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0 1&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, with levels:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Levels&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;  λ (λ λ (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 1&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This has the same diagram of what refers to what:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span&gt; λ   (λ   λ   (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2   1&lt;&#x2F;span&gt;&lt;span&gt;))   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0
&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;|    |    \&lt;&#x2F;span&gt;&lt;span&gt;———&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&#x2F;   |     |
&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;|    |            |     |
&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;|    \&lt;&#x2F;span&gt;&lt;span&gt;————————————&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&#x2F;     |
&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;\&lt;&#x2F;span&gt;&lt;span&gt;———————————————————————&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(As it should! These two representations represent the same term.)&lt;&#x2F;p&gt;
&lt;p&gt;As you might expect, de Bruijn indexes and levels are each beneficial in their own situations.&lt;&#x2F;p&gt;
&lt;p&gt;Generally, De Bruijn indexes are &quot;more useful&quot; than De Bruijn levels, as they&#x27;re &quot;more local&quot;. In order to work with levels, you need to know &quot;how deep&quot; you are in a term at all times.&lt;&#x2F;p&gt;
&lt;p&gt;De Bruijn indexes give us the advantage that we can freely create new binders without the need for any information about where in a term we are, whereas de Bruijn levels give us the advantage when moving a term under a binder, free variables in said term do not need to be modified. Generally, one has many more free variables in a term than bound ones.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span&gt; λ (λ λ (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 1&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0
&lt;&#x2F;span&gt;&lt;span&gt;               ^ this zero&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt; λ (λ (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1 0&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;       ^ ^ is still zero&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;!
&lt;&#x2F;span&gt;&lt;span&gt;       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;|
&lt;&#x2F;span&gt;&lt;span&gt;       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;\&lt;&#x2F;span&gt;&lt;span&gt; we had to modify this one though
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;other-advantages&quot;&gt;Other advantages&lt;&#x2F;h2&gt;
&lt;p&gt;Something that can come up quite a lot in various contexts is comparing whether two terms are equal or not. There are many complicated ways to do so, but de Bruijn gives us an advantage in a critical one, called &quot;alpha-equivalence&quot;. Consider the following two terms:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span&gt;λf&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; λx&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; f x
&lt;&#x2F;span&gt;&lt;span&gt;λg&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; λy&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; g y
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;These terms should clearly be equal, right? They do the exact same thing. In this case, we consider them &quot;alpha-equivalent&quot;, meaning they are equal up to the names of variables. Alpha renaming is the process of renaming one term to match the names of another, so that they are &quot;clearly&quot; equal.&lt;&#x2F;p&gt;
&lt;p&gt;Let us consider the de Bruijn index representation of both of these terms:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span&gt;λf&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; λx&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; f x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; λ λ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1 0
&lt;&#x2F;span&gt;&lt;span&gt;λg&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; λy&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; g y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; λ λ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1 0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Isn&#x27;t that nice? They&#x27;ve gone from being alpha-equivalent, but not quite equal, to being equal. de Bruijn gives us the ability to compare terms for equality without having to consider alpha-equivalence at all.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrapup&quot;&gt;Wrapup&lt;&#x2F;h2&gt;
&lt;p&gt;De Bruijn indexes and levels can also be summed up via the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span&gt;λa&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; λb&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; λc&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt; c
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;indexes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;λ λ λ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0
&lt;&#x2F;span&gt;&lt;span&gt;^ ^ ^
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2 1 0
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;levels&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;λ λ λ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2
&lt;&#x2F;span&gt;&lt;span&gt;^ ^ ^
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0 1 2
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;if you’re “here”&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;  v
&lt;&#x2F;span&gt;&lt;span&gt;λ λ λ
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;Using indexes, adding any binders further left doesn’t affect the current binder&#x27;s variables, or any further right.&lt;&#x2F;li&gt;
&lt;li&gt;Using levels, adding any binders further right doesn’t affect the current binder&#x27;s variables, or any further left.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;de-bruijn-index-widget&quot;&gt;De Bruijn index widget&lt;&#x2F;h2&gt;
&lt;p&gt;Try it out! Some example terms to try:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#272822;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;\f x. f x
&lt;&#x2F;span&gt;&lt;span&gt;\x x. x
&lt;&#x2F;span&gt;&lt;span&gt;\x. (x (\y. y))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;\x. \y. y x -- will not work
&lt;&#x2F;span&gt;&lt;span&gt;do \x. (\y. y x) or \x y. y x instead
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(sorry, it does over-parenthesize a bit :P)&lt;&#x2F;p&gt;
&lt;input name=&quot;searchTxt&quot; type=&quot;text&quot; maxlength=&quot;512&quot; id=&quot;searchTxt&quot; class=&quot;searchField&quot; placeholder=&quot;Type here!&quot;&#x2F;&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot; id=&quot;goober&quot;&gt;
&lt;p&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;script&gt;
document.getElementById(&#x27;searchTxt&#x27;).style.height=&quot;100px&quot;;
document.getElementById(&#x27;searchTxt&#x27;).style.fontSize=&quot;14pt&quot;;

&#x2F;&#x2F;creates a listener for when you press a key
window.onkeyup = keyup;
 var inputTextValue;

function keyup(e) {
  &#x2F;&#x2F;setting your input text to the global Javascript Variable for every key press
  inputTextValue = document.getElementById(&#x27;searchTxt&#x27;).value;

  &#x2F;&#x2F;listens for you to press the ENTER key, at which point your web address will change to the one you have input in the search box
	
  let p = parse(&quot;\\_. (&quot; + inputTextValue + &quot;)&quot;);
	let k = debru(p);
  let s = printer(k);
	let sp = s.slice(5).slice(0,-3);
  const thing = document.getElementById(&#x27;goober&#x27;);
  thing.innerHTML = &quot;&lt;span&gt;&quot; + sp + &quot;&lt;&#x2F;span&gt;&quot;
}
&lt;&#x2F;script&gt;
&lt;h2 id=&quot;alternatives&quot;&gt;Alternatives&lt;&#x2F;h2&gt;
&lt;p&gt;It is worth noting that there are several other methods for gaining the same, or similar, advantages as de Bruijn gives. This post is not intended to explain them, but I will list several here so that the curious reader may read further (tip: when searching, append &quot;lambda calculus&quot; to find the right results quicker):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;HOAS, or &quot;Higher Order Abstract Syntax&quot;&lt;&#x2F;li&gt;
&lt;li&gt;PHOAS, or &quot;Parametric HOAS&quot;&lt;&#x2F;li&gt;
&lt;li&gt;Locally nameless&lt;&#x2F;li&gt;
&lt;li&gt;Nominal signatures&lt;&#x2F;li&gt;
&lt;li&gt;Well-scoped de Bruijn indices&lt;&#x2F;li&gt;
&lt;li&gt;Well-scoped names&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;doi.acm.org&#x2F;10.1145&#x2F;2034773.2034817&quot;&gt;“Nameless,
Painless”&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Abstract scope graphs&lt;&#x2F;li&gt;
&lt;li&gt;Abstract Binding Trees&lt;&#x2F;li&gt;
&lt;li&gt;Co-de Bruijn indices&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;As you can see, there are many approaches! Jesper Cockx has an excellent summary of almost all of these, which can be found &lt;a href=&quot;https:&#x2F;&#x2F;jesper.sikanda.be&#x2F;posts&#x2F;1001-syntax-representations.html&quot;&gt;here.&lt;&#x2F;a&gt; Notably, many are intended for formalization efforts rather than for computational usage.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes&lt;&#x2F;h2&gt;
&lt;footer class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;Technically, this is not actually needed. It is sufficient to keep track of everything and rename only names that would overlap. See &lt;a href=&quot;https:&#x2F;&#x2F;www.microsoft.com&#x2F;en-us&#x2F;research&#x2F;wp-content&#x2F;uploads&#x2F;2002&#x2F;07&#x2F;inline.pdf&quot;&gt;here&lt;&#x2F;a&gt; for more. &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;A free variable is one that is not bound by the expression we are currently considering. For example, in &lt;code&gt;λ x. f x&lt;&#x2F;code&gt;, &lt;code&gt;f&lt;&#x2F;code&gt; is free, but &lt;code&gt;x&lt;&#x2F;code&gt; is not. &lt;a href=&quot;#fr-2-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;footer&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Dependent types suck actually</title>
        <published>2025-04-01T00:00:00+00:00</published>
        <updated>2025-04-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/dependent-types-suck/"/>
        <id>https://blueberrywren.dev/blog/dependent-types-suck/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/dependent-types-suck/">&lt;p&gt;STOP DOING DEPENDENT TYPES&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Types were not supposed to be given computation!&lt;&#x2F;li&gt;
&lt;li&gt;YEARS of typechecking but NO real world use for going higher than GADTS&lt;&#x2F;li&gt;
&lt;li&gt;Wanted to go higher anyway for a laugh? We had a tool for that: It was called RUNTIME VERIFICATION&lt;&#x2F;li&gt;
&lt;li&gt;&quot;Yes please give me &lt;code&gt;Id A x x&lt;&#x2F;code&gt; of something. Please give me &lt;code&gt;Vec (m + n) A&lt;&#x2F;code&gt; of it.&quot; -- Statements dreamed up by the UTTERLY INSANE&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Look at what computer scientists have been doing, with all the languages and typecheckers we built for them:
(This is REAL dependent types, done by REAL computer scientists)&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;agda&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-agda &quot;&gt;&lt;code class=&quot;language-agda&quot; data-lang=&quot;agda&quot;&gt;&lt;span&gt;sq2 : ◀.F-map-iso (◀.F-map-iso (ρ≅ Iso⁻¹)) ∙Iso α≅
&lt;&#x2F;span&gt;&lt;span&gt;    ≡ (α≅ ∙Iso α≅) ∙Iso ▶.F-map-iso (λ≅ Iso⁻¹)
&lt;&#x2F;span&gt;&lt;span&gt;sq2 = ≅-path $
&lt;&#x2F;span&gt;&lt;span&gt;    α→ _ _ _ ∘ ((ρ← ⊗₁ id) ⊗₁ id)    ≡
&lt;&#x2F;span&gt;&lt;span&gt;    (ρ← ⊗₁ ⌜ id ⊗₁ id ⌝) ∘ α→ _ _ _  ≡
&lt;&#x2F;span&gt;&lt;span&gt;    (ρ← ⊗₁ id) ∘ α→ _ _ _            ≡˘
&lt;&#x2F;span&gt;&lt;span&gt;    (id ⊗₁ λ←) ∘ α→ _ _ _ ∘ α→ _ _ _ ∎
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;lean&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-lean &quot;&gt;&lt;code class=&quot;language-lean&quot; data-lang=&quot;lean&quot;&gt;&lt;span&gt;theorem integral_re {f : X → 𝕜} (hf : Integrable f μ) :
&lt;&#x2F;span&gt;&lt;span&gt;    ∫ x, RCLike.re (f x) ∂μ = RCLike.re (∫ x, f x ∂μ) :=
&lt;&#x2F;span&gt;&lt;span&gt;  (@RCLike.reCLM 𝕜 _).integral_comp_comm hf
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;coq&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-coq &quot;&gt;&lt;code class=&quot;language-coq&quot; data-lang=&quot;coq&quot;&gt;&lt;span&gt;Lemma next_spoke_ring (y : G) : y \in r -&amp;gt; next r y = face (spoke y).
&lt;&#x2F;span&gt;&lt;span&gt;Proof.
&lt;&#x2F;span&gt;&lt;span&gt;move=&amp;gt; ry; have [cycFp Up] := andP ucycFp.
&lt;&#x2F;span&gt;&lt;span&gt;rewrite -{1}[y]nodeK (next_map inj_spoke) ?rev_uniq &#x2F;&#x2F; (next_rev Up).
&lt;&#x2F;span&gt;&lt;span&gt;rewrite -[prev p _]faceK &#x2F;spoke ee -(canRL nodeK (nnn y)).
&lt;&#x2F;span&gt;&lt;span&gt;by rewrite (eqP (prev_cycle cycFp _)) &#x2F;&#x2F; -Ep -Er.
&lt;&#x2F;span&gt;&lt;span&gt;Qed.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&quot;Hello I would like &lt;code&gt;(p : f ∘ g ≡ h ∘ k)&lt;&#x2F;code&gt; apples please&quot;&lt;&#x2F;p&gt;
&lt;p&gt;they have played us for absolute fools
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;details&gt;
  &lt;summary&gt;credits&lt;&#x2F;summary&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Agda credit: &lt;a href=&quot;https:&#x2F;&#x2F;1lab.dev&#x2F;Cat.Monoidal.Base.html&quot;&gt;1Lab&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Lean credit: &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;leanprover-community&#x2F;mathlib4&#x2F;blob&#x2F;362bdac45f1c3e9307252e394f8ecfff137c4d85&#x2F;Mathlib&#x2F;MeasureTheory&#x2F;Integral&#x2F;SetIntegral.lean#L1183-L1185&quot;&gt;Mathlib4&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Rocq credit: &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rocq-community&#x2F;fourcolor&#x2F;blob&#x2F;master&#x2F;theories&#x2F;proof&#x2F;birkhoff.v&quot;&gt;4 Color Theorem Proof&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;details&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A short excerpt on pattern unification</title>
        <published>2025-03-30T00:00:00+00:00</published>
        <updated>2025-03-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/pattern-unification-short/"/>
        <id>https://blueberrywren.dev/blog/pattern-unification-short/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/pattern-unification-short/">&lt;p&gt;Preface: Low effort post.&lt;&#x2F;p&gt;
&lt;p&gt;The following is an excerpt from a discord conversation about dependent pattern unification. In short, pattern unification is one method for solving
unification goals such as the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;haskell&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-haskell &quot;&gt;&lt;code class=&quot;language-haskell&quot; data-lang=&quot;haskell&quot;&gt;&lt;span&gt;id &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A
&lt;&#x2F;span&gt;&lt;span&gt;id &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; x
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B
&lt;&#x2F;span&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; id _ x
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, we have that our type argument to &lt;code&gt;id&lt;&#x2F;code&gt; is a hole, so we must solve it.&lt;&#x2F;p&gt;
&lt;p&gt;We are working with a de Brujin representation, so the above actually looks something like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;haskell&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-haskell &quot;&gt;&lt;code class=&quot;language-haskell&quot; data-lang=&quot;haskell&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let :&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; λ λ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let :&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; λ λ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt; _ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Once we&#x27;ve gotten to the point of writing that hole, what was once &lt;code&gt;id&lt;&#x2F;code&gt; is now &lt;code&gt;2&lt;&#x2F;code&gt; (Two levels of lambda binders in the way.). As such, performing this
solving takes slightly more work, as we can&#x27;t simply plug in the result of unification - the de Brujin wouldn&#x27;t line up.&lt;&#x2F;p&gt;
&lt;p&gt;In this conversation, we were discussing relative to András Kovács&#x27; excellent &quot;elab-zoo&quot;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;AndrasKovacs&#x2F;elaboration-zoo&#x2F;&quot;&gt;found here&lt;&#x2F;a&gt;.
We are discussing &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;AndrasKovacs&#x2F;elaboration-zoo&#x2F;blob&#x2F;master&#x2F;03-holes&#x2F;pattern-unification.txt&quot;&gt;&lt;code&gt;03-holes&#x2F;pattern-unification.txt&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;AndrasKovacs&#x2F;elaboration-zoo&#x2F;blob&#x2F;master&#x2F;03-holes&#x2F;Main.hs&quot;&gt;&lt;code&gt;&#x2F;03-holes&#x2F;Main.hs&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; in particular, the former being a formal treatment of what happens &lt;em&gt;after&lt;&#x2F;em&gt; you find a solution, and the latter being an implementation of pattern unification (amongst other things).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;comments-before-the-fact&quot;&gt;Comments before the fact&lt;&#x2F;h3&gt;
&lt;p&gt;I think this explanation is somewhat reasonable for what&#x27;s actually happening. Nothing will replace the original document, of course! Go give that a read (preferably before you read this.)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;warning&quot;&gt;Warning!&lt;&#x2F;h2&gt;
&lt;p&gt;This conversation is &lt;em&gt;only&lt;&#x2F;em&gt; going to make sense if you&#x27;ve had a look at at &lt;em&gt;least&lt;&#x2F;em&gt; the latter linked file above (&lt;code&gt;Main.hs&lt;&#x2F;code&gt;). I recommend also having a look at &lt;code&gt;pattern-unification.txt&lt;&#x2F;code&gt; if you really want to grasp it, though.&lt;&#x2F;p&gt;
&lt;p&gt;I also make no concrete warning that the below is 100% correct; while it is to the best of ability, i&#x27;m still learning this too!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-conversation-as-written-minorly-edited-to-exclude-comments-from-people-other-than-me&quot;&gt;The conversation as written, minorly edited to exclude comments from people other than me&lt;&#x2F;h3&gt;
&lt;p&gt;(In reference to &lt;code&gt;pattern-unification.txt&lt;&#x2F;code&gt;)&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;most of this is what you do &lt;em&gt;after&lt;&#x2F;em&gt; you&#x27;ve &quot;found the solution&quot;
finding the &quot;solution&quot; is vaguely your normal unification procedure
when you find a hole, you put a meta in it, when you unify something with that meta you &quot;solve&quot; it&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&quot;Normal unification&quot; here is your fairly traditional unification for typechecking; it is somewhat different in a dependent setting, but not
too different. (Look here later for a series on this!)&lt;&#x2F;p&gt;
&lt;p&gt;All of the following is then discussing &lt;code&gt;Main.hs&lt;&#x2F;code&gt; and the concrete implementation of solving a metavariable.
This maps somewhat closely from &lt;code&gt;pattern-unification.txt&lt;&#x2F;code&gt;, but can be understood standalone.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Andras&#x27; puts it better than i could:&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;{-
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;The actual unification algorithm is fairly simple, it works in a structural
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;fashion, like conversion checking before.  The main complication, as we&amp;#39;ve seen,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;is the pattern unification case.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;-}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;A small break while I write the following&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span&gt;  (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;VFlex&lt;&#x2F;span&gt;&lt;span&gt; m sp , t&amp;#39;           ) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; solve l m sp t&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;  (t          , &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;VFlex&lt;&#x2F;span&gt;&lt;span&gt; m&amp;#39; sp&amp;#39; ) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; solve l m&amp;#39; sp&amp;#39; t
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;VFlex&lt;&#x2F;code&gt; is what elab-zoo calls the thing holding an unsolved metavariable (here &lt;code&gt;m&lt;&#x2F;code&gt; or &lt;code&gt;m&#x27;&lt;&#x2F;code&gt;), and a &quot;spine&quot; &lt;code&gt;sp&lt;&#x2F;code&gt;, which is a list of everything bound in the context when &lt;code&gt;m&lt;&#x2F;code&gt; was created&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;you can then imagine the meta to be, essentially, a function, taking everything bound as arguments (which is what it actually is, in elab zoo)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span&gt;id &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;U&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A
&lt;&#x2F;span&gt;&lt;span&gt;id &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; x
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;U&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B
&lt;&#x2F;span&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; id _ y
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;m &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= ???
&lt;&#x2F;span&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; id (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;m &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y) y
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;here our normal typechecking would try to unify &lt;code&gt;?m&lt;&#x2F;code&gt;&#x27;s &lt;code&gt;???&lt;&#x2F;code&gt; with &lt;code&gt;B&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;the actual solving is then handled by &lt;code&gt;solve&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span style=&quot;color:#75715e;&quot;&gt;--       Γ      ?α         sp       rhs
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;solve &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;:: &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;Lvl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;MetaVar &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;Spine &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;Val &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#66d9ef;&quot;&gt;IO &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66d9ef;&quot;&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;solve gamma m sp rhs &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= do
&lt;&#x2F;span&gt;&lt;span&gt;  pren &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; invert gamma sp
&lt;&#x2F;span&gt;&lt;span&gt;  rhs  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; rename m pren rhs
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; solution &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; eval &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;[] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; lams (dom pren) rhs
&lt;&#x2F;span&gt;&lt;span&gt;  modifyIORef&amp;#39; mcxt &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;$ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;IM&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;insert (unMetaVar m) (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;Solved&lt;&#x2F;span&gt;&lt;span&gt; solution)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;B&lt;&#x2F;code&gt; would be our &lt;code&gt;rhs&lt;&#x2F;code&gt; here&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;you need to remember we&#x27;re working with debrujin, so the solution to our metavariable (which may reference things in the context of where the meta was created, of course) should exist in a different context (a &quot;mostly&quot; empty one, with only the arguments to our meta).&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;invert&lt;&#x2F;code&gt;, which is &lt;code&gt;^⁻¹&lt;&#x2F;code&gt; in the pattern unification text, creates a renaming from our original context (&lt;code&gt;sp&lt;&#x2F;code&gt;) to the desired new context, with only our meta arguments&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;rename&lt;&#x2F;code&gt; takes our &lt;code&gt;rhs&lt;&#x2F;code&gt; and uses the renaming to take it to the new context (it takes &lt;code&gt;m&lt;&#x2F;code&gt; as an argument because it does an occurs check at the same time, recursive solutions are no good)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;finally we add the needed lambdas for our function meta (debrujin, remember), evaluate it in the empty context in order to take it into the value domain, and plug it in as the solution&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;so then our final solution is&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span&gt;id &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;U&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A
&lt;&#x2F;span&gt;&lt;span&gt;id &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; x
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;U&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B
&lt;&#x2F;span&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; id _ y
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;m &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B
&lt;&#x2F;span&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; id (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;m &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y) y
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;?m is fully inline though, so&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span&gt;id &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;U&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A
&lt;&#x2F;span&gt;&lt;span&gt;id &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; x
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;U&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B
&lt;&#x2F;span&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; id ((λ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y) y
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;which is obviously equal to the &quot;clear solution&quot;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre data-lang=&quot;hs&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-hs &quot;&gt;&lt;code class=&quot;language-hs&quot; data-lang=&quot;hs&quot;&gt;&lt;span&gt;id2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; id &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt; y
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;and so clearly we&#x27;ve solved it!&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;comments-after-the-fact&quot;&gt;Comments after the fact&lt;&#x2F;h3&gt;
&lt;p&gt;I don&#x27;t really have any other comments. There will (hopefully shortly) start appearing a &quot;tutorial&quot; sort of series on writing a dependent language with holes, so some of this
will definitely come up in that, and I&#x27;ll probably write some more comments here after i&#x27;ve gone and written that tutorial.&lt;&#x2F;p&gt;
&lt;p&gt;Hope this helps somebody!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Welcome back.</title>
        <published>2025-03-27T00:00:00+00:00</published>
        <updated>2025-03-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/2025-03-27/"/>
        <id>https://blueberrywren.dev/blog/2025-03-27/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/2025-03-27/">&lt;h1 id=&quot;hey-hey&quot;&gt;hey hey&lt;&#x2F;h1&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Hi, world.</title>
        <published>2023-06-17T00:00:00+00:00</published>
        <updated>2023-06-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Blueberry Wren
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blueberrywren.dev/blog/first/"/>
        <id>https://blueberrywren.dev/blog/first/</id>
        
        <content type="html" xml:base="https://blueberrywren.dev/blog/first/">&lt;p&gt;This is just a little blog i&#x27;m doing for the sake of spreading stuff I learn about. Fun, right?&lt;&#x2F;p&gt;
&lt;p&gt;There will be mostly math and programming. \(a \to b\)&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ocaml&quot; style=&quot;background-color:#272822;color:#f8f8f2;&quot; class=&quot;language-ocaml &quot;&gt;&lt;code class=&quot;language-ocaml&quot; data-lang=&quot;ocaml&quot;&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a6e22e;&quot;&gt;fac &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;= if&lt;&#x2F;span&gt;&lt;span&gt; n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;&amp;lt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;then &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt; n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; fac (n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f92672;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ae81ff;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;$$\forall a. \forall b. (\forall c. c \to c) \to (a, b) \to (a, b)$$&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
