<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://unfooling.com/unfooling.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://unfooling.com/unfooling.com/" rel="alternate" type="text/html" hreflang="en-US" /><updated>2026-06-08T09:37:25-04:00</updated><id>https://unfooling.com/unfooling.com/feed.xml</id><title type="html">Unfooling</title><subtitle>Writing about computers and other beautiful and worthwhile things.</subtitle><author><name>Andrew Chen</name><email>(λx.λy.λz. yz@x) gmail.com andrewchen 14250</email></author><entry><title type="html">Growing Up Mischievous</title><link href="https://unfooling.com/unfooling.com/growing-up-mischievous/" rel="alternate" type="text/html" title="Growing Up Mischievous" /><published>2026-04-02T12:30:00-04:00</published><updated>2026-04-02T12:30:00-04:00</updated><id>https://unfooling.com/unfooling.com/growing-up-mischievous</id><content type="html" xml:base="https://unfooling.com/unfooling.com/growing-up-mischievous/"><![CDATA[<p>I was born in Shanghai, China. 2002. My maternal grandmother was a doctor practicing internal medicine. I grew up weak-bodied and had pneumonia twice. When mucus overaccumulated, metal tubes forced themselves into a frightened, well-behaved boy in an operating room of silver and white. My grandmother overprotected me, her father and uncle had died of tuberculosis after all. When I would later attend international school for fourth and fifth grade, I daily observed my mortal enemy from afar. Pockets of dark, dense smog rose from bleak factories as my bus drove on the hundred-foot-tall interstate into the city.</p>

<p>Have I sadfished you? Baited! Despite the overprotection, I was <em>wicked</em>! Conor Mcgregor must’ve copied my childhood strut. I was Boy-Scout-Russelling all these adults out here</p>

<p><img src="/assets/img/russell.jpg" alt="Boy Scout Russell" /></p>

<p>with a Chinese riddle booklet in hand and a silly cap on head, I quizzed down the adults I met. I had the best grades but was disruptive enough to be kicked out of the classroom. Peeking through the warped windows, I kept making silly faces at my friends much to the groan of my teachers. I also believed through proper breathing, one can obtain superpowers through instanteous transfer of energy from the Dan Tian mid section. That’s what they wrote in the WuXia novels, so, sometimes I was caught medidating (and I had to play stupid because that’s what the main characters with special talent had to do to avoid earlh ).</p>

<p>Once, my school hosted a storytelling competition. We were supposed to prepare a story to deliver in class, the winner of each class tells it in front of the whole school. I forgot to prepare. My greatest improvisation ensued: In my story, I would fall into a pig pen and get out of it bullfighter style. I got to the school competition by unanimous vote. That day, I danced like a bullfighter with my dad’s red windbreaker as I delivered the story crisply. In that sauce red auditorium, I caught my crush’s gaze somewhere from the upper left corner as my friends were keeling over with laughter a few rows down. She was sitting at the edge of her seat, staring at me brightly. So I peacocked.</p>

<p>For my mischief, my mother sent me to military training for a summer, much to my grandmother’s objection. At the camp, everyone had to memorize the entirety of San Zi Jing, a Confucian classic. I still caused trouble and subjected my dorm of eight-year-olds to hold planks for an hour during post-lunch nap time. I came back from the camp propagandized and enlightened. I only walked in military steps around the house for a few months and begged my grandmother to let me wash her feet, citing Confucian ideals.</p>

<p>But my mischief went on. All the adults talked about the same stuff. I was so bored of it, and I decided their time could be better spent participating in my games. From reading a crap ton—I stayed up until 4am some nights to read and even wrote some Wuxia chapters with a flashlight under the blanket—I smuggled in a serious vocabulary that I would use to terrorize the adults. For the Chinese language, this means you know a lot of four-word idioms. Everyone knows a few hundred idioms and poetry stanzas from Chinese classes, but they don’t use them much in the vernacular. Instead of saying something is shocking, you could say that something “splits the stone and startles the heavens” (石破天惊). I dragged adults into unskippable games of connect-the-idioms: I say an idiom, you say an idiom whose first letter starts with my last, and so on.</p>

<p>I never beat the taxi drivers though. Not even when I am all grown. Last year when I visited, I played it with a taxi driver. Soon enough, he started skipping my turns, riffing off of his idioms, then barrelling into poetry lines and pop song lyrics, all while navigating busy Shanghai streets under the downpour.</p>]]></content><author><name>Andrew Chen</name><email>(λx.λy.λz. yz@x) gmail.com andrewchen 14250</email></author><summary type="html"><![CDATA[I was born in Shanghai, China. 2002. My maternal grandmother was a doctor practicing internal medicine. I grew up weak-bodied and had pneumonia twice. When mucus overaccumulated, metal tubes forced themselves into a frightened, well-behaved boy in an operating room of silver and white. My grandmother overprotected me, her father and uncle had died of tuberculosis after all. When I would later attend international school for fourth and fifth grade, I daily observed my mortal enemy from afar. Pockets of dark, dense smog rose from bleak factories as my bus drove on the hundred-foot-tall interstate into the city.]]></summary></entry><entry><title type="html">Absurd Beli Proses</title><link href="https://unfooling.com/unfooling.com/beli-absurdisms/" rel="alternate" type="text/html" title="Absurd Beli Proses" /><published>2026-03-03T12:30:00-05:00</published><updated>2026-03-03T12:30:00-05:00</updated><id>https://unfooling.com/unfooling.com/beli-absurdisms</id><content type="html" xml:base="https://unfooling.com/unfooling.com/beli-absurdisms/"><![CDATA[<p>Beli is a food rating app. Hey, you imagine the food.</p>

<p><strong>#1</strong>: At 乌鹊 restaurant</p>

<p>As kayne thanks god for Jay Electra for being “down with the mission” in the hit piece “Saint Pablo”, I thank the ogs of CCP - the class of 1921 - for the same. Je’Ri was piping out that New Shit, looping Eternal Sunshine raw no drums no hook. CCP was printing that New Idea, and youth was the first bloom amongst a hundred flowers.</p>

<p>Then one started an affair with a Rothchild while the other started killing the Rothschildren and the doctors and teachers of the People’s Republic of China.</p>

<p>2/19/26,
At Nanhu (the South Lake), where the first CCP meeting took place securely in a boat.</p>

<p><strong>#2</strong>: At Nha Trang Restaurant, Falls Church, Virginia</p>

<p>Where the line formed for the tofu place, take a left, around the corner. A store. Can’t see from outside. Oils and Chinese produce. Walk in, an Asian at the register, it’s a weighted register. It’s sectioned off, facing the window. Weird. The Asian has vaneers. Colin compliments her teeth, Colin receives thanks. I scan around: Guan Yu statue, lunar new years calendar in traditional Chinese. Weird. I make conversation; I ask about the store, hands in my pockets. She responds vaguely - “An agency”. I think I know. Is it the hands in the pockets? i walk away. We all know we’re not the customer.</p>

<p><strong>#3</strong>: At Breeze Bakery Cafe, Anndale, Virginia</p>

<p>The creature America: its head strip malls, its belly interstate highways, and its fat ass the overall rectangular but internally 65 degrees parking lots. You eat on top of the creature as it feasts on itself.</p>]]></content><author><name>Andrew Chen</name><email>(λx.λy.λz. yz@x) gmail.com andrewchen 14250</email></author><category term="food" /><summary type="html"><![CDATA[Beli is a food rating app. Hey, you imagine the food.]]></summary></entry><entry><title type="html">Verified Parser pt.1 - Vermillion, the Certified LL(1) Parser Generator</title><link href="https://unfooling.com/unfooling.com/verifying-parsers/" rel="alternate" type="text/html" title="Verified Parser pt.1 - Vermillion, the Certified LL(1) Parser Generator" /><published>2025-02-03T02:01:00-05:00</published><updated>2025-02-03T02:01:00-05:00</updated><id>https://unfooling.com/unfooling.com/verifying-parsers</id><content type="html" xml:base="https://unfooling.com/unfooling.com/verifying-parsers/"><![CDATA[<p>Parsers come in two forms. In the first form, they are parser generators.
In the second, they are parser combinators. These two forms have very different backgrounds, but they are dual.</p>

<p>Researchers are interested in similar properties:</p>
<ol>
  <li>For parser generators, researchers verify that the parser generator is sound, complete, and unambiguous.</li>
  <li>For parser combinators, researchers verify that the combinators are total, prefix-secure, and satisfy roundtrip (for binary parsing).</li>
</ol>

<p>I start this review with an intro to formal methods, then I explain traditional parser generation. Finally, I dive into the source code and present
what the verification code looks like under the hood. In particular, I show how to prove that the <a href="https://github.com/slasser/vermillion">Vermillion</a> LL(1) parser generator, written in Rocq, must not parse left-recursive grammars. 
In the next post, I explain parser combinators and show how the <a href="https://github.com/secure-foundations/vest">Vest</a> library proves roundtrip for specific binary parser combinators.</p>

<p>This post is meant for everyone. If you have experience in Coq, you should be able to understand
the concept of abstract, inductive specification that I keep repeating in the verification section.
If you don’t, just focus on getting the big ideas. But don’t feel defeated if you don’t understand the 
proofs themselves — they are mechanized according to complex inductive definitions. 
I, for one, don’t understand them completely.</p>

<h2 id="background-formal-methods">Background: Formal Methods</h2>
<p>In a simplified view, formal methods is about expanding your unit tests to cover the entire input domain.</p>

<p>But how?</p>

<p>It is computationally infeasible to run tests for every plausible input.
Instead, to reason about infinity, we have to be inductive.
The philosophy of induction is woven into the programming languages of formal methods
(most of which can be called proof assistants):</p>

<ol>
  <li>Structures are defined inductively.</li>
</ol>

<p>This goes from natural numbers to lists to domain-specific
languages embedded within proof assistants. To elaborate, natural numbers are defined in
their Peano form: <code class="language-plaintext highlighter-rouge">0</code> is a <code class="language-plaintext highlighter-rouge">nat</code>, and given <code class="language-plaintext highlighter-rouge">n: nat</code>, <code class="language-plaintext highlighter-rouge">n + 1</code> is a nat. For lists,
<code class="language-plaintext highlighter-rouge">[1, 2, 3]</code> is represented as <code class="language-plaintext highlighter-rouge">Cons 1 (Cons 2 (Cons 3 Nil))</code>. As for embedded languages,
see the definition of <code class="language-plaintext highlighter-rouge">com</code> <a href="https://softwarefoundations.cis.upenn.edu/lf-current/Imp.html#com">here</a>.
You are probably more familiar with the latter since we know that code gets parsed into trees
that follow recursive grammar rules. But defining primitives inductively might be the bigger surprise.</p>

<ol>
  <li>Proofs can be inductive.</li>
</ol>

<p>When every structure in your proof is defined inductively, your proofs can make use of induction!</p>

<p>The other important part about formal methods to mention, in an introduction, is the concept of totality, which means “provably terminating” and “covers entire input domain”, i.e., not partial.
Functions in Turing-complete languages, on the other hand, are partial. Haskell will give a warning
for functions not covering the entire input domain, but it’s just a warning.</p>

<p>When I started learning about formal methods a few months ago, it took me 
a few days to realize that these “formal method languages” (e.g., Coq, Idris, Isabelle) are
adding a lot of constraints to programming languages.
That is to say, there exist programs in Turing-complete languages that you can’t write in these “formal methods languages”.</p>

<p>But it took me a while to understand why, and why such constraints give power.
First, there’s this thing called the Curry-Howard Correspondence that makes algebra, logic, and type theory isomorphic. Software folks will find type theory intuitive, but it is more logic and math flavored.</p>

<p>The Curry-Howard Correspondence leads to the isomorphism between programs and proofs. 
In proof assistants, propositions are types, and proofs are terms (programs). <a href="https://softwarefoundations.cis.upenn.edu/lf-current/ProofObjects.html">To prove a proposition, construct a proof program whose type is that proposition</a>.</p>

<p>Here’s the key: Proofs must be provably terminating. This makes sense - 
a proof that loops isn’t a proof; a proof must terminate.
Since proofs are programs, programs are provably terminating as well. 
But if our programs are total, our language can’t be Turing-complete, since Turing machines are allowed to go into the “loop” state!</p>

<p>So, by adding constraints (totality) to our language, we have made it more powerful (our language can prove things). Developers often first experience this in their encounter with Haskell’s type system or Rust’s borrow checker: You wage a series of mini-wars against the compiler. 
But when the linter goes green, you have many more guarantees about the correctness of your program.</p>

<blockquote>
  <p>Structures, strictures, though they bind,</p>

  <p>Strangely liberate the mind.</p>
</blockquote>

<h2 id="background-parsing">Background: Parsing</h2>
<p>Parsing is the process of attempting to ingest a raw string into some structured format, according
to some rules. 
The structured format is often a tree, but it need not be. Even the act of lifting
the phone number <code class="language-plaintext highlighter-rouge">(123)-456-7899</code> into a Haskell record <code class="language-plaintext highlighter-rouge">PhoneNum { area: "123", mid: "456", rest: "7899" }</code>
is considered parsing.
But traditionally, parsing is focused on parsing programming languages, so the structured format
is a tree. I focus on traditional parsing in this post.</p>

<p>In traditional parsing, parsing follows the definition of a context-free grammar (CFG). A parser 
generator takes in the grammar and outputs a parser, which often comes in the form of some lookup table:
The parsing procedure is general and utilize the specific table.</p>

<p>A context-free grammar is a set of (recursive) generation rules, often written in the Backus-Naur form.
For example, here is the CFG for arithmetic:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>E -&gt; E + E
E -&gt; E - E
E -&gt; E * E
E -&gt; E / E
E -&gt; (E)
E -&gt; Number
</code></pre></div></div>

<p>The leftmost elements are nonterminals. <code class="language-plaintext highlighter-rouge">E</code> is the only nonterminal. The right-hand side to the <code class="language-plaintext highlighter-rouge">-&gt;</code> is
called the gamma. Symbols that aren’t on the left-hand side are terminals. For example,
<code class="language-plaintext highlighter-rouge">+</code>, <code class="language-plaintext highlighter-rouge">-</code>, and even <code class="language-plaintext highlighter-rouge">(</code> and <code class="language-plaintext highlighter-rouge">)</code> are terminals.</p>

<p>Each line naturally shows a production, a valid expansion for a nonterminal. You could choose to write
all of the productions for a nonterminal together:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>E -&gt; E + E | E - E | E * E | E / E | (E) | Number
</code></pre></div></div>

<p>Here is how we can expand an <code class="language-plaintext highlighter-rouge">E</code> into <code class="language-plaintext highlighter-rouge">3 + 5 + 8</code>:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>E -&gt; E + E
E -&gt; E + E + E
E -&gt; Number + Number + Number
E -&gt; 3 + 5 + 8
</code></pre></div></div>
<p>Currently, to check if an input is expandable by the grammar, we mentally create heuristics to choose the
correct productions at each step. But a computer needs something more deterministic. In the ideal case,
the computer knows which production to expand into just by looking at the next input token and remembering 
the context we are in, i.e., which nonterminal we are parsing. This is called top-down, predictive parsing.</p>

<p>This ideal case is possible if our grammar is LL(1). Most parser generators support LR(1), or some stronger versions of it. 
LR(1) is strictly stronger than LL(1). But LL(1) is faster, choosing productions right away, as opposed to shifting 
and reducing in LR(1).</p>

<p>A grammar is LL(1) if it satisfies one property:</p>
<ol>
  <li>No productions for the same nonterminal have coinciding first terminals.</li>
</ol>

<p><code class="language-plaintext highlighter-rouge">E</code> does not satisfy this property. For example, two productions for <code class="language-plaintext highlighter-rouge">E</code>, <code class="language-plaintext highlighter-rouge">E + E</code> and <code class="language-plaintext highlighter-rouge">E - E</code>,
both have <code class="language-plaintext highlighter-rouge">(</code> as their first terminal.</p>

<p>But, since productions can be nullable (written as <code class="language-plaintext highlighter-rouge">A -&gt; epsilon</code>), there needs to be one additional criterion:</p>
<ol>
  <li>For any nullable nonterminal <code class="language-plaintext highlighter-rouge">A</code>, the set of candidate first terminals of <code class="language-plaintext highlighter-rouge">A</code>, denoted <code class="language-plaintext highlighter-rouge">FIRST(A)</code>, cannot 
intersect with <code class="language-plaintext highlighter-rouge">FOLLOW(A)</code>, which lists, from all productions, the first token of the symbols that follows <code class="language-plaintext highlighter-rouge">A</code>.</li>
</ol>

<p>After computing FIRST and FOLLOW sets for each nonterminal (which can be done through a straightforward fixed-point algorithm), we can construct the parsing lookup table.
The lookup table is a map between <code class="language-plaintext highlighter-rouge">(nonterminal, lookahead token)</code> and a production, since the goal is to know which production to choose next.</p>

<p>For each production <code class="language-plaintext highlighter-rouge">A -&gt; α</code>:</p>
<ul>
  <li>For each terminal t in <code class="language-plaintext highlighter-rouge">FIRST(α)</code>, add the production to <code class="language-plaintext highlighter-rouge">table(A,t)</code>.</li>
  <li>If α is nullable, for each terminal t in <code class="language-plaintext highlighter-rouge">FOLLOW(A)</code>, add <code class="language-plaintext highlighter-rouge">A -&gt; α</code> to <code class="language-plaintext highlighter-rouge">table(A,t)</code></li>
</ul>

<p>The construction of the <code class="language-plaintext highlighter-rouge">FIRST</code> and <code class="language-plaintext highlighter-rouge">FOLLOW</code> maps never throws.
The errors are handled as we add entries: If we try to add a production to a table cell that already contains one,
there is ambiguity. Hence, the grammar is not LL(1) and we throw an error.</p>

<p>During parsing, we maintain a stack of expected symbols (initialized with the start symbol) and an input stream of terminals. At each step:</p>
<ul>
  <li>If the top of stack is a terminal, match it with input or error</li>
  <li>If top of stack is nonterminal A and next input is t, look up <code class="language-plaintext highlighter-rouge">table(A,t)</code>:
    <ul>
      <li>If empty, syntax error</li>
      <li>If production A → α exists, pop A and push α (reversed) onto stack</li>
    </ul>
  </li>
  <li>Repeat until stack is empty (accept) or error occurs</li>
</ul>

<p>An LL(1) grammar is unambiguous: We know exactly which production to choose when we are expanding a nonterminal.
This implies that a string can only have one parse tree.
Our arithmetic language above doesn’t satisfy this property;
we can expand <code class="language-plaintext highlighter-rouge">E + E</code> into <code class="language-plaintext highlighter-rouge">E + E + E</code> either through expanding the first <code class="language-plaintext highlighter-rouge">E</code> or the second, which results in 
two parse trees.</p>

<p>Unambiguity is important for programming languages: A program should have exactly one tree! For natural language,
it doesn’t matter as much.</p>

<h2 id="vermillion-the-certified-ll1-parser-generator">Vermillion, the certified LL(1) parser generator</h2>
<p>The general workflow of verifying a parser generator is composed of four parts:</p>
<ol>
  <li>Provide an inductive specification for definitions and behaviors in our parser</li>
  <li>Implement the concrete fixpoints that constructs the parsing table</li>
  <li>Show the equivalence of the concrete implementation and the inductive specification</li>
  <li>Prove properties about parsers. <em>These properties are exactly the verified surface of our parsers</em>.</li>
</ol>

<p>Then, since the concrete implementation is 1-to-1 with the inductive specification, it implies that 
our concrete parsers satisfy the properties proved in 4.</p>

<p>I show real code for each part. You should digest a few of the inductive definitions 
but skim the proofs.</p>

<h3 id="using-vermillion">Using Vermillion</h3>
<p>Before going under the hood and studying the verification code, let’s first look at how we can 
use the certified parser generator.</p>

<p>The input to the generator is a grammar encoded in Coq. Here’s Grammar 3.11 from 
Appel’s “Modern Compiler Implementation in ML”:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>S -&gt; if E then S else S
S -&gt; begin S L
S -&gt; print E

L -&gt; end
L -&gt; ; S L

E -&gt; num = num 
</code></pre></div></div>

<p>To encode this grammar, we must first supply the nonterminals, terminals, and the “semantic actions”.
The semantic actions are mappings between symbols (nonterminals and terminals) and 
data types in Coq. For example, the terminal <code class="language-plaintext highlighter-rouge">Num</code> will map to the built-in type <code class="language-plaintext highlighter-rouge">nat</code>, 
and the nonterminal <code class="language-plaintext highlighter-rouge">S</code> (a sentence) will map to a <code class="language-plaintext highlighter-rouge">stmt</code> data type (<code class="language-plaintext highlighter-rouge">stmt</code> must be defined).
After parsing a string, the resulting tree nodes are semantic actions.</p>

<p>Here are the encodings of nonterminals, terminals, and semantic actions:</p>
<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">Inductive</span><span class="w"> </span><span class="no">exp</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w">
</span><span class="o">|</span><span class="w"> </span><span class="no">Cmp_exp</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">nat</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">nat</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">exp</span><span class="pi">.</span><span class="w">

</span><span class="k">Inductive</span><span class="w"> </span><span class="no">stmt</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w">
</span><span class="o">|</span><span class="w"> </span><span class="no">If_stmt</span><span class="w">    </span><span class="p">:</span><span class="w"> </span><span class="no">exp</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">stmt</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">stmt</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">stmt</span><span class="w">
</span><span class="o">|</span><span class="w"> </span><span class="no">Begin_stmt</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">list</span><span class="w"> </span><span class="no">stmt</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">stmt</span><span class="w">
</span><span class="o">|</span><span class="w"> </span><span class="no">Print_stmt</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">exp</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">stmt</span><span class="pi">.</span><span class="w">

</span><span class="k">Inductive</span><span class="w"> </span><span class="no">terminal'</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w">
</span><span class="o">|</span><span class="w"> </span><span class="no">If</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="no">Then</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="no">Else</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="no">Begin</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="k">Print</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="k">End</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="no">Semi</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="no">Num</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="no">Eq</span><span class="pi">.</span><span class="w">
  
</span><span class="k">Inductive</span><span class="w"> </span><span class="no">nonterminal'</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w">
</span><span class="o">|</span><span class="w"> </span><span class="no">S</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="no">L</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="no">E</span><span class="pi">.</span><span class="w">

</span><span class="k">Definition</span><span class="w"> </span><span class="no">t_semty</span><span class="w"> </span><span class="o">(</span><span class="no">a</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">terminal</span><span class="o">)</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="kr">Type</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w">
  </span><span class="kr">match</span><span class="w"> </span><span class="no">a</span><span class="w"> </span><span class="kp">with</span><span class="w">
  </span><span class="o">|</span><span class="w"> </span><span class="no">Num</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="no">nat</span><span class="w">
  </span><span class="o">|</span><span class="w"> </span><span class="p">_</span><span class="w">   </span><span class="o">=&gt;</span><span class="w"> </span><span class="no">unit</span><span class="w">
  </span><span class="kr">end</span><span class="pi">.</span><span class="w">

</span><span class="k">Definition</span><span class="w"> </span><span class="no">nt_semty</span><span class="w"> </span><span class="o">(</span><span class="no">x</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">nonterminal</span><span class="o">)</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="kr">Type</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w">
  </span><span class="kr">match</span><span class="w"> </span><span class="no">x</span><span class="w"> </span><span class="kp">with</span><span class="w">
  </span><span class="o">|</span><span class="w"> </span><span class="no">S</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="no">stmt</span><span class="w">
  </span><span class="o">|</span><span class="w"> </span><span class="no">L</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="no">list</span><span class="w"> </span><span class="no">stmt</span><span class="w">
  </span><span class="o">|</span><span class="w"> </span><span class="no">E</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="no">exp</span><span class="w">
  </span><span class="kr">end</span><span class="pi">.</span><span class="w">
</span></code></pre></div></div>

<p>Note that <code class="language-plaintext highlighter-rouge">stmt</code> has three constructors, which corresponds to the number of productions <code class="language-plaintext highlighter-rouge">S</code> has.</p>

<p>So far, we have only defined the elements of the grammar; we have not yet encoded the productions:</p>
<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">Definition</span><span class="w"> </span><span class="no">g311</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">grammar</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w">
  </span><span class="o">{|</span><span class="w"> </span><span class="no">start</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="no">S</span><span class="w"> </span><span class="p">;</span><span class="w">
     </span><span class="no">prods</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="o">[</span><span class="no">existT</span><span class="w"> </span><span class="no">action_ty</span><span class="w">
                      </span><span class="o">(</span><span class="no">S</span><span class="o">,</span><span class="w"> </span><span class="o">[</span><span class="no">T</span><span class="w"> </span><span class="no">If</span><span class="p">;</span><span class="w"> </span><span class="no">NT</span><span class="w"> </span><span class="no">E</span><span class="p">;</span><span class="w"> </span><span class="no">T</span><span class="w"> </span><span class="no">Then</span><span class="p">;</span><span class="w"> </span><span class="no">NT</span><span class="w"> </span><span class="no">S</span><span class="p">;</span><span class="w"> </span><span class="no">T</span><span class="w"> </span><span class="no">Else</span><span class="p">;</span><span class="w"> </span><span class="no">NT</span><span class="w"> </span><span class="no">S</span><span class="o">])</span><span class="w">
                      </span><span class="o">(</span><span class="kr">fun</span><span class="w"> </span><span class="no">tup</span><span class="w"> </span><span class="o">=&gt;</span><span class="w">
                         </span><span class="kr">match</span><span class="w"> </span><span class="no">tup</span><span class="w"> </span><span class="kp">with</span><span class="w">
                         </span><span class="o">|</span><span class="w"> </span><span class="o">(</span><span class="p">_</span><span class="o">,</span><span class="w"> </span><span class="o">(</span><span class="no">e</span><span class="o">,</span><span class="w"> </span><span class="o">(</span><span class="p">_</span><span class="o">,</span><span class="w"> </span><span class="o">(</span><span class="no">s1</span><span class="o">,</span><span class="w"> </span><span class="o">(</span><span class="p">_</span><span class="o">,</span><span class="w"> </span><span class="o">(</span><span class="no">s2</span><span class="o">,</span><span class="w"> </span><span class="p">_</span><span class="o">))))))</span><span class="w"> </span><span class="o">=&gt;</span><span class="w">
                           </span><span class="no">If_stmt</span><span class="w"> </span><span class="no">e</span><span class="w"> </span><span class="no">s1</span><span class="w"> </span><span class="no">s2</span><span class="w">
                         </span><span class="kr">end</span><span class="o">)</span><span class="p">;</span><span class="w">
                 
               </span><span class="no">existT</span><span class="w"> </span><span class="no">action_ty</span><span class="w">
                      </span><span class="o">(</span><span class="no">S</span><span class="o">,</span><span class="w"> </span><span class="o">[</span><span class="no">T</span><span class="w"> </span><span class="no">Begin</span><span class="p">;</span><span class="w"> </span><span class="no">NT</span><span class="w"> </span><span class="no">S</span><span class="p">;</span><span class="w"> </span><span class="no">NT</span><span class="w"> </span><span class="no">L</span><span class="o">])</span><span class="w">
                      </span><span class="o">(</span><span class="kr">fun</span><span class="w"> </span><span class="no">tup</span><span class="w"> </span><span class="o">=&gt;</span><span class="w">
                         </span><span class="kr">match</span><span class="w"> </span><span class="no">tup</span><span class="w"> </span><span class="kp">with</span><span class="w">
                         </span><span class="o">|</span><span class="w"> </span><span class="o">(</span><span class="p">_</span><span class="o">,</span><span class="w"> </span><span class="o">(</span><span class="no">s</span><span class="o">,</span><span class="w"> </span><span class="o">(</span><span class="no">ss</span><span class="o">,</span><span class="w"> </span><span class="p">_</span><span class="o">)))</span><span class="w"> </span><span class="o">=&gt;</span><span class="w">
                           </span><span class="no">Begin_stmt</span><span class="w"> </span><span class="o">(</span><span class="no">s</span><span class="w"> </span><span class="p">::</span><span class="w"> </span><span class="no">ss</span><span class="o">)</span><span class="w">
                         </span><span class="kr">end</span><span class="o">)</span><span class="p">;</span><span class="w">

               </span><span class="no">existT</span><span class="w"> </span><span class="no">action_ty</span><span class="w">
                      </span><span class="o">(</span><span class="no">S</span><span class="o">,</span><span class="w"> </span><span class="o">[</span><span class="no">T</span><span class="w"> </span><span class="k">Print</span><span class="p">;</span><span class="w"> </span><span class="no">NT</span><span class="w"> </span><span class="no">E</span><span class="o">])</span><span class="w">
                      </span><span class="o">(</span><span class="kr">fun</span><span class="w"> </span><span class="no">tup</span><span class="w"> </span><span class="o">=&gt;</span><span class="w">
                         </span><span class="kr">match</span><span class="w"> </span><span class="no">tup</span><span class="w"> </span><span class="kp">with</span><span class="w">
                         </span><span class="o">|</span><span class="w"> </span><span class="o">(</span><span class="p">_</span><span class="o">,</span><span class="w"> </span><span class="o">(</span><span class="no">e</span><span class="o">,</span><span class="w"> </span><span class="p">_</span><span class="o">))</span><span class="w"> </span><span class="o">=&gt;</span><span class="w">
                           </span><span class="no">Print_stmt</span><span class="w"> </span><span class="no">e</span><span class="w">
                         </span><span class="kr">end</span><span class="o">)</span><span class="p">;</span><span class="w">
               </span><span class="o">...</span><span class="w"> </span><span class="no">you</span><span class="w"> </span><span class="no">get</span><span class="w"> </span><span class="no">the</span><span class="w"> </span><span class="no">idea</span><span class="w">
  </span><span class="o">]|}</span><span class="w">
</span></code></pre></div></div>

<p>The 3.11 grammar has no nullable productions. If you have a nullable production, it will look like:</p>
<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="no">existT</span><span class="w"> </span><span class="no">action_ty</span><span class="w">
      </span><span class="o">(</span><span class="no">A</span><span class="o">,</span><span class="w"> </span><span class="o">[])</span><span class="w"> </span><span class="c">(* Empty list! *)</span><span class="w">
      </span><span class="o">(</span><span class="kr">fun</span><span class="w"> </span><span class="no">tup</span><span class="w"> </span><span class="o">=&gt;</span><span class="w">
          </span><span class="kr">match</span><span class="w"> </span><span class="no">tup</span><span class="w"> </span><span class="kp">with</span><span class="w">
          </span><span class="o">|</span><span class="w"> </span><span class="p">_</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="no">AStruct</span><span class="w">
          </span><span class="kr">end</span><span class="o">)</span><span class="p">;</span><span class="w">
</span></code></pre></div></div>
<p>Check out this <a href="https://github.com/BlastWind/vermillion/blob/master/MyExample.v">example</a> in my Vermillion fork where I encode
the following grammar, which has nullable productions:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>E  -&gt; TE'
E' -&gt; +TE' | epsilon
T  -&gt; FT'
T' -&gt; *FT' | epsilon
F  -&gt; (E)  | Num
</code></pre></div></div>

<p>Now, we can use the parser generator to build a parser (more precisely, the parsing tables),
and then invoke the parse procedure (with the tables) on our inputs.</p>

<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">(* tt is the unit type *)</span><span class="w">
</span><span class="k">Definition</span><span class="w"> </span><span class="no">example_prog</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">list</span><span class="w"> </span><span class="no">token</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w">
  </span><span class="o">[</span><span class="no">tok</span><span class="w"> </span><span class="no">If</span><span class="w"> </span><span class="no">tt</span><span class="p">;</span><span class="w"> </span><span class="no">tok</span><span class="w"> </span><span class="no">Num</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span><span class="w"> </span><span class="no">tok</span><span class="w"> </span><span class="no">Eq</span><span class="w"> </span><span class="no">tt</span><span class="p">;</span><span class="w"> </span><span class="no">tok</span><span class="w"> </span><span class="no">Num</span><span class="w"> </span><span class="mi">5</span><span class="p">;</span><span class="w"> </span><span class="no">tok</span><span class="w"> </span><span class="no">Then</span><span class="w"> </span><span class="no">tt</span><span class="p">;</span><span class="w">
     </span><span class="no">tok</span><span class="w"> </span><span class="k">Print</span><span class="w"> </span><span class="no">tt</span><span class="p">;</span><span class="w"> </span><span class="no">tok</span><span class="w"> </span><span class="no">Num</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span><span class="w"> </span><span class="no">tok</span><span class="w"> </span><span class="no">Eq</span><span class="w"> </span><span class="no">tt</span><span class="p">;</span><span class="w"> </span><span class="no">tok</span><span class="w"> </span><span class="no">Num</span><span class="w"> </span><span class="mi">5</span><span class="p">;</span><span class="w">
   </span><span class="no">tok</span><span class="w"> </span><span class="no">Else</span><span class="w"> </span><span class="no">tt</span><span class="p">;</span><span class="w">
     </span><span class="no">tok</span><span class="w"> </span><span class="k">Print</span><span class="w"> </span><span class="no">tt</span><span class="p">;</span><span class="w"> </span><span class="no">tok</span><span class="w"> </span><span class="no">Num</span><span class="w"> </span><span class="mi">42</span><span class="p">;</span><span class="w"> </span><span class="no">tok</span><span class="w"> </span><span class="no">Eq</span><span class="w"> </span><span class="no">tt</span><span class="p">;</span><span class="w"> </span><span class="no">tok</span><span class="w"> </span><span class="no">Num</span><span class="w"> </span><span class="mi">42</span><span class="o">].</span><span class="w">

</span><span class="k">Compute</span><span class="w"> </span><span class="o">(</span><span class="kr">match</span><span class="w"> </span><span class="no">parseTableOf</span><span class="w"> </span><span class="no">g311</span><span class="w"> </span><span class="kp">with</span><span class="w">
         </span><span class="o">|</span><span class="w"> </span><span class="no">inl</span><span class="w"> </span><span class="no">msg</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="no">inl</span><span class="w"> </span><span class="no">msg</span><span class="w">
         </span><span class="o">|</span><span class="w"> </span><span class="no">inr</span><span class="w"> </span><span class="no">tbl</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="no">inr</span><span class="w"> </span><span class="o">(</span><span class="no">parse</span><span class="w"> </span><span class="no">tbl</span><span class="w"> </span><span class="o">(</span><span class="no">NT</span><span class="w"> </span><span class="no">S</span><span class="o">)</span><span class="w"> </span><span class="no">example_prog</span><span class="o">)</span><span class="w">
         </span><span class="kr">end</span><span class="o">).</span><span class="w">

</span><span class="c">(* You will see a tree made up of semantic action nodes! *)</span><span class="w">
</span></code></pre></div></div>

<p>If your grammar is not LL(1), then it will be rejected at <code class="language-plaintext highlighter-rouge">parseTableOf</code>. If your input
is not recognizable by the parser, then it will give an <code class="language-plaintext highlighter-rouge">inl</code> error message within <code class="language-plaintext highlighter-rouge">parse</code>.</p>

<h3 id="1-inductive-specifications">1. Inductive specifications</h3>
<p>Let’s start light: Recall, what does it mean for a symbol to be nullable?</p>

<p>A symbol is nullable if it has a production that can go to epsilon. For example, <code class="language-plaintext highlighter-rouge">A</code> is nullable:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>A -&gt; b | c | d | epsilon
</code></pre></div></div>
<p>but <code class="language-plaintext highlighter-rouge">A</code> is also nullable here:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>A -&gt; B | c
B -&gt; d | epsilon
</code></pre></div></div>

<p>In Coq, we translate the natural language description of “a production can go to epsilon” as:</p>
<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">Inductive</span><span class="w"> </span><span class="no">nullable_sym</span><span class="w"> </span><span class="o">(</span><span class="no">g</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">grammar</span><span class="o">)</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">symbol</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="kr">Prop</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w">
</span><span class="o">|</span><span class="w"> </span><span class="no">NullableSym</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="kr">forall</span><span class="w"> </span><span class="no">x</span><span class="w"> </span><span class="no">ys</span><span class="w"> </span><span class="no">f</span><span class="o">,</span><span class="w">
    </span><span class="no">In</span><span class="w"> </span><span class="o">(</span><span class="no">existT</span><span class="w"> </span><span class="p">_</span><span class="w"> </span><span class="o">(</span><span class="no">x</span><span class="o">,</span><span class="w"> </span><span class="no">ys</span><span class="o">)</span><span class="w"> </span><span class="no">f</span><span class="o">)</span><span class="w"> </span><span class="no">g</span><span class="o">.(</span><span class="no">prods</span><span class="o">)</span><span class="w">
    </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">nullable_gamma</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="no">ys</span><span class="w">
    </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">nullable_sym</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="o">(</span><span class="no">NT</span><span class="w"> </span><span class="no">x</span><span class="o">)</span><span class="w">
</span><span class="kp">with</span><span class="w"> </span><span class="no">nullable_gamma</span><span class="w"> </span><span class="o">(</span><span class="no">g</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">grammar</span><span class="o">)</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">list</span><span class="w"> </span><span class="no">symbol</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="kr">Prop</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="no">NullableNil</span><span class="w">  </span><span class="p">:</span><span class="w"> </span><span class="no">nullable_gamma</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="o">[]</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="no">NullableCons</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="kr">forall</span><span class="w"> </span><span class="no">hd</span><span class="w"> </span><span class="no">tl</span><span class="o">,</span><span class="w">
          </span><span class="no">nullable_sym</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="no">hd</span><span class="w">
          </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">nullable_gamma</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="no">tl</span><span class="w">
          </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">nullable_gamma</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="o">(</span><span class="no">hd</span><span class="w"> </span><span class="p">::</span><span class="w"> </span><span class="no">tl</span><span class="o">).</span><span class="w">
</span></code></pre></div></div>

<p>You are looking at the definition of an inductive proposition. This defines how to
create proofs of a symbol <code class="language-plaintext highlighter-rouge">s</code> to be a <code class="language-plaintext highlighter-rouge">nullable_sym</code>: You must supply a nullable gamma <code class="language-plaintext highlighter-rouge">ys</code>
where <code class="language-plaintext highlighter-rouge">(s, ys)</code> is a valid pairing in the grammar’s production.</p>

<p>Mutually, <code class="language-plaintext highlighter-rouge">nullable_gamma</code> must be defined: An empty production is trivially a <code class="language-plaintext highlighter-rouge">nullable_gamma</code>
through the <code class="language-plaintext highlighter-rouge">NullableNil</code> constructor. More interestingly, a gamma’s nullability can be determined by 
the nullability of its head and tail. In summary, the <code class="language-plaintext highlighter-rouge">nullable_sym</code> inductive prop allows us to “choose
a gamma” to show nullability from, and the <code class="language-plaintext highlighter-rouge">nullable_gamma</code> inductive prop allows us to break up the 
symbols in the gamma and recurse into <code class="language-plaintext highlighter-rouge">nullable_sym</code>.</p>

<p>Similar specifications are defined for what it means to be a <code class="language-plaintext highlighter-rouge">first_sym</code>, a <code class="language-plaintext highlighter-rouge">follow_sym</code>, then
a <code class="language-plaintext highlighter-rouge">lookahead_for</code>, and at last culminating in <code class="language-plaintext highlighter-rouge">sys_derives_prefix</code>:</p>
<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="w">    </span><span class="k">Inductive</span><span class="w"> </span><span class="no">sym_derives_prefix</span><span class="w"> </span><span class="o">(</span><span class="no">g</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">grammar</span><span class="o">)</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="kr">Prop</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w">  
    </span><span class="o">|</span><span class="w"> </span><span class="no">T_sdp</span><span class="w"> </span><span class="p">:</span><span class="w">
          </span><span class="c">(* A terminal can derive an element of the corresponding type (determined with t_semty), *)</span><span class="w">
          </span><span class="no">sym_derives_prefix</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="o">(</span><span class="no">T</span><span class="w"> </span><span class="no">a</span><span class="o">)</span><span class="w"> </span><span class="o">[</span><span class="no">existT</span><span class="w"> </span><span class="p">_</span><span class="w"> </span><span class="no">a</span><span class="w"> </span><span class="no">v</span><span class="o">]</span><span class="w"> </span><span class="no">v</span><span class="w"> </span><span class="no">r</span><span class="w">
    </span><span class="o">|</span><span class="w"> </span><span class="no">NT_sdp</span><span class="w"> </span><span class="p">:</span><span class="w">
        </span><span class="c">(* A nonterminal can derive a sequence of tokens if:
           1) There exists a production rule for this nonterminal in the grammar
           2) The next token in the input stream is a valid lookahead for this production
           3) The right-hand side of the production (gamma) can derive the token sequence
           The semantic value is computed by applying the production's action to the derived values *)</span><span class="w">
        </span><span class="no">In</span><span class="w"> </span><span class="o">(</span><span class="no">existT</span><span class="w"> </span><span class="p">_</span><span class="w"> </span><span class="o">(</span><span class="no">x</span><span class="o">,</span><span class="w"> </span><span class="no">gamma</span><span class="o">)</span><span class="w"> </span><span class="no">f</span><span class="o">)</span><span class="w"> </span><span class="no">g</span><span class="o">.(</span><span class="no">prods</span><span class="o">)</span><span class="w"> </span><span class="c">(* Multiple productions allowed *)</span><span class="w">
        </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">lookahead_for</span><span class="w"> </span><span class="o">(</span><span class="no">peek</span><span class="w"> </span><span class="o">(</span><span class="no">w</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="no">r</span><span class="o">))</span><span class="w"> </span><span class="no">x</span><span class="w"> </span><span class="no">gamma</span><span class="w"> </span><span class="no">g</span><span class="w">
        </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">gamma_derives_prefix</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="no">gamma</span><span class="w"> </span><span class="no">w</span><span class="w"> </span><span class="no">vs</span><span class="w"> </span><span class="no">r</span><span class="w">
        </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">sym_derives_prefix</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="o">(</span><span class="no">NT</span><span class="w"> </span><span class="no">x</span><span class="o">)</span><span class="w"> </span><span class="no">w</span><span class="w"> </span><span class="o">(</span><span class="no">f</span><span class="w"> </span><span class="no">vs</span><span class="o">)</span><span class="w"> </span><span class="no">r</span><span class="w">
    </span><span class="kp">with</span><span class="w"> </span><span class="no">gamma_derives_prefix</span><span class="w"> </span><span class="o">(</span><span class="no">g</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">grammar</span><span class="o">)</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="kr">Prop</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w">
         </span><span class="o">|</span><span class="w"> </span><span class="no">Nil_gdp</span><span class="w"> </span><span class="p">:</span><span class="w">
             </span><span class="c">(* An empty sequence of symbols derives an empty sequence of tokens *)</span><span class="w">
             </span><span class="no">gamma_derives_prefix</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="o">[]</span><span class="w"> </span><span class="o">[]</span><span class="w"> </span><span class="no">tt</span><span class="w"> </span><span class="no">r</span><span class="w">
         </span><span class="o">|</span><span class="w"> </span><span class="no">Cons_gdp</span><span class="w"> </span><span class="p">:</span><span class="w">
             </span><span class="c">(* A sequence of symbols derives a token sequence if:
                1) The first symbol derives some prefix of tokens
                2) The rest of the symbols derive the remaining tokens
                The semantic values are paired together as we go *)</span><span class="w">
             </span><span class="no">sym_derives_prefix</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="no">s</span><span class="w"> </span><span class="no">wpre</span><span class="w"> </span><span class="no">v</span><span class="w"> </span><span class="o">(</span><span class="no">wsuf</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="no">r</span><span class="o">)</span><span class="w">
             </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">gamma_derives_prefix</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="no">ss</span><span class="w"> </span><span class="no">wsuf</span><span class="w"> </span><span class="no">vs</span><span class="w"> </span><span class="no">r</span><span class="w">
             </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">gamma_derives_prefix</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="o">(</span><span class="no">s</span><span class="w"> </span><span class="p">::</span><span class="w"> </span><span class="no">ss</span><span class="o">)</span><span class="w"> </span><span class="o">(</span><span class="no">wpre</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="no">wsuf</span><span class="o">)</span><span class="w"> </span><span class="o">(</span><span class="no">v</span><span class="o">,</span><span class="w"> </span><span class="no">vs</span><span class="o">)</span><span class="w"> </span><span class="no">r</span><span class="pi">.</span><span class="w">
</span></code></pre></div></div>
<p>I omitted the parameters to save space. 
It might be better to see the git diff <a href="https://github.com/slasser/vermillion/compare/master...BlastWind:vermillion:master?expand=1">view</a>
between my fork and original; I have the same comments there.</p>

<p><code class="language-plaintext highlighter-rouge">sym_derives_prefix g s w v r</code> means:
Symbol <code class="language-plaintext highlighter-rouge">s</code> can derive a sequence of tokens <code class="language-plaintext highlighter-rouge">w</code> (producing semantic value <code class="language-plaintext highlighter-rouge">v</code>)
with any remaining tokens <code class="language-plaintext highlighter-rouge">r</code>, all
according to grammar <code class="language-plaintext highlighter-rouge">g</code>.</p>

<p>The definition <code class="language-plaintext highlighter-rouge">sym_derives_prefix</code> is used, for example, in <code class="language-plaintext highlighter-rouge">Corollary LL1_derivation_deterministic</code>.
Determinism is encoded as: If we can fathom two derivations, i.e., 
<code class="language-plaintext highlighter-rouge">sym_derives_prefix g s w  v  r</code> and <code class="language-plaintext highlighter-rouge">sym_derives_prefix g s w' v' r'</code>, then actually,
<code class="language-plaintext highlighter-rouge">w = w' /\ r = r'</code>.</p>

<h3 id="2-the-table-construction-algorithm">2. The table construction algorithm</h3>
<p>The table construction algorithm is implemented as a series of Rocq fixpoints (total functions). Each fixpoint computation builds a different set/map needed for the final parse table.
These are essentially the Coq implementations of the LL(1) table construction algorithm as described in the parsing background section.</p>
<ol>
  <li><code class="language-plaintext highlighter-rouge">NULLABLE</code> set (via <code class="language-plaintext highlighter-rouge">mkNullableSet</code>)</li>
</ol>

<p>In Vermillion, the FIRST map cannot contain epsilons, instead, emptiness is tracked with a separate, <code class="language-plaintext highlighter-rouge">NULLABLE</code> set.</p>

<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="no">Program</span><span class="w"> </span><span class="k">Fixpoint</span><span class="w"> </span><span class="no">mkNullableSet'</span><span class="w"> 
        </span><span class="o">(</span><span class="no">ps</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">list</span><span class="w"> </span><span class="no">production</span><span class="o">)</span><span class="w"> 
        </span><span class="o">(</span><span class="no">nu</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nn">NtSet</span><span class="p">.</span><span class="no">t</span><span class="o">)</span><span class="w">
        </span><span class="o">{</span><span class="w"> </span><span class="no">measure</span><span class="w"> </span><span class="o">(</span><span class="no">countNullCands</span><span class="w"> </span><span class="no">ps</span><span class="w"> </span><span class="no">nu</span><span class="o">)</span><span class="w"> </span><span class="o">}</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w">
  </span><span class="kr">let</span><span class="w"> </span><span class="no">nu'</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="no">nullablePass</span><span class="w"> </span><span class="no">ps</span><span class="w"> </span><span class="no">nu</span><span class="w"> </span><span class="kr">in</span><span class="w">
  </span><span class="kr">if</span><span class="w"> </span><span class="nn">NtSet</span><span class="p">.</span><span class="no">eq_dec</span><span class="w"> </span><span class="no">nu</span><span class="w"> </span><span class="no">nu'</span><span class="w"> </span><span class="kr">then</span><span class="w">
    </span><span class="no">nu</span><span class="w">
  </span><span class="kr">else</span><span class="w">
    </span><span class="no">mkNullableSet'</span><span class="w"> </span><span class="no">ps</span><span class="w"> </span><span class="no">nu'</span><span class="pi">.</span><span class="w">
</span></code></pre></div></div>
<p>Each <code class="language-plaintext highlighter-rouge">nullablePass</code> adds nonterminals to the set if their productions can be nullable. The measure <code class="language-plaintext highlighter-rouge">countNullCands</code> ensures termination by counting how many candidates remain.</p>

<ol>
  <li><code class="language-plaintext highlighter-rouge">FIRST</code>, <code class="language-plaintext highlighter-rouge">FOLLOW</code> map</li>
</ol>

<p>Similarly, the <code class="language-plaintext highlighter-rouge">FIRST</code> and <code class="language-plaintext highlighter-rouge">FOLLOW</code> maps are constructed by individual passes until we reach the fixpoint. We 
keep a count on the remaining candidates to determine the fixpoint.</p>

<ol>
  <li>Parsing table
Using the <code class="language-plaintext highlighter-rouge">NULLABLE</code> set, the <code class="language-plaintext highlighter-rouge">FIRST</code> and <code class="language-plaintext highlighter-rouge">FOLLOW</code> maps, we compute the list of entries to add. 
Then, we fold over the list of entries, adding them one by one to the table, throwing
when there are duplicates (by returning an <code class="language-plaintext highlighter-rouge">inl</code>).</li>
</ol>

<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">Definition</span><span class="w"> </span><span class="no">mkParseTable</span><span class="w"> </span><span class="o">(</span><span class="no">ps</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">list</span><span class="w"> </span><span class="no">table_entry</span><span class="o">)</span><span class="w"> </span><span class="p">:</span><span class="w">
  </span><span class="nn">Datatypes</span><span class="p">.</span><span class="no">sum</span><span class="w"> </span><span class="no">string</span><span class="w"> </span><span class="no">parse_table</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w">
  </span><span class="no">fold_right</span><span class="w"> </span><span class="no">addEntry</span><span class="w"> </span><span class="o">(</span><span class="no">inr</span><span class="w"> </span><span class="no">empty_table</span><span class="o">)</span><span class="w"> </span><span class="no">ps</span><span class="pi">.</span><span class="w"> </span><span class="c">(* addEntry throws when we encounter duplicate! *)</span><span class="w">

</span><span class="k">Definition</span><span class="w"> </span><span class="no">parseTableOf</span><span class="w"> </span><span class="o">(</span><span class="no">g</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">grammar</span><span class="o">)</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nn">Datatypes</span><span class="p">.</span><span class="no">sum</span><span class="w"> </span><span class="no">string</span><span class="w"> </span><span class="no">parse_table</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w">
  </span><span class="kr">match</span><span class="w"> </span><span class="no">findDup</span><span class="w"> </span><span class="p">_</span><span class="w"> </span><span class="no">base_production_eq_dec</span><span class="w"> </span><span class="o">(</span><span class="no">baseProductions</span><span class="w"> </span><span class="no">g</span><span class="o">)</span><span class="w"> </span><span class="kp">with</span><span class="w">
  </span><span class="o">|</span><span class="w"> </span><span class="no">Some</span><span class="w"> </span><span class="no">b</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="no">inl</span><span class="w"> </span><span class="o">(</span><span class="no">dupMessage</span><span class="w"> </span><span class="no">b</span><span class="o">)</span><span class="w">
  </span><span class="o">|</span><span class="w"> </span><span class="no">None</span><span class="w">   </span><span class="o">=&gt;</span><span class="w"> 
  </span><span class="kr">let</span><span class="w"> </span><span class="no">nu</span><span class="w">    </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="no">mkNullableSet</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="kr">in</span><span class="w">
    </span><span class="kr">let</span><span class="w"> </span><span class="no">nu_pf</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="no">mkNullableSet_correct</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="kr">in</span><span class="w">
    </span><span class="kr">let</span><span class="w"> </span><span class="no">fi</span><span class="w">    </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="no">mkFirstMap</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="no">nu</span><span class="w"> </span><span class="kr">in</span><span class="w">
    </span><span class="kr">let</span><span class="w"> </span><span class="no">fi_pf</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="no">mkFirstMap_correct</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="no">nu</span><span class="w"> </span><span class="no">nu_pf</span><span class="w"> </span><span class="kr">in</span><span class="w">
    </span><span class="kr">let</span><span class="w"> </span><span class="no">fo</span><span class="w">    </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="no">mkFollowMap</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="no">nu</span><span class="w"> </span><span class="no">fi</span><span class="w"> </span><span class="no">fi_pf</span><span class="w"> </span><span class="kr">in</span><span class="w">
    </span><span class="kr">let</span><span class="w"> </span><span class="no">es</span><span class="w">    </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="no">mkEntries</span><span class="w"> </span><span class="no">nu</span><span class="w"> </span><span class="no">fi</span><span class="w"> </span><span class="no">fo</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="kr">in</span><span class="w">
    </span><span class="no">mkParseTable</span><span class="w"> </span><span class="no">es</span><span class="w">
  </span><span class="kr">end</span><span class="pi">.</span><span class="w">
</span></code></pre></div></div>

<h3 id="3-table-construction-algorithm-makes-correct-parse-tables">3. Table construction algorithm makes correct parse tables</h3>
<p>And now, we bridge the implementation with the specification. The bridging theorems are <code class="language-plaintext highlighter-rouge">parseTableOf_sound</code> and <code class="language-plaintext highlighter-rouge">parseTableOf_complete</code>:</p>

<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">Theorem</span><span class="w"> </span><span class="no">parseTableOf_sound</span><span class="w"> </span><span class="p">:</span><span class="w"> 
  </span><span class="kr">forall</span><span class="w"> </span><span class="o">(</span><span class="no">g</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">grammar</span><span class="o">)</span><span class="w"> </span><span class="o">(</span><span class="no">tbl</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">parse_table</span><span class="o">),</span><span class="w">
    </span><span class="no">parseTableOf</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="no">inr</span><span class="w"> </span><span class="no">tbl</span><span class="w">
    </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">parse_table_correct</span><span class="w"> </span><span class="no">tbl</span><span class="w"> </span><span class="no">g</span><span class="pi">.</span><span class="w">

</span><span class="k">Theorem</span><span class="w"> </span><span class="no">parseTableOf_complete</span><span class="w"> </span><span class="p">:</span><span class="w">
  </span><span class="kr">forall</span><span class="w"> </span><span class="o">(</span><span class="no">g</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">grammar</span><span class="o">)</span><span class="w"> </span><span class="o">(</span><span class="no">tbl</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">parse_table</span><span class="o">),</span><span class="w">
    </span><span class="no">unique_productions</span><span class="w"> </span><span class="no">g</span><span class="w">
    </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">parse_table_correct</span><span class="w"> </span><span class="no">tbl</span><span class="w"> </span><span class="no">g</span><span class="w"> 
    </span><span class="o">-&gt;</span><span class="w"> </span><span class="kp">exists</span><span class="w"> </span><span class="o">(</span><span class="no">tbl'</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">parse_table</span><span class="o">),</span><span class="w">
      </span><span class="nn">ParseTable</span><span class="p">.</span><span class="no">Equal</span><span class="w"> </span><span class="no">tbl</span><span class="w"> </span><span class="no">tbl'</span><span class="w"> </span><span class="o">/\</span><span class="w"> </span><span class="no">parseTableOf</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="no">inr</span><span class="w"> </span><span class="no">tbl'</span><span class="pi">.</span><span class="w">
</span></code></pre></div></div>

<p>The first says: If our table construction fixpoint successfully makes a table,
then that table satisfies <code class="language-plaintext highlighter-rouge">parse_table_correct</code>, meaning:</p>
<ol>
  <li>(Soundness) If there is a nonterminal and lookahead <code class="language-plaintext highlighter-rouge">(nt, la)</code> pair that finds a certain <code class="language-plaintext highlighter-rouge">gamma</code> in the table, then <code class="language-plaintext highlighter-rouge">nt -&gt; gamma</code> must be a
production in the grammar with <code class="language-plaintext highlighter-rouge">la</code> as the <code class="language-plaintext highlighter-rouge">lookahead_for</code> (inductively defined) <code class="language-plaintext highlighter-rouge">nt</code> in the <code class="language-plaintext highlighter-rouge">gamma</code> production.</li>
  <li>(Completeness) For all <code class="language-plaintext highlighter-rouge">nonterminal -&gt; gamma</code> productions, if a lookahead <code class="language-plaintext highlighter-rouge">la</code> is the <code class="language-plaintext highlighter-rouge">lookahead_for</code> (inductively defined) for the <code class="language-plaintext highlighter-rouge">gamma</code>, then 
<code class="language-plaintext highlighter-rouge">(nonterminal, la)</code> is in the table.</li>
</ol>

<p>Conversely, if there exists a table satisfying <code class="language-plaintext highlighter-rouge">parse_table_correct</code>, then there exists a grammar that makes this exact table under <code class="language-plaintext highlighter-rouge">parseTableOf</code>.</p>

<p>How can these be proved? Correctness is defined as soundness + completeness, let’s zoom in on completeness:</p>

<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">Lemma</span><span class="w"> </span><span class="no">mkParseTable_complete</span><span class="w"> </span><span class="p">:</span><span class="w">
  </span><span class="kr">forall</span><span class="w"> </span><span class="o">(</span><span class="no">es</span><span class="w">  </span><span class="p">:</span><span class="w"> </span><span class="no">list</span><span class="w"> </span><span class="no">table_entry</span><span class="o">)</span><span class="w">
          </span><span class="o">(</span><span class="no">g</span><span class="w">   </span><span class="p">:</span><span class="w"> </span><span class="no">grammar</span><span class="o">)</span><span class="w">
          </span><span class="o">(</span><span class="no">tbl</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">parse_table</span><span class="o">),</span><span class="w">
    </span><span class="no">unique_productions</span><span class="w"> </span><span class="no">g</span><span class="w">
    </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">entries_correct</span><span class="w"> </span><span class="no">es</span><span class="w"> </span><span class="no">g</span><span class="w">
    </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">parse_table_correct</span><span class="w"> </span><span class="no">tbl</span><span class="w"> </span><span class="no">g</span><span class="w">
    </span><span class="o">-&gt;</span><span class="w"> </span><span class="kp">exists</span><span class="w"> </span><span class="no">tbl'</span><span class="o">,</span><span class="w">
        </span><span class="nn">ParseTable</span><span class="p">.</span><span class="no">Equal</span><span class="w"> </span><span class="no">tbl</span><span class="w"> </span><span class="no">tbl'</span><span class="w">
        </span><span class="o">/\</span><span class="w"> </span><span class="no">mkParseTable</span><span class="w"> </span><span class="no">es</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="no">inr</span><span class="w"> </span><span class="no">tbl'</span><span class="pi">.</span><span class="w">

</span><span class="k">Theorem</span><span class="w"> </span><span class="no">parseTableOf_complete</span><span class="w"> </span><span class="p">:</span><span class="w">
  </span><span class="kr">forall</span><span class="w"> </span><span class="o">(</span><span class="no">g</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">grammar</span><span class="o">)</span><span class="w"> </span><span class="o">(</span><span class="no">tbl</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">parse_table</span><span class="o">),</span><span class="w">
    </span><span class="no">unique_productions</span><span class="w"> </span><span class="no">g</span><span class="w">
    </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">parse_table_correct</span><span class="w"> </span><span class="no">tbl</span><span class="w"> </span><span class="no">g</span><span class="w"> 
    </span><span class="o">-&gt;</span><span class="w"> </span><span class="kp">exists</span><span class="w"> </span><span class="o">(</span><span class="no">tbl'</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">parse_table</span><span class="o">),</span><span class="w">
      </span><span class="nn">ParseTable</span><span class="p">.</span><span class="no">Equal</span><span class="w"> </span><span class="no">tbl</span><span class="w"> </span><span class="no">tbl'</span><span class="w"> </span><span class="o">/\</span><span class="w"> </span><span class="no">parseTableOf</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="no">inr</span><span class="w"> </span><span class="no">tbl'</span><span class="pi">.</span><span class="w">
</span><span class="k">Proof</span><span class="pi">.</span><span class="w">
  </span><span class="kp">intros</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="no">tbl</span><span class="w"> </span><span class="no">Hu</span><span class="w"> </span><span class="no">Ht</span><span class="pi">.</span><span class="w">
  </span><span class="kp">unfold</span><span class="w"> </span><span class="no">unique_productions</span><span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="no">Hu</span><span class="p">;</span><span class="w"> </span><span class="kp">unfold</span><span class="w"> </span><span class="no">parseTableOf</span><span class="pi">.</span><span class="w">
  </span><span class="no">pose</span><span class="w"> </span><span class="no">proof</span><span class="w"> </span><span class="no">Hu</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="no">Hu'</span><span class="p">;</span><span class="w"> </span><span class="kp">eapply</span><span class="w"> </span><span class="no">NoDup_findDup_None_iff</span><span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="no">Hu'</span><span class="p">;</span><span class="w"> </span><span class="kp">rewrite</span><span class="w"> </span><span class="no">Hu'</span><span class="pi">.</span><span class="w">
  </span><span class="kp">eapply</span><span class="w"> </span><span class="no">mkParseTable_complete</span><span class="p">;</span><span class="w"> </span><span class="kp">eauto</span><span class="pi">.</span><span class="w">
  </span><span class="kp">eapply</span><span class="w"> </span><span class="no">mkEntries_correct</span><span class="p">;</span><span class="w"> </span><span class="kp">eauto</span><span class="pi">.</span><span class="w">
  </span><span class="o">-</span><span class="w"> </span><span class="kp">apply</span><span class="w"> </span><span class="no">mkNullableSet_correct</span><span class="p">;</span><span class="w"> </span><span class="kp">auto</span><span class="pi">.</span><span class="w">
  </span><span class="o">-</span><span class="w"> </span><span class="kp">apply</span><span class="w"> </span><span class="no">mkFirstMap_correct</span><span class="pi">.</span><span class="w">
    </span><span class="kp">apply</span><span class="w"> </span><span class="no">mkNullableSet_correct</span><span class="p">;</span><span class="w"> </span><span class="kp">auto</span><span class="pi">.</span><span class="w">
  </span><span class="o">-</span><span class="w"> </span><span class="kp">apply</span><span class="w"> </span><span class="no">mkFollowMap_correct</span><span class="p">;</span><span class="w"> </span><span class="kp">auto</span><span class="pi">.</span><span class="w">
    </span><span class="kp">apply</span><span class="w"> </span><span class="no">mkNullableSet_correct</span><span class="p">;</span><span class="w"> </span><span class="kp">auto</span><span class="pi">.</span><span class="w">
</span><span class="k">Qed</span><span class="pi">.</span><span class="w">
</span></code></pre></div></div>

<p>The completeness of the final parse table is encoded in <code class="language-plaintext highlighter-rouge">parseTableOf_complete</code>. <code class="language-plaintext highlighter-rouge">parseTableOf_complete</code> depends on <code class="language-plaintext highlighter-rouge">mkParseTable_complete</code>,
which reduces the goal of showing completeness of <code class="language-plaintext highlighter-rouge">parseTableOf</code> (constructed by adding entries individually and throwing on duplicates)
to showing <code class="language-plaintext highlighter-rouge">mkEntries_correct</code>.</p>

<p>This reduction is possible due to this important, bridging lemma:</p>
<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">Lemma</span><span class="w"> </span><span class="no">invariant_iff_parse_table_correct</span><span class="w"> </span><span class="p">:</span><span class="w">
  </span><span class="kr">forall</span><span class="w"> </span><span class="o">(</span><span class="no">g</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">grammar</span><span class="o">)</span><span class="w"> </span><span class="o">(</span><span class="no">es</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">list</span><span class="w"> </span><span class="no">table_entry</span><span class="o">)</span><span class="w"> </span><span class="o">(</span><span class="no">tbl</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">parse_table</span><span class="o">),</span><span class="w">
    </span><span class="no">entries_correct</span><span class="w"> </span><span class="no">es</span><span class="w"> </span><span class="no">g</span><span class="w">
    </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">table_correct_wrt_entries</span><span class="w"> </span><span class="no">tbl</span><span class="w"> </span><span class="no">es</span><span class="w">
        </span><span class="o">&lt;-&gt;</span><span class="w"> </span><span class="no">parse_table_correct</span><span class="w"> </span><span class="no">tbl</span><span class="w"> </span><span class="no">g</span><span class="pi">.</span><span class="w">
</span></code></pre></div></div>

<p>To show <code class="language-plaintext highlighter-rouge">mkEntries_correct</code>, we ought to show each construction procedure for each substructure is correct.
The key to these proofs is well-founded induction on the number of candidates. For example, 
on each <code class="language-plaintext highlighter-rouge">nullablePass</code> (implementational), the number of null candidates decreases, 
which coincides with the null candidates increasing in an inductively built nullable.</p>

<p>I don’t fully understand the mechanics of these proofs — there are pieces I haven’t explained,
but I hope this gives a big enough picture.</p>

<h3 id="4-proving-properties-about-parsers">4. Proving properties about parsers</h3>
<p>I present the theorem <code class="language-plaintext highlighter-rouge">LL1_parse_table_impl_no_left_recursion</code> and its proof.
The theorem is written with inductive definitions. 
But because we have connected the implementational <code class="language-plaintext highlighter-rouge">parseTableOf</code>
to the inductive definitions, our real algorithms will also enjoy <code class="language-plaintext highlighter-rouge">LL1_parse_table_impl_no_left_recursion</code>.</p>

<p>Here is the location of the proof in the grand proof tree:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>└── LL1_derivation_deterministic 
    (Unambiguity)
    ├── parse_terminates_without_error 
    │   └── LL1_parse_table_impl_no_left_recursion &lt;--------------------------------------------- We are here!
    |       (Proves that a correct LL(1) parse table cannot have left recursion)
    │       ├── sized_first_sym_det 
    |           (Shows that the size of first set derivations is deterministic)
    │           └── first_sym_rhs_eqs 
    |               (Proves that if two productions for same nonterminal can derive same first token, they must be identical)
    │               └── no_first_follow_conflict 
    |                   (A symbol cannot have same token in both FIRST and FOLLOW sets if nullable)
</code></pre></div></div>

<p>And here is the theorem and proof:</p>

<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">Lemma</span><span class="w"> </span><span class="no">LL1_parse_table_impl_no_left_recursion</span><span class="w"> </span><span class="p">:</span><span class="w">
  </span><span class="kr">forall</span><span class="w"> </span><span class="o">(</span><span class="no">g</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">grammar</span><span class="o">)</span><span class="w"> </span><span class="o">(</span><span class="no">tbl</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">parse_table</span><span class="o">)</span><span class="w"> 
          </span><span class="o">(</span><span class="no">x</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">nonterminal</span><span class="o">)</span><span class="w"> </span><span class="o">(</span><span class="no">la</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">lookahead</span><span class="o">),</span><span class="w">
    </span><span class="no">parse_table_correct</span><span class="w"> </span><span class="no">tbl</span><span class="w"> </span><span class="no">g</span><span class="w">
    </span><span class="o">-&gt;</span><span class="w"> </span><span class="o">~</span><span class="w"> </span><span class="no">left_recursive</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="o">(</span><span class="no">NT</span><span class="w"> </span><span class="no">x</span><span class="o">)</span><span class="w"> </span><span class="no">la</span><span class="pi">.</span><span class="w">
</span></code></pre></div></div>
<p>where <code class="language-plaintext highlighter-rouge">left_recursive</code> is defined as an inductive proposition:</p>
<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">Inductive</span><span class="w"> </span><span class="no">nullable_path</span><span class="w"> </span><span class="o">(</span><span class="no">g</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">grammar</span><span class="o">)</span><span class="w"> </span><span class="o">(</span><span class="no">la</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">lookahead</span><span class="o">)</span><span class="w"> </span><span class="p">:</span><span class="w">
  </span><span class="no">symbol</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">symbol</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="kr">Prop</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w">
</span><span class="o">|</span><span class="w"> </span><span class="no">DirectPath</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="kr">forall</span><span class="w"> </span><span class="no">x</span><span class="w"> </span><span class="no">z</span><span class="w"> </span><span class="no">gamma</span><span class="w"> </span><span class="no">f</span><span class="w"> </span><span class="no">pre</span><span class="w"> </span><span class="no">suf</span><span class="o">,</span><span class="w">
    </span><span class="no">In</span><span class="w"> </span><span class="o">(</span><span class="no">existT</span><span class="w"> </span><span class="p">_</span><span class="w"> </span><span class="o">(</span><span class="no">x</span><span class="o">,</span><span class="w"> </span><span class="no">gamma</span><span class="o">)</span><span class="w"> </span><span class="no">f</span><span class="o">)</span><span class="w"> </span><span class="no">g</span><span class="o">.(</span><span class="no">prods</span><span class="o">)</span><span class="w">
    </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">gamma</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="no">pre</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="no">NT</span><span class="w"> </span><span class="no">z</span><span class="w"> </span><span class="p">::</span><span class="w"> </span><span class="no">suf</span><span class="w">
    </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">nullable_gamma</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="no">pre</span><span class="w">
    </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">lookahead_for</span><span class="w"> </span><span class="no">la</span><span class="w"> </span><span class="no">x</span><span class="w"> </span><span class="no">gamma</span><span class="w"> </span><span class="no">g</span><span class="w">
    </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">nullable_path</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="no">la</span><span class="w"> </span><span class="o">(</span><span class="no">NT</span><span class="w"> </span><span class="no">x</span><span class="o">)</span><span class="w"> </span><span class="o">(</span><span class="no">NT</span><span class="w"> </span><span class="no">z</span><span class="o">)</span><span class="w">
</span><span class="o">|</span><span class="w"> </span><span class="no">IndirectPath</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="kr">forall</span><span class="w"> </span><span class="no">x</span><span class="w"> </span><span class="no">y</span><span class="w"> </span><span class="no">z</span><span class="w"> </span><span class="no">gamma</span><span class="w"> </span><span class="no">f</span><span class="w"> </span><span class="no">pre</span><span class="w"> </span><span class="no">suf</span><span class="o">,</span><span class="w">
    </span><span class="no">In</span><span class="w"> </span><span class="o">(</span><span class="no">existT</span><span class="w"> </span><span class="p">_</span><span class="w"> </span><span class="o">(</span><span class="no">x</span><span class="o">,</span><span class="w"> </span><span class="no">gamma</span><span class="o">)</span><span class="w"> </span><span class="no">f</span><span class="o">)</span><span class="w"> </span><span class="no">g</span><span class="o">.(</span><span class="no">prods</span><span class="o">)</span><span class="w">
    </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">gamma</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="no">pre</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="no">NT</span><span class="w"> </span><span class="no">y</span><span class="w"> </span><span class="p">::</span><span class="w"> </span><span class="no">suf</span><span class="w">
    </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">nullable_gamma</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="no">pre</span><span class="w">
    </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">lookahead_for</span><span class="w"> </span><span class="no">la</span><span class="w"> </span><span class="no">x</span><span class="w"> </span><span class="no">gamma</span><span class="w"> </span><span class="no">g</span><span class="w">
    </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">nullable_path</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="no">la</span><span class="w"> </span><span class="o">(</span><span class="no">NT</span><span class="w"> </span><span class="no">y</span><span class="o">)</span><span class="w"> </span><span class="o">(</span><span class="no">NT</span><span class="w"> </span><span class="no">z</span><span class="o">)</span><span class="w">
    </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">nullable_path</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="no">la</span><span class="w"> </span><span class="o">(</span><span class="no">NT</span><span class="w"> </span><span class="no">x</span><span class="o">)</span><span class="w"> </span><span class="o">(</span><span class="no">NT</span><span class="w"> </span><span class="no">z</span><span class="o">).</span><span class="w">

</span><span class="k">Definition</span><span class="w"> </span><span class="no">left_recursive</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="no">sym</span><span class="w"> </span><span class="no">la</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w">
  </span><span class="no">nullable_path</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="no">la</span><span class="w"> </span><span class="no">sym</span><span class="w"> </span><span class="no">sym</span><span class="pi">.</span><span class="w">
</span></code></pre></div></div>

<p>For example, in</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>A → ε B c
B → ε C d 
C → e
</code></pre></div></div>

<p>there is a direct nullable path from <code class="language-plaintext highlighter-rouge">A</code> to <code class="language-plaintext highlighter-rouge">B</code> and from <code class="language-plaintext highlighter-rouge">B</code> to <code class="language-plaintext highlighter-rouge">C</code>. Therefore, transitively, there
is an indirect path from <code class="language-plaintext highlighter-rouge">A</code> to <code class="language-plaintext highlighter-rouge">C</code>.</p>

<p>The proof works by contradiction. It assumes left recursion exists and derives a contradiction in two cases.
There are two cases because left recursion can be built with <code class="language-plaintext highlighter-rouge">DirectPath</code> and <code class="language-plaintext highlighter-rouge">IndirectPath</code>.</p>

<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">Proof</span><span class="pi">.</span><span class="w">
  </span><span class="kp">intros</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="no">t</span><span class="w"> </span><span class="no">x</span><span class="w"> </span><span class="no">la</span><span class="w"> </span><span class="no">Ht</span><span class="p">;</span><span class="w"> </span><span class="kp">unfold</span><span class="w"> </span><span class="no">not</span><span class="p">;</span><span class="w"> </span><span class="kp">intros</span><span class="w"> </span><span class="no">Hlr</span><span class="p">;</span><span class="w"> </span><span class="kp">red</span><span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="no">Hlr</span><span class="pi">.</span><span class="w">
  </span><span class="c">(* Get the production that starts the left recursion *)</span><span class="w">
  </span><span class="no">assert</span><span class="w"> </span><span class="o">(</span><span class="no">Hex</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="kp">exists</span><span class="w"> </span><span class="no">gamma</span><span class="w"> </span><span class="no">f</span><span class="o">,</span><span class="w">
             </span><span class="no">In</span><span class="w"> </span><span class="o">(</span><span class="no">existT</span><span class="w"> </span><span class="p">_</span><span class="w"> </span><span class="o">(</span><span class="no">x</span><span class="o">,</span><span class="w"> </span><span class="no">gamma</span><span class="o">)</span><span class="w"> </span><span class="no">f</span><span class="o">)</span><span class="w"> </span><span class="no">g</span><span class="o">.(</span><span class="no">prods</span><span class="o">)</span><span class="w">
             </span><span class="o">/\</span><span class="w"> </span><span class="no">lookahead_for</span><span class="w"> </span><span class="no">la</span><span class="w"> </span><span class="no">x</span><span class="w"> </span><span class="no">gamma</span><span class="w"> </span><span class="no">g</span><span class="o">).</span><span class="w">
  </span><span class="o">{</span><span class="w"> </span><span class="kp">apply</span><span class="w"> </span><span class="no">nullable_path_exists_production</span><span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="no">Hlr</span><span class="p">;</span><span class="w"> </span><span class="kp">auto</span><span class="pi">.</span><span class="w"> </span><span class="o">}</span><span class="w">
  </span><span class="kp">destruct</span><span class="w"> </span><span class="no">Hex</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="o">[</span><span class="no">gamma</span><span class="w"> </span><span class="o">[</span><span class="no">f</span><span class="w"> </span><span class="o">[</span><span class="no">Hi</span><span class="w"> </span><span class="no">Hl</span><span class="o">]]].</span><span class="w">
  
  </span><span class="c">(* Split into two cases based on how the lookahead is derived *)</span><span class="w">
  </span><span class="kp">destruct</span><span class="w"> </span><span class="no">Hl</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="o">[</span><span class="no">Hfg</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="o">[</span><span class="no">Hng</span><span class="w"> </span><span class="no">Hfo</span><span class="o">]].</span><span class="w">

  </span><span class="o">...</span><span class="w"> </span><span class="no">to</span><span class="w"> </span><span class="no">be</span><span class="w"> </span><span class="no">continued</span><span class="w">
</span></code></pre></div></div>

<p>For both cases, the general approach is to say that the length of the nullable path must strictly decrease
as we go down the path.</p>

<p>For example, in</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>A --nullable-path--&gt; B --nullable-path--&gt; C
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">A</code>’s nullable path is 3, <code class="language-plaintext highlighter-rouge">B</code>’s is 2, and <code class="language-plaintext highlighter-rouge">C</code>’s is 1.</p>

<p>But since we have left recursion, the path length doesn’t decrease once we get back to the same nonterminal, so we 
contradict this:</p>

<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="w">  </span><span class="c">(* Case 1: DirectPath *)</span><span class="w">
  </span><span class="o">-</span><span class="w"> </span><span class="no">assert</span><span class="w"> </span><span class="o">(</span><span class="no">Hf</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">first_sym</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="no">la</span><span class="w"> </span><span class="o">(</span><span class="no">NT</span><span class="w"> </span><span class="no">x</span><span class="o">))</span><span class="w"> </span><span class="no">by</span><span class="w"> </span><span class="o">(</span><span class="no">inv</span><span class="w"> </span><span class="no">Hfg</span><span class="p">;</span><span class="w"> </span><span class="kp">eauto</span><span class="o">).</span><span class="w">
    </span><span class="kp">eapply</span><span class="w"> </span><span class="no">sized_first_sym_np</span><span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="no">Hf</span><span class="p">;</span><span class="w"> </span><span class="kp">eauto</span><span class="pi">.</span><span class="w">
    </span><span class="kp">destruct</span><span class="w"> </span><span class="no">Hf</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="o">[</span><span class="no">n</span><span class="w"> </span><span class="o">[</span><span class="no">n'</span><span class="w"> </span><span class="o">[</span><span class="no">Hf</span><span class="w"> </span><span class="o">[</span><span class="no">Hf'</span><span class="w"> </span><span class="no">Hlt</span><span class="o">]]]].</span><span class="w">
    </span><span class="kp">eapply</span><span class="w"> </span><span class="no">sized_first_sym_det</span><span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="no">Hf</span><span class="p">;</span><span class="w"> </span><span class="kp">eauto</span><span class="pi">.</span><span class="w">
    </span><span class="no">lia</span><span class="pi">.</span><span class="w">

  </span><span class="c">(* Case 2: IndirectPath *)</span><span class="w">  
  </span><span class="o">-</span><span class="w"> </span><span class="no">assert</span><span class="w"> </span><span class="o">(</span><span class="no">Hns</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">nullable_sym</span><span class="w"> </span><span class="no">g</span><span class="w"> </span><span class="o">(</span><span class="no">NT</span><span class="w"> </span><span class="no">x</span><span class="o">))</span><span class="w"> </span><span class="no">by</span><span class="w"> </span><span class="kp">eauto</span><span class="pi">.</span><span class="w">
    </span><span class="kp">eapply</span><span class="w"> </span><span class="no">exist_decreasing_nullable_sym_sizes_in_null_path</span><span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="no">Hns</span><span class="p">;</span><span class="w"> </span><span class="kp">eauto</span><span class="pi">.</span><span class="w">
    </span><span class="kp">destruct</span><span class="w"> </span><span class="no">Hns</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="o">[</span><span class="no">n</span><span class="w"> </span><span class="o">[</span><span class="no">n'</span><span class="w"> </span><span class="o">[</span><span class="no">Hs</span><span class="w"> </span><span class="o">[</span><span class="no">Hs'</span><span class="w"> </span><span class="no">Hlt</span><span class="o">]]]].</span><span class="w">
    </span><span class="kp">eapply</span><span class="w"> </span><span class="no">sized_nullable_sym_det</span><span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="no">Hs</span><span class="p">;</span><span class="w"> </span><span class="kp">eauto</span><span class="pi">.</span><span class="w">
    </span><span class="no">lia</span><span class="pi">.</span><span class="w">
</span></code></pre></div></div>

<p>For both branches, before the final <code class="language-plaintext highlighter-rouge">lia</code>, there are these two hypotheses in the proof state:</p>
<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="no">Hlt</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">n'</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="no">n</span><span class="w">
</span><span class="no">Hf</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">n'</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="no">n</span><span class="w">
</span></code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">lia</code> automatically observes a contradiction, solving our goal.</p>]]></content><author><name>Andrew Chen</name><email>(λx.λy.λz. yz@x) gmail.com andrewchen 14250</email></author><category term="formal-methods" /><summary type="html"><![CDATA[Parsers come in two forms. In the first form, they are parser generators. In the second, they are parser combinators. These two forms have very different backgrounds, but they are dual.]]></summary></entry><entry><title type="html">Problems in Your Head, Problems in My Head</title><link href="https://unfooling.com/unfooling.com/problems-to-keep-in-your-head/" rel="alternate" type="text/html" title="Problems in Your Head, Problems in My Head" /><published>2024-12-17T11:07:00-05:00</published><updated>2024-12-17T11:07:00-05:00</updated><id>https://unfooling.com/unfooling.com/problems-to-keep-in-your-head</id><content type="html" xml:base="https://unfooling.com/unfooling.com/problems-to-keep-in-your-head/"><![CDATA[<p>This post serves three goals:</p>
<ol>
  <li>Encourage you to marinate on problems,</li>
  <li>Prelude a practical information organization framework,</li>
  <li>Give you my problems.</li>
</ol>

<p>I will occasionally update this post with new problems.</p>

<h3 id="encouragement">Encouragement</h3>
<p>I have observed, smart people can explain intricate, problems 
succinctly and can fluidly back up their points 
with examples and stories.</p>

<p>They seem to communicate and store information in a natural
problem-solution, cause-effect framework. Their brain can
constantly juggle numerous problems. Their neural connectivity
between concepts are strong.</p>

<p>My thesis: It is the exact act of constantly juggling problems 
over a long period of time,
connecting them with other concepts, infusing them with stories,
that makes you smart. It also helps you appear smart, as 
that information is lucid and ready.</p>

<p>And while the geniuses might be unconsciously doing this, 
there is nothing preventing us from consciously adapting
this practice. Feynman was the first I know to suggest this —</p>
<blockquote>
  <p>“[To be a genius],
you have to keep a dozen of your favorite problems constantly present
in your mind, although by and large they will lay in a dormant state.
Every time you hear or read a new trick or a new result, test it against
each of your twelve problems to see whether it helps.”</p>
</blockquote>

<p>Richard Hamming exclaimed the same —</p>

<blockquote>
  <p>[Most great scientists] have something between 10 and 20 important problems for which they are looking for an attack. 
And when they see a new idea come up, one hears them say “Well that bears on this problem.”</p>
</blockquote>

<p>Pick your problems and set a daily reminder to resurface them.</p>

<h3 id="organizing-information-at-large">Organizing Information At Large</h3>
<p>There are big problems, small ideas, quick sketches… How do we organize all of these?
How do we ingest information? Can we become fluid with all of them?
Should the problems we pick only be big challenges?</p>

<p>I present some thoughts and untested hypotheses on these but leave this section partial.
Developing a total framework for genius science thinking deserves a whole book.</p>

<ol>
  <li>
    <p>You only know what you can teach. Before you pick your problems, 
discover what you know by heart: What can you teach a class on, right now?
What are you confident in writing a textbook on?</p>
  </li>
  <li>
    <p>There are two tiers of information: Fundamental and junk. 
Information you deem fundamental make up what you know. 
Since what you know is a good chunk of who you are, these information
<strong>make up your identity</strong>. Therefore, they are very, very important.
After ingestion, they should be queued for prepping into 
a format ready for scientific communication. They are composed 
into stories or written in prose. They should be revisited intermittently (active recall).
You should consciously classify information as either fundamental or junk.
Most information lie in the no mans land of “might be useful”. 
But, you aren’t going to retrieve or use the “might be useful” unless you need it,
so, with time, they are as good as garbage.</p>
  </li>
  <li>
    <p>Your big problems are your super fundamental information. They are your organs, your chakras.
When enlisting new fundamental information, you should consider how it
relates to your big problems.</p>
  </li>
  <li>
    <p>It may be useful to embark on your “Great Reconstruction”. I will experiment with this.
I plan to go through my obsidian app and delete all information that “might be useful”.
I will then label each note as uningested, slowly go through them, reingesting them
with the rules I posed in 2).</p>
  </li>
  <li>
    <p>Information can be recalled easier if it maintains casual relationships with other information.
When I studied Algebra last year, I justified the algebraic rules for an “ideal” as the precise
constraints that allow rings to quotient over during canonical decomposition. This is not 
the way it’s taught, but the two hours I spent finding this casual relationship allowed me 
to still remember this fact.</p>
  </li>
</ol>

<h3 id="my-big-problems">My Big Problems</h3>
<p>I am formulating my initial problem list as of writing (Dec 2024). I stumbled upon these through personal curiosities, but expect
future listings to be inspired by my colleagues, or by you, my reader.</p>

<h5 id="the-expression-problem">The Expression Problem.</h5>

<p>Category: Software engineering.</p>

<p>Enlisted: Dec 2024.</p>

<p>Intro: How can you expand the datatype and extend the functionality orthogonally?
As of right now, I know effect systems in Haskell to make for the cleanest approach.
But I need to investigate other languages and type-level programming.</p>

<h5 id="extent-of-the-curry-howard-correspondence">Extent of the Curry-Howard correspondence.</h5>

<p>Category: Type theory.</p>

<p>Enlisted: Dec 2024.</p>

<p>Intro: Curry-Howard correspondance envelopes proof-as-programs. For example,
<code class="language-plaintext highlighter-rouge">exists n. n = 0</code>, a proposition, is considered a type. When you construct a term
with this type, you have provided a proof for the proposition.</p>

<p>But the correspondance runs deeper than proof-as-programs. The polymorphic lambda calculus is the same as
System-F; Many lambda calculi have equivalent power with certain logics;
Logic can be encoded in lambda calculi.</p>

<p>Where is the boundary of this interpretation?</p>

<h5 id="integrating-formal-verifications-in-turing-complete-languages">Integrating formal verifications in Turing-complete languages.</h5>

<p>Category: Type theory.</p>

<p>Enlisted: Dec 2024.</p>

<p>Intro: How can I prove that <code class="language-plaintext highlighter-rouge">forall n: nat, n + 0 = n</code>, in say, Python? 
The coq approach would be to define <code class="language-plaintext highlighter-rouge">nat</code> inductively, and prove
statement with induction. But what if we just hook this to a SMT solver?
Or, maybe <code class="language-plaintext highlighter-rouge">forall n: nat, n + 0</code> doesn’t matter, it’s not something 
real software writes?
I first came across this problem in June 2023
through the <a href="https://github.com/magmide/magmide#this-is-an-exciting-idea-how-can-i-help">magmide</a> repo.
I actually conversed with the author through emails as a complete noob at the time. Coincidentally,
I am employed on a program that deals precisely with this.</p>

<h5 id="building-a-microscope-and-microbiology-for-llms">Building a microscope and microbiology for LLMs.</h5>

<p>Category: LLM interpretability.</p>

<p>Enlisted: Dec 2024.</p>

<p>Intro: I first came across the field in Dec 2023 through the transformer circuits <a href="https://transformer-circuits.pub/">thread</a>.</p>

<h5 id="providing-more-rigor-for-llms">Providing more rigor for LLMs.</h5>

<p>Category: Category theory, LLM, neurosymbolism.</p>

<p>Intro: We are at a limit with transformers. Can we provide more <a href="https://arxiv.org/abs/2104.13478">rigor</a> for the next generation of LLMs? 
Can you encode logic into <a href="https://link.springer.com/book/10.1007/978-3-031-71167-1">them</a>?</p>

<h5 id="something-quantum">Something Quantum.</h5>

<p>Category: Quantum.</p>

<p>I know nothing right now. But I’ll slowly develop this. I’m definitely more interested on the algorithmic application side.</p>]]></content><author><name>Andrew Chen</name><email>(λx.λy.λz. yz@x) gmail.com andrewchen 14250</email></author><category term="idea" /><summary type="html"><![CDATA[This post serves three goals: Encourage you to marinate on problems, Prelude a practical information organization framework, Give you my problems.]]></summary></entry><entry><title type="html">Real, Intermediate Haskell Lenses - Part 1</title><link href="https://unfooling.com/unfooling.com/intermediate-lenses/" rel="alternate" type="text/html" title="Real, Intermediate Haskell Lenses - Part 1" /><published>2024-09-14T12:00:00-04:00</published><updated>2024-09-14T12:00:00-04:00</updated><id>https://unfooling.com/unfooling.com/intermediate-lenses</id><content type="html" xml:base="https://unfooling.com/unfooling.com/intermediate-lenses/"><![CDATA[<p>Recently, I started reading <a href="https://github.com/BlastWind/swarm"><code class="language-plaintext highlighter-rouge">swarm</code></a>, a resource gathering + programming game built with Haskell. I went to <code class="language-plaintext highlighter-rouge">swarm</code>’s <a href="https://github.com/swarm-game/swarm/commit/479b10e98685cdc4c7c7f1935b679b6b83819dcf">very first commit</a>. The 200-liner is able to render the following,</p>

<p><img src="unfooling.com/assets/img/swarm-first-commit.gif" alt="Sample GIF" /></p>

<p>and I was already stumped by the code! What in the lens are these snippets —</p>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">-- r :: Robot, </span>
<span class="c1">-- robotProgram :: Lens' Robot [Command]</span>
<span class="c1">-- p :: Command</span>
<span class="p">(</span><span class="n">r</span> <span class="o">&amp;</span> <span class="n">robotProgram</span> <span class="o">.~</span> <span class="n">p</span><span class="p">)</span>

<span class="c1">-- world :: Lens' GameState [[Char]]</span>
<span class="c1">-- row, col :: Int</span>
<span class="n">preuse</span> <span class="o">$</span> <span class="n">world</span> <span class="o">.</span> <span class="n">ix</span> <span class="n">row</span> <span class="o">.</span> <span class="n">ix</span> <span class="n">col</span>

<span class="c1">-- inventory :: Lens' GameState (Map Item Int)</span>
<span class="n">inventory</span> <span class="o">.</span> <span class="n">at</span> <span class="p">(</span><span class="kt">Resource</span> <span class="n">h</span><span class="p">)</span> <span class="o">.</span> <span class="n">non</span> <span class="mi">0</span> <span class="o">+=</span> <span class="mi">1</span>
</code></pre></div></div>

<p>What’re the functions the fancy symbols like <code class="language-plaintext highlighter-rouge">.~</code>? And what do combinators such as <code class="language-plaintext highlighter-rouge">preuse</code> and <code class="language-plaintext highlighter-rouge">ix</code> do? Hopefully you can understand these after this piece. Kmett’s lenses library is focused around the <code class="language-plaintext highlighter-rouge">Lens</code> type, so I first give you a whirlwind tour of <code class="language-plaintext highlighter-rouge">Lens</code> (part 1). But to understand the snippet, we need to explore a more general <code class="language-plaintext highlighter-rouge">Traversal</code> type, and, how <code class="language-plaintext highlighter-rouge">Lens</code>/<code class="language-plaintext highlighter-rouge">Traversal</code> interact with <code class="language-plaintext highlighter-rouge">State</code> (<code class="language-plaintext highlighter-rouge">mtl</code>-ified with <code class="language-plaintext highlighter-rouge">MonadState</code>). That will be part 2.</p>

<h3 id="a-tour-of-lens">A Tour of <code class="language-plaintext highlighter-rouge">Lens</code></h3>
<p>A <code class="language-plaintext highlighter-rouge">Lens</code> is <em>basically</em> type synonym for</p>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">type</span> <span class="kt">Lens</span> <span class="n">s</span> <span class="n">a</span> <span class="o">=</span> <span class="n">forall</span> <span class="n">f</span><span class="o">.</span> <span class="kt">Functor</span> <span class="n">f</span> <span class="o">=&gt;</span> <span class="p">(</span><span class="n">a</span> <span class="o">-&gt;</span> <span class="n">f</span> <span class="n">a</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">s</span> <span class="o">-&gt;</span> <span class="n">f</span> <span class="n">s</span>
</code></pre></div></div>

<p>Function-wise, a <code class="language-plaintext highlighter-rouge">Lens</code> can be thought of as both a getter and a setter. We can transform a <code class="language-plaintext highlighter-rouge">Lens s a</code> both 
into a getter and a setter by applying the <code class="language-plaintext highlighter-rouge">Lens</code> with the right functor. 
<code class="language-plaintext highlighter-rouge">s</code> is the larger object that <em>should</em> contain some <code class="language-plaintext highlighter-rouge">a</code>.</p>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">get</span> <span class="o">::</span> <span class="kt">Lens</span> <span class="n">s</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="n">s</span> <span class="o">-&gt;</span> <span class="n">a</span><span class="p">)</span>
<span class="n">get</span> <span class="n">l</span> <span class="n">s</span> <span class="o">=</span> <span class="n">getConst</span> <span class="o">$</span> <span class="n">l</span> <span class="kt">Const</span> <span class="n">s</span>

<span class="n">over</span> <span class="o">::</span> <span class="kt">Lens</span> <span class="n">s</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="n">a</span> <span class="o">-&gt;</span> <span class="n">a</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="n">s</span> <span class="o">-&gt;</span> <span class="n">s</span><span class="p">)</span>
<span class="n">over</span> <span class="n">l</span> <span class="n">f</span> <span class="n">a</span> <span class="o">=</span> <span class="n">runIdentity</span> <span class="o">$</span> <span class="n">l</span> <span class="p">(</span><span class="nf">\</span><span class="n">b</span> <span class="o">-&gt;</span> <span class="kt">Identity</span> <span class="p">(</span><span class="n">f</span> <span class="n">b</span><span class="p">))</span> <span class="n">a</span>
</code></pre></div></div>

<p>I explicitly wrapped the <code class="language-plaintext highlighter-rouge">(s -&gt; a)</code> in <code class="language-plaintext highlighter-rouge">get</code> to emphasize the
high-order form. I.e., <code class="language-plaintext highlighter-rouge">get</code> is a transformation from <code class="language-plaintext highlighter-rouge">Lens s a</code> to a <code class="language-plaintext highlighter-rouge">(s -&gt; a)</code>. A getter gives you an <code class="language-plaintext highlighter-rouge">a</code> from a <code class="language-plaintext highlighter-rouge">s</code>. In <code class="language-plaintext highlighter-rouge">get</code>’s definition, 
<code class="language-plaintext highlighter-rouge">f</code> is specialized to <code class="language-plaintext highlighter-rouge">Const</code> to make everything work.</p>

<p>A setter typically has the form <code class="language-plaintext highlighter-rouge">s -&gt; a -&gt; s</code>. I.e., <code class="language-plaintext highlighter-rouge">set</code> takes in 
object <code class="language-plaintext highlighter-rouge">s</code> and a constant <code class="language-plaintext highlighter-rouge">a</code> to update some inner field with, and gives
you back the updated <code class="language-plaintext highlighter-rouge">s</code>. Instead of <code class="language-plaintext highlighter-rouge">set</code>, we naturally get a more general <code class="language-plaintext highlighter-rouge">over</code> here, allowing us to consider the previous <code class="language-plaintext highlighter-rouge">a</code> in the update.</p>

<p>The following <strong>crucial</strong> point will wrap up the background: A <code class="language-plaintext highlighter-rouge">Lens s a</code> contains the concrete logic 
to “hit” an <code class="language-plaintext highlighter-rouge">a</code> from a <code class="language-plaintext highlighter-rouge">s</code>. For example,</p>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">data</span> <span class="kt">Person</span>  <span class="o">=</span> <span class="kt">Person</span> <span class="p">{</span> <span class="n">age</span> <span class="o">::</span> <span class="kt">Int</span><span class="p">,</span> <span class="n">address</span> <span class="o">::</span> <span class="kt">Address</span> <span class="p">}</span>
<span class="kr">data</span> <span class="kt">Address</span> <span class="o">=</span> <span class="kt">Address</span> <span class="p">{</span> <span class="n">streetName</span> <span class="o">::</span> <span class="kt">String</span> <span class="p">}</span>

<span class="c1">-- Contains the logic to hit the address from a person </span>
<span class="n">ex1</span> <span class="o">::</span> <span class="kt">Lens'</span> <span class="kt">Person</span> <span class="kt">String</span>
<span class="n">ex1</span> <span class="n">f</span> <span class="n">s</span> <span class="o">=</span> <span class="p">(</span><span class="nf">\</span><span class="n">streetName'</span> <span class="o">-&gt;</span> <span class="n">s</span> <span class="p">{</span> <span class="n">address</span> <span class="o">=</span> <span class="p">(</span><span class="n">address</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span> <span class="n">streetName</span> <span class="o">=</span> <span class="n">streetName'</span><span class="p">}</span> <span class="p">})</span> <span class="o">&lt;$&gt;</span> <span class="n">f</span> <span class="p">((</span><span class="n">streetName</span> <span class="o">.</span> <span class="n">address</span> <span class="p">)</span> <span class="n">s</span><span class="p">)</span>

<span class="c1">-- Contains the logic to hit a Char from a [Char]. The only way to have a valid definition is if </span>
<span class="c1">-- we choose a specific index</span>
<span class="n">ex2</span> <span class="o">::</span> <span class="kt">Lens'</span> <span class="p">[</span><span class="kt">Char</span><span class="p">]</span> <span class="kt">Char</span>
<span class="n">ex2</span> <span class="n">f</span> <span class="n">s</span> <span class="o">=</span> <span class="p">(</span><span class="nf">\</span><span class="n">a'</span> <span class="o">-&gt;</span> <span class="n">setAt</span> <span class="mi">3</span> <span class="n">a'</span> <span class="n">s</span><span class="p">)</span> <span class="o">&lt;$&gt;</span> <span class="n">f</span> <span class="p">(</span><span class="n">s</span> <span class="o">!!</span> <span class="mi">3</span><span class="p">)</span>
</code></pre></div></div>

<p>Note, we can also make nonsensical <code class="language-plaintext highlighter-rouge">Lens</code>, for example</p>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ex3</span> <span class="o">::</span> <span class="kt">Lens'</span> <span class="kt">String</span> <span class="kt">Int</span>
<span class="n">ex3</span> <span class="n">f</span> <span class="n">s</span> <span class="o">=</span> <span class="n">s</span> <span class="o">&lt;$</span> <span class="n">f</span> <span class="mi">0</span>

<span class="n">ex4</span> <span class="o">::</span> <span class="kt">Lens'</span> <span class="p">[</span><span class="kt">Char</span><span class="p">]</span> <span class="kt">Char</span>
<span class="n">ex4</span> <span class="n">f</span> <span class="n">s</span> <span class="o">=</span> <span class="n">s</span> <span class="o">&lt;$</span> <span class="n">f</span> <span class="sc">'a'</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">ex1 :: Lens' String Int</code> should provide a means to get/set an <code class="language-plaintext highlighter-rouge">Int</code> in a <code class="language-plaintext highlighter-rouge">String</code>, but that’s absurd  — <code class="language-plaintext highlighter-rouge">String</code> doesn’t contain an <code class="language-plaintext highlighter-rouge">Int</code>. However, <code class="language-plaintext highlighter-rouge">Lens'</code> allow us to write such a vacuous <code class="language-plaintext highlighter-rouge">Lens' String Int</code>. We provide a concrete <code class="language-plaintext highlighter-rouge">Int</code> (<code class="language-plaintext highlighter-rouge">0</code> in this case) in order to lift it into <code class="language-plaintext highlighter-rouge">f Int</code> via <code class="language-plaintext highlighter-rouge">f 0</code>. Once we are in the functor, we apply <code class="language-plaintext highlighter-rouge">fmap (const s) :: Int -&gt; String</code> to build a <code class="language-plaintext highlighter-rouge">f String</code> (simplified with <code class="language-plaintext highlighter-rouge">&lt;$</code>). In fact, we can vacuously write a value of type <code class="language-plaintext highlighter-rouge">Lens' s Int</code>.</p>

<p>What about <code class="language-plaintext highlighter-rouge">ex2</code>? It should be possible to (unsafely) get/set a <code class="language-plaintext highlighter-rouge">Char</code> inside of a <code class="language-plaintext highlighter-rouge">[Char]</code>. However, our implementation does not update our <code class="language-plaintext highlighter-rouge">s :: [Char]</code> at all. We are again providing a concrete value (<code class="language-plaintext highlighter-rouge">'a' :: Char</code> in this case) just to get into <code class="language-plaintext highlighter-rouge">f Char</code>, which <code class="language-plaintext highlighter-rouge">s &lt;$</code> latches onto.</p>

<p><strong>For all concrete <code class="language-plaintext highlighter-rouge">s</code> and <code class="language-plaintext highlighter-rouge">a</code>, <code class="language-plaintext highlighter-rouge">Lens' s a</code> can be written vacuously. It is up to you to provide a reasonable definition.</strong>
After applying its 3 arguments, a sensible <code class="language-plaintext highlighter-rouge">Lens' s a</code> should update some <code class="language-plaintext highlighter-rouge">a</code> within the given <code class="language-plaintext highlighter-rouge">s</code>.</p>]]></content><author><name>Andrew Chen</name><email>(λx.λy.λz. yz@x) gmail.com andrewchen 14250</email></author><category term="haskell" /><summary type="html"><![CDATA[Recently, I started reading swarm, a resource gathering + programming game built with Haskell. I went to swarm’s very first commit. The 200-liner is able to render the following,]]></summary></entry><entry><title type="html">Art of Copying Art</title><link href="https://unfooling.com/unfooling.com/how-to-copy/" rel="alternate" type="text/html" title="Art of Copying Art" /><published>2024-09-07T08:00:00-04:00</published><updated>2024-09-07T08:00:00-04:00</updated><id>https://unfooling.com/unfooling.com/how-to-copy</id><content type="html" xml:base="https://unfooling.com/unfooling.com/how-to-copy/"><![CDATA[<p>My passion for writing rekindled last week. I go straight to Google. I search “how to become a writer”. I see 7 links — 3 blue, 4 purple. I still open the purple reddit link.</p>

<blockquote>
  <p>Practice, practice, practice.</p>
</blockquote>

<p>or,</p>

<blockquote>
  <p>Write a lot. And read a lot.</p>
</blockquote>

<p>or, for maximum effectiveness,</p>

<blockquote>
  <p>Start.</p>
</blockquote>

<p>Well…  Write <em>what</em>? And draw <em>what</em>? Or compose <em>what</em>? I get the gist though, since, once you are serious about learning the craft and start putting in serious time, you naturally and gradually tune to a better learning process. But, I want to alleviate some of that initial anxiety. Some good constraints can liberate.</p>

<p>I’ll propose a linear learning methods that works for many arts. First, an interlude on how machines learn.</p>

<h3 id="the-machine">The Machine</h3>
<p>Heuristic and inductive biases for the machine’s learning process is purposefully designed, sourcing the records of the human mind. Even the most standard algorithm, self-supervised learning, rationally models how we learn. The machine is initially dumb (it is initialized with random weights), but it gets good at, for example drawing, by repeating the following, many, many times:</p>

<p>The machine generates an image. The machine now looks a real artpiece and contrasts its generation with the artpiece (calculating loss). The machine updates itself to better adapt to the artpiece.</p>

<p>Artists are told to do master studies; writers are told to read. But these processes are inert. I think, what is missing, is the original generation preceding the adaptation.</p>

<h3 id="the-adversarial-method">The Adversarial Method</h3>
<p>Instead of reading, or plain copying, I do this:</p>
<ol>
  <li>Select a passage from an author whose style intrigues you. The granularity I experimented with are the early chapters in Mo Yan’s <em>Big Breasts and Wide Hips</em> (3-4 pages long).</li>
  <li>Skim the passage. If you have good short term recall of details, return when they vanish. Alternatively, you could skip the skim and elect AI to summarize.</li>
  <li>The key step: Instead of attempting at your rendition of the entire passage, localize to things that matters using AI. For example, I want to train my “show not tell”, so I paste the passage to Claude, and ask it to replace paragraphs of descriptions with <code class="language-plaintext highlighter-rouge">&lt;summary of paragraph&gt;</code>.</li>
  <li>I fill in the <code class="language-plaintext highlighter-rouge">&lt;&gt;</code>s.</li>
  <li>I critically analyze my work to the authors.</li>
</ol>

<p>See my prompt and an example conversation <a href="https://github.com/BlastWind/unfooling_blog/blob/gh-pages/appendix/2024-09-06-how-to-copy.markdown">here</a>.</p>]]></content><author><name>Andrew Chen</name><email>(λx.λy.λz. yz@x) gmail.com andrewchen 14250</email></author><category term="art" /><summary type="html"><![CDATA[My passion for writing rekindled last week. I go straight to Google. I search “how to become a writer”. I see 7 links — 3 blue, 4 purple. I still open the purple reddit link.]]></summary></entry><entry><title type="html">13 week Mech Interp Study Journal</title><link href="https://unfooling.com/unfooling.com/13-week-mech-interp-study/" rel="alternate" type="text/html" title="13 week Mech Interp Study Journal" /><published>2023-10-28T12:00:00-04:00</published><updated>2023-10-28T12:00:00-04:00</updated><id>https://unfooling.com/unfooling.com/13-week-mech-interp-study</id><content type="html" xml:base="https://unfooling.com/unfooling.com/13-week-mech-interp-study/"><![CDATA[<h3 id="foreword">Foreword</h3>
<!-- Cross all history, we might just be living in the most anticipatory time. Billions of neurons, organized as subgraphs and circuitries, firing millions of "AI will revolutionize..."s everyday. But most of us, even those that happen to study computer science, and even those that happen to study artificial intelligence, seems to not grasp the gravity of the moment. Indeed, so much happened so quickly that perhaps, our circuitries have overfitted on the irregular progression of science.

I read my first alignment paper this week, and it has reignited my once diminished passion for AI and machine learning. Though my future occupation in formal verifications does not have too much correspondance to AI yet, I have, as a scientist, a moral responsibility to understand this field fully. Of course, as an undergrad who's writing his thesis on LLMs -->
<p>Mech Interp is super cool! I’m gonna set aside 13 weeks to study it. In these 13 weeks, I plan to master basic ML math, master transformers, read a couple mech interp papers in depth, and hopefully carry out some small-scaled, original mech interp exploration.</p>

<p>Note, this is a direct mirror of my personal log in my Obsidian vault, and some formatting might not be appropriate (I will format everything at the end).</p>

<h3 id="timeline">Timeline</h3>
<p><strong>Target</strong>: 10/28/2023 to 1/26/2023 (end of my winter break)</p>

<h3 id="undated-day-1">Undated Day 1</h3>
<ul>
  <li>Read some basic definitions of <em>Linear Algebra Done Right</em>.
    <h3 id="undated-day-2">Undated Day 2</h3>
  </li>
  <li>Finished <em>Linear Algebra Done Right</em> Chapter 1. Re-learnt subspaces, sums of subspaces, direct sums.</li>
  <li>Looking ahead, to solidfy my linear algebra for MI, I should master Chapter 1-3, 5-6, and 7d. More importantly, I need to spend some time everyday in finding connections of the niche linear algebra techniques are used for ML.</li>
  <li>I found one such connection today (querying ChatGPT): Gradients should be initialized with orthonormal matrices in order to preserve the magnitude of gradients.</li>
</ul>

<h3 id="day-1">Day 1</h3>
<ul class="task-list">
  <li>Read <em>Linear Algebra Done Right</em> Chapter 2 up until the last definition. I think basis and theorems regarding bases drilled in the definition of linear independence and span.</li>
  <li>Tomorrow, I just want to finish up the definition, do a few problems. Then, I want to skim some high-level material on why bases matters for machine learning; in particular, I hear a lot about “orthonormal” bases in ML, when and why do they come up?</li>
  <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />Why bases matter for machine learning - high level view. 📅 2023-10-28 ✅ 2023-10-28</li>
</ul>

<h3 id="day-2">Day 2</h3>
<ul>
  <li>Yesterday i assigned the “why bases matters” task, I have a high-level answer: To address the curse of dimensionality and other dimension related issues. Keywords are privileged, non-privileged bases, PCA, SVD.
    <ul>
      <li>Resources: https://harrisonpim.com/blog/privileged-vs-non-privileged-bases-in-machine-learning</li>
    </ul>
  </li>
</ul>

<h3 id="day-3">Day 3</h3>
<p>Skipped</p>

<h3 id="day-4">Day 4</h3>
<ul>
  <li>Did 15 exercises for [[Chapter 2]]. I didn’t try too hard, I looked at the solution if I can’t solve in 5 mins.</li>
</ul>

<h3 id="day-5">Day 5</h3>
<p>Skipped</p>

<h3 id="day-6">Day 6</h3>
<p>Skipped</p>

<h3 id="day-7-11-03-2023">Day 7 (11-03-2023)</h3>
<p>Wrote MLP forward stuff.</p>

<p>Watched this great <a href="https://www.youtube.com/watch?v=Gey9CG6R6w8">video</a> by WhyML on Skip connection and residual blocks.</p>

<ul class="task-list">
  <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />Review Batch Normaliztaion, Optimizers, Regularization, Gradient Clipping, Weight Constraints, Weight Normalization, Layer Normalization 📅 2023-11-04 ✅ 2023-11-09</li>
  <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />What is Skip Connections and Residual Blocks? 📅 2023-11-03 ✅ 2023-11-04</li>
  <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />Understand the gradients that are taken. 📅 2023-11-12 ✅ 2023-11-15</li>
</ul>

<h3 id="day-8-11-04-2023">Day 8 (11-04-2023)</h3>
<p>Studied backpropagation. I used multiple resources: The original sparse encoder article, some random article by ML-dawn, and Brilliant Wiki. But, when I revisited 3b1b’s video, that’s the one that made it all click. Tomorrow, I plan to rewatch the video and take a lot of notes.</p>

<h3 id="day-9-11-05-2023">Day 9 (11-05-2023)</h3>
<p>Rewatched 3b1b’s video and I think all the formulae individually makes sense. Tomorrow, I’ll try to</p>
<ul>
  <li>Derive the gradients from scratch</li>
  <li>If I get them right, give a shot at drawing derivative diagrams for a MLP</li>
  <li>Implement backprop in MLP.</li>
</ul>

<h3 id="day-10-18-11-06-2023-to-11-14-2023">Day 10-18 (11-06-2023 to 11-14-2023)</h3>
<p>Skipped. Not gonna lie, played a little too much minesweeper.</p>

<h3 id="day-19">Day 19</h3>
<ul>
  <li>Deleted my online minesweeper account. Started 2 weeks ago and sunk 35 hours into it, no good, those hours will now be redirected to mech interp.</li>
  <li>Watched Neel Nanda’s <a href="https://www.youtube.com/watch?v=bZvPLRZx-V8">MI and Math</a> talk and annotated it. The slides are <a href="https://docs.google.com/presentation/d/1hQHsWcoxtBQKj4mTgFtMA9KgDjkyAcjEWjxDwXq5EPg/edit#slide=id.g24176faf163_0_225">here</a></li>
  <li>40 mins into ML street talk episode with Neel Nanda. Take aways:
    <ul>
      <li>A biologist’s getting hands dirty view might be more appropriate than a mathematician’s view. A good quality of a mech interp researcher is someone who can <em>handle</em> a surprise.</li>
    </ul>
  </li>
</ul>

<p>My goals this week is to start understanding transformers well, read this paper, and get a sense of the other techniques I gotta study (dimensionality reduction, Fourier transform even?).</p>

<p><strong>Idea</strong>: Analyze transformers that implement simple regexes / text manipulation patterns?</p>

<h3 id="day-20">Day 20</h3>
<ul>
  <li>Read the <a href="https://jalammar.github.io/visualizing-neural-machine-translation-mechanics-of-seq2seq-models-with-attention/">Attention</a> blog post, it is a prior of the <a href="https://jalammar.github.io/illustrated-transformer/">Illustrated Transformers</a> guide.</li>
</ul>

<p>Some knowledge tasks.</p>
<ul class="task-list">
  <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />Understand: What is the Curse of Dimensionality? 📅 2023-11-17</li>
  <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />Master PCA 📅 2023-11-19</li>
</ul>

<p>Inspired by Neel’s talks yesterday, I will run a mech interp notebook this week to get a feel of the tools.</p>
<ul class="task-list">
  <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />Run, completely, one mech interp notebook 📅 2023-11-17</li>
</ul>]]></content><author><name>Andrew Chen</name><email>(λx.λy.λz. yz@x) gmail.com andrewchen 14250</email></author><category term="project" /><summary type="html"><![CDATA[Foreword &lt;!– Cross all history, we might just be living in the most anticipatory time. Billions of neurons, organized as subgraphs and circuitries, firing millions of “AI will revolutionize…”s everyday. But most of us, even those that happen to study computer science, and even those that happen to study artificial intelligence, seems to not grasp the gravity of the moment. Indeed, so much happened so quickly that perhaps, our circuitries have overfitted on the irregular progression of science.]]></summary></entry><entry><title type="html">October Proses • 十月的随笔</title><link href="https://unfooling.com/unfooling.com/october-proses/" rel="alternate" type="text/html" title="October Proses • 十月的随笔" /><published>2023-10-11T12:00:00-04:00</published><updated>2023-10-11T12:00:00-04:00</updated><id>https://unfooling.com/unfooling.com/october-proses</id><content type="html" xml:base="https://unfooling.com/unfooling.com/october-proses/"><![CDATA[<h3 id="壹--角度">壹 • 角度</h3>
<p>生处的坐标，位置不同，头扬的角度不同，思考的事情也必然不同。躺在一只肥猪下看天空，小猪似乎也变成了天蓬元帅。
我写中文时，就容易变得文艺。在搞科研时，只有在户外才引入潮水一般涌来的思路。
通常来讲，文言是文言，数学是数学。可是，哲学家们似乎非常喜欢在黑板上谈心。他们用着 “first principle” 的借口轰炸着
由艺术，由生命而生的伦理。</p>

<p>依我见，伦理不是哲学应所侵犯的领域。伦理是生命，是苦难，是我们哭泣的理由，是人情味。这种味道，还是不要过多去”taxonomize”的好。</p>

<p>您读我刚才写着的时候可能脑海里闪过一些画面：呆板，毫无勃起力的哲学家，数学家，挂个老老的眼镜，低着头，慢吞吞得在黑板上画着圆圈。假若您的确思其画面，那么抱歉，您入了我写这一段篇的圈套。搞纯理论的数学家也可以让我们的生命细胞脉动。</p>

<h3 id="所有的一切推着我们前进">所有的一切推着我们前进</h3>
<p>昨天重返了《功夫熊猫1》。其中有一场景十分有趣。</p>

<p><strong>乌龟师傅</strong>:</p>
<blockquote>
  <p>人违逆不了命运。</p>
</blockquote>

<p><strong>浣熊师傅</strong>:</p>
<blockquote>
  <p>[猛踹了大树] 但，我可控制桃子什么时候掉落，也可控制它在哪里生长。</p>
</blockquote>

<p><strong>乌龟师傅</strong>:</p>
<blockquote>
  <p>对，但无论怎样，一颗桃核总会繁衍一棵桃树。</p>
</blockquote>

<p>记得美国脱口秀之王George Carlin说过，气候维护者们总是声称，全球变暖破坏了地球。瞎搞，以前陨石撞地球时对于地球来说不过是挠个痒。其实，我们只是怕气候变暖搞糟了人类。所以，虽然可能有一天，人类会停止繁衍与前进。但这个宇宙永远不会，滴答滴答，微生物又在另一个星球上诞生了。</p>

<h3 id="中文是抽象的">中文是抽象的</h3>
<p>我其实总觉得，我们的中文是抽象的。举个例子，道德经说的“一生二，二生三，三生万物”，似乎概括了数学里“induction”的这个概念。这一点我得留至十一月去多想想。</p>

<h3 id="论madman">论“Madman”</h3>
<p>十一月再说吧。</p>]]></content><author><name>Andrew Chen</name><email>(λx.λy.λz. yz@x) gmail.com andrewchen 14250</email></author><category term="prose" /><category term="随笔" /><summary type="html"><![CDATA[壹 • 角度 生处的坐标，位置不同，头扬的角度不同，思考的事情也必然不同。躺在一只肥猪下看天空，小猪似乎也变成了天蓬元帅。 我写中文时，就容易变得文艺。在搞科研时，只有在户外才引入潮水一般涌来的思路。 通常来讲，文言是文言，数学是数学。可是，哲学家们似乎非常喜欢在黑板上谈心。他们用着 “first principle” 的借口轰炸着 由艺术，由生命而生的伦理。]]></summary></entry><entry><title type="html">Programming Languages Journal</title><link href="https://unfooling.com/unfooling.com/pl-journal/" rel="alternate" type="text/html" title="Programming Languages Journal" /><published>2023-06-28T12:00:00-04:00</published><updated>2023-06-28T12:00:00-04:00</updated><id>https://unfooling.com/unfooling.com/pl-journal</id><content type="html" xml:base="https://unfooling.com/unfooling.com/pl-journal/"><![CDATA[<h3 id="foreword">Foreword</h3>

<p>I have come to a point in my Haskell journey where I should start learning about other programming languages (PL) fields. Towards the end of my <a href="https://unfooling.com/fp-journal/">FP journal</a>, I started diving into Category Theory and formal verifications, endeavours that shouldn’t be documented in a “FP Journal”. As such, I’ve decided to start a PL journal, documenting all of my PL ventures. Unlike the previous journal, I do not plan to elaborate on the concepts I made sense of, as these elaborations often turn into word rambles in the moment.</p>

<h1 id="2023">2023</h1>
<h2 id="june">June</h2>

<p><strong>28th</strong></p>

<p>Understanding the relationships between LTL (Linear Temporal Logic), Haskell, model-checkers, and proof assistants. Conclusion: TLA+ (model checker) can be used to model LTL statements and verify them. There exists LTL libraries in Haskell but they appear to be more data modelling purposes.</p>

<p><strong>29th</strong></p>

<ul>
  <li>Chris (from work) sent me two papers:
    <ul>
      <li><a href="https://cs.uwaterloo.ca/~bbonakda/teaching/CS745/papers/RV.pdf">Runtime Verification for LTL and TLTL</a></li>
      <li><a href="https://www.cs.rice.edu/~vardi/papers/vol1000.pdf">Alternating Automata and Program Verification</a>
  These papers supposedly describe how LTL statements can really be translated (down?) to a FSM (Finite State Machine). From there, any language can be used to implement this FSM (since a simple FSM is just a <code class="language-plaintext highlighter-rouge">while</code> loop + <code class="language-plaintext highlighter-rouge">switch</code> statements).
  I will zoom in on these tomorrow.</li>
    </ul>
  </li>
  <li>Watched a video on <a href="https://www.youtube.com/watch?v=FqDHSIpWJRw&amp;t=331s&amp;ab_channel=Serokell">linear logic</a>. Everyday I’m hearing 5 new jargons, at the end of this week I ought to layout a taxonomy of the topics.</li>
</ul>

<h2 id="july">July</h2>

<p><strong>1st to 14th</strong></p>
<ul>
  <li>Read the first 10 pages of the Lamport’s TLA <a href="https://lamport.azurewebsites.net/pubs/lamport-actions.pdf">paper</a> that covers TLA motivation and semantics.</li>
  <li>Watched the <a href="https://www.youtube.com/watch?v=VHWEldcSx14&amp;list=PLhZdSWbNhIbCQKxUta0VrDGg3gLguedIh&amp;index=1&amp;ab_channel=songsong">first lecture</a> of RWTH Aachen University’s Model Checking course.</li>
  <li>Talked to ChatGPT a lot to derive a taxonomy of formal verifications technique. Lectures do better jobs covering these types of information though — ChatGPT don’t really come up with memorable sayings.</li>
  <li>Came across <a href="https://www.youtube.com/watch?v=FqDHSIpWJRw&amp;t=14s&amp;ab_channel=Serokell">Linear Types</a>, didn’t understand much.</li>
  <li>Submitted my first paper ever (it’s on program analysis) to SCAM’23! I can reveal more if it gets accepted.</li>
  <li>Read the intro of Pierce’s <a href="https://softwarefoundations.cis.upenn.edu/lf-current/Basics.html">Software Foundations</a>.</li>
  <li>Read the first two chapter of Pierce’s TAPL — currently, I don’t find type theory as interesting as formal verifications. Though, I do believe that enjoyment is a linear combinations of the interestingness of the topic’s pure abstractions, the topic’s applicability, and one’s current understanding of the field. When it comes to type theory, I don’t have any of these.</li>
</ul>

<p><strong>15th to 19th</strong></p>
<ul>
  <li>Read the docs of the <code class="language-plaintext highlighter-rouge">servant</code> library thoroughly: It’s the first library I encountered that uses <code class="language-plaintext highlighter-rouge">DataKinds</code>.</li>
  <li>Read up on the expression problem (encountered through <code class="language-plaintext highlighter-rouge">servant</code>’s paper). Supposedly, Object Algebras of OOP or advanced Haskell type features can address it.</li>
  <li>Going back to reading Milewski’s Category Theory for Programmers because I should be knowing what Kelsili Arrow and natural transformations are at this point.
    <ul>
      <li>Finished Chapter 3. Interesting idea: Think of functions in their uncurried form more. If I think of <code class="language-plaintext highlighter-rouge">mappend</code> as <code class="language-plaintext highlighter-rouge">m -&gt; (m -&gt; m)</code>, I can see it as a mapping between an element of a monoid set to a function acting on that set!</li>
    </ul>
  </li>
</ul>

<p><strong>Week 4</strong></p>
<ul>
  <li>Listened to two episodes of the Haskell Interlude podcast: One with Gabriella Gonzalez, and one with Graham Hutton. Professor Hutton’s honesty and passion was, simply put, inspiring. The also-inspiring Gabriella mentioned two interesting things I’ll look into: Monad Reader and Dhall.</li>
  <li>Listened to Conal Elliot talking about <a href="https://www.typetheoryforall.com/2022/05/09/17-The-Lost-Elegance-of-Computation-(Conal-Elliott).html">the lost elegance of computation</a>. Unique and poignant philosophy, inspired by Conal’s passion, I ought to read John Backus’s famou 1977 Turing award <a href="https://dl.acm.org/doi/pdf/10.1145/359576.359579">lecture</a> and read into FRP.</li>
  <li>Read Monad Reader issue <a href="https://themonadreader.files.wordpress.com/2011/10/issue19.pdf">19</a>; learned about the <code class="language-plaintext highlighter-rouge">Coroutine</code> monad; I was able to use <code class="language-plaintext highlighter-rouge">Iteratee</code> and <code class="language-plaintext highlighter-rouge">Generator</code> to successfully implement a basic sketch of a program for work.</li>
</ul>

<h2 id="august">August</h2>
<p><strong>Week 1</strong></p>
<ul>
  <li>Spent a weekend in FRP via Heinrich’s <a href="https://github.com/HeinrichApfelmus/frp-guides">guide</a>. Big idea: <code class="language-plaintext highlighter-rouge">Behaviors</code> are continous and <code class="language-plaintext highlighter-rouge">Events</code> are discrete, but, they can be easily composed and transformed to one another.</li>
  <li>React-banana uses <code class="language-plaintext highlighter-rouge">MonadMoment</code>, which is also a <code class="language-plaintext highlighter-rouge">MonadFix</code>. I tried reading <a href="https://elvishjerricco.github.io/2017/08/22/monadfix-is-time-travel.html">MonadFix is Time Travel</a>. I only partially understood what’s going on even with after reading another <a href="https://www.parsonsmatt.org/2016/10/26/grokking_fix.html">article</a> because I lack a complete understanding of laziness, thunks, and <code class="language-plaintext highlighter-rouge">seq</code>, so, I started reading Haskell wikibook’s laziness <a href="https://en.wikibooks.org/wiki/Haskell/Laziness">article</a>.</li>
</ul>

<p><strong>Week 2</strong></p>
<ul>
  <li>Finished my internship at TwoSix technologies, looking forward in returning as a formal methods researcher next summer!</li>
  <li>Coming across the following for the first time: Refinement types, cubic type theory, the K framework.</li>
  <li>I want to dedicate my time fully to reading 2 materials: Software Foundations (SF) and the Milewski’s Category Theory handbook, until school begins.</li>
  <li>Finished the Basics chapter of SF’s Logical Foundations (LF) book. Good old functional programming!</li>
  <li>Read Chapter 5-8 of the category theory book. I need to spend some time to gather more examples…</li>
</ul>

<h1 id="2024">2024</h1>
<h3 id="august-1">August</h3>
<p>Holy snap! I haven’t updated this in year. In the past year I got a lot more comfortable with Haskell —</p>
<ul>
  <li>I am implementing a <a href="https://github.com/BlastWind/hearthstone-battlegrounds">clone</a> of hearthstone-battlegrounds in Haskell. I learned <code class="language-plaintext highlighter-rouge">mtl</code>-style typeclasses through this.</li>
  <li>I got 60% through the <em>Thinking In Types</em> book.</li>
  <li>I am actively picking up little tricks and gems. For example, in the past month, I discovered the “semantic editor combinator” composition <a href="https://github.com/ekmett/lens/wiki/Derivation">trick</a> and the concept of “algebra blindness” per the recommendation of this <a href="http://jackkelly.name/wiki/haskell/learning.html">list</a></li>
</ul>

<p><strong>Week 2</strong></p>
<ul>
  <li>Biggest problem I resolved this week is writing tests for battlegrounds. In particular, how does one control random behaviors in tests without modifying the game logic (the stuff that is random)? For my case, I find the solution to be twofold —
    <ul>
      <li>
        <p>For randomness in high-level functions, e.g., <code class="language-plaintext highlighter-rouge">turn :: (MonadRandom m) =&gt; CombatState -&gt; m CombatState</code>, take the random values in as argument. So, if the attacker and defender each turn is random, then refactor to <code class="language-plaintext highlighter-rouge">turn :: AttackIndex -&gt; DefendIndex -&gt; CombatState -&gt; CombatState</code>.</p>
      </li>
      <li>
        <p>For randomness in card effects, e.g., I wish to control the coiler (which summons 2 random deathrattles) to summon specific deathrattles, build a DSL. Initially, I thought I can do away without a DSL — I delayed the summon effect by changing <code class="language-plaintext highlighter-rouge">Summon Card</code> to <code class="language-plaintext highlighter-rouge">Summon (MonadRandom m =&gt; \combatState -&gt; m Card)</code>. But, functions can’t implement <code class="language-plaintext highlighter-rouge">Eq</code>. So, I built a DSL that covers all the needs: <code class="language-plaintext highlighter-rouge">data CardEffect = Summon Criteria</code> and <code class="language-plaintext highlighter-rouge">data Criteria = SpecificCard Card | ByTier Card | ByKeyword Card</code>.</p>
      </li>
    </ul>
  </li>
</ul>

<p><strong>Week 3</strong></p>
<ul>
  <li>Thought: Be ware of the ambiguity of “power”. I feel no problem phrasing, “A square is more powerful than a Rectangle”, because, a square is a rectangle, and not vice versa. However, consider the fact that “A <code class="language-plaintext highlighter-rouge">Lens</code> is a <code class="language-plaintext highlighter-rouge">Traversal</code>”. Observing that while a <code class="language-plaintext highlighter-rouge">Lens</code> hits one target, <code class="language-plaintext highlighter-rouge">Traversal</code> can hit zero or many targets; so, I conclude that while <code class="language-plaintext highlighter-rouge">Lens</code> is more powerful from the type perspective, <code class="language-plaintext highlighter-rouge">Traversal</code> instead feels more powerful. Perhaps, the better phrasing is using “is a” for specifying type system hierarchy, and “generalizing” instead of “powerful” for operational capability.</li>
  <li>I feel unqualified in many decisions while coding <code class="language-plaintext highlighter-rouge">hearthstone-battlegrounds</code>, this pushed me to read a successful Haskell game: <code class="language-plaintext highlighter-rouge">swarm</code>, a resource gathering and programming game.
    <ul>
      <li><code class="language-plaintext highlighter-rouge">swarm</code> uses <code class="language-plaintext highlighter-rouge">lens</code> beautifully. I dug deeply into <code class="language-plaintext highlighter-rouge">lens</code> and can understand most of the <code class="language-plaintext highlighter-rouge">lens</code> code in <code class="language-plaintext highlighter-rouge">swarm</code>.</li>
      <li><code class="language-plaintext highlighter-rouge">swarm</code> comes with its robot programming language. To get theorectically underpinned for understanding <code class="language-plaintext highlighter-rouge">swarm-lang</code>, I started WYAH and finished the parsing chapter. But, I believe I need to read the type-system chapter to be ready.</li>
    </ul>
  </li>
</ul>]]></content><author><name>Andrew Chen</name><email>(λx.λy.λz. yz@x) gmail.com andrewchen 14250</email></author><category term="project" /><summary type="html"><![CDATA[Foreword]]></summary></entry><entry><title type="html">Abundance and Scarcity</title><link href="https://unfooling.com/unfooling.com/abundance-and-scarcity/" rel="alternate" type="text/html" title="Abundance and Scarcity" /><published>2022-11-20T05:38:29-05:00</published><updated>2022-11-20T05:38:29-05:00</updated><id>https://unfooling.com/unfooling.com/abundance-and-scarcity</id><content type="html" xml:base="https://unfooling.com/unfooling.com/abundance-and-scarcity/"><![CDATA[<p>Update: I was ignorant when I first wrote this — I couldn’t even name a handful of mathematical insights derived this century (but there are plenty). I should’ve instead explored why ancient mathematicians <strong>appeared</strong> smarter. I think this appearance is mainly due to the fact that they picked up low-hanging and foundational fruits. These attributes, in conjunction with time, made more modern people aware of their work, thus contributing to the illusory truth effect.</p>

<p>Below lies the original blog:
***
Opinion: Ancient mathematicians are smarter.  </p>

<p>But, the Mesopotamians, or ancient Greeks, or Renaissance-undergoing Prussians weren’t just genetically smart: What’re some fundamental principles that fostered such an intellectual environment?</p>

<ol>
  <li>Totally Diminishing Marginal Utility</li>
</ol>

<p>Marginal utility, an Econ jargon, is the satisfaction derived from consuming a product. Diminishing marginal utility observes marginal utilities over all products consumed, and rules that <code class="language-plaintext highlighter-rouge">Consuming the (N+1)th item derives less pleasure than consuming the Nth</code>.</p>

<p>But, I’m afraid, due to the abundance of information, ALL marginal utilities on academic materials have decreased: <code class="language-plaintext highlighter-rouge">Consuming Euler's Elements of Algebra in the 2000s derives less pleasure than consuming it in the 1600s</code>.</p>

<p>The consequence of abundance is the lost of scarcity, the lost of the human nature to care for vulnerable, precious things.</p>

<ol>
  <li>Diminishing Focus</li>
</ol>

<p>Neil Postman wrote that whole <code class="language-plaintext highlighter-rouge">Amusing Ourselves to Death</code> book that I remember reading in high school for actually, self-help purposes. However, what he observed in 1985 about the dangers of TV and media must’ve tripled by today. His main theory was that television reduces important things to mere entertainment, therefore diluting focus and purpose.</p>

<ol>
  <li>Less Purpose</li>
</ol>

<p>On the note of less purpose: Mathematicians were really smart during war times. Alan Turing and his colleagues recruited through crossword puzzle contests cracked the enigma, and the whole space race thing was another level of spectacle (Oh gosh, spectacle, did I just reduce the space race to mere entertainment?).</p>

<p>Although us contemporary folks can still find purpose without war and religion, those purposes were embedded in our systems and simple to follow. Today, we are out of luck, our lives are comparably easier, which ironically makes living a purposeful life harder.</p>]]></content><author><name>Andrew Chen</name><email>(λx.λy.λz. yz@x) gmail.com andrewchen 14250</email></author><category term="idea" /><summary type="html"><![CDATA[Update: I was ignorant when I first wrote this — I couldn’t even name a handful of mathematical insights derived this century (but there are plenty). I should’ve instead explored why ancient mathematicians appeared smarter. I think this appearance is mainly due to the fact that they picked up low-hanging and foundational fruits. These attributes, in conjunction with time, made more modern people aware of their work, thus contributing to the illusory truth effect.]]></summary></entry></feed>