<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>Brad Parker</title><link>https://bradparker.id.au</link><description>I've been making software professionally for about nine years and I really love it. I believe software has this empowering potential, I believe everyone should be able to understand it if they want to. This means I prefer open and accessible tools and standards wherever possible. It also means I try to learn in the open, sharing what I learn as I learn it.</description><item><title>Books, Badgers and Big Numbers</title><link>https://bradparker.id.au/posts/books-badgers-and-big-numbers</link><description>&lt;p&gt;I stumbled into what might be some combinatorial esoterica and I can't stop thinking about it.&lt;/p&gt;
&lt;h2 id="books"&gt;Books&lt;/h2&gt;
&lt;p&gt;Up until April 2023 we had a pretty special second hand book shop up the road, next to the local café&lt;a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;. While it was there my mid morning coffee runs usually involved having a browse and I often picked something up.&lt;/p&gt;
&lt;div class="list-none grid grid-cols-2 grid-rows-2 gap-3"&gt;
  &lt;div&gt;

&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/finds/chaos.webp" alt="The cover the book Chaos by James Gleick" /&gt;&lt;/p&gt;
  &lt;/div&gt;
  &lt;div&gt;

&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/finds/linear-algebra-and-its-applications.webp" alt="The cover the book Linear Algebra and Its Applications by Gilbert Strang" /&gt;&lt;/p&gt;
  &lt;/div&gt;
  &lt;div&gt;

&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/finds/the-wonderful-world-of-steam-locomotives.webp" alt="The cover of the book The Wonderful World of Steam Locomotives by P. B. Whitehouse" /&gt;&lt;/p&gt;
  &lt;/div&gt;
  &lt;div&gt;

&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/finds/dancing-with-cats.webp" alt="The cover of the book Dancing With Cats by Burton Silver and Heather Busch" /&gt;&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;A lot of the books I was buying were non-fiction, and it's this I'd like to blame on my over-thinking their organisation. I wanted everything grouped by subject, rather than author or title or year or anything like that. So in the end I signed up for a &lt;a href="https://www.librarything.com"&gt;LibraryThing&lt;/a&gt; account and used their codes to sort everything.&lt;/p&gt;
&lt;h2 id="badgers"&gt;Badgers&lt;/h2&gt;
&lt;p&gt;Some time last year LibraryThing let me know they'd made me a Year In Review. You know, like Spotify does. It's not really my jam, but I clicked through anyway and ended up reading this sentence:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;And make sure your floors will support the added weight of 4.90 adult badgers!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I'd scanned in all our books at once, so this doesn't represent how many books we added to our collection in 2024, but rather the whole lot. At any rate, it's common now that when I look at our bookshelves I find myself trying to imagine five adult badgers somehow sitting in them. Which is hard, given that I have no idea how big an adult badger is.&lt;/p&gt;
&lt;h2 id="big-numbers"&gt;Big Numbers&lt;/h2&gt;
&lt;p&gt;Despite the badgers, it's not all that many books really. But even still I felt the need to choose &lt;em&gt;some&lt;/em&gt; sort of ordered arrangement. Now, without worrying about the usefulness of any particular arrangement, I wonder how many options there really are? How many ways could I have arranged these books?&lt;/p&gt;
&lt;p&gt;In &lt;a href="https://bradparker.id.au/posts/crossing-paths-with-descartes"&gt;my last post&lt;/a&gt; I talked about enumerating possibilities, but in all the examples I used I permitted every possible option. Nothing was excluded, even if two coin tosses or dice throws resulted in the same outcome I still counted them as a unique possibility. What I was talking about there were Cartesian Products. That is: given a set of options &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; and a set of options &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; the total range of possibilities of combing both is &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;A \times B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;, the Cartesian Product of the sets &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; and &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;B&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;{&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;}&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;{&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;}&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mrow&gt;&lt;mo stretchy="true" form="prefix"&gt;{&lt;/mo&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;mo stretchy="true" form="postfix"&gt;}&lt;/mo&gt;&lt;/mrow&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding="application/x-tex"&gt;
\begin{align*}
A &amp;amp;= \{\text{a}, \text{b}, \text{c}\} \\
B &amp;amp;= \{1, 2, 3\} \\
A \times B &amp;amp;= \begin{Bmatrix}
(\text{a}, 1) &amp;amp; (\text{a}, 2) &amp;amp; (\text{a}, 3) \\
(\text{b}, 1) &amp;amp; (\text{b}, 2) &amp;amp; (\text{b}, 3) \\
(\text{c}, 1) &amp;amp; (\text{c}, 2) &amp;amp; (\text{c}, 3)
\end{Bmatrix}
\end{align*}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;The total number of possibilities is the size of each input set multiplied together.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;×&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;B&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;9&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding="application/x-tex"&gt;
\begin{align*}
|A| &amp;amp;= 3 \\
|B| &amp;amp;= 3 \\
|A \times B|
&amp;amp;= |A| \times |B| \\
&amp;amp;= 9
\end{align*}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;What if we imagine that arrangements are the same as combined sets of possibilities? That we can choose an element (any element) from the set &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; &lt;em&gt;'number of elements in &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;'&lt;/em&gt; (a.k.a. &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;|A|&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;) times? We might then say that the total number of arrangements of the elements in &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;A&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;, is &lt;nobr&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;|A^{|A|}|&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;.&lt;/nobr&gt;&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mtext mathvariant="italic"&gt;𝑁𝑜. 𝑎𝑟𝑟𝑎𝑛𝑔𝑒𝑚𝑒𝑛𝑡𝑠 𝑜𝑓 &lt;/mtext&gt;&lt;mspace width="0.333em"&gt;&lt;/mspace&gt;&lt;/mrow&gt;&lt;mi&gt;𝐴&lt;/mi&gt;&lt;/mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mover&gt;&lt;mover&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;×&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;×&lt;/mi&gt;&lt;mi&gt;.&lt;/mi&gt;&lt;mi&gt;.&lt;/mi&gt;&lt;mi&gt;.&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mrow&gt;&lt;mo accent="true"&gt;⏞&lt;/mo&gt;&lt;/mover&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mrow&gt;&lt;/mover&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;
\mathit{\text{No. arrangements of } A} = \overbrace{|A| \times |A| \times ... \times |A|}^{|A|}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;More concretely.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;{&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;}&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;msup&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mrow&gt;&lt;mo stretchy="true" form="prefix"&gt;{&lt;/mo&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="center" style="text-align: center"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;mo stretchy="true" form="postfix"&gt;}&lt;/mo&gt;&lt;/mrow&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;msup&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mrow&gt;&lt;/msup&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;×&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;×&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;27&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding="application/x-tex"&gt;
\begin{align*}
A &amp;amp;= \{\text{a}, \text{b}, \text{c}\} \\
A^{|A|}
&amp;amp;= A \times A \times A \\
&amp;amp;= \begin{Bmatrix}
(\text{a}, \text{a}, \text{a}) &amp;amp; (\text{a}, \text{a}, \text{b}) &amp;amp; (\text{a}, \text{a}, \text{c}) \\
(\text{a}, \text{b}, \text{a}) &amp;amp; (\text{a}, \text{b}, \text{b}) &amp;amp; (\text{a}, \text{b}, \text{c}) \\
(\text{a}, \text{c}, \text{a}) &amp;amp; (\text{a}, \text{c}, \text{b}) &amp;amp; (\text{a}, \text{c}, \text{c}) \\
(\text{b}, \text{a}, \text{a}) &amp;amp; (\text{b}, \text{a}, \text{b}) &amp;amp; (\text{b}, \text{a}, \text{c}) \\
(\text{b}, \text{b}, \text{a}) &amp;amp; (\text{b}, \text{b}, \text{b}) &amp;amp; (\text{b}, \text{b}, \text{c}) \\
(\text{b}, \text{c}, \text{a}) &amp;amp; (\text{b}, \text{c}, \text{b}) &amp;amp; (\text{b}, \text{c}, \text{c}) \\
(\text{c}, \text{a}, \text{a}) &amp;amp; (\text{c}, \text{a}, \text{b}) &amp;amp; (\text{c}, \text{a}, \text{c}) \\
(\text{c}, \text{b}, \text{a}) &amp;amp; (\text{c}, \text{b}, \text{b}) &amp;amp; (\text{c}, \text{b}, \text{c}) \\
(\text{c}, \text{c}, \text{a}) &amp;amp; (\text{c}, \text{c}, \text{b}) &amp;amp; (\text{c}, \text{c}, \text{c})
\end{Bmatrix} \\
|A^{|A|}|
&amp;amp;= |A| \times |A| \times |A| \\
&amp;amp;= 27
\end{align*}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;But we know that's not right. There are many things in there which aren't &lt;em&gt;arrangements&lt;/em&gt;. Arranging a collection won't duplicate any of its elements, so things like &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(\text{a}, \text{a}, \text{a})&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; and &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(\text{c}, \text{b}, \text{b})&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; shouldn't be counted.&lt;/p&gt;
&lt;p&gt;What we need is a method to count arrangements that accounts for elements being used only once. Because that's how we might lay out an arrangement of some collection. We'd select an item to start with, then select the next item from what's left, then the next from what's left, and so on until we've placed every item and run out of options to select from.&lt;/p&gt;
&lt;p&gt;For example, given the following collection of items.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/abc-large.webp" loading="lazy" width="630" height="378" alt="The letters, &amp;#39;a&amp;#39;, &amp;#39;b&amp;#39; and &amp;#39;c&amp;#39;" /&gt;&lt;/p&gt;
&lt;p&gt;We could arrange them like so.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: center;"&gt;Step&lt;/th&gt;
&lt;th&gt;Options&lt;/th&gt;
&lt;th&gt;Selection&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: center;"&gt;&lt;span class="founders-grotesk"&gt;1&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/abc.webp" loading="lazy" width="210" height="126" alt="The letters &amp;#39;a&amp;#39;, &amp;#39;b&amp;#39; and &amp;#39;c&amp;#39;" /&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/b.webp" loading="lazy" width="210" height="126" alt="The letter &amp;#39;b&amp;#39;" /&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/b.webp" loading="lazy" width="210" height="126" alt="The letter &amp;#39;b&amp;#39;" /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center;"&gt;&lt;span class="founders-grotesk"&gt;2&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/ac.webp" loading="lazy" width="210" height="126" alt="The letters &amp;#39;a&amp;#39; and &amp;#39;c&amp;#39;" /&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/a.webp" loading="lazy" width="210" height="126" alt="The letter &amp;#39;a&amp;#39;" /&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/ba.webp" loading="lazy" width="210" height="126" alt="The letter &amp;#39;b&amp;#39;" /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center;"&gt;&lt;span class="founders-grotesk"&gt;3&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/c.webp" loading="lazy" width="210" height="126" alt="The letter &amp;#39;c&amp;#39;" /&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/c.webp" loading="lazy" width="210" height="126" alt="The letter &amp;#39;c&amp;#39;" /&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/bac.webp" loading="lazy" width="210" height="126" alt="The letter &amp;#39;b&amp;#39;" /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;At each step the set of options reduces by one. Once 'b' is put down, only 'a' and 'c' are left. On the next step once 'a' is put down only 'c' is left. So, in general, rather than this.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mtext mathvariant="italic"&gt;𝑁𝑜. 𝑎𝑟𝑟𝑎𝑛𝑔𝑒𝑚𝑒𝑛𝑡𝑠 𝑜𝑓 &lt;/mtext&gt;&lt;mspace width="0.333em"&gt;&lt;/mspace&gt;&lt;/mrow&gt;&lt;mi&gt;𝐴&lt;/mi&gt;&lt;/mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mover&gt;&lt;mover&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;×&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;×&lt;/mi&gt;&lt;mi&gt;.&lt;/mi&gt;&lt;mi&gt;.&lt;/mi&gt;&lt;mi&gt;.&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mrow&gt;&lt;mo accent="true"&gt;⏞&lt;/mo&gt;&lt;/mover&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mrow&gt;&lt;/mover&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;
\mathit{\text{No. arrangements of } A} = \overbrace{|A| \times |A| \times ... \times |A|}^{|A|}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;What we have instead is this.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mtext mathvariant="italic"&gt;𝑁𝑜. 𝑎𝑟𝑟𝑎𝑛𝑔𝑒𝑚𝑒𝑛𝑡𝑠 𝑜𝑓 &lt;/mtext&gt;&lt;mspace width="0.333em"&gt;&lt;/mspace&gt;&lt;/mrow&gt;&lt;mi&gt;𝐴&lt;/mi&gt;&lt;/mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;×&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;−&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;−&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mi&gt;.&lt;/mi&gt;&lt;mi&gt;.&lt;/mi&gt;&lt;mi&gt;.&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;
\mathit{\text{No. arrangements of } A} = |A| \times (|A| - 1) \times (|A| - 2) ... \times 1
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;For the 'a', 'b', 'c' example then we'd have.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;{&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;}&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mtext mathvariant="italic"&gt;𝑁𝑜. 𝑎𝑟𝑟𝑎𝑛𝑔𝑒𝑚𝑒𝑛𝑡𝑠 𝑜𝑓 &lt;/mtext&gt;&lt;mspace width="0.333em"&gt;&lt;/mspace&gt;&lt;/mrow&gt;&lt;mi&gt;𝐴&lt;/mi&gt;&lt;/mrow&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;×&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;−&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;6&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding="application/x-tex"&gt;
\begin{align*}
A &amp;amp;= \{\text{a}, \text{b}, \text{c}\} \\
\mathit{\text{No. arrangements of } A}
&amp;amp;= |A| \times (|A| - 1) \times 1 \\
&amp;amp;= 3 \times 2 \times 1 \\
&amp;amp;= 6
\end{align*}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;And here they all are.&lt;/p&gt;
&lt;div class="list-none grid grid-cols-3 grid-rows-2 gap-3"&gt;
  &lt;div&gt;
    &lt;img width="210" height="126" loading="lazy" alt="The letters &amp;#39;a&amp;#39;, &amp;#39;b&amp;#39; and &amp;#39;c&amp;#39;" src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/abc.webp"&gt;&lt;/img&gt;
  &lt;/div&gt;
  &lt;div&gt;
    &lt;img width="210" height="126" loading="lazy" alt="The letters &amp;#39;a&amp;#39;, &amp;#39;c&amp;#39; and &amp;#39;b&amp;#39;" src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/acb.webp"&gt;&lt;/img&gt;
  &lt;/div&gt;
  &lt;div&gt;
    &lt;img width="210" height="126" loading="lazy" alt="The letters &amp;#39;b&amp;#39;, &amp;#39;a&amp;#39; and &amp;#39;c&amp;#39;" src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/bac.webp"&gt;&lt;/img&gt;
  &lt;/div&gt;
  &lt;div&gt;
    &lt;img width="210" height="126" loading="lazy" alt="The letters &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39; and &amp;#39;a&amp;#39;" src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/bca.webp"&gt;&lt;/img&gt;
  &lt;/div&gt;
  &lt;div&gt;
    &lt;img width="210" height="126" loading="lazy" alt="The letters &amp;#39;c&amp;#39;, &amp;#39;a&amp;#39; and &amp;#39;b&amp;#39;" src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/cab.webp"&gt;&lt;/img&gt;
  &lt;/div&gt;
  &lt;div&gt;
    &lt;img width="210" height="126" loading="lazy" alt="The letters &amp;#39;c&amp;#39;, &amp;#39;b&amp;#39; and &amp;#39;a&amp;#39;" src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/cba.webp"&gt;&lt;/img&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;The result you get from multiplying all the numbers less than some number is called the &lt;em&gt;factorial&lt;/em&gt; of that number. It's written like this: &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;n!&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;, and can be defined like this:&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;.&lt;/mi&gt;&lt;mi&gt;.&lt;/mi&gt;&lt;mi&gt;.&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;
n! = n \times (n - 1) \times (n - 2) \times ... \times 2 \times 1
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;Right now we've got 419 books which can be sorted by a code. So how many ways could I have arranged them? What's the factorial of 419?&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;419&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;418&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;417&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;.&lt;/mi&gt;&lt;mi&gt;.&lt;/mi&gt;&lt;mi&gt;.&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;
419 \times 418 \times 417 \times ... \times 3 \times 2 \times 1
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;It's this extremely large number.&lt;/p&gt;
&lt;p&gt;2,&lt;wbr/&gt;908,&lt;wbr/&gt;421,&lt;wbr/&gt;057,&lt;wbr/&gt;896,&lt;wbr/&gt;340,&lt;wbr/&gt;474,&lt;wbr/&gt;361,&lt;wbr/&gt;403,&lt;wbr/&gt;432,&lt;wbr/&gt;093,&lt;wbr/&gt;534,&lt;wbr/&gt;061,&lt;wbr/&gt;335,&lt;wbr/&gt;411,&lt;wbr/&gt;576,&lt;wbr/&gt;803,&lt;wbr/&gt;237,&lt;wbr/&gt;495,&lt;wbr/&gt;067,&lt;wbr/&gt;620,&lt;wbr/&gt;711,&lt;wbr/&gt;879,&lt;wbr/&gt;592,&lt;wbr/&gt;887,&lt;wbr/&gt;139,&lt;wbr/&gt;553,&lt;wbr/&gt;095,&lt;wbr/&gt;110,&lt;wbr/&gt;943,&lt;wbr/&gt;225,&lt;wbr/&gt;026,&lt;wbr/&gt;262,&lt;wbr/&gt;406,&lt;wbr/&gt;188,&lt;wbr/&gt;778,&lt;wbr/&gt;320,&lt;wbr/&gt;680,&lt;wbr/&gt;189,&lt;wbr/&gt;451,&lt;wbr/&gt;711,&lt;wbr/&gt;755,&lt;wbr/&gt;153,&lt;wbr/&gt;962,&lt;wbr/&gt;269,&lt;wbr/&gt;093,&lt;wbr/&gt;225,&lt;wbr/&gt;791,&lt;wbr/&gt;463,&lt;wbr/&gt;391,&lt;wbr/&gt;282,&lt;wbr/&gt;309,&lt;wbr/&gt;784,&lt;wbr/&gt;673,&lt;wbr/&gt;974,&lt;wbr/&gt;891,&lt;wbr/&gt;888,&lt;wbr/&gt;521,&lt;wbr/&gt;144,&lt;wbr/&gt;472,&lt;wbr/&gt;954,&lt;wbr/&gt;435,&lt;wbr/&gt;530,&lt;wbr/&gt;212,&lt;wbr/&gt;518,&lt;wbr/&gt;938,&lt;wbr/&gt;132,&lt;wbr/&gt;427,&lt;wbr/&gt;719,&lt;wbr/&gt;386,&lt;wbr/&gt;733,&lt;wbr/&gt;483,&lt;wbr/&gt;011,&lt;wbr/&gt;170,&lt;wbr/&gt;577,&lt;wbr/&gt;979,&lt;wbr/&gt;186,&lt;wbr/&gt;407,&lt;wbr/&gt;238,&lt;wbr/&gt;784,&lt;wbr/&gt;514,&lt;wbr/&gt;071,&lt;wbr/&gt;038,&lt;wbr/&gt;335,&lt;wbr/&gt;200,&lt;wbr/&gt;586,&lt;wbr/&gt;427,&lt;wbr/&gt;023,&lt;wbr/&gt;669,&lt;wbr/&gt;168,&lt;wbr/&gt;853,&lt;wbr/&gt;348,&lt;wbr/&gt;715,&lt;wbr/&gt;855,&lt;wbr/&gt;934,&lt;wbr/&gt;206,&lt;wbr/&gt;590,&lt;wbr/&gt;666,&lt;wbr/&gt;886,&lt;wbr/&gt;642,&lt;wbr/&gt;210,&lt;wbr/&gt;446,&lt;wbr/&gt;229,&lt;wbr/&gt;488,&lt;wbr/&gt;444,&lt;wbr/&gt;697,&lt;wbr/&gt;075,&lt;wbr/&gt;683,&lt;wbr/&gt;231,&lt;wbr/&gt;304,&lt;wbr/&gt;763,&lt;wbr/&gt;674,&lt;wbr/&gt;216,&lt;wbr/&gt;898,&lt;wbr/&gt;857,&lt;wbr/&gt;425,&lt;wbr/&gt;205,&lt;wbr/&gt;633,&lt;wbr/&gt;114,&lt;wbr/&gt;990,&lt;wbr/&gt;510,&lt;wbr/&gt;459,&lt;wbr/&gt;902,&lt;wbr/&gt;307,&lt;wbr/&gt;876,&lt;wbr/&gt;760,&lt;wbr/&gt;425,&lt;wbr/&gt;583,&lt;wbr/&gt;148,&lt;wbr/&gt;615,&lt;wbr/&gt;724,&lt;wbr/&gt;632,&lt;wbr/&gt;751,&lt;wbr/&gt;661,&lt;wbr/&gt;133,&lt;wbr/&gt;203,&lt;wbr/&gt;237,&lt;wbr/&gt;905,&lt;wbr/&gt;432,&lt;wbr/&gt;668,&lt;wbr/&gt;028,&lt;wbr/&gt;736,&lt;wbr/&gt;816,&lt;wbr/&gt;553,&lt;wbr/&gt;087,&lt;wbr/&gt;322,&lt;wbr/&gt;961,&lt;wbr/&gt;245,&lt;wbr/&gt;249,&lt;wbr/&gt;766,&lt;wbr/&gt;243,&lt;wbr/&gt;189,&lt;wbr/&gt;634,&lt;wbr/&gt;620,&lt;wbr/&gt;342,&lt;wbr/&gt;650,&lt;wbr/&gt;104,&lt;wbr/&gt;310,&lt;wbr/&gt;228,&lt;wbr/&gt;160,&lt;wbr/&gt;720,&lt;wbr/&gt;464,&lt;wbr/&gt;432,&lt;wbr/&gt;084,&lt;wbr/&gt;583,&lt;wbr/&gt;406,&lt;wbr/&gt;587,&lt;wbr/&gt;932,&lt;wbr/&gt;793,&lt;wbr/&gt;842,&lt;wbr/&gt;882,&lt;wbr/&gt;817,&lt;wbr/&gt;312,&lt;wbr/&gt;083,&lt;wbr/&gt;420,&lt;wbr/&gt;305,&lt;wbr/&gt;011,&lt;wbr/&gt;614,&lt;wbr/&gt;174,&lt;wbr/&gt;094,&lt;wbr/&gt;373,&lt;wbr/&gt;347,&lt;wbr/&gt;653,&lt;wbr/&gt;327,&lt;wbr/&gt;314,&lt;wbr/&gt;151,&lt;wbr/&gt;733,&lt;wbr/&gt;173,&lt;wbr/&gt;716,&lt;wbr/&gt;990,&lt;wbr/&gt;349,&lt;wbr/&gt;453,&lt;wbr/&gt;642,&lt;wbr/&gt;618,&lt;wbr/&gt;332,&lt;wbr/&gt;498,&lt;wbr/&gt;813,&lt;wbr/&gt;131,&lt;wbr/&gt;703,&lt;wbr/&gt;848,&lt;wbr/&gt;734,&lt;wbr/&gt;139,&lt;wbr/&gt;461,&lt;wbr/&gt;889,&lt;wbr/&gt;356,&lt;wbr/&gt;833,&lt;wbr/&gt;404,&lt;wbr/&gt;468,&lt;wbr/&gt;988,&lt;wbr/&gt;162,&lt;wbr/&gt;294,&lt;wbr/&gt;586,&lt;wbr/&gt;549,&lt;wbr/&gt;217,&lt;wbr/&gt;704,&lt;wbr/&gt;913,&lt;wbr/&gt;958,&lt;wbr/&gt;653,&lt;wbr/&gt;349,&lt;wbr/&gt;142,&lt;wbr/&gt;669,&lt;wbr/&gt;023,&lt;wbr/&gt;627,&lt;wbr/&gt;237,&lt;wbr/&gt;073,&lt;wbr/&gt;393,&lt;wbr/&gt;370,&lt;wbr/&gt;291,&lt;wbr/&gt;667,&lt;wbr/&gt;739,&lt;wbr/&gt;306,&lt;wbr/&gt;611,&lt;wbr/&gt;350,&lt;wbr/&gt;729,&lt;wbr/&gt;516,&lt;wbr/&gt;327,&lt;wbr/&gt;327,&lt;wbr/&gt;902,&lt;wbr/&gt;034,&lt;wbr/&gt;218,&lt;wbr/&gt;650,&lt;wbr/&gt;157,&lt;wbr/&gt;031,&lt;wbr/&gt;351,&lt;wbr/&gt;111,&lt;wbr/&gt;738,&lt;wbr/&gt;938,&lt;wbr/&gt;367,&lt;wbr/&gt;328,&lt;wbr/&gt;649,&lt;wbr/&gt;342,&lt;wbr/&gt;699,&lt;wbr/&gt;827,&lt;wbr/&gt;177,&lt;wbr/&gt;333,&lt;wbr/&gt;219,&lt;wbr/&gt;328,&lt;wbr/&gt;746,&lt;wbr/&gt;468,&lt;wbr/&gt;751,&lt;wbr/&gt;048,&lt;wbr/&gt;295,&lt;wbr/&gt;766,&lt;wbr/&gt;233,&lt;wbr/&gt;367,&lt;wbr/&gt;259,&lt;wbr/&gt;458,&lt;wbr/&gt;382,&lt;wbr/&gt;317,&lt;wbr/&gt;867,&lt;wbr/&gt;840,&lt;wbr/&gt;592,&lt;wbr/&gt;639,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000,&lt;wbr/&gt;000.&lt;/p&gt;
&lt;p&gt;And here's the kind of question that led to my current cosy combinatorial corner: given a sorted list of all possible arrangements, what is the (&lt;em&gt;deep breath&lt;/em&gt;) 2,&lt;wbr/&gt;844,&lt;wbr/&gt;113,&lt;wbr/&gt;050,&lt;wbr/&gt;416,&lt;wbr/&gt;543,&lt;wbr/&gt;052,&lt;wbr/&gt;622,&lt;wbr/&gt;601,&lt;wbr/&gt;377,&lt;wbr/&gt;724,&lt;wbr/&gt;177,&lt;wbr/&gt;730,&lt;wbr/&gt;794,&lt;wbr/&gt;635,&lt;wbr/&gt;580,&lt;wbr/&gt;558,&lt;wbr/&gt;165,&lt;wbr/&gt;101,&lt;wbr/&gt;289,&lt;wbr/&gt;087,&lt;wbr/&gt;907,&lt;wbr/&gt;211,&lt;wbr/&gt;046,&lt;wbr/&gt;617,&lt;wbr/&gt;413,&lt;wbr/&gt;162,&lt;wbr/&gt;202,&lt;wbr/&gt;727,&lt;wbr/&gt;992,&lt;wbr/&gt;682,&lt;wbr/&gt;826,&lt;wbr/&gt;505,&lt;wbr/&gt;610,&lt;wbr/&gt;602,&lt;wbr/&gt;434,&lt;wbr/&gt;122,&lt;wbr/&gt;752,&lt;wbr/&gt;894,&lt;wbr/&gt;055,&lt;wbr/&gt;956,&lt;wbr/&gt;478,&lt;wbr/&gt;001,&lt;wbr/&gt;246,&lt;wbr/&gt;987,&lt;wbr/&gt;975,&lt;wbr/&gt;654,&lt;wbr/&gt;867,&lt;wbr/&gt;880,&lt;wbr/&gt;927,&lt;wbr/&gt;440,&lt;wbr/&gt;389,&lt;wbr/&gt;088,&lt;wbr/&gt;878,&lt;wbr/&gt;653,&lt;wbr/&gt;260,&lt;wbr/&gt;211,&lt;wbr/&gt;539,&lt;wbr/&gt;374,&lt;wbr/&gt;415,&lt;wbr/&gt;866,&lt;wbr/&gt;208,&lt;wbr/&gt;792,&lt;wbr/&gt;187,&lt;wbr/&gt;943,&lt;wbr/&gt;989,&lt;wbr/&gt;161,&lt;wbr/&gt;515,&lt;wbr/&gt;680,&lt;wbr/&gt;780,&lt;wbr/&gt;226,&lt;wbr/&gt;637,&lt;wbr/&gt;325,&lt;wbr/&gt;041,&lt;wbr/&gt;170,&lt;wbr/&gt;571,&lt;wbr/&gt;521,&lt;wbr/&gt;944,&lt;wbr/&gt;136,&lt;wbr/&gt;857,&lt;wbr/&gt;756,&lt;wbr/&gt;357,&lt;wbr/&gt;610,&lt;wbr/&gt;408,&lt;wbr/&gt;690,&lt;wbr/&gt;480,&lt;wbr/&gt;987,&lt;wbr/&gt;642,&lt;wbr/&gt;359,&lt;wbr/&gt;289,&lt;wbr/&gt;070,&lt;wbr/&gt;142,&lt;wbr/&gt;617,&lt;wbr/&gt;861,&lt;wbr/&gt;100,&lt;wbr/&gt;311,&lt;wbr/&gt;817,&lt;wbr/&gt;255,&lt;wbr/&gt;304,&lt;wbr/&gt;659,&lt;wbr/&gt;710,&lt;wbr/&gt;866,&lt;wbr/&gt;175,&lt;wbr/&gt;534,&lt;wbr/&gt;883,&lt;wbr/&gt;866,&lt;wbr/&gt;241,&lt;wbr/&gt;789,&lt;wbr/&gt;715,&lt;wbr/&gt;155,&lt;wbr/&gt;834,&lt;wbr/&gt;223,&lt;wbr/&gt;460,&lt;wbr/&gt;969,&lt;wbr/&gt;127,&lt;wbr/&gt;343,&lt;wbr/&gt;122,&lt;wbr/&gt;506,&lt;wbr/&gt;553,&lt;wbr/&gt;271,&lt;wbr/&gt;818,&lt;wbr/&gt;293,&lt;wbr/&gt;567,&lt;wbr/&gt;727,&lt;wbr/&gt;306,&lt;wbr/&gt;529,&lt;wbr/&gt;166,&lt;wbr/&gt;052,&lt;wbr/&gt;023,&lt;wbr/&gt;268,&lt;wbr/&gt;045,&lt;wbr/&gt;186,&lt;wbr/&gt;141,&lt;wbr/&gt;937,&lt;wbr/&gt;347,&lt;wbr/&gt;041,&lt;wbr/&gt;818,&lt;wbr/&gt;966,&lt;wbr/&gt;122,&lt;wbr/&gt;038,&lt;wbr/&gt;640,&lt;wbr/&gt;793,&lt;wbr/&gt;796,&lt;wbr/&gt;799,&lt;wbr/&gt;685,&lt;wbr/&gt;516,&lt;wbr/&gt;455,&lt;wbr/&gt;929,&lt;wbr/&gt;549,&lt;wbr/&gt;507,&lt;wbr/&gt;013,&lt;wbr/&gt;186,&lt;wbr/&gt;833,&lt;wbr/&gt;430,&lt;wbr/&gt;265,&lt;wbr/&gt;450,&lt;wbr/&gt;466,&lt;wbr/&gt;044,&lt;wbr/&gt;505,&lt;wbr/&gt;744,&lt;wbr/&gt;178,&lt;wbr/&gt;793,&lt;wbr/&gt;393,&lt;wbr/&gt;254,&lt;wbr/&gt;499,&lt;wbr/&gt;311,&lt;wbr/&gt;497,&lt;wbr/&gt;130,&lt;wbr/&gt;361,&lt;wbr/&gt;821,&lt;wbr/&gt;989,&lt;wbr/&gt;719,&lt;wbr/&gt;697,&lt;wbr/&gt;224,&lt;wbr/&gt;981,&lt;wbr/&gt;301,&lt;wbr/&gt;053,&lt;wbr/&gt;842,&lt;wbr/&gt;088,&lt;wbr/&gt;290,&lt;wbr/&gt;183,&lt;wbr/&gt;796,&lt;wbr/&gt;995,&lt;wbr/&gt;774,&lt;wbr/&gt;643,&lt;wbr/&gt;108,&lt;wbr/&gt;623,&lt;wbr/&gt;128,&lt;wbr/&gt;572,&lt;wbr/&gt;424,&lt;wbr/&gt;596,&lt;wbr/&gt;295,&lt;wbr/&gt;207,&lt;wbr/&gt;864,&lt;wbr/&gt;719,&lt;wbr/&gt;379,&lt;wbr/&gt;479,&lt;wbr/&gt;419,&lt;wbr/&gt;093,&lt;wbr/&gt;894,&lt;wbr/&gt;525,&lt;wbr/&gt;035,&lt;wbr/&gt;709,&lt;wbr/&gt;405,&lt;wbr/&gt;252,&lt;wbr/&gt;305,&lt;wbr/&gt;572,&lt;wbr/&gt;483,&lt;wbr/&gt;849,&lt;wbr/&gt;439,&lt;wbr/&gt;595,&lt;wbr/&gt;150,&lt;wbr/&gt;582,&lt;wbr/&gt;362,&lt;wbr/&gt;925,&lt;wbr/&gt;993,&lt;wbr/&gt;365,&lt;wbr/&gt;553,&lt;wbr/&gt;189,&lt;wbr/&gt;173,&lt;wbr/&gt;069,&lt;wbr/&gt;073,&lt;wbr/&gt;069,&lt;wbr/&gt;239,&lt;wbr/&gt;396,&lt;wbr/&gt;792,&lt;wbr/&gt;666,&lt;wbr/&gt;051,&lt;wbr/&gt;139,&lt;wbr/&gt;882,&lt;wbr/&gt;098,&lt;wbr/&gt;736,&lt;wbr/&gt;318,&lt;wbr/&gt;227,&lt;wbr/&gt;488,&lt;wbr/&gt;496,&lt;wbr/&gt;884,&lt;wbr/&gt;365,&lt;wbr/&gt;414,&lt;wbr/&gt;402,&lt;wbr/&gt;236,&lt;wbr/&gt;391,&lt;wbr/&gt;348,&lt;wbr/&gt;245,&lt;wbr/&gt;541,&lt;wbr/&gt;096,&lt;wbr/&gt;370,&lt;wbr/&gt;960,&lt;wbr/&gt;228,&lt;wbr/&gt;964,&lt;wbr/&gt;587,&lt;wbr/&gt;593,&lt;wbr/&gt;160,&lt;wbr/&gt;349,&lt;wbr/&gt;264,&lt;wbr/&gt;902,&lt;wbr/&gt;263,&lt;wbr/&gt;727,&lt;wbr/&gt;302,&lt;wbr/&gt;169,&lt;wbr/&gt;421,&lt;wbr/&gt;863,&lt;wbr/&gt;892,&lt;wbr/&gt;154,&lt;wbr/&gt;866,&lt;wbr/&gt;370,&lt;wbr/&gt;306,&lt;wbr/&gt;041,&lt;wbr/&gt;614,&lt;wbr/&gt;127,&lt;wbr/&gt;727,&lt;wbr/&gt;830,&lt;wbr/&gt;967,&lt;wbr/&gt;236,&lt;wbr/&gt;995,&lt;wbr/&gt;581,&lt;wbr/&gt;667,&lt;wbr/&gt;801,&lt;wbr/&gt;392,&lt;wbr/&gt;480,&lt;wbr/&gt;447,&lt;wbr/&gt;679,&lt;wbr/&gt;422,&lt;wbr/&gt;359,&lt;wbr/&gt;386,&lt;wbr/&gt;205,&lt;wbr/&gt;525,&lt;wbr/&gt;674,&lt;wbr/&gt;979,&lt;wbr/&gt;615,&lt;wbr/&gt;059,&lt;wbr/&gt;536,&lt;wbr/&gt;733,&lt;wbr/&gt;032,&lt;wbr/&gt;646,&lt;wbr/&gt;807,&lt;wbr/&gt;296,&lt;wbr/&gt;164,&lt;wbr/&gt;119,&lt;wbr/&gt;104,&lt;wbr/&gt;440,&lt;wbr/&gt;573,&lt;wbr/&gt;184,&lt;wbr/&gt;560,&lt;wbr/&gt;777,&lt;wbr/&gt;118,&lt;wbr/&gt;243rd one? You know … for example.&lt;/p&gt;
&lt;h2 id="lexicographic-order"&gt;Lexicographic order&lt;/h2&gt;
&lt;p&gt;How might arrangements be sorted? To answer that I'd need to define when one arrangement should come before another. Here's a scheme.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Step through pairs of elements from both arrangements. I.E. First look at the first element of arrangement &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; and the first element from arrangement &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;, then the second element from arrangement &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; and the second element from arrangement &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;, and so on.&lt;/li&gt;
&lt;li&gt;For the first pair with mismatching elements, if the element from &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; should come before the element from &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; then the whole arrangement &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; should come before the arrangement &lt;nobr&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;.&lt;/nobr&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, here's two arrangements of the first three letters of the alphabet.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding="application/x-tex"&gt;
\begin{align*}
x &amp;amp;= (\text{b}, \text{c}, \text{a}) \\
y &amp;amp;= (\text{b}, \text{a}, \text{c})
\end{align*}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;ol type="1"&gt;
&lt;li&gt;Compare the first element of each ordering: &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;x_1 = \text{b}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; and &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;y_1 = \text{b}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;. They match, so move onto the next pair of elements.&lt;/li&gt;
&lt;li&gt;Compare the second element of each ordering: &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;x_2 = \text{c}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; and &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;y_2 = \text{a}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;. They don't match and &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;annotation encoding="application/x-tex"&gt;\text{a}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; comes before &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;annotation encoding="application/x-tex"&gt;\text{c}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;, therefore &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; comes before &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Sorting elements this way will result in them being in &lt;a href="https://en.wikipedia.org/wiki/Lexicographic_order"&gt;&lt;em&gt;Lexicographic order&lt;/em&gt;&lt;/a&gt;, and it might seem like the way mostly everything is sorted in day to day life … because it is! This is how we sort words in the dictionary, hence the name.&lt;/p&gt;
&lt;h2 id="indexing"&gt;Indexing&lt;/h2&gt;
&lt;p&gt;The example above sorts arrangements with reference to a pre-existing ordering of their elements: the alphabet. But it didn't &lt;em&gt;have&lt;/em&gt; to. We could've used some other ordering, and ended up with a different result. If we lived in an alternate timeline where the Latin alphabet began &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(\text{c}, \text{a}, \text{b})&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; rather than &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(\text{a}, \text{b}, \text{c})&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; then the order of our example arrangements would be reversed and &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; would come before &lt;nobr&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;.&lt;/nobr&gt;&lt;/p&gt;
&lt;p&gt;The alphabet we have is one possible arrangement. One of 403,&lt;wbr/&gt;291,&lt;wbr/&gt;461,&lt;wbr/&gt;126,&lt;wbr/&gt;605,&lt;wbr/&gt;635,&lt;wbr/&gt;584,&lt;wbr/&gt;000,&lt;wbr/&gt;000 options in fact. To reduce confusion when talking about any alternative arrangements we can choose to ignore the specific elements of whatever collection we're arranging and instead refer only to their position in some select &lt;em&gt;conventional&lt;/em&gt; ordering. The alphabet is the convention for letters, where 'a' is first, 'b' is second, 'c' is third, and so on. We can then discuss other arrangements by saying only where elements 1, 2, and 3 are. For example, the arrangement &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(\text{b}, \text{a}, \text{c})&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; becomes &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(2, 1, 3)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;.&lt;/p&gt;
&lt;p&gt;When we can use a sequence of numbers to refer to all the elements of a collection we're able to say that the collection is &lt;em&gt;indexed&lt;/em&gt; by those numbers. The numbers &lt;em&gt;point to&lt;/em&gt; elements in the collection.&lt;a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For our books I'll use &lt;em&gt;Alphabetical by title&lt;/em&gt; as the conventional ordering. This then defines the Lexicographic order for the list of possible arrangements.&lt;/p&gt;
&lt;h2 id="lehmer-codes"&gt;Lehmer codes&lt;/h2&gt;
&lt;p&gt;Right, here we go: Lehmer codes index all possible arrangements of collections of elements, and they do so in Lexicographic order.&lt;/p&gt;
&lt;p&gt;To see how we can revisit my earlier example of laying out the first three letters of the alphabet.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: center;"&gt;Step&lt;/th&gt;
&lt;th&gt;Options&lt;/th&gt;
&lt;th&gt;Selection&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: center;"&gt;&lt;span class="founders-grotesk"&gt;1&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/abc.webp" loading="lazy" width="210" height="126" alt="The letters &amp;#39;a&amp;#39;, &amp;#39;b&amp;#39; and &amp;#39;c&amp;#39;" /&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/b.webp" loading="lazy" width="210" height="126" alt="The letter &amp;#39;b&amp;#39;" /&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/b.webp" loading="lazy" width="210" height="126" alt="The letter &amp;#39;b&amp;#39;" /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center;"&gt;&lt;span class="founders-grotesk"&gt;2&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/ac.webp" loading="lazy" width="210" height="126" alt="The letters &amp;#39;a&amp;#39; and &amp;#39;c&amp;#39;" /&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/a.webp" loading="lazy" width="210" height="126" alt="The letter &amp;#39;a&amp;#39;" /&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/ba.webp" loading="lazy" width="210" height="126" alt="The letter &amp;#39;b&amp;#39;" /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center;"&gt;&lt;span class="founders-grotesk"&gt;3&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/c.webp" loading="lazy" width="210" height="126" alt="The letter &amp;#39;c&amp;#39;" /&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/c.webp" loading="lazy" width="210" height="126" alt="The letter &amp;#39;c&amp;#39;" /&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/bac.webp" loading="lazy" width="210" height="126" alt="The letter &amp;#39;b&amp;#39;" /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Lehmer codes end up recording the steps in this procedure as a sequence of choices of index. Like so:&lt;/p&gt;
&lt;ol type="1"&gt;
&lt;li&gt;Select the second option.&lt;/li&gt;
&lt;li&gt;Select the first option from what's left.&lt;/li&gt;
&lt;li&gt;Select the first option from what's left.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now, the indexes in Lehmer codes all begin at 0, rather than 1, so for the arrangement: &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(\text{b}, \text{a}, \text{c})&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;, we have this sequence of choices: &lt;nobr&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(1, 0, 0)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;.&lt;/nobr&gt;&lt;/p&gt;
&lt;p&gt;Here are &lt;em&gt;all&lt;/em&gt; the choices someone could make when laying out the first three letters of the alphabet.&lt;/p&gt;
&lt;table class="table-style-none table-fixed founders-grotesk"&gt;
  &lt;thead&gt;
    &lt;tr class="b"&gt;
      &lt;th&gt;Step 1&lt;/th&gt;
      &lt;th&gt;Step 2&lt;/th&gt;
      &lt;th&gt;Step 3&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody class="f6"&gt;
    &lt;tr&gt;
      &lt;td rowspan="2" class="bt b--moon-gray pr2"&gt;
        &lt;p&gt;0 from (a, b, c)&lt;/p&gt;
        &lt;img width="210" height="126" loading="lazy" alt="The letter &amp;#39;a&amp;#39;" src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/a.webp"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td class="bt b--moon-gray pr2"&gt;
        &lt;p&gt;0 from (b, c)&lt;/p&gt;
        &lt;img width="210" height="126" loading="lazy" alt="The letters &amp;#39;a&amp;#39; and &amp;#39;b&amp;#39;" src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/ab.webp"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td class="bt b--moon-gray"&gt;
        &lt;p&gt;0 from (c)&lt;/p&gt;
        &lt;img width="210" height="126" loading="lazy" alt="The letters &amp;#39;a&amp;#39;, &amp;#39;b&amp;#39; and &amp;#39;c&amp;#39;" src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/abc.webp"&gt;&lt;/img&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td class="pr2 pb2"&gt;
        &lt;p&gt;1 from (b, c)&lt;/p&gt;
        &lt;img width="210" height="126" loading="lazy" alt="The letters &amp;#39;a&amp;#39; and &amp;#39;c&amp;#39;" src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/ac.webp"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td class="pb2"&gt;
        &lt;p&gt;0 from (b)&lt;/p&gt;
        &lt;img width="210" height="126" loading="lazy" alt="The letters &amp;#39;a&amp;#39;, &amp;#39;c&amp;#39; and &amp;#39;b&amp;#39;" src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/acb.webp"&gt;&lt;/img&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td rowspan="2" class="bt b--moon-gray pr2"&gt;
        &lt;p&gt;1 from (a, b, c)&lt;/p&gt;
        &lt;img width="210" height="126" loading="lazy" alt="The letter &amp;#39;b&amp;#39;" src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/b.webp"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td class="bt b--moon-gray pr2"&gt;
        &lt;p&gt;0 from (a, c)&lt;/p&gt;
        &lt;img width="210" height="126" loading="lazy" alt="The letters &amp;#39;b&amp;#39; and &amp;#39;a&amp;#39;" src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/ba.webp"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td class="bt b--moon-gray"&gt;
        &lt;p&gt;0 from (c)&lt;/p&gt;
        &lt;img width="210" height="126" loading="lazy" alt="The letters &amp;#39;b&amp;#39;, &amp;#39;a&amp;#39;, and &amp;#39;c&amp;#39;" src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/bac.webp"&gt;&lt;/img&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td class="pr2 pb2"&gt;
        &lt;p&gt;1 from (a, c)&lt;/p&gt;
        &lt;img width="210" height="126" loading="lazy" alt="The letters &amp;#39;b&amp;#39; and &amp;#39;c&amp;#39;" src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/bc.webp"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td class="pb2"&gt;
        &lt;p&gt;0 from (a)&lt;/p&gt;
        &lt;img width="210" height="126" loading="lazy" alt="The letters &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39; and &amp;#39;a&amp;#39;" src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/bca.webp"&gt;&lt;/img&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td rowspan="2" class="bt b--moon-gray pr2"&gt;
        &lt;p&gt;2 from (a, b, c)&lt;/p&gt;
        &lt;img width="210" height="126" loading="lazy" alt="The letter &amp;#39;c&amp;#39;" src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/c.webp"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td class="bt b--moon-gray pr2"&gt;
        &lt;p&gt;0 from (a, b)&lt;/p&gt;
        &lt;img width="210" height="126" loading="lazy" alt="The letters &amp;#39;c&amp;#39; and &amp;#39;a&amp;#39;" src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/ca.webp"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td class="bt b--moon-gray"&gt;
        &lt;p&gt;0 from (b)&lt;/p&gt;
        &lt;img width="210" height="126" loading="lazy" alt="The letters &amp;#39;c&amp;#39;, &amp;#39;a&amp;#39; and &amp;#39;b&amp;#39;" src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/cab.webp"&gt;&lt;/img&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td class="pr2 pb2"&gt;
        &lt;p&gt;1 from (a, b)&lt;/p&gt;
        &lt;img width="210" height="126" loading="lazy" alt="The letters &amp;#39;c&amp;#39; and &amp;#39;b&amp;#39;" src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/cb.webp"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td class="pb2"&gt;
        &lt;p&gt;0 from (a)&lt;/p&gt;
        &lt;img width="210" height="126" loading="lazy" alt="The letters &amp;#39;c&amp;#39;, &amp;#39;b&amp;#39; and &amp;#39;a&amp;#39;" src="https://bradparker.id.au/content/posts/books-badgers-and-big-numbers/assets/images/permutations/cba.webp"&gt;&lt;/img&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Which can be condensed into this list of sequences.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(0, 0, 0)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/li&gt;
&lt;li&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(0, 1, 0)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/li&gt;
&lt;li&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(1, 0, 0)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/li&gt;
&lt;li&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(1, 1, 0)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/li&gt;
&lt;li&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(2, 0, 0)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/li&gt;
&lt;li&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(2, 1, 0)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And here's the nifty trick: this is counting, but it's counting in a number system quite unlike the one we use day to day.&lt;/p&gt;
&lt;p&gt;At the first step there are &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;3!&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; (a.k.a &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;3 \times 2 \times 1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;) possible outcomes, then at the second step there are &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;2!&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;. I could also say that at the second step there are &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mi&gt;/&lt;/mi&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(3 \times 2 \times 1) / 3&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; choices. It's the same thing, but by saying it that way I'm trying to emphasise that the first choice puts the rest of the sequence into one of three branches.&lt;/p&gt;
&lt;p&gt;I could also try to emphasize that this way: when you choose 'b' you &lt;em&gt;skip over&lt;/em&gt; the &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;2!&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; possibilities you might've reached if you'd chosen 'a'. When you choose 'c' you &lt;em&gt;skip over&lt;/em&gt; the &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;2!&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; possibilities from choosing 'a', and also the &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;2!&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; from 'b'. So when choosing 'c' you skip over &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;2 \times 2!&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; possibilities.&lt;/p&gt;
&lt;p&gt;When viewed this way it's is not &lt;em&gt;completely&lt;/em&gt; unlike ordinary counting. If asked to find the 243rd &lt;em&gt;something&lt;/em&gt; you could &lt;em&gt;skip over&lt;/em&gt; the first 200 things, then you could &lt;em&gt;skip over&lt;/em&gt; the next 40 things, finally arriving at the 3rd thing after that. By choosing 2 in the hundreds place this number goes down the branch where the range of possibilities is within &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;200&lt;/mn&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;&amp;lt;&lt;/mo&gt;&lt;mn&gt;300&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;200 \leq n \lt 300&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;.&lt;/p&gt;
&lt;p&gt;What's different in the case of these sequences of index choices is that instead of hundreds, tens and ones we have &lt;nobr&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;2!&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;s&lt;/nobr&gt;, &lt;nobr&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;1!&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;s&lt;/nobr&gt; and &lt;nobr&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;0!&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;s&lt;/nobr&gt;.&lt;/p&gt;
&lt;p&gt;What happens then if we multiply each index in the above list of sequences by its factorial place value? (Just as we do with ordinary numbers.)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(0 \times 2!, 0 \times 1!, 0 \times 0!) = (0, 0, 0)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/li&gt;
&lt;li&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(0 \times 2!, 1 \times 1!, 0 \times 0!) = (0, 1, 0)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/li&gt;
&lt;li&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(1 \times 2!, 0 \times 1!, 0 \times 0!) = (2, 0, 0)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/li&gt;
&lt;li&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(1 \times 2!, 1 \times 1!, 0 \times 0!) = (2, 1, 0)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/li&gt;
&lt;li&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;4&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(2 \times 2!, 0 \times 1!, 0 \times 0!) = (4, 0, 0)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/li&gt;
&lt;li&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;!&lt;/mi&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;4&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(2 \times 2!, 1 \times 1!, 0 \times 0!) = (4, 1, 0)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Interesting, and now if we add the places together? (Again, just as we do with ordinary numbers.)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;0 + 0 + 0 = 0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/li&gt;
&lt;li&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;0 + 1 + 0 = 1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/li&gt;
&lt;li&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;2 + 0 + 0 = 2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/li&gt;
&lt;li&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;2 + 1 + 0 = 3&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/li&gt;
&lt;li&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;4&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;4&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;4 + 0 + 0 = 4&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/li&gt;
&lt;li&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;4&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;5&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;4 + 1 + 0 = 5&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What we're looking at here is the &lt;a href="https://en.wikipedia.org/wiki/Factorial_number_system"&gt;&lt;em&gt;Factorial number system&lt;/em&gt;&lt;/a&gt;, and how factorial numbers can be converted into ordinary, decimal numbers.&lt;/p&gt;
&lt;p&gt;Now, factorial numbers are not just factorial numbers, they are also Lehmer codes. The number 2 is the decimal representation of the Lehmer code &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(1, 0, 0)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;. Which is a sequence of choices made when laying out an arrangement of elements. It's possible to transform that sequence of choices into indexes into the original collection. If we do so with the sequence &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(1, 0, 0)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; we get these indexes: &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(1, 0, 2)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;. Following those indexes back to the letters they point to we get &lt;nobr&gt;&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;b&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;a&lt;/mtext&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;c&lt;/mtext&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(\text{b}, \text{a}, \text{c})&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;.&lt;/nobr&gt;&lt;/p&gt;
&lt;p&gt;This gives me everything I need to answer my silly question: What is the 2,&lt;wbr/&gt;844, … 243rd possible arrangement of our 5-ish badgers worth of books? I only have to take that number, subtract one, convert that from decimal to factorial, and then use those digits as &lt;em&gt;instructions&lt;/em&gt; for laying out an arrangement. This all happens very quickly. It takes about two hundredths of a second to go from an enormous number to a list of books.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; BS.writeFile &amp;quot;sorted_books.json&amp;quot; (Aeson.encode (decodeLehmer books (toFactorial n)))
(0.02 secs, 17,994,448 bytes)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class="javascript"&gt;&lt;code&gt;[
  {
    &amp;quot;author&amp;quot;: &amp;quot;Tufte, Edward R.&amp;quot;,
    &amp;quot;code&amp;quot;: &amp;quot;001.4226&amp;quot;,
    &amp;quot;title&amp;quot;: &amp;quot;The Visual Display of Quantitative Information&amp;quot;
  },
  {
    &amp;quot;author&amp;quot;: &amp;quot;Weizenbaum, Joseph&amp;quot;,
    &amp;quot;code&amp;quot;: &amp;quot;001.64&amp;quot;,
    &amp;quot;title&amp;quot;: &amp;quot;Computer Power and Human Reason&amp;quot;
  },
  {
    &amp;quot;author&amp;quot;: &amp;quot;Gleick, James&amp;quot;,
    &amp;quot;code&amp;quot;: &amp;quot;003.857&amp;quot;,
    &amp;quot;title&amp;quot;: &amp;quot;Chaos: Making a New Science&amp;quot;
  },
  {
    &amp;quot;author&amp;quot;: &amp;quot;Galloway, Alexander&amp;quot;,
    &amp;quot;code&amp;quot;: &amp;quot;004.09&amp;quot;,
    &amp;quot;title&amp;quot;: &amp;quot;Uncomputable: Play and Politics In the Long Digital Age&amp;quot;
    // ...&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I think that's really something.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Having written this I can think of a couple of reasons I've found Lehmer codes so interesting.&lt;/p&gt;
&lt;p&gt;Firstly, there's something indescribably cool about how they work. Embedded in the numbers of this very strange number system is the procedure for encoding and decoding them as arrangments of elements. The strange number system is perfectly suited to encoding and decoding arrangements, it's factorial! This, to me, feels simultaneously obvious and obscure and I love it.&lt;/p&gt;
&lt;p&gt;Secondly, when I first came across Lehmer codes I was unaware of so many of the foundations upon which they're built, and it left me a bit awe struck. I was overwhelmed thinking about all the &lt;em&gt;epistemic iterations&lt;/em&gt;&lt;a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt; it would take to arrive at something like this. All the large and small thoughts, and all the people who thought them.&lt;/p&gt;
&lt;p&gt;At the end of the day I have no idea if Lehmer codes will ever prove to be practically useful to me. Regardless, I do know that I find them wonderful.&lt;/p&gt;
&lt;section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn1"&gt;&lt;p&gt;We were very sad to see Logical Unsanity close. The ABC did a nice feature at the time: &lt;a href="https://www.abc.net.au/news/2018-04-08/quirky-tin-shed-bookshop-offers-booklovers-sanctuary-brisbane/9618992"&gt;&lt;em&gt;Quirky tin shed bookshop 'born out of laziness' offers booklovers' sanctuary&lt;/em&gt;&lt;/a&gt;&lt;a href="#fnref1" class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id="fn2"&gt;&lt;blockquote&gt;
&lt;p&gt;… from &lt;em&gt;indicare&lt;/em&gt; "to point out," …&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="https://www.etymonline.com/word/index"&gt;Index - Etymology, Origin &amp;amp; Meaning&lt;/a&gt;&lt;a href="#fnref2" class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id="fn3"&gt;&lt;p&gt;This is a term I've just come across from reading &lt;a href="https://jamesvincent.info/beyond-measure"&gt;&lt;em&gt;Beyond Measure&lt;/em&gt; by James Vincent&lt;/a&gt; (2022). It was coined by Hasok Chang in his book &lt;em&gt;Inventing Temperature&lt;/em&gt; (2004).&lt;a href="#fnref3" class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description><author>hi@bradparker.id.au (Brad Parker)</author><guid>https://bradparker.id.au/posts/books-badgers-and-big-numbers</guid><pubDate>Sat, 21 Jun 2025 00:00:00 UTC</pubDate></item><item><title>Crossing paths with Descartes</title><link>https://bradparker.id.au/posts/crossing-paths-with-descartes</link><description>&lt;p&gt;Lately I've been thinking about really fun solutions. You know, those solutions which use some insight you were completely unaware of and make it all look like magic. It's been more than once that I've found myself stumbling into something called &lt;em&gt;combinatorics&lt;/em&gt; when trying to learn more about them. On the way to better understanding these combinatorial solutions I've been reflecting on things more foundational. Here, hang on, I'll try to explain what I mean.&lt;/p&gt;
&lt;h2 id="two-up"&gt;Two-up&lt;/h2&gt;
&lt;p&gt;Two-up is a game played in Australia. Someone tosses two coins in the air, at the same time, and people place bets on the outcome. It is forbidden by law except for one day of the year, ANZAC day. If you want to understand why betting on a coin toss might be outlawed (and otherwise just enjoy a great if but harrowing read) I reckon &lt;a href="https://en.wikipedia.org/wiki/Wake_in_Fright_(novel)"&gt;Wake in Fright&lt;/a&gt; is worth your time.&lt;/p&gt;
&lt;p&gt;How many possible states can two coins be in? The first coin can be heads or tails, and the second coin can be heads or tails.&lt;/p&gt;
&lt;table class="table-style-none table-fixed"&gt;
  &lt;thead class="sr-only"&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;Second heads&lt;/th&gt;
      &lt;th&gt;Second tails&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody class="flex flex-col gap-3"&gt;
    &lt;tr class="flex flex-row gap-3"&gt;
      &lt;th class="sr-only"&gt;First heads&lt;/th&gt;
      &lt;td&gt;
        &lt;figure&gt;
          &lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/two-up/heads-heads.jpeg.webp" width="560" height="448"&gt;&lt;/img&gt;
          &lt;figcaption&gt;
            First heads, second heads
          &lt;/figcaption&gt;
        &lt;/figure&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;figure&gt;
          &lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/two-up/heads-tails.jpeg.webp" width="560" height="448"&gt;&lt;/img&gt;
          &lt;figcaption&gt;
            First heads, second tails
          &lt;/figcaption&gt;
        &lt;/figure&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr class="flex flex-row gap-3"&gt;
      &lt;th class="sr-only"&gt;First tails&lt;/th&gt;
      &lt;td&gt;
        &lt;figure&gt;
          &lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/two-up/tails-heads.jpeg.webp" width="560" height="448"&gt;&lt;/img&gt;
          &lt;figcaption&gt;
            First tails, second heads
          &lt;/figcaption&gt;
        &lt;/figure&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;figure&gt;
          &lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/two-up/tails-tails.jpeg.webp" width="560" height="448"&gt;&lt;/img&gt;
          &lt;figcaption&gt;
            First tails, second tails
          &lt;/figcaption&gt;
        &lt;/figure&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;tbody&gt;
&lt;/table&gt;

&lt;p&gt;There are two coins, each with two sides they could land on.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mtext mathvariant="italic"&gt;𝑁𝑜. 𝑜𝑓 𝑠𝑖𝑑𝑒𝑠 𝑐𝑜𝑖𝑛 1&lt;/mtext&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mtext mathvariant="italic"&gt;𝑁𝑜. 𝑜𝑓 𝑠𝑖𝑑𝑒𝑠 𝑐𝑜𝑖𝑛 2&lt;/mtext&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext mathvariant="italic"&gt;𝑁𝑜. 𝑜𝑓 𝑝𝑜𝑠𝑠𝑖𝑏𝑖𝑙𝑖𝑡𝑖𝑒𝑠&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;
\mathit{\text{No. of sides coin 1}} \times \mathit{\text{No. of sides coin 2}}
= \mathit{\text{No. of possibilities}}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;So.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;4&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;
2 \times 2 = 4
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;In Two-up two of these possibilities are counted as the same outcome. The order of the coins doesn't matter, which is handy, keeping track of them flying through the air, a few pints deep, would surely be diabolical. So one outcome ends up being twice as likely as the other two. Sounds simple, ends up pretty complicated for &lt;a href="https://en.wikipedia.org/wiki/Wake_in_Fright_(novel)#Plot_summary"&gt;John Grant&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="hazard"&gt;Hazard&lt;/h2&gt;
&lt;p&gt;Hazard is a dice game which was popular in 17th and 18th century England. Someone rolls a pair of dice and places bets on the outcome. The rules for assessing the success or failure of an outcome are fairly complicated. It's referenced in Chaucer's &lt;em&gt;Canterbury Tales&lt;/em&gt; in a passage that may have given rise to the idiom "at sixes and sevens", which refers to being in a state of confusion or disarray. I've never read &lt;em&gt;Canterbury tales&lt;/em&gt;, I suspect if I tried I'd end up at sixes and sevens.&lt;/p&gt;
&lt;p&gt;How many possible states can two dice be in? The first dice can have any one of the numbers one to six face up, as can the second.&lt;/p&gt;
&lt;table class="table-style-none table-fixed min-w-full border-separate border-spacing-3 founders-grotesk"&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th class="text-center"&gt;&lt;/th&gt;
      &lt;th class="text-center"&gt;1&lt;/th&gt;
      &lt;th class="text-center"&gt;2&lt;/th&gt;
      &lt;th class="text-center"&gt;3&lt;/th&gt;
      &lt;th class="text-center"&gt;4&lt;/th&gt;
      &lt;th class="text-center"&gt;5&lt;/th&gt;
      &lt;th class="text-center"&gt;6&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th class="align-middle"&gt;1&lt;/th&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 1 side up, the second with the 1 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/1-1.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 1 side up, the second with the 2 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/1-2.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 1 side up, the second with the 3 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/1-3.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 1 side up, the second with the 4 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/1-4.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 1 side up, the second with the 5 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/1-5.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 1 side up, the second with the 6 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/1-6.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th class="align-middle"&gt;2&lt;/th&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 2 side up, the second with the 1 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/2-1.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 2 side up, the second with the 2 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/2-2.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 2 side up, the second with the 3 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/2-3.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 2 side up, the second with the 4 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/2-4.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 2 side up, the second with the 5 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/2-5.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 2 side up, the second with the 6 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/2-6.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th class="align-middle"&gt;3&lt;/th&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 3 side up, the second with the 1 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/3-1.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 3 side up, the second with the 2 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/3-2.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 3 side up, the second with the 3 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/3-3.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 3 side up, the second with the 4 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/3-4.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 3 side up, the second with the 5 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/3-5.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 3 side up, the second with the 6 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/3-6.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th class="align-middle"&gt;4&lt;/th&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 4 side up, the second with the 1 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/4-1.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 4 side up, the second with the 2 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/4-2.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 4 side up, the second with the 3 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/4-3.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 4 side up, the second with the 4 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/4-4.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 4 side up, the second with the 5 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/4-5.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 4 side up, the second with the 6 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/4-6.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th class="align-middle"&gt;5&lt;/th&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 5 side up, the second with the 1 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/5-1.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 5 side up, the second with the 2 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/5-2.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 5 side up, the second with the 3 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/5-3.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 5 side up, the second with the 4 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/5-4.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 5 side up, the second with the 5 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/5-5.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 5 side up, the second with the 6 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/5-6.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th class="align-middle"&gt;6&lt;/th&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 6 side up, the second with the 1 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/6-1.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 6 side up, the second with the 2 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/6-2.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 6 side up, the second with the 3 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/6-3.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 6 side up, the second with the 4 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/6-4.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 6 side up, the second with the 5 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/6-5.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
      &lt;td&gt;
        &lt;img loading="lazy" alt="Two dice. The first with the 6 side up, the second with the 6 side up" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/hazard/6-6.JPEG.190.webp" width="190" height="127"&gt;&lt;/img&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;There are two dice, each with six sides they could land on.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mtext mathvariant="italic"&gt;𝑁𝑜. 𝑜𝑓 𝑠𝑖𝑑𝑒𝑠 𝑑𝑖𝑐𝑒 1&lt;/mtext&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mtext mathvariant="italic"&gt;𝑁𝑜. 𝑜𝑓 𝑠𝑖𝑑𝑒𝑠 𝑑𝑖𝑐𝑒 2&lt;/mtext&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext mathvariant="italic"&gt;𝑁𝑜. 𝑜𝑓 𝑝𝑜𝑠𝑠𝑖𝑏𝑖𝑙𝑖𝑡𝑖𝑒𝑠&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;
\mathit{\text{No. of sides dice 1}} \times \mathit{\text{No. of sides dice 2}}
= \mathit{\text{No. of possibilities}}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;So.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;6&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;6&lt;/mn&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;36&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;
6 \times 6 = 36
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;As with Two-up, many of these possibilities are counted as the same outcome. All that matters is the sum of the numbers on each dice. So not only is 6 and 4 equal to 4 and 6, but also 3 and 7. But we needn't worry about all that.&lt;/p&gt;
&lt;h2 id="dna"&gt;DNA&lt;/h2&gt;
&lt;p&gt;One more game of chance.&lt;/p&gt;
&lt;p&gt;Deoxyribonucleic acid is a pretty special molecule. Two chains of smaller molecular units (called nucleotides) each zipped together by the attractive force brought about by electron density being greater nearer to nitrogen or oxygen atoms than hydrogen atoms.&lt;/p&gt;
&lt;p&gt;DNA nucleotides all have a deoxyribose component attached to one of four different sub-units (nitrogenous bases): adenine, cytosine, guanine and thymine. It's from these we get the letters we use to denote the genetic code: A, C, G and T.&lt;/p&gt;
&lt;p&gt;DNA serves multiple purposes. One is as a sort of template that informs protein construction. Proteins are also pretty special molecules, built out of one or more chains (polypeptides) of other molecular units (amino acids).&lt;/p&gt;
&lt;p&gt;In 1961 Francis Crick, Sydney Brenner, Leslie Barnett and R. J. Watts-Tobin figured out that this process of protein construction requires that the nucleotides that make up the protein-templating parts of DNA come in groups of three. They called these groups &lt;em&gt;codons&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;How many different codons could there be?&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/codons/codons.svg" loading="lazy" width="1208" height="852" alt="A three dimensional four by four by four grid of images, forming roughly a cube. Each image is a group of three cookies which are in the shapes of letters. The only letters used are A, T, G and C. The first image is of three &amp;#39;A&amp;#39; cookies. The second a &amp;#39;T&amp;#39; cookie and two &amp;#39;A&amp;#39; cookies. The third a &amp;#39;G&amp;#39; cookie and two &amp;#39;A&amp;#39; cookies and so on through all possible combinations." /&gt;&lt;/p&gt;
&lt;p&gt;There are three 'slots' in each codon, which could each be filled by one of four nucleotide types.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mtext mathvariant="italic"&gt;𝑁𝑜. 𝑜𝑓 𝑛𝑢𝑐𝑙𝑒𝑜𝑡𝑖𝑑𝑒𝑠&lt;/mtext&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mtext mathvariant="italic"&gt;𝑁𝑜. 𝑜𝑓 𝑛𝑢𝑐𝑙𝑒𝑜𝑡𝑖𝑑𝑒𝑠&lt;/mtext&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mtext mathvariant="italic"&gt;𝑁𝑜. 𝑜𝑓 𝑛𝑢𝑐𝑙𝑒𝑜𝑡𝑖𝑑𝑒𝑠&lt;/mtext&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext mathvariant="italic"&gt;𝑁𝑜. 𝑜𝑓 𝑝𝑜𝑠𝑠𝑖𝑏𝑙𝑒 𝑐𝑜𝑑𝑜𝑛𝑠&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;
\mathit{\text{No. of nucleotides}} \times \mathit{\text{No. of nucleotides}} \times \mathit{\text{No. of nucleotides}}
= \mathit{\text{No. of possible codons}}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;So.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;4&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;4&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;4&lt;/mn&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;64&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;
4 \times 4 \times 4 = 64
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;In 1954 Watson and Crick intuited a list of the 20 amino acids believed to be constructed according to DNA's template. They were inspired to do so in response to a tidy, but ultimately incorrect, geometric explanation of the process put forward by a theoretical physicist, George Gamow. Later, in 1956, they came up with their own tidy, but ultimately incorrect, combinatorial explanation.&lt;a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This seems like fiendishly complex stuff, there's sure to be many red herrings on the path to the right explanation. I guess that's just how the &lt;a href="https://www.ikea.com/au/en/p/kafferep-biscuits-letter-shaped-70546375/"&gt;cookie&lt;/a&gt; crumbles.&lt;/p&gt;
&lt;h2 id="quartets"&gt;Quartets&lt;/h2&gt;
&lt;p&gt;The string quartet has been around as a musical genre and an ensemble instrumentation since the 1750s. In 1825 Beethoven wrote some particularly spicy quartets, numbers 12 to 16, the last major compositions he completed. I love them, though not everyone does. A contemporary of Beethoven, and composer himself, Louis Spohr, described them as "indecipherable, uncorrected horrors."&lt;/p&gt;
&lt;p&gt;Three of the quartets, 15, 13, and 14, centre thematically around particular groupings of four notes, groupings united by how far away their constituents are from each other. Which has me wondering what indecipherable, uncorrected horrors might lurk in the collection of all possible voicings a string quartet could play?&lt;/p&gt;
&lt;p&gt;First, how many are there? I'm honestly not sure, the ranges of these instruments are a bit flexible, it can depend on the player, whether harmonics are included, the construction of a particular instance of an instrument. I'll use these ranges so we can at least get a ballpark figure.&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;Violin&lt;/dt&gt;
&lt;dd&gt;
G3 - A7, 51 notes
&lt;/dd&gt;
&lt;dt&gt;Viola&lt;/dt&gt;
&lt;dd&gt;
C3 - E6, 41 notes
&lt;/dd&gt;
&lt;dt&gt;Cello&lt;/dt&gt;
&lt;dd&gt;
C2 - A5, 46 notes
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;The first and second violins can each play any one of 51 notes, the viola one of 41, and the cello one of 46. So.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;51&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;51&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;41&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;46&lt;/mn&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;4,905,486&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;
51 \times 51 \times 41 \times 46 = \text{4,905,486}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;That is a lot.&lt;/p&gt;
&lt;h3 id="in-space"&gt;In space&lt;/h3&gt;
&lt;p&gt;It's a vast space of possibilities, and Beethoven's four note groupings are in there somewhere, but where? Where, for example, is Cello E4, Viola F4, Second Violin G♯4, First Violin A4? An arrangement of notes played by specific instruments which from now on I will refer to as The Voicing.&lt;/p&gt;
&lt;p&gt;It might seem like a nonsense question, but at least it can be answered, and one answer is this: we can think of each instrument as a dimension in space and plot The Voicing within it. Instead of the familiar three dimensions we think of moving about in day to day life, left-right, up-down and forward-backward, we have four dimensions: the &lt;strong&gt;cello&lt;/strong&gt;, the &lt;strong&gt;viola&lt;/strong&gt;, the &lt;strong&gt;second violin&lt;/strong&gt; and the &lt;strong&gt;first violin&lt;/strong&gt;. Because each instrument is constrained in the range of notes it can play we're really talking about some four dimensional shape. We can imagine plotting coordinates within this shape by measuring how far along each dimension a point extends. Starting at 0, being the lowest note that instrument can play, and counting each subsequent note, ending at the highest. I appreciate that counting from 0 might seem odd, but I've spent too much time with computers and it does make some of the following a little simpler.&lt;/p&gt;
&lt;p&gt;So, where is The Voicing within that shape? It's at the position: &lt;strong&gt;Cello&lt;/strong&gt; = 28, &lt;strong&gt;Viola&lt;/strong&gt; = 17, &lt;strong&gt;Second Violin&lt;/strong&gt; = 13 and &lt;strong&gt;First Violin&lt;/strong&gt; = 14. And where is that exactly? Well, I can't show you. Unlike the examples of coin tosses, dice rolls or DNA codons, I can't create a visualisation of this space of possibilities. I've never seen any four dimensional things, and I lack the imagination to even try to picture them. What I can do though is change the four dimensional space of possibilities into a different shape and show you that instead.&lt;/p&gt;
&lt;p&gt;To demonstrate, here's a two dimensional space of possibilities. Perhaps imagine it's a duet of tiny, five tone, glockenspiels.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5-space-1-small.webp" loading="lazy" width="630" height="280" alt="Colourful marbles arranged on a five by five grid. The first row is blue, the second row is green, the third row is yellow, the fourth row is orange and the fifth row is red." /&gt;&lt;/p&gt;
&lt;p&gt;Because this shape doesn't go on forever and I'm not planning on breaking any marbles into pieces two dimensions can be flattened into one by placing each row end to end. A rectangle can become a line.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5-space-2-small.webp" loading="lazy" width="630" height="280" alt="Colourful marbles, arranged on a mostly five by five grid. The first row is ten marbles wide, the second row is missing, it was moved from to the end of the first row." /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5-space-3-small.webp" loading="lazy" width="630" height="280" alt="Colourful marbles, arranged on a mostly five by five grid. The first row is fifteen marbles wide, the second and third rows are missing, they have been moved to the first row." /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5-space-4-small.webp" loading="lazy" width="630" height="280" alt="Colourful marbles, arranged on a mostly five by five grid. The first row is twenty marbles wide, the second, third and fourth rows are missing, they have been moved to the first row." /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5-space-5-small.webp" loading="lazy" width="630" height="280" alt="Colourful marbles, arranged in a row of twenty five." /&gt;&lt;/p&gt;
&lt;p&gt;With this scheme the second yellow marble moves from column 1 row 2 to column 11 row 0. Each marble is being counted, left to right along each row.&lt;/p&gt;
&lt;ol class="list-none grid grid-cols-3 grid-rows-4 gap-3"&gt;
  &lt;li&gt;

&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5-counting-00-small.webp" loading="lazy" width="210" height="158" alt="Colourful marbles arranged on a five by five grid. There&amp;#39;s a single blue marble in the first row and in the first column. There is no second row. In the third row the first two columns are empty, the remaining columns are occupied by white marbles. The fourth and fifth rows are filled with white marbles." /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;

&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5-counting-01-small.webp" loading="lazy" width="210" height="158" alt="Colourful marbles arranged on a five by five grid. There are two blue marbles in the first row, in the first and second columns. There is no second row. In the third row the first two columns are empty, the remaining columns are occupied by white marbles. The fourth and fifth rows are filled with white marbles." /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;

&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5-counting-02-small.webp" loading="lazy" width="210" height="158" alt="Colourful marbles arranged on a five by five grid. There are three blue marbles in the first row. There is no second row. In the third row the first two columns are empty, the remaining columns are occupied by white marbles. The fourth and fifth rows are filled with white marbles." /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;

&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5-counting-03-small.webp" loading="lazy" width="210" height="158" alt="Colourful marbles arranged on a five by five grid. There are four blue marbles in the first row. There is no second row. In the third row the first two columns are empty, the remaining columns are occupied by white marbles. The fourth and fifth rows are filled with white marbles." /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;

&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5-counting-04-small.webp" loading="lazy" width="210" height="158" alt="Colourful marbles arranged on a five by five grid. The first row is filled with blue marbles. There is no second row. In the third row the first two columns are empty, the remaining columns are occupied by white marbles. The fourth and fifth rows are filled with white marbles." /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;

&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5-counting-05-small.webp" loading="lazy" width="210" height="158" alt="Colourful marbles arranged on a five by five grid. The first row is filled with blue marbles. There is a single green marble in the second row. In the third row the first two columns are empty, the remaining columns are occupied by white marbles. The fourth and fifth rows are filled with white marbles." /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;

&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5-counting-06-small.webp" loading="lazy" width="210" height="158" alt="Colourful marbles arranged on a five by five grid. The first row is filled with blue marbles. There are two green marbles in the second row. In the third row the first two columns are empty, the remaining columns are occupied by white marbles. The fourth and fifth rows are filled with white marbles." /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;

&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5-counting-07-small.webp" loading="lazy" width="210" height="158" alt="Colourful marbles arranged on a five by five grid. The first row is filled with blue marbles. There are three green marbles in the second row. In the third row the first two columns are empty, the remaining columns are occupied by white marbles. The fourth and fifth rows are filled with white marbles." /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;

&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5-counting-08-small.webp" loading="lazy" width="210" height="158" alt="Colourful marbles arranged on a five by five grid. The first row is filled with blue marbles. There are four green marbles in the second row. In the third row the first two columns are empty, the remaining columns are occupied by white marbles. The fourth and fifth rows are filled with white marbles." /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;

&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5-counting-09-small.webp" loading="lazy" width="210" height="158" alt="Colourful marbles arranged on a five by five grid. The first row is filled with blue marbles. The second row is filled with green marbles. In the third row the first two columns are empty, the remaining columns are occupied by white marbles. The fourth and fifth rows are filled with white marbles." /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;

&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5-counting-10-small.webp" loading="lazy" width="210" height="158" alt="Colourful marbles arranged on a five by five grid. The first row is filled with blue marbles. The second row is filled with green marbles. In the third row the first column has a yellow marble in it, the second is empty, the remaining columns are occupied by white marbles. The fourth and fifth rows are filled with white marbles." /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;

&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5-counting-11-small.webp" loading="lazy" width="210" height="158" alt="Colourful marbles arranged on a five by five grid. The first row is filled with blue marbles. The second row is filled with green marbles. In the third row the first two columns have yellow marbles in them, the remaining columns are occupied by white marbles. The fourth and fifth rows are filled with white marbles." /&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In general, columns are counted &lt;em&gt;row number&lt;/em&gt; times (in this case 2), then &lt;em&gt;column number&lt;/em&gt; is added.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mtext mathvariant="italic"&gt;𝑁𝑜. 𝑜𝑓 𝑐𝑜𝑙𝑢𝑚𝑛𝑠&lt;/mtext&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mtext mathvariant="italic"&gt;𝑅𝑜𝑤 𝑛𝑢𝑚𝑏𝑒𝑟&lt;/mtext&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mtext mathvariant="italic"&gt;𝐶𝑜𝑙𝑢𝑚𝑛 𝑛𝑢𝑚𝑏𝑒𝑟&lt;/mtext&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;
\mathit{\text{No. of columns}} \times \mathit{\text{Row number}} + \mathit{\text{Column number}}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;With the addition of another imaginary glockenspiel the same process can be demonstrated in three dimensions, this time labeled &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;, &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;, and &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;z&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5x5-space-1-small-with-axes.webp" loading="lazy" width="630" height="473" alt="Colourful magnetic blocks, arranged in a cube, five wide, five high and five deep. There are arrows labelling the width, height, and depth as &amp;#39;x&amp;#39;, &amp;#39;y&amp;#39; and &amp;#39;z&amp;#39; respectively." /&gt;&lt;/p&gt;
&lt;p&gt;This three dimensional shape can become a two dimensional shape by unstacking each layer and placing them end to end.&lt;/p&gt;
&lt;div class="grid gap-3 grid-rows-2 grid-cols-2"&gt;

&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5x5-space-1-small.webp" loading="lazy" width="630" height="473" alt="Colourful magnetic blocks, arranged in a cube, five wide, five high and five deep. Each layer has a different colour of magnetic block. Top to bottom it goes: blue, green, yellow, red and black." /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5x5-space-2-small.webp" loading="lazy" width="630" height="473" alt="Colourful magnetic blocks, arranged in a rectangular prism, five wide, five high and four deep. Each layer has a different colour of magnetic block. Top to bottom it goes: blue, green, yellow, and red. A black five by five square of blocks sits just behind." /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5x5-space-3-small.webp" loading="lazy" width="630" height="473" alt="Colourful magnetic blocks, arranged in a rectangular prism, five wide, five high and three deep. Each layer has a different colour of magnetic block. Top to bottom it goes: blue, green and yellow. Two five by five squares of blocks sit just behind, one red and one black." /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5x5-space-4-small.webp" loading="lazy" width="630" height="473" alt="Colourful magnetic blocks, arranged in a rectangular prism, five wide, five high and two deep. Each layer has a different colour of magnetic block. The top is blue, and the bottom is green. Three five by five squares of blocks sit just behind, one yellow, one red and one black." /&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5x5-space-5-small.webp" loading="lazy" width="630" height="473" alt="Five five-by-five squares of magnetic blocks laid out in a line. Each has a different colour of block: blue, green, yellow, red and black." /&gt;&lt;/p&gt;
&lt;p&gt;The yellow cube that begins at position &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;x = 1, y = 2, z = 1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; ends up at position &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;11&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;x = 1, y = 0, z = 11&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5x5-space-open-with-arrow-small.webp" loading="lazy" width="630" height="473" alt="Colourful magnetic blocks, arranged in a cube, five wide, five high and five deep. The top two layers have been removed to reveal the yellow layer, an arrow is pointing to the block one in from the side and the top." /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5x5-space-5-with-arrow-small.webp" loading="lazy" width="630" height="473" alt="Five five-by-five squares of magnetic blocks laid out in a line. Each has a different colour of block: blue, green, yellow, red and black. An arrow is pointing to the block one in from the side and one in from the top within the yellow square of blocks." /&gt;&lt;/p&gt;
&lt;p&gt;Because the &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; dimension will now always be 0 we can ignore it which allows us to say: position &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(1, 2, 1)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; has moved to &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;11&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(1, 11)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;. More generally we could say: any position &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(x, y, z)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; has moved to position &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;Z&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;×&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;(x, |Z| \times y + z)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;. Where &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;Z&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;|Z|&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; means: the total number of possible values of &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;z&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;. The &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;z&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; dimension has now absorbed the &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;y&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; dimension.&lt;/p&gt;
&lt;p&gt;As with turning two dimensions into one, this counts positions. However here they're not all counted in one go. There's a count per &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;x&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; value.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/5x5x5-counting.svg" loading="lazy" width="1204" height="942" alt="A three dimensional five by five by five grid of rectangles, forming roughly a cube. Each rectangle is labelled with the two dimensional position they&amp;#39;d have if each layer were unstacked and placed end to end. The rectangles labelled (1, 0) through to (1, 11) are highlighted." /&gt;&lt;/p&gt;
&lt;p&gt;Unstacking the four dimensional shape containing all the string quartet voicings by combining the two violins into one dimension yields a three dimensional rectangular prism of these measurements: &lt;strong&gt;Cello&lt;/strong&gt; = 46, &lt;strong&gt;Viola&lt;/strong&gt; = 41, &lt;strong&gt;Violins&lt;/strong&gt; = 2,601.&lt;/p&gt;
&lt;p&gt;Allotting one cubic millimetre to each voicing yields something very roughly the size and shape of one of these standard cuts of timber. (If you look closely you might see a magpie for scale.)&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/45x90x2400-space.webp" loading="lazy" width="630" height="473" alt="A piece of timber laid out on a bitumen road. It&amp;#39;s 45mm by 90mm by 2400mm." /&gt;&lt;/p&gt;
&lt;p&gt;The profile is wrong, it should be nearly square, and it's too short by about 200 millimeters. But it still helps me to look at it and think about what it tells me about the space of possibilities we've been talking about.&lt;/p&gt;
&lt;p&gt;Firstly though, what it doesn't tell me is much about The Voicing. It can be found at &lt;strong&gt;Cello&lt;/strong&gt; = 28, &lt;strong&gt;Viola&lt;/strong&gt; = 17, &lt;strong&gt;Violins&lt;/strong&gt; = 677. Which is about where I've placed this marble, except it'd be embedded within the timber, roughly in the centre of the cross-section.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/images/spaces/45x90x2400-space-with-arrow.webp" loading="lazy" width="630" height="473" alt="A piece of timber laid out on a bitumen road. It&amp;#39;s 45mm by 90mm by 2400mm. There&amp;#39;s a white arrow pointing to a white marble resting on top. The marble is about one quarter to one third along the length." /&gt;&lt;/p&gt;
&lt;p&gt;I just don't find it all that enlightening to see. What I do find enlightening is imagining what happens to this piece of timber if we continue this process of unstacking dimensions.&lt;/p&gt;
&lt;p&gt;If a three dimensional set of possibilities can be unstacked into a two dimensional set, then we can imagine slicing this piece of timber into one millimeter thin layers and laying them out side by side. If the timber were the right length to begin with we'd have a roughly 2.6 by 1.8 metre rectangular sheet. Which doesn't seem all that surprising to me.&lt;/p&gt;
&lt;p&gt;Now, if a two dimensional set of possibilities can be unstacked into a one dimensional set, then we can imagine slicing this sheet into one millimetre by one millimetre pieces of dowel and laying them out end to end. If we did so we'd have a nearly five kilometre long line.&lt;/p&gt;
&lt;p&gt;It doesn't change the numbers, but it does change my perspective. It reminds me of how unintuitive it is that each tiny cell in our bodies contains chromosomes that, if unwound, would be two metres in length.&lt;/p&gt;
&lt;h3 id="in-time"&gt;In time&lt;/h3&gt;
&lt;p&gt;Laying everything out in a line like this is, in a sense, providing a way to visit every possibility in a space. If it were to be stacked back up again we'd have a path which snakes (in this case a very orderly, if but zig-zaggy, snake) through the whole four dimensional shape. Unstacking the whole thing into a line has laid every voicing out in a sequence.&lt;/p&gt;
&lt;p&gt;Having this sequence enables us to turn any four note voicing into a single, unique, number between 0 and 4,905,485. For example The Voicing, which, in the space of all string quartet voicings, has the coordinates &lt;strong&gt;Cello&lt;/strong&gt; = 28, &lt;strong&gt;Viola&lt;/strong&gt; = 17, &lt;strong&gt;Second Violin&lt;/strong&gt; = 13, &lt;strong&gt;First Violin&lt;/strong&gt; = 14, becomes 1,371,932.&lt;/p&gt;
&lt;p&gt;By referring to the scheme for unstacking shapes explored above it's possible to describe a method for finding the number (&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;) of any voicing made up of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A note played by the first violin (&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;annotation encoding="application/x-tex"&gt;v_1&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;), from within the set of notes it can play (&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;V&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;)&lt;/li&gt;
&lt;li&gt;A note played by the second violin (&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;annotation encoding="application/x-tex"&gt;v_2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;), from within the set of notes it can play (&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;V&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;)&lt;/li&gt;
&lt;li&gt;A note played by the viola (&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;w&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;), from within the set of notes it can play (&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;W&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;)&lt;a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A note played by the cello (&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;c&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;), from within the set of notes it can play (&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;C&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each dimension can be unstacked just as the rows of the five by five grid of marbles were laid out end to end.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding="application/x-tex"&gt;
\begin{align*}
&amp;amp; (v_1, v_2, w, c) \\
&amp;amp; (v_1 \times |V| + v_2, w, c) \\
&amp;amp; ((v_1 \times |V| + v_2) \times |W| + w, c) \\
n =&amp;amp; ((v_1 \times |V| + v_2) \times |W| + w) \times |C| + c
\end{align*}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;Where putting '&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;annotation encoding="application/x-tex"&gt;|&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;' either side of the name for a set of things means "the total number of things in the set." For example &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;|C|&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; means: the total number of notes a cello can play.&lt;/p&gt;
&lt;p&gt;This allows for counting through all the voicings and it bears a resemblance to how we usually count things. A number such as 1,825 is usually thought of as "5 ones, plus 2 tens, plus 8 hundreds, plus 1 thousand." However it could also be stated as follows.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mtext mathvariant="normal"&gt;1,825&lt;/mtext&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;8&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;5&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;8&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;5&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;18&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;5&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;180&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;5&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;182&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;5&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;1,820&lt;/mtext&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;5&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;1,825&lt;/mtext&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding="application/x-tex"&gt;
\begin{align*}
\text{1,825}
&amp;amp;= ((1 \times 10 + 8) \times 10 + 2) \times 10 + 5 \\
&amp;amp;= ((10 + 8) \times 10 + 2) \times 10 + 5 \\
&amp;amp;= (18 \times 10 + 2) \times 10 + 5 \\
&amp;amp;= (180 + 2) \times 10 + 5 \\
&amp;amp;= 182 \times 10 + 5 \\
&amp;amp;= \text{1,820} + 5 \\
&amp;amp;= \text{1,825}
\end{align*}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;Which to me looks like successively pushing the ones place to the left, by multiplying by ten, to make room for the next ones value.&lt;/p&gt;
&lt;p&gt;This suggests there should be a method for finding The Voicing's number which more closely matches how we talk about everyday numbers, and indeed there is, though it might not look the same at first flush.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;×&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;×&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;×&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;14&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;51&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;41&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;46&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;13&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;41&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;46&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;17&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;46&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;28&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;1,371,932&lt;/mtext&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding="application/x-tex"&gt;
\begin{align*}
n &amp;amp;= v_1 \times (|V| \times |W| \times |C|) + v_2 \times (|W| \times |C|) + w \times |C| + c \\
&amp;amp;= 14 \times (51 \times 41 \times 46) + 13 \times (41 \times 46) + 17 \times 46 + 28 \\
&amp;amp;= \text{1,371,932}
\end{align*}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;It's possible to express the number 1,825 equivalently.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mtext mathvariant="normal"&gt;1,825&lt;/mtext&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;8&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;10&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;5&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;1,825&lt;/mtext&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding="application/x-tex"&gt;
\begin{align*}
\text{1,825}
&amp;amp;= 1 \times (10 \times 10 \times 10) + 8 \times (10 \times 10) + 2 \times 10 + 5 \\
&amp;amp;= \text{1,825}
\end{align*}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;Which suggests that these two expressions are equivalent in general.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;×&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;×&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;×&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;×&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding="application/x-tex"&gt;
\begin{align*}
n
&amp;amp;= ((v_1 \times |V| + v_2) \times |W| + w) \times |C| + c \\
&amp;amp;= (v_1 \times |V| + v_2) \times (|W| \times |C|) + v \times |C| + c \\
&amp;amp;= v_1 \times (|V| \times |W| \times |C|) + v_2 \times (|W| \times |C|) + v \times |C| + c
\end{align*}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;What has been arrived at here looks to me like a sort of number system&lt;a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;. One that counts through all the voicings a string quartet can play, just as we might count anything else. What makes this a little more interesting is that it doesn't &lt;em&gt;just&lt;/em&gt; count, it &lt;em&gt;encodes&lt;/em&gt;. Unlike when counting many things in day to day life, counting these voicings using the method described allows for recovering the original four parts from the single number assigned to them when counted.&lt;/p&gt;
&lt;p&gt;To perform this recovery, to decode what was encoded, we need to undo each multiplication and addition which converted the note positions into their corresponding number. To undo one step of multiplication and addition we can use what's called &lt;a href="https://en.wikipedia.org/wiki/Euclidean_division"&gt;&lt;em&gt;Euclidean division&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you ever did long division in school, where you figured out how many times some number (the "divisor", &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;d&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;) fit into some other number (&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;) with some remainder (&lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;r&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;) left over, you've done Euclidean division. It's division where you end up with a whole number (the "quotient" &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;q&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;), and possibly some remainder; some amount smaller than the number you were dividing by.&lt;/p&gt;
&lt;p&gt;Let's say we begin with some number &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; which we know to be made by multiplying some number &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;q&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; by some number &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;d&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; and then adding some number &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;r&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; (which we know is less than &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;d&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;) to that.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;
n = q \times d + r
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;This is an abstract form of the numbers we're aiming to decode.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding="application/x-tex"&gt;
\begin{align*}
n &amp;amp;= ((v_1 \times |V| + v_2) \times |W| + w) \times |C| + c \\
q &amp;amp;= ((v_1 \times |V| + v_2) \times |W| + w) \\
d &amp;amp;= |C| \\
r &amp;amp;= c \\
n &amp;amp;= q \times d + r
\end{align*}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;Which can be shuffled around to produce &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;q&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mfrac&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;/mrow&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mfrac&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;
q = \frac{n - r}{d}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;And also &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;r&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;
r = n - q \times d
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;There are &lt;a href="https://en.wikipedia.org/wiki/Modulo#Variants_of_the_definition"&gt;several methods to figure out &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;q&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/a&gt;, one is to perform something called &lt;em&gt;floored division&lt;/em&gt; which is regular division but the result is rounded down to the nearest whole number. It's written like this.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;⌊&lt;/mo&gt;&lt;mfrac&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mfrac&gt;&lt;mo stretchy="false" form="postfix"&gt;⌋&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;
q = \lfloor \frac{n}{d} \rfloor
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;Floored division discards the remainder, but it can be recovered with one of the above shufflings.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;
r = n - q \times d
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;This provides us with a procedure for decoding a number step by step, which goes something like this.&lt;/p&gt;
&lt;ol type="1"&gt;
&lt;li&gt;&lt;p&gt;Begin with the number we want to decode.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;51&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;41&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mo stretchy="false" form="postfix"&gt;)&lt;/mo&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;46&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;1,371,932&lt;/mtext&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding="application/x-tex"&gt;
\begin{align*}
n
&amp;amp;= ((v_1 \times |V| + v_2) \times |W| + w) \times |C| + c \\
&amp;amp;= ((v_1 \times 51 + v_2) \times 41 + w) \times 46 + c \\
&amp;amp;= \text{1,371,932}
\end{align*}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then, find the value for &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;msub&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/msub&gt;&lt;annotation encoding="application/x-tex"&gt;q_c&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;, the first quotient, by using floored division with &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;|C|&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; as the denominator.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;msub&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/msub&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;⌊&lt;/mo&gt;&lt;mfrac&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mo stretchy="false" form="postfix"&gt;⌋&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;⌊&lt;/mo&gt;&lt;mfrac&gt;&lt;mtext mathvariant="normal"&gt;1,371,932&lt;/mtext&gt;&lt;mn&gt;46&lt;/mn&gt;&lt;/mfrac&gt;&lt;mo stretchy="false" form="postfix"&gt;⌋&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;29,824&lt;/mtext&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding="application/x-tex"&gt;
\begin{align*}
q_c
&amp;amp;= \lfloor \frac{n}{|C|} \rfloor \\
&amp;amp;= \lfloor \frac{\text{1,371,932}}{46} \rfloor \\
&amp;amp;= \text{29,824} \\
\end{align*}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;Which can be used to find &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;c&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;, the note the cello plays, by using the shuffling which gave us &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;r&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; above.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;×&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/msub&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;1,371,932&lt;/mtext&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;46&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;29,824&lt;/mtext&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;28&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding="application/x-tex"&gt;
\begin{align*}
c &amp;amp;= n - |C| \times q_c \\
&amp;amp;= \text{1,371,932} - 46 \times \text{29,824} \\
&amp;amp;= 28
\end{align*}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;The first layer of addition and multiplication has now been peeled off.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mtext mathvariant="normal"&gt;1,371,932&lt;/mtext&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;×&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/msub&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;28&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;46&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;29,824&lt;/mtext&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding="application/x-tex"&gt;
\begin{align*}
\text{1,371,932}
&amp;amp;= c + |C| \times q_c \\
&amp;amp;= 28 + 46 \times \text{29,824}
\end{align*}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The process is then repeated beginning from &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;msub&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/msub&gt;&lt;annotation encoding="application/x-tex"&gt;q_c&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; instead of &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;n&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; to find &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;msub&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;/msub&gt;&lt;annotation encoding="application/x-tex"&gt;q_w&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;, the second quotient.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;msub&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;/msub&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;⌊&lt;/mo&gt;&lt;mfrac&gt;&lt;msub&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/msub&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mo stretchy="false" form="postfix"&gt;⌋&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;⌊&lt;/mo&gt;&lt;mfrac&gt;&lt;mtext mathvariant="normal"&gt;29,824&lt;/mtext&gt;&lt;mn&gt;41&lt;/mn&gt;&lt;/mfrac&gt;&lt;mo stretchy="false" form="postfix"&gt;⌋&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;727&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding="application/x-tex"&gt;
\begin{align*}
q_w
&amp;amp;= \lfloor \frac{q_c}{|W|} \rfloor \\
&amp;amp;= \lfloor \frac{\text{29,824}}{41} \rfloor \\
&amp;amp;= 727 \\
\end{align*}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;Which can be used to find &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;annotation encoding="application/x-tex"&gt;w&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;, the note the viola plays.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/msub&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;×&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;/msub&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mtext mathvariant="normal"&gt;29,824&lt;/mtext&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;41&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;727&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;17&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding="application/x-tex"&gt;
\begin{align*}
w &amp;amp;= q_c - |W| \times q_w \\
&amp;amp;= \text{29,824} - 41 \times 727 \\
&amp;amp;= 17
\end{align*}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We repeat the process once more to find &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;msub&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;/msub&gt;&lt;annotation encoding="application/x-tex"&gt;q_{v_2}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; in order to find &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;annotation encoding="application/x-tex"&gt;v_2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;, the note the second violin plays.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;msub&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;/msub&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;⌊&lt;/mo&gt;&lt;mfrac&gt;&lt;msub&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;/msub&gt;&lt;mrow&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;/mrow&gt;&lt;/mfrac&gt;&lt;mo stretchy="false" form="postfix"&gt;⌋&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;⌊&lt;/mo&gt;&lt;mfrac&gt;&lt;mn&gt;727&lt;/mn&gt;&lt;mn&gt;51&lt;/mn&gt;&lt;/mfrac&gt;&lt;mo stretchy="false" form="postfix"&gt;⌋&lt;/mo&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;14&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;/msub&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mo stretchy="false" form="prefix"&gt;|&lt;/mo&gt;&lt;mi&gt;×&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;/msub&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;727&lt;/mn&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;51&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mn&gt;14&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;13&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding="application/x-tex"&gt;
\begin{align*}
q_{v_2}
&amp;amp;= \lfloor \frac{q_w}{|V|} \rfloor \\
&amp;amp;= \lfloor \frac{727}{51} \rfloor \\
&amp;amp;= 14 \\
v_2 &amp;amp;= q_w - |V| \times q_{v_2} \\
&amp;amp;= 727 - 51 \times 14 \\
&amp;amp;= 13 \\
\end{align*}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;By finding &lt;math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;msub&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;/msub&gt;&lt;annotation encoding="application/x-tex"&gt;q_{v_2}&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt; we've already found the note the first violin plays.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;q&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;/msub&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;14&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding="application/x-tex"&gt;
\begin{align*}
v_1
&amp;amp;= q_{v_2} \\
&amp;amp;= 14
\end{align*}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With that we're done.&lt;/p&gt;
&lt;figure class="wide"&gt;

&lt;p&gt;&lt;math display="block" xmlns="http://www.w3.org/1998/Math/MathML"&gt;&lt;semantics&gt;&lt;mtable&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;28&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;17&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/msub&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;13&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;mtr&gt;&lt;mtd columnalign="right" style="text-align: right; padding-right: 0"&gt;&lt;msub&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/msub&gt;&lt;/mtd&gt;&lt;mtd columnalign="left" style="text-align: left; padding-left: 0"&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;14&lt;/mn&gt;&lt;/mtd&gt;&lt;/mtr&gt;&lt;/mtable&gt;&lt;annotation encoding="application/x-tex"&gt;
\begin{align*}
c &amp;amp;= 28 \\
w &amp;amp;= 17 \\
v_2 &amp;amp;= 13 \\
v_1 &amp;amp;= 14
\end{align*}
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;With this ability to decode ordinary numbers into string quartet voicings it's possible to enumerate all the possible voicings just by counting from 0 to 4,905,485. Doing so sounds like this.&lt;/p&gt;
&lt;figure id="string-quartet-linear-initial"&gt;
  &lt;audio class="w-full" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/audio/string-quartet-linear.ogg" controls&gt;&lt;/audio&gt;

  &lt;figcaption&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; without JavaScript you'll get about a six minute sample.&lt;/p&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;template id="string-quartet-linear"&gt;
&lt;figure&gt;
  &lt;button id="string-quartet-linear-control"&gt;
    Play
  &lt;/button&gt;

  &lt;figcaption&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; if reading on a mobile device you may need to disable silent mode to hear this.&lt;/p&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/template&gt;

&lt;p&gt;At this speed, ten notes per second, it would take you more than a day and a half of uninterrupted listening to reach The Voicing. I like it. I think it sounds very meditative. Very &lt;em&gt;swoopey&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Turning voicings into numbers has also afforded us the opportunity to be disorderly, rather than orderly, snakes. We can use a non-repeating random number generator&lt;a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"&gt;&lt;sup&gt;4&lt;/sup&gt;&lt;/a&gt; to erratically jump around, but still visit each and every voicing no more than once. I'm not sure if there's any telling when you'll hit The Voicing, but it's in there. To hear them all, to make sure you've heard &lt;em&gt;the one&lt;/em&gt;, would take over five days and sixteen hours.&lt;/p&gt;
&lt;figure id="string-quartet-random-initial"&gt;
  &lt;audio class="w-full" src="https://bradparker.id.au/content/posts/crossing-paths-with-descartes/assets/audio/string-quartet-random.ogg" controls&gt;&lt;/audio&gt;

  &lt;figcaption&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; without JavaScript you'll get about a six minute sample.&lt;/p&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;template id="string-quartet-random"&gt;
&lt;figure&gt;
  &lt;button id="string-quartet-random-control"&gt;
    Play
  &lt;/button&gt;

  &lt;figcaption&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; if reading on a mobile device you may need to disable silent mode to hear this.&lt;/p&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/template&gt;

&lt;p&gt;If I listen for long enough I can talk myself into hearing bass lines and melodies. I think it's sort of fun. &lt;em&gt;Bleep, bloop&lt;/em&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;And now here we are at the end, having found some sort of path through an overwhelming space of possibilities. Not only that, along the way we've been able to visit an Australian literary classic, confusing dice games from Early modern Britain, attempts to explain the bewildering complexities of DNA, and some really banging Beethoven. I hope you enjoyed walking it as much as I enjoyed finding it.&lt;/p&gt;
&lt;p&gt;Thank you for your time.&lt;/p&gt;
&lt;script type="module" async src="/content/posts/crossing-paths-with-descartes/assets/javascript/string-quartet-voicings.js"&gt;&lt;/script&gt;

&lt;section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn1"&gt;&lt;p&gt;&lt;a href="https://www.chemistryviews.org/details/ezine/11312121/Deciphering_the_Genetic_Code_The_Most_Beautiful_False_Theory_in_Biochemistry__Pa/"&gt;Deciphering the Genetic Code: The Most Beautiful False Theory in Biochemistry – Part 1&lt;/a&gt;&lt;a href="#fnref1" class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id="fn2"&gt;&lt;p&gt;I'm sorry, there's already a 'v' and 'w' is just the next letter in the alphabet. If it helps pronounce it "wiola" in your head. Or out loud. Whatever you're up for.&lt;a href="#fnref2" class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id="fn3"&gt;&lt;p&gt;A &lt;a href="https://en.wikipedia.org/wiki/Mixed_radix"&gt;mixed radix number system&lt;/a&gt;.&lt;a href="#fnref3" class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id="fn4"&gt;&lt;p&gt;In this case a &lt;a href="https://en.wikipedia.org/wiki/Lehmer_random_number_generator"&gt;Lehmer random number generator&lt;/a&gt;.&lt;a href="#fnref4" class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description><author>hi@bradparker.id.au (Brad Parker)</author><guid>https://bradparker.id.au/posts/crossing-paths-with-descartes</guid><pubDate>Sat, 31 May 2025 00:00:00 UTC</pubDate></item><item><title>The danger of using models as metaphors</title><link>https://bradparker.id.au/posts/the-danger-of-using-models-as-metaphors</link><description>&lt;p&gt;&lt;img src="https://bradparker.id.au/assets/images/tangram-small.webp" alt="A tangram that&amp;#39;s not quite put together righ" /&gt;&lt;/p&gt;
&lt;p&gt;I read Elinor Ostrom's book &lt;em&gt;Governing the commons&lt;/em&gt; on a whim after seeing it mentioned in a discussion about open source software communities. I believe this isn't an uncommon way for software folk to become aware of this book. Of the many fascinating insights Ostrom presents there are a few that have really stuck with me. My personally sticky insights aren't really related to the core argument, it's all well out of my wheel house after all. My ears most pricked up when Ostrom wrote about the social responsibilities of scientists and the social impact of social research.&lt;/p&gt;
&lt;p&gt;Towards the start of the book in a subsection of the first chapter entitled &lt;em&gt;The metaphorical use of models&lt;/em&gt; Ostrom writes.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When models are used as metaphors, an author usually points to the similarity between one or two variables in a natural setting and one or two variables in a model. If calling attention to similarities is all that is intended by the metaphor, it serves the usual purpose of rapidly conveying information in graphic form. These three models have frequently been used metaphorically, however, for another purpose. The similarity between the many individuals jointly using a resource in a natural setting and the many individuals jointly producing a suboptimal result in the model has been used to convey a sense that further similarities are present.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Later she provides an example to illustrate how bad things can get when models become metaphors and are then used to create policy.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Relying on metaphors as the foundation for policy advice can lead to results substantially different from those presumed to be likely. Nationalizing the ownership of forests in Third World countries, for example, has been advocated on the grounds that local villagers cannot manage forests as to sustain their productivity and their value in reducing soil erosion. In countries where small villages had owned and regulated their local communal forests for generations, nationalization meant expropriation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The three models being referred to in the first quotation are prior attempts to explain the dynamics of common resource governance, but we needn't go into any more detail than that. What I seem to have taken away from this is a broader point about the danger of attempting to fit insights onto a domain over which they were never intended to apply. It's possible I'm zooming out too far, for example one of the model-cum-metaphors Ostrom is referring to above is the &lt;a href="https://en.wikipedia.org/wiki/Prisoner&amp;#39;s_dilemma"&gt;prisoner's dilemma&lt;/a&gt; which has a precise definition, but this starts to feel close to an impulse in my field. We software developers love a structuring metaphor, such as &lt;a href="https://en.wikipedia.org/wiki/Pattern_language#Application_domains"&gt;architecture&lt;/a&gt; or cellular biology&lt;a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;How do we know when we've inadvertently turned a model into a metaphor and misapplied it? When we've latched onto those couple of similar variables and missed all the dissimilar ones? Ostrom's suggestion is fairly simple to state: if your data contradicts the model you're trying to apply, either your data is wrong, the model is wrong, or the model doesn't fit your domain. This could perhaps be summarised, flippantly, as "do science." Indeed her argument against the inevitability of &lt;a href="https://en.wikipedia.org/wiki/Tragedy_of_the_commons"&gt;the tragedy of the commons&lt;/a&gt; is that there are ample examples of self-organizing communities who share common resources without falling prey to the effect.&lt;/p&gt;
&lt;p&gt;I'm not exactly sure where all this leads me. Wanting to apply the scientific method to find the boundaries of the myriad structuring metaphors we use to think and communicate sure sounds exhausting; for all involved. But on the other hand we run the risk of accidentally limiting ourselves, or causing real harm, by labouring under a seemingly well justified but ill-fitting model. I genuinely have no idea what I'm supposed to do with these thoughts, but at least now I've shared my unease.&lt;/p&gt;
&lt;section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn1"&gt;&lt;blockquote&gt;
&lt;p&gt;And then there is the idea of simulation itself, where the whole idea of “data” and “state” starts to get eclipsed by “competent objects” that can cooperate, much more like biological cells and human societies can.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;From Alan Kay answering the question &lt;a href="https://www.quora.com/What-thought-process-would-lead-one-to-invent-object-oriented-programming/answer/Alan-Kay-11"&gt;'What thought process would lead one to invent object-oriented programming?' on Quora&lt;/a&gt;&lt;a href="#fnref1" class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description><author>hi@bradparker.id.au (Brad Parker)</author><guid>https://bradparker.id.au/posts/the-danger-of-using-models-as-metaphors</guid><pubDate>Thu, 21 Mar 2024 00:00:00 UTC</pubDate></item><item><title>Using Nix to deploy a Haskell web app to Heroku</title><link>https://bradparker.id.au/posts/using-nix-to-deploy-a-haskell-web-app-to-heroku</link><description>&lt;p&gt;Let's say we've written a web app in Haskell.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ curl http://localhost:8000/hello/World
Hello, World!

$ curl http://localhost:8000/hello/Haskell
Hello, Haskell!&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It sure would be nice if we could share it with other people. Let's deploy this wonderful thing to the &lt;em&gt;internet&lt;/em&gt; using Heroku.&lt;/p&gt;
&lt;h2 id="haskell-and-nix"&gt;Haskell and Nix&lt;/h2&gt;
&lt;p&gt;Thanks to the &lt;a href="https://nixos.org/nix/"&gt;Nix&lt;/a&gt; using Haskell community packaging up Haskell libraries and executables is very convenient.&lt;/p&gt;
&lt;p&gt;First, we'll make a directory for our project.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~ $ mkdir haskell-on-heroku
~ $ cd $_
~/haskell-on-heroku $&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we can ask Cabal to get us started with a scaffold.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/haskell-on-heroku $ nix run \
&amp;gt; nixpkgs.cabal-install \
&amp;gt; --command cabal init \
&amp;gt; --minimal \
&amp;gt; --cabal-version=2.4&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, we add a &lt;code&gt;default.nix&lt;/code&gt; which makes use of &lt;a href="https://github.com/NixOS/cabal2nix"&gt;&lt;code&gt;cabal2nix&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="nix"&gt;&lt;code&gt;{ haskellPackages ? (import &amp;lt;nixpkgs&amp;gt; {}).haskellPackages }:
  haskellPackages
    .callCabal2nix &amp;quot;haskell-on-heroku&amp;quot; ./. {}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And it's now ready to try out.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/haskell-on-heroku $ nix run \
&amp;gt; --file default.nix \
&amp;gt; env --command cabal new-run
# ...
Hello, Haskell!&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="an-amazing-web-application"&gt;An amazing web application&lt;/h2&gt;
&lt;p&gt;Our web server uses the nifty Haskell library &lt;a href="https://hackage.haskell.org/package/servant-server"&gt;Servant server&lt;/a&gt; so we'll need to add it and &lt;a href="https://hackage.haskell.org/package/warp"&gt;Warp&lt;/a&gt; as dependancies to &lt;code&gt;haskell-on-heroku.cabal&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="diff"&gt;&lt;code&gt; executable haskell-on-heroku
   main-is:             Main.hs
   build-depends:       base &amp;gt;=4.12 &amp;amp;&amp;amp; &amp;lt;4.13
+                     , servant-server
+                     , warp
   default-language:    Haskell2010&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We'll probably also need to put the implementation of our app in &lt;code&gt;Main.hs&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -Wall #-}

module Main where

import Control.Applicative ((&amp;lt;|&amp;gt;))
import Data.Proxy (Proxy (Proxy))
import Network.Wai.Handler.Warp (run)
import Servant
  ( (:&amp;gt;),
    Capture,
    Get,
    Handler,
    PlainText,
    serve,
  )
import System.Environment (getEnv)

type Greeter =
  &amp;quot;hello&amp;quot;
    :&amp;gt; Capture &amp;quot;name&amp;quot; String
    :&amp;gt; Get &amp;#39;[PlainText] String

greet :: String -&amp;gt; Handler String
greet name =
  pure $ &amp;quot;Hello, &amp;quot; &amp;lt;&amp;gt; name &amp;lt;&amp;gt; &amp;quot;!&amp;quot;

getPort :: IO Int
getPort =
  read &amp;lt;$&amp;gt; getEnv &amp;quot;PORT&amp;quot; &amp;lt;|&amp;gt; pure 8000

main :: IO ()
main = do
  port &amp;lt;- getPort
  run port $ serve (Proxy @Greeter) greet&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="a-deployable-image"&gt;A deployable image&lt;/h2&gt;
&lt;p&gt;The Docker-using members of the Nix community have made building docker-compatible images from Nix derivations very convenient.&lt;/p&gt;
&lt;p&gt;To try it out put the following in a file somewhere, say &lt;code&gt;~/hello.nix&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="nix"&gt;&lt;code&gt;let
  nixpkgs = import &amp;lt;nixpkgs&amp;gt; {};
in
  nixpkgs.dockerTools.buildImage {
    name = &amp;quot;hello-docker-nix&amp;quot;;
    tag = &amp;quot;latest&amp;quot;;
    contents = [ nixpkgs.hello ];
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then build it.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~ $ nix-build hello.nix&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Load the result.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~ $ docker load &amp;lt; result&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And finally run it.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~ $ docker run hello-docker-nix:latest hello
Hello, world!&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can put our package in a docker-compatible image in a similar fashion. Put the following in a file called &lt;code&gt;release.nix&lt;/code&gt; in your &lt;code&gt;haskell-on-heroku&lt;/code&gt; project directory.&lt;/p&gt;
&lt;pre class="nix"&gt;&lt;code&gt;{ nixpkgs ? import &amp;lt;nixpkgs&amp;gt; {} }:
let
  inherit (nixpkgs)
    callPackage
    dockerTools;

  package = callPackage ./. {};
in
  dockerTools.buildImage {
    name = &amp;quot;haskell-on-heroku&amp;quot;;
    tag = &amp;quot;latest&amp;quot;;
    contents = [
      package
    ];
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using the &lt;a href="https://github.com/NixOS/nixpkgs/blob/f9be656873dacbc5f51f0cea41e5c4ea0f358b2b/lib/customisation.nix#L117"&gt;&lt;code&gt;callPackage&lt;/code&gt;&lt;/a&gt; helper means we're less likely to accidentally end up with multiple versions of the Nix packages set. If that should happen, our app would still run fine, we just might end up with a bigger than necessary image.&lt;/p&gt;
&lt;p&gt;Let's try to build it and see how big it is.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/haskell-on-heroku $ nix-build release.nix
# ... build output
~/haskell-on-heroku $ docker load &amp;lt; result
3f5a871dd9ee: Loading layer   38.1MB/38.1MB
Loaded image: haskell-on-heroku:latest&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It's about 38.1 megabytes. That's not bad.&lt;/p&gt;
&lt;p&gt;Now, I'm going to save us some trouble and add &lt;a href="https://www.busybox.net/"&gt;&lt;code&gt;busybox&lt;/code&gt;&lt;/a&gt; to our image and also make sure it has a &lt;code&gt;Cmd&lt;/code&gt; configured.&lt;/p&gt;
&lt;pre class="diff"&gt;&lt;code&gt;diff --git a/release.nix b/release.nix
index 8fa2527..e14a534 100644
--- a/release.nix
+++ b/release.nix
@@ -3,7 +3,8 @@
 let
   inherit (nixpkgs)
     callPackage
-    dockerTools;
+    dockerTools
+    busybox;

   package = callPackage ./. {};
 in
@@ -12,5 +13,9 @@ in
     tag = &amp;quot;latest&amp;quot;;
     contents = [
       package
+      busybox
     ];
+    config = {
+      Cmd = [&amp;quot;/bin/${package.pname}&amp;quot;];
+    };
   }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We need to specify a command so Heroku knows how to run the container it'll create from our image. We need &lt;code&gt;busybox&lt;/code&gt; because Heroku will attempt to run our image's command with &lt;code&gt;bash -c&lt;/code&gt;. Images built with Nix's &lt;code&gt;dockerTools&lt;/code&gt; are so minimal they don't have &lt;code&gt;bash&lt;/code&gt; or even &lt;code&gt;/bin/sh&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="shipping-it"&gt;Shipping it&lt;/h2&gt;
&lt;p&gt;We now have everything we need. The last steps are to create a Heroku application, push our image to the Heroku registry and release it.&lt;/p&gt;
&lt;p&gt;First, assuming you already have a Heroku account, log into the Heroku command line.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/haskell-on-heroku $ nix run nixpkgs.heroku \
&amp;gt; --command heroku login&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then also login into the container registry.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/haskell-on-heroku $ nix run nixpkgs.heroku \
&amp;gt; --command heroku container:login&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next create an app.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/haskell-on-heroku $ nix run nixpkgs.heroku \
&amp;gt; --command heroku create&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Build our image.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/haskell-on-heroku $ nix-build release.nix&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Load it.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/haskell-on-heroku $ docker load &amp;lt; result&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tag it with our Heroku application's name and the process type we'd like to run it as.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/haskell-on-heroku $ docker tag \
&amp;gt; haskell-on-heroku \
&amp;gt; registry.heroku.com/infinite-anchorage-09330/web&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Push it to the registry.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/haskell-on-heroku $ docker push \
&amp;gt; registry.heroku.com/infinite-anchorage-09330/web&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And, lastly, release it.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/haskell-on-heroku $ nix run nixpkgs.heroku \
&amp;gt; heroku container:release -a infinite-anchorage-09330 web&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hey presto, our amazing application will now be accessible by the whole world. How cool.&lt;/p&gt;
&lt;p&gt;That does seem like a lot to remember, however, so we'd best pop as much of it as we can in a script. A script we might call &lt;code&gt;./deploy&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="bash"&gt;&lt;code&gt;#!/usr/bin/env bash

set -exu

app_name=$1
result=$(nix-build --no-out-link release.nix)

docker load &amp;lt; $result
docker tag haskell-on-heroku registry.heroku.com/$app_name/web
docker push registry.heroku.com/$app_name/web

nix run nixpkgs.heroku --command \
  heroku container:release -a $app_name web&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that building and deployment is a little more manageable.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/haskell-on-heroku $ ./deploy infinite-anchorage-09330&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;p&gt;I've prepared a &lt;a href="https://github.com/bradparker/haskell-on-heroku"&gt;repository&lt;/a&gt; of everything we've gone through here as a reference. With any luck it may help someone get their awesome Haskell application onto the mad expanse that is the internet.&lt;/p&gt;</description><author>hi@bradparker.id.au (Brad Parker)</author><guid>https://bradparker.com/content/posts/2020-02-16-using-nix-to-deploy-a-haskell-web-app-to-heroku.html</guid><pubDate>Sun, 16 Feb 2020 00:00:00 UTC</pubDate></item><item><title>Home sweet home</title><link>https://bradparker.id.au/posts/home-sweet-home</link><description>&lt;p&gt;The operations practice of defining &lt;a href="https://en.wikipedia.org/wiki/Infrastructure_as_code"&gt;&lt;em&gt;infrastructure as code&lt;/em&gt;&lt;/a&gt; has been popular for a while, and it’s for good reason. Lot's of strange and unexpected things can happen to our &lt;strong&gt;very important&lt;/strong&gt; web-servers, so being able to quickly build another one in a (close to) identical state can be very handy. Sadly, strange and unexpected things don't just happen to web-servers, they can happen our development machines too. And, heck, they're also pretty important.&lt;/p&gt;
&lt;p&gt;Like infrastructure, can we define some of the state of our laptops using code? I'm not sure, but I think so, at least I'll explain what I've tried.&lt;/p&gt;
&lt;h2 id="bootstrapping-scripts"&gt;Bootstrapping scripts&lt;/h2&gt;
&lt;p&gt;First, I used a &lt;a href="https://github.com/bradparker/dotfiles/tree/174c7e07dfa137152fdd941fe187635bb30994f6"&gt;lightly modified fork&lt;/a&gt; of &lt;a href="https://github.com/ryanb/dotfiles"&gt;Ryan Bates' dot files&lt;/a&gt; which bootstraps itself using a lovely &lt;a href="https://github.com/ryanb/dotfiles/blob/ca4d95179b62ceb1a760a2922953edd01d75c382/Rakefile#L5"&gt;rake task&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This went pretty well. I didn't have to bootstrap new machines too often, I didn't really have many preferences regarding command line tools, and I only had so many technology stacks to be setup for.&lt;/p&gt;
&lt;p&gt;The trouble came when I wanted to &lt;em&gt;change things&lt;/em&gt;. It wasn't always clear to me that the changes I made would be applied properly when I ran the script on a fresh machine. It always seemed that I missed something and had to do some manual work in addition to the rake task.&lt;/p&gt;
&lt;p&gt;The only part that I found to be very predicable were the files that were symlinked into my home directory. So after a while I cut the repository down to &lt;a href="https://github.com/bradparker/dotfiles/tree/28b4dcf7e27d61badef3a29f97d8faef6cc66d0f"&gt;nothing but those&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="staying-fresh"&gt;Staying fresh&lt;/h2&gt;
&lt;p&gt;A colleague introduced a few us at Everydayhero to &lt;a href="https://freshshell.com/"&gt;Fresh&lt;/a&gt;. It's great and with it I &lt;em&gt;just started&lt;/em&gt; to feel that my development machine had become easily recoverable. I could run &lt;code&gt;fresh&lt;/code&gt; on a minimally setup Macbook as well as on one I'd been working away on for months and the results were, more or less, the same.&lt;/p&gt;
&lt;p&gt;Even though I still didn't do all that much with Fresh that couldn't be achieved with symlinking I did &lt;a href="https://github.com/bradparker/dotfiles/blob/663a66ca5959edb20284b487f8580475ec37c822/freshrc#L32-L35"&gt;begin to see the potential&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Despite this I was still looking for something more complete. Fresh managed a lot, but it didn't manage &lt;em&gt;everything&lt;/em&gt;. The plurality of &lt;em&gt;thing managers&lt;/em&gt; I was using became apparent when I finally &lt;a href="https://github.com/bradparker/dotfiles/blob/9e990d99d4bb6b85a2d847d5f47131d974add526/README.md"&gt;documented&lt;/a&gt; how I'd been setting everything up.&lt;/p&gt;
&lt;h2 id="home-manager"&gt;Home manager&lt;/h2&gt;
&lt;p&gt;I'd been using &lt;a href="https://nixos.org/nix/"&gt;Nix&lt;/a&gt; as a &lt;a href="https://brew.sh/"&gt;Homebrew&lt;/a&gt; replacement for a while before finding &lt;a href="https://github.com/rycee/home-manager"&gt;Home manager&lt;/a&gt;. It's given me the ability to consolidate almost everything I need to setup and update my development machines into &lt;a href="https://github.com/bradparker/dotfiles/blob/master/README.md#0-optional-run-the-install-script"&gt;one command&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Apart from simplifying the process of setting up a new machine, Home manager has also allowed to me to manage more &lt;em&gt;stuff&lt;/em&gt; more predictably.&lt;/p&gt;
&lt;h3 id="utilities"&gt;Utilities&lt;/h3&gt;
&lt;p&gt;There are a few non-default command line utilities I find myself always installing. Before Home manager if I wanted to setup a new machine I'd usually be moving lists of currently installed dependencies around.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;brad@old $ brew list &amp;gt; deps.txt

brad@new $ xargs brew install &amp;lt; deps.txt&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I'd moved to Nix before becoming aware of &lt;a href="https://github.com/Homebrew/homebrew-bundle"&gt;Homebrew Bundle's&lt;/a&gt; Brewfile, which looks like a great solution. Just not quite as holistic as I've found Nix / Home manager to be and with it my &lt;a href="https://github.com/bradparker/dotfiles/blob/b721261ea5b1aae448c45e63d99069d79571ca75/nixpkgs/home.nix#L86-L122"&gt;list of utilities&lt;/a&gt; is easy to manage.&lt;/p&gt;
&lt;h3 id="vim"&gt;Vim&lt;/h3&gt;
&lt;p&gt;Before Home manager I'd used a few of the popular Vim plugin managers (&lt;a href="https://github.com/tpope/vim-pathogen"&gt;Pathogen&lt;/a&gt;, &lt;a href="https://github.com/VundleVim/Vundle.vim"&gt;Vundle&lt;/a&gt; and &lt;a href="https://github.com/junegunn/vim-plug"&gt;Plug&lt;/a&gt;). They all worked well for me, but with my &lt;a href="https://github.com/bradparker/dotfiles/blob/b721261ea5b1aae448c45e63d99069d79571ca75/nixpkgs/home.nix#L3-L32"&gt;current setup&lt;/a&gt; I get a good plugin manager for Vim without an extra tool or installation step.&lt;/p&gt;
&lt;h3 id="tmux"&gt;Tmux&lt;/h3&gt;
&lt;p&gt;I've only ever used two Tmux plugins. Initially I installed them with &lt;a href="https://github.com/tmux-plugins/tpm"&gt;TPM&lt;/a&gt; but now I install them with &lt;a href="https://github.com/bradparker/dotfiles/blob/b721261ea5b1aae448c45e63d99069d79571ca75/nixpkgs/home.nix#L40-L48"&gt;Home manager&lt;/a&gt; (Tmux sensible gets included by default).&lt;/p&gt;
&lt;h3 id="bash"&gt;Bash&lt;/h3&gt;
&lt;p&gt;Sometimes it's nice to string utilities together into &lt;a href="https://github.com/bradparker/dotfiles/blob/master/nixpkgs/programs/bash/fuzzy-cd.sh"&gt;useful aliases&lt;/a&gt;, or try to bring a &lt;a href="https://github.com/bradparker/dotfiles/blob/master/nixpkgs/programs/bash/clipboard.sh"&gt;little more consistency&lt;/a&gt; to working across both macOS and Linux. Sadly, those niceties can get out of hand, so I've found it useful to factor them out into &lt;a href="https://github.com/bradparker/dotfiles/blob/b721261ea5b1aae448c45e63d99069d79571ca75/nixpkgs/home.nix#L63-L84"&gt;bite-sized chunks&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="git"&gt;Git&lt;/h3&gt;
&lt;p&gt;I get &lt;em&gt;a lot&lt;/em&gt; of use from &lt;a href="https://github.com/bradparker/dotfiles/blob/master/nixpkgs/home.nix#L57-L59"&gt;Git bash completions&lt;/a&gt; and &lt;a href="https://github.com/bradparker/dotfiles/blob/master/nixpkgs/programs/git/gitconfig#L4-L12"&gt;a few handy aliases&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;I get all of that, and a few other things, installed and configured with one tool. What's more:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It's repeatable, if my environment bootstraps once I'm confident it'll do so again.&lt;/li&gt;
&lt;li&gt;It's idempotent, I can keep running &lt;code&gt;home-manager switch&lt;/code&gt; as often as I like without issues.&lt;/li&gt;
&lt;li&gt;It works, more or less, the same on both my work machines running macOS and my home laptop running &lt;a href="https://www.pureos.net/"&gt;PureOS&lt;/a&gt;, a Debian fork. Because it's so repeatable I'm able to set up a &lt;a href="https://travis-ci.org/bradparker/dotfiles"&gt;build pipeline&lt;/a&gt; which ensures that every update I make will install happily on both platforms. I accept that this is perhaps taking things too far.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now that I've said that, and now that I'm pretty comfortable with the approach, I expect I'll push it a little further. Why not?&lt;/p&gt;</description><author>hi@bradparker.id.au (Brad Parker)</author><guid>https://bradparker.com/content/posts/2020-02-12-home-sweet-home.html</guid><pubDate>Wed, 12 Feb 2020 00:00:00 UTC</pubDate></item><item><title>Getting close to the conceptual metal</title><link>https://bradparker.id.au/posts/getting-close-to-the-conceptual-metal</link><description>&lt;p&gt;A few years ago I watched the &lt;a href="https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-001-structure-and-interpretation-of-computer-programs-spring-2005/video-lectures/"&gt;&lt;em&gt;Structure and interpretation of computer programs&lt;/em&gt; video lectures&lt;/a&gt;, kindly posted publicly by MIT OpenCourseWare. There's so much interesting material in them but one part really struck me, in &lt;a href="https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-001-structure-and-interpretation-of-computer-programs-spring-2005/video-lectures/5b-computational-objects/"&gt;&lt;em&gt;5B: Computational Objects&lt;/em&gt;&lt;/a&gt; Gerald Jay Sussman defines a pair "in terms of nothing but air, hot air".&lt;/p&gt;
&lt;pre class="scheme"&gt;&lt;code&gt;(define (cons x y)
  (λ (m) (m x y)))

(define (car x)
  (x (λ (a b) a)))

(define (cdr x)
  (x (λ (a b) b)))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Previous lectures had established pairs as a sort of fundamental thing. After all, pairs could be used to make lists and in Lisp once you've got pairs and lists you've got &lt;em&gt;a lot&lt;/em&gt;. Sussman, however, was revealing that there was a level below that, there was an even more fundamental thing: functions.&lt;/p&gt;
&lt;p&gt;Later, through learning &lt;a href="https://haskell.org"&gt;Haskell&lt;/a&gt;, I became familiar with the concept of &lt;a href="https://bradbow.com/posts/2017-09-14-adts.html"&gt;algebraic data types&lt;/a&gt;. It was astonishing to me that you could make so much out of so little. You seemingly only need types that are "pair-like" (&lt;em&gt;products&lt;/em&gt;) and types that are "either-like" (&lt;em&gt;sums&lt;/em&gt;).&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;data Product a b
  = P a b

data Sum a b
  = A a
  | B b

newtype Maybe a
  = Maybe (Sum () a)

newtype List a
  = List (Maybe (Product a (List a)))

newtype NonEmpty a
  = NonEmpty (Product a (List a))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When Sussman chalked up that pair made of nothing but "hot air" he attributed the encoding to &lt;a href="https://en.wikipedia.org/wiki/Alonzo_Church"&gt;Alonzo Church&lt;/a&gt;. Appreciating that many other types can be made from pair-like things and either-like things, I wondered if there existed a Church encoding for &lt;code&gt;Either&lt;/code&gt;. After all, with &lt;code&gt;Either&lt;/code&gt; and &lt;code&gt;Pair&lt;/code&gt; it sure seemed like I'd be able to construct anything else I needed. I found Church encodings for lots of other interesting things, like &lt;a href="https://en.wikipedia.org/wiki/Church_encoding#Church_Booleans"&gt;booleans&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Church_encoding#Church_numerals"&gt;natural numbers&lt;/a&gt;, but nothing quite like &lt;code&gt;Either&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Eventually I'd happen across &lt;a href="https://oxij.org/paper/ExceptionallyMonadic/ExceptionallyMonadic.xetex.pdf#24"&gt;Scott encoding&lt;/a&gt;, named for &lt;a href="https://en.wikipedia.org/wiki/Dana_Scott"&gt;Dana Scott&lt;/a&gt; to whom it is attributed. It's super interesting.&lt;/p&gt;
&lt;h2 id="scott-encoding"&gt;Scott encoding&lt;/h2&gt;
&lt;p&gt;With Scott encoding we have a consistent method for representing any algebraic datatype in the untyped &lt;a href="https://www.futurelearn.com/courses/functional-programming-haskell/0/steps/27249"&gt;lambda calculus&lt;/a&gt;. It goes something like this: say we have a datatype &lt;em&gt;D&lt;/em&gt;, with &lt;em&gt;N&lt;/em&gt; &lt;a href="https://wiki.haskell.org/Constructor#Data_constructor"&gt;constructors&lt;/a&gt;, (&lt;em&gt;d&lt;/em&gt;&lt;sub&gt;1&lt;/sub&gt; … &lt;em&gt;d&lt;sub&gt;N&lt;/sub&gt;&lt;/em&gt;), such that constructor &lt;em&gt;d&lt;sub&gt;i&lt;/sub&gt;&lt;/em&gt; has &lt;a href="https://en.wikipedia.org/wiki/Arity"&gt;arity&lt;/a&gt; &lt;em&gt;A&lt;sub&gt;i&lt;/em&gt;. The Scott encoding for constructor &lt;em&gt;d&lt;sub&gt;i&lt;/sub&gt;&lt;/em&gt; of &lt;em&gt;D&lt;/em&gt; would be:&lt;/p&gt;
&lt;figure class="figure"&gt;
&lt;em&gt;d&lt;sub&gt;i&lt;/sub&gt;&lt;/em&gt; := &lt;em&gt;λx&lt;/em&gt;&lt;sub&gt;1&lt;/sub&gt; … &lt;em&gt;x&lt;sub&gt;A&lt;sub&gt;i&lt;/sub&gt;&lt;/sub&gt;&lt;/em&gt;. &lt;em&gt;λc&lt;/em&gt;&lt;sub&gt;1&lt;/sub&gt; … &lt;em&gt;c&lt;sub&gt;N&lt;/sub&gt;&lt;/em&gt;. &lt;em&gt;c&lt;sub&gt;i&lt;/sub&gt;&lt;/em&gt; &lt;em&gt;x&lt;/em&gt;&lt;sub&gt;1&lt;/sub&gt; … &lt;em&gt;x&lt;sub&gt;A&lt;sub&gt;i&lt;/sub&gt;&lt;/sub&gt;&lt;/em&gt;
&lt;/figure&gt;

&lt;p&gt;If you've never seen this sort of notation before don't worry we'll be moving to mostly Haskell soon enough. Until then we could have a couple of swings at stating this in words.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Each constructor, &lt;em&gt;d&lt;/em&gt;&lt;sub&gt;1&lt;/sub&gt; through &lt;em&gt;d&lt;sub&gt;N&lt;/sub&gt;&lt;/em&gt;, is responsible for accepting the arguments needed to call its chosen &lt;a href="https://en.wikibooks.org/wiki/Haskell/Continuation_passing_style"&gt;continuation&lt;/a&gt;, any one of &lt;em&gt;c&lt;/em&gt;&lt;sub&gt;1&lt;/sub&gt; through &lt;em&gt;c&lt;sub&gt;N&lt;/sub&gt;&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;There is one continuation per constructor (&lt;em&gt;c&lt;sub&gt;i&lt;/sub&gt;&lt;/em&gt; is the continuation for &lt;em&gt;d&lt;sub&gt;i&lt;/sub&gt;&lt;/em&gt;), and each continuation needs to be passed all the arguments its constructor was passed (&lt;em&gt;d&lt;sub&gt;i&lt;/sub&gt;&lt;/em&gt; was passed &lt;em&gt;x&lt;/em&gt;&lt;sub&gt;1&lt;/sub&gt; … &lt;em&gt;x&lt;sub&gt;A&lt;sub&gt;i&lt;/sub&gt;&lt;/sub&gt;&lt;/em&gt; and so &lt;em&gt;c&lt;sub&gt;i&lt;/sub&gt;&lt;/em&gt; will passed them as well).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this way values are held in the closure of each constructor. These internal values are &lt;em&gt;used&lt;/em&gt; when the consumer of a value of type &lt;em&gt;D&lt;/em&gt; passes in a continuation which will accept them as arguments.&lt;/p&gt;
&lt;p&gt;To develop an intuition for how this actually works we can try converting some well-known Haskell data types to this encoding.&lt;/p&gt;
&lt;h3 id="pair"&gt;Pair&lt;/h3&gt;
&lt;p&gt;To Scott encode any one constructor for a given datatype we need to know how many other constructors it has, and how many arguments each of them accept. Haskell's pair type looks like syntax, however by asking GHCi for some information about it we can see that its much like any other user-defined datatype.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ghci
&amp;gt; :info (,)
data (,) a b = (,) a b  -- Defined in `GHC.Tuple&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It has one constructor which happens to share the name of its type.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; :type (,)
(,) :: a -&amp;gt; b -&amp;gt; (a, b)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For our purposes we'll rename the &lt;code&gt;(,)&lt;/code&gt; type to &lt;em&gt;Pair&lt;/em&gt; and the &lt;code&gt;(,)&lt;/code&gt; constructor to &lt;em&gt;pair&lt;/em&gt;. As &lt;em&gt;Pair's&lt;/em&gt; only constructor, &lt;em&gt;pair&lt;/em&gt; need only accept one continuation &lt;em&gt;c&lt;/em&gt;. The arguments that &lt;em&gt;pair&lt;/em&gt; accepts, such that it can call &lt;em&gt;c&lt;/em&gt; with them, are the resulting &lt;em&gt;Pair's&lt;/em&gt; first and second elements.&lt;/p&gt;
&lt;figure class="figure"&gt;
  &lt;em&gt;pair&lt;/em&gt; := &lt;em&gt;λx&lt;/em&gt;&lt;sub&gt;1&lt;/sub&gt;, &lt;em&gt;x&lt;/em&gt;&lt;sub&gt;2&lt;/sub&gt;. &lt;em&gt;λc&lt;/em&gt;. &lt;em&gt;c x&lt;/em&gt;&lt;sub&gt;1&lt;/sub&gt; &lt;em&gt;x&lt;/em&gt;&lt;sub&gt;2&lt;/sub&gt;
&lt;/figure&gt;

&lt;p&gt;But what is &lt;em&gt;Pair&lt;/em&gt;? How might we write the type of a function that accepts a &lt;em&gt;Pair&lt;/em&gt;? First we might rewrite &lt;em&gt;pair&lt;/em&gt; in Haskell, initially as a fairly direct translation.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;pair = \x1 x2 -&amp;gt; \c -&amp;gt; c x1 x2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, without the first explicit lambda.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;pair x1 x2 = \c -&amp;gt; c x1 x2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That can be loaded into GHCi or into a &lt;a href="http://repl.it"&gt;Repl.it&lt;/a&gt; Haskell session in order to find its inferred type.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ghci
GHCi, version 8.6.5: http://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/brad/.ghci
&amp;gt; pair x1 x2 = \c -&amp;gt; c x1 x2
&amp;gt; :type pair
pair :: t1 -&amp;gt; t2 -&amp;gt; (t1 -&amp;gt; t2 -&amp;gt; t3) -&amp;gt; t3&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You might be wondering why these lambdas are arranged the way they are. Why not use any of the following, equivalent, arrangements.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;pair = \x1 -&amp;gt; \x2 -&amp;gt; \c -&amp;gt; c x1 x2
pair = \x1 -&amp;gt; \x2 c -&amp;gt; c x1 x2
pair = \x1 x2 c -&amp;gt; c x1 x2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The answer is that I'm sneakily trying to reveal what the &lt;em&gt;Pair&lt;/em&gt; component of &lt;code&gt;pair&lt;/code&gt;'s type is, and, as it ends up, what the datatype component of any Scott encoded constructor's type happens to be.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;type Pair t1 t2 t3
  = (t1 -&amp;gt; t2 -&amp;gt; t3) -&amp;gt; t3&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The equivalent Haskell type, &lt;code&gt;(,) a b&lt;/code&gt; has one less type variable. It's interesting to think about what it would mean for &lt;code&gt;Pair&lt;/code&gt; to ditch &lt;code&gt;t3&lt;/code&gt; somehow.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;type Pair t1 t2
  = (t1 -&amp;gt; t2 -&amp;gt; _) -&amp;gt; _&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One way of looking at this is that it's up to the continuation (&lt;em&gt;c&lt;/em&gt;) what it does with &lt;em&gt;x&lt;/em&gt;&lt;sub&gt;1&lt;/sub&gt; and &lt;em&gt;x&lt;/em&gt;&lt;sub&gt;2&lt;/sub&gt;, the constructor (&lt;em&gt;pair&lt;/em&gt;) doesn't get a say. This means that whatever &lt;em&gt;pair&lt;/em&gt; returns must work &lt;em&gt;for anything&lt;/em&gt; its &lt;em&gt;consumer&lt;/em&gt; may want to produce. In Haskell types we might say that &lt;code&gt;Pair&lt;/code&gt; must work &lt;em&gt;for all&lt;/em&gt; possible types its provided continuation could return.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;type Pair t1 t2
  = forall t3. (t1 -&amp;gt; t2 -&amp;gt; t3) -&amp;gt; t3

pair :: Pair a b
pair a b = \c -&amp;gt; c a b&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Is this equivalent to &lt;code&gt;(,)&lt;/code&gt;? How might we tell? One way might be to write a function which converts &lt;code&gt;(,)&lt;/code&gt;s into &lt;code&gt;Pair&lt;/code&gt;s and one which converts &lt;code&gt;Pair&lt;/code&gt;s into &lt;code&gt;(,)&lt;/code&gt;s. Then, given those two functions, we should be able to observe that their composition doesn't &lt;em&gt;do&lt;/em&gt; anything. Or put another way: for these two functions:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;from :: (a, b) -&amp;gt; Pair a b
from = _

to :: Pair a b -&amp;gt; (a, b)
to = _&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Their composition in either direction is equivalent to an identity function.&lt;/p&gt;
&lt;figure class="figure"&gt;
  &lt;em&gt;from&lt;/em&gt; ∘ &lt;em&gt;to&lt;/em&gt; = &lt;em&gt;id&lt;sub&gt;Pair&lt;/sub&gt;&lt;/em&gt;&lt;br /&gt;
  &lt;em&gt;to&lt;/em&gt; ∘ &lt;em&gt;from&lt;/em&gt; = &lt;em&gt;id&lt;sub&gt;(,)&lt;/sub&gt;&lt;/em&gt;
&lt;/figure&gt;

&lt;p&gt;If these two functions can be written, and they have this property, it means that &lt;code&gt;Pair&lt;/code&gt; and &lt;code&gt;(,)&lt;/code&gt; are &lt;a href="https://en.wiktionary.org/wiki/isomorphic"&gt;isomorphic&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So then, is it possible to write &lt;code&gt;from&lt;/code&gt;?&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;from :: (a, b) -&amp;gt; Pair a b
from (a, b) = _&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which is sort of asking: given an &lt;code&gt;a&lt;/code&gt; and a &lt;code&gt;b&lt;/code&gt;, is it possible to construct a &lt;code&gt;Pair a b&lt;/code&gt;?&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;from :: (a, b) -&amp;gt; Pair a b
from (a, b) = pair a b&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;How about &lt;code&gt;to&lt;/code&gt;?&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;to :: Pair a b -&amp;gt; (a, b)
to p = _&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Recall that &lt;code&gt;p&lt;/code&gt; is a function waiting to be passed a continuation. That continuation will be passed both an &lt;code&gt;a&lt;/code&gt; and a &lt;code&gt;b&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;to :: Pair a b -&amp;gt; (a, b)
to p = p (\a b -&amp;gt; _)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So now, given an &lt;code&gt;a&lt;/code&gt; and a &lt;code&gt;b&lt;/code&gt; can we construct an &lt;code&gt;(a, b)&lt;/code&gt;?&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;to :: Pair a b -&amp;gt; (a, b)
to p = p (\a b -&amp;gt; (a, b))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that done: is &lt;em&gt;to&lt;/em&gt; ∘ &lt;em&gt;from&lt;/em&gt; an identity function? It does seem so.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; (to . from) (1, 2)
(1,2)
&amp;gt; (to . from) (True, &amp;quot;Nifty&amp;quot;)
(True,&amp;quot;Nifty&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Without a &lt;a href="https://hackage.haskell.org/package/base-4.12.0.0/docs/Text-Show.html"&gt;&lt;code&gt;Show&lt;/code&gt;&lt;/a&gt; or &lt;a href="http://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Eq.html"&gt;&lt;code&gt;Eq&lt;/code&gt;&lt;/a&gt; instance for &lt;code&gt;(-&amp;gt;)&lt;/code&gt; it's hard to observe the same for &lt;em&gt;from&lt;/em&gt; ∘ &lt;em&gt;to&lt;/em&gt;. We can at least observe what &lt;em&gt;to&lt;/em&gt; ∘ &lt;em&gt;from&lt;/em&gt; ∘ &lt;em&gt;to&lt;/em&gt; does.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; (to . from . to) (pair 1 2)
(1,2)
&amp;gt; (to . from . to) (pair True &amp;quot;Very nifty&amp;quot;)
(True,&amp;quot;Very nifty&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Well, I'm convinced. Are you? For further tangible evidence you could try re-implementing everything in &lt;a href="http://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Tuple.html"&gt;&lt;code&gt;Data.Tuple&lt;/code&gt;&lt;/a&gt; in terms of &lt;code&gt;Pair&lt;/code&gt;. It's a pretty fun exercise and helped me to become more comfortable with these lambda-only pairs.&lt;/p&gt;
&lt;h3 id="either"&gt;Either&lt;/h3&gt;
&lt;p&gt;In Haskell &lt;code&gt;Either&lt;/code&gt; is defined like this:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;data Either a b
  = Left a
  | Right b&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For the purposes of Scott encoding we can say that &lt;em&gt;Either&lt;/em&gt; has two constructors which each accept one argument. This means that whatever each constructor returns will accept two continuations which themselves each accept one argument. Each constructor will accept an argument to pass to their chosen continuation.&lt;/p&gt;
&lt;p&gt;The first constructor &lt;em&gt;left&lt;/em&gt;, then, will accept one argument to pass to the first continuation.&lt;/p&gt;
&lt;figure class="figure"&gt;
  &lt;em&gt;left&lt;/em&gt; := &lt;em&gt;λx. λc&lt;sub&gt;1&lt;/sub&gt;, c&lt;sub&gt;2&lt;/sub&gt;. c&lt;sub&gt;1&lt;/sub&gt; x&lt;/em&gt;
&lt;/figure&gt;

&lt;p&gt;And the second will accept one to pass to the second continuation.&lt;/p&gt;
&lt;figure class="figure"&gt;
  &lt;em&gt;right&lt;/em&gt; := &lt;em&gt;λx. λc&lt;sub&gt;1&lt;/sub&gt;, c&lt;sub&gt;2&lt;/sub&gt;. c&lt;sub&gt;2&lt;/sub&gt; x&lt;/em&gt;
&lt;/figure&gt;

&lt;p&gt;Each continuation can accept an argument of a different type (say &lt;em&gt;c&lt;sub&gt;1&lt;/sub&gt;&lt;/em&gt; takes an &lt;em&gt;α&lt;/em&gt; and &lt;em&gt;c&lt;sub&gt;2&lt;/sub&gt;&lt;/em&gt; takes a &lt;em&gt;β&lt;/em&gt;) but both should return something of the same type (say &lt;em&gt;γ&lt;/em&gt;). The reason for this is how values of the &lt;em&gt;Either&lt;/em&gt; type are used, this may become evident later. Using a &lt;a href="https://en.wikipedia.org/wiki/System_F"&gt;polymorphic lambda calculus&lt;/a&gt; rather than an untyped lambda calculus we can write out how those types line up.&lt;/p&gt;
&lt;figure class="figure"&gt;
  &lt;em&gt;left&lt;/em&gt; := &lt;em&gt;Λα, β, γ. λx &lt;sup&gt;α&lt;/sup&gt;. λc&lt;sub&gt;1&lt;/sub&gt; &lt;sup&gt;α → γ&lt;/sup&gt;, c&lt;sub&gt;2&lt;/sub&gt; &lt;sup&gt;β → γ&lt;/sup&gt;. c&lt;sub&gt;1&lt;/sub&gt; x&lt;/em&gt;&lt;br /&gt;
  &lt;em&gt;right&lt;/em&gt; := &lt;em&gt;Λα, β, γ. λx &lt;sup&gt;β&lt;/sup&gt;. λc&lt;sub&gt;1&lt;/sub&gt; &lt;sup&gt;α → γ&lt;/sup&gt;, c&lt;sub&gt;2&lt;/sub&gt; &lt;sup&gt;β → γ&lt;/sup&gt;. c&lt;sub&gt;2&lt;/sub&gt; x&lt;/em&gt;
&lt;/figure&gt;

&lt;p&gt;For me at least, it's a little easier to see in Haskell.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;left :: a -&amp;gt; (a -&amp;gt; c) -&amp;gt; (b -&amp;gt; c) -&amp;gt; c
left x = \c1 c2 -&amp;gt; c1 x

right :: b -&amp;gt; (a -&amp;gt; c) -&amp;gt; (b -&amp;gt; c) -&amp;gt; c
right x = \c1 c2 -&amp;gt; c2 x&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As we did with &lt;em&gt;Pair&lt;/em&gt;, we might ask: where's &lt;em&gt;Either&lt;/em&gt; in all of that? And, as with &lt;em&gt;Pair&lt;/em&gt;, I have sneakily positioned certain lambdas to try and point it out. However, in this case another method might be to put &lt;em&gt;left&lt;/em&gt; and &lt;em&gt;right&lt;/em&gt; side by side and view their shared return type.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;left  :: a -&amp;gt; ((a -&amp;gt; c) -&amp;gt; (b -&amp;gt; c) -&amp;gt; c)
right :: b -&amp;gt; ((a -&amp;gt; c) -&amp;gt; (b -&amp;gt; c) -&amp;gt; c)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which might yield the following.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;type Either a b c
  = (a -&amp;gt; c) -&amp;gt; (b -&amp;gt; c) -&amp;gt; c&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As with &lt;em&gt;Pair&lt;/em&gt; we can make sure that the choice of &lt;code&gt;c&lt;/code&gt; is left solely up to the consumer of an &lt;code&gt;Either&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;type Either a b
  = forall c. (a -&amp;gt; c) -&amp;gt; (b -&amp;gt; c) -&amp;gt; c

left :: a -&amp;gt; Either a b
left x = \c1 c2 -&amp;gt; c1 x

right :: b -&amp;gt; Either a b
right x = \c1 c2 -&amp;gt; c2 x&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Can we write &lt;em&gt;to&lt;/em&gt; and &lt;em&gt;from&lt;/em&gt; for converting between our &lt;em&gt;Either&lt;/em&gt; and Haskell's?&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;from :: Prelude.Either a b -&amp;gt; Either a b
from = _

to :: Either a b -&amp;gt; Prelude.Either a b
to = _&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For &lt;em&gt;from&lt;/em&gt; we can be given a &lt;code&gt;Left&lt;/code&gt; containing an &lt;code&gt;a&lt;/code&gt; or a &lt;code&gt;Right&lt;/code&gt; containing a &lt;code&gt;b&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;from :: Prelude.Either a b -&amp;gt; Either a b
from e =
  case e of
    Left a -&amp;gt; _
    Right b -&amp;gt; _&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So we have two questions to answer. Given an &lt;code&gt;a&lt;/code&gt; can I construct an &lt;code&gt;Either a b&lt;/code&gt;?&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;from :: Prelude.Either a b -&amp;gt; Either a b
from e =
  case e of
    Left a -&amp;gt; left a
    Right b -&amp;gt; _&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Given a &lt;code&gt;b&lt;/code&gt; can I construct an &lt;code&gt;Either a b&lt;/code&gt;?&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;from :: Prelude.Either a b -&amp;gt; Either a b
from e =
  case e of
    Left a -&amp;gt; left a
    Right b -&amp;gt; right b&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For &lt;em&gt;to&lt;/em&gt; it would be nice if we could use a &lt;code&gt;case&lt;/code&gt; expression as we did with &lt;em&gt;from&lt;/em&gt; and in a sense we can.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;to :: Either a b -&amp;gt; Prelude.Either a b
to e =
  e
    (\a -&amp;gt; _)
    (\b -&amp;gt; _)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This was less clear when looking at &lt;code&gt;Pair&lt;/code&gt; and &lt;code&gt;(,)&lt;/code&gt; but Scott-encoded datatypes are almost ready-made &lt;code&gt;case&lt;/code&gt; expressions. Each continuation is like a constructor-only pattern-match.&lt;/p&gt;
&lt;p&gt;As with &lt;em&gt;to&lt;/em&gt; we again have two questions to answer, and they're very similar. First, given an &lt;code&gt;a&lt;/code&gt; can I construct a &lt;code&gt;Prelude.Either a b&lt;/code&gt;?&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;to :: Either a b -&amp;gt; Prelude.Either a b
to e =
  e
    (\a -&amp;gt; Left a)
    (\b -&amp;gt; _)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, given a &lt;code&gt;b&lt;/code&gt; can I construct a &lt;code&gt;Prelude.Either a b&lt;/code&gt;?&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;to :: Either a b -&amp;gt; Prelude.Either a b
to e =
  e
    (\a -&amp;gt; Left a)
    (\b -&amp;gt; Right b)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Are &lt;code&gt;Prelude.Either&lt;/code&gt; and &lt;code&gt;Either&lt;/code&gt; equivalent?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; to (from (Left &amp;quot;Hrm?&amp;quot;))
Left &amp;quot;Hrm?&amp;quot;
&amp;gt; to (from (to (left &amp;quot;Ahhhhh&amp;quot;)))
Left &amp;quot;Ahhhhh&amp;quot;
&amp;gt; to (from (Right 2))
Right 2
&amp;gt; to (from (to (right 14)))
Right 14&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Looks likely. Re-implementing everything in &lt;a href="https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Either.html"&gt;&lt;code&gt;Data.Either&lt;/code&gt;&lt;/a&gt; would sure be convincing.&lt;/p&gt;
&lt;h2 id="from-hot-air-to-solid-ground"&gt;From hot air to solid ground&lt;/h2&gt;
&lt;p&gt;This is all well and good but I'm still left wondering what could actually be &lt;em&gt;built&lt;/em&gt; with this. Knowing, intellectually, that Haskell's &lt;code&gt;Either&lt;/code&gt; and the lambdas-only &lt;em&gt;Either&lt;/em&gt; are equivalent isn't as satisfying as using &lt;em&gt;Either&lt;/em&gt; and &lt;em&gt;Pair&lt;/em&gt; to write real(ish) programs.&lt;/p&gt;
&lt;p&gt;We &lt;em&gt;could&lt;/em&gt; use &lt;em&gt;Either&lt;/em&gt; and &lt;em&gt;Pair&lt;/em&gt; to write a little REPL which evaluates Lisp-like expressions.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ runhaskell HotAir.hs
Enter an expression to evaluate. E.G.
(+ (* (+ 12 7) 100) 58)
&amp;gt; (+ 1 2)
3
&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Yeah, let's do that.&lt;/p&gt;
&lt;p&gt;To make things less onerous this little language could be limited to only adding and multiplying natural numbers. No &lt;code&gt;define&lt;/code&gt;, no &lt;code&gt;λ&lt;/code&gt;. Nothing other than positive integer literals (&lt;code&gt;0&lt;/code&gt;, &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt; …), addition (&lt;code&gt;+&lt;/code&gt;) and multiplication (&lt;code&gt;*&lt;/code&gt;).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; (define (sqr x) (* x x))
Error: Unexpected char: &amp;#39;d&amp;#39;
&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Before we begin: this is going to move quite fast. Don't worry if you miss some of the details of the implementation. It's more important to be &lt;em&gt;generally&lt;/em&gt; aware of what the program does and to keep in mind that we're building it as a bit of a stress test for our lambda-only datatypes. If you'd like to learn more about how to build programs in Haskell I'd reccomend all the material produced by &lt;a href="https://typeclasses.com/"&gt;Typeclasses&lt;/a&gt; and the &lt;a href="https://github.com/data61/fp-course"&gt;Data61 Functional Programming Course&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now, the first thing we should do is redefine &lt;em&gt;Pair&lt;/em&gt; and &lt;em&gt;Either&lt;/em&gt; using &lt;code&gt;newtype&lt;/code&gt;, rather than &lt;code&gt;type&lt;/code&gt; (GHC is pretty great, but sometimes we need to cut it some slack).&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# OPTIONS_GHC -Wall -Werror #-}

module HotAir where

newtype Pair a b = Pair
  { runPair ::
      forall c.
      (a -&amp;gt; b -&amp;gt; c) -&amp;gt;
      c
  }

pair :: a -&amp;gt; b -&amp;gt; Pair a b
pair x1 x2 = Pair \c -&amp;gt; c x1 x2

newtype Either a b = Either
  { runEither ::
      forall c.
      (a -&amp;gt; c) -&amp;gt;
      (b -&amp;gt; c) -&amp;gt;
      c
  }

left :: a -&amp;gt; Either a b
left x = Either \c1 _ -&amp;gt; c1 x

right :: b -&amp;gt; Either a b
right x = Either \_ c2 -&amp;gt; c2 x&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, we might define a &lt;a href="http://www.cs.nott.ac.uk/~pszgmh/pearl.pdf"&gt;monadic parser&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;import Data.String (String)

newtype Parser a = Parser
  { parse ::
      String -&amp;gt;
      Either String (Pair a String)
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A &lt;code&gt;satisfy&lt;/code&gt; function for creating a &lt;code&gt;Parser&lt;/code&gt; which compares the next character using given &lt;code&gt;Char -&amp;gt; Bool&lt;/code&gt; predicate would be handy.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;{-# LANGUAGE LambdaCase #-}

import Data.Bool (Bool)
import Data.Char (Char)
import Data.List ((++))

satisfy :: (Char -&amp;gt; Bool) -&amp;gt; Parser Char
satisfy p = Parser \case
  [] -&amp;gt; left &amp;quot;Unexpected EOF&amp;quot;
  (c : cs) -&amp;gt;
    if p c
      then right (pair c cs)
      else left (&amp;quot;Unexpected char: &amp;quot; ++ show c)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can use it to define a &lt;code&gt;char&lt;/code&gt; function which matches a specific &lt;code&gt;Char&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;import Data.Eq ((==))

char :: Char -&amp;gt; Parser Char
char = satisfy . (==)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor.html#t:Functor"&gt;&lt;code&gt;Functor&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Applicative.html#t:Applicative"&gt;&lt;code&gt;Applicative&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Applicative.html#t:Alternative"&gt;&lt;code&gt;Alternative&lt;/code&gt;&lt;/a&gt; instances for &lt;code&gt;Parser&lt;/code&gt; will make composing and manipulating them nicer.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;import Control.Applicative
  ( Alternative (empty, (&amp;lt;|&amp;gt;)),
    Applicative (pure, (&amp;lt;*&amp;gt;)),
  )
import Data.Function (const)
import Data.Functor (Functor (fmap))

instance Functor Parser where
  fmap :: (a -&amp;gt; b) -&amp;gt; Parser a -&amp;gt; Parser b
  fmap f pa =
    Parser \str -&amp;gt;
      runEither (parse pa str)
        left
        (\p -&amp;gt; right (runPair p (pair . f)))

instance Applicative Parser where
  pure :: a -&amp;gt; Parser a
  pure a = Parser (right . pair a)

  (&amp;lt;*&amp;gt;) :: Parser (a -&amp;gt; b) -&amp;gt; Parser a -&amp;gt; Parser b
  pf &amp;lt;*&amp;gt; pa =
    Parser \str -&amp;gt;
      runEither (parse f str)
        left
        (\p -&amp;gt; runPair p (\f -&amp;gt; parse (fmap f pa)))

instance Alternative Parser where
  empty :: Parser a
  empty = Parser (const (left &amp;quot;Empty&amp;quot;))

  (&amp;lt;|&amp;gt;) :: Parser a -&amp;gt; Parser a -&amp;gt; Parser a
  Parser l &amp;lt;|&amp;gt; Parser r =
    Parser \str -&amp;gt;
      runEither (l str)
        (const (r str))
        right&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A convenient way to ignore unused input will be useful, too.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;fst :: Pair a b -&amp;gt; a
fst = (`runPair` const)

execParser :: Parser a -&amp;gt; String -&amp;gt; Either String a
execParser p str =
  runEither (parse p str)
    left
    (right . fst)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That should be enough to write an &lt;code&gt;eval&lt;/code&gt; function for our little language.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;import Control.Applicative (some, (*&amp;gt;), (&amp;lt;*))
import Data.Char (isDigit)
import Data.Functor ((&amp;lt;$), (&amp;lt;$&amp;gt;))
import GHC.Num ((*), (+))
import Numeric.Natural (Natural)

eval :: String -&amp;gt; Either String Natural
eval = execParser expression
  where
    expression :: Parser Natural
    expression = natural &amp;lt;|&amp;gt; application
    natural :: Parser Natural
    natural = read &amp;lt;$&amp;gt; some (satisfy isDigit)
    application :: Parser Natural
    application =
      char &amp;#39;(&amp;#39; *&amp;gt; operator &amp;lt;* space
        &amp;lt;*&amp;gt; expression &amp;lt;* space
        &amp;lt;*&amp;gt; expression &amp;lt;* char &amp;#39;)&amp;#39;
    operator :: Parser (Natural -&amp;gt; Natural -&amp;gt; Natural)
    operator = (+) &amp;lt;$ char &amp;#39;+&amp;#39; &amp;lt;|&amp;gt; (*) &amp;lt;$ char &amp;#39;*&amp;#39;
    space :: Parser Char
    space = char &amp;#39; &amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, a &lt;code&gt;main&lt;/code&gt; function that lets a user input expressions and view the result of evaluating them.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;module HotAir (main) where

import Control.Monad (forever)
import System.IO
  ( IO,
    getLine,
    print,
    putStr,
    putStrLn,
  )

main :: IO ()
main = do
  putStrLn &amp;quot;Enter an expression to evaluate. E.G.&amp;quot;
  putStrLn &amp;quot;(+ (* (+ 12 7) 100) 58)&amp;quot;
  forever $ do
    putStr &amp;quot;&amp;gt; &amp;quot;
    line &amp;lt;- getLine
    runEither (eval line)
      (putStrLn . (&amp;quot;Error: &amp;quot; ++))
      print&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And here it is, a little REPL made of &lt;em&gt;mostly&lt;/em&gt; hot air.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# OPTIONS_GHC -Wall -Werror #-}

module HotAir (main) where

import Control.Applicative
  ( Alternative (empty, (&amp;lt;|&amp;gt;)),
    Applicative (pure, (&amp;lt;*&amp;gt;)),
    some,
    (*&amp;gt;),
    (&amp;lt;*),
  )
import Control.Monad (forever)
import Data.Bool (Bool)
import Data.Char (Char, isDigit)
import Data.Eq ((==))
import Data.Function (const, ($), (.))
import Data.Functor (Functor (fmap), (&amp;lt;$), (&amp;lt;$&amp;gt;))
import Data.List ((++))
import Data.String (String)
import GHC.Num ((*), (+))
import Numeric.Natural (Natural)
import System.IO
  ( IO,
    getLine,
    print,
    putStr,
    putStrLn,
  )
import Text.Read (read)
import Text.Show (Show (show))

newtype Pair a b = Pair
  { runPair ::
      forall c.
      (a -&amp;gt; b -&amp;gt; c) -&amp;gt;
      c
  }

pair :: a -&amp;gt; b -&amp;gt; Pair a b
pair x1 x2 = Pair \c -&amp;gt; c x1 x2

fst :: Pair a b -&amp;gt; a
fst = (`runPair` const)

newtype Either a b = Either
  { runEither ::
      forall c.
      (a -&amp;gt; c) -&amp;gt;
      (b -&amp;gt; c) -&amp;gt;
      c
  }

left :: a -&amp;gt; Either a b
left x = Either \c1 _ -&amp;gt; c1 x

right :: b -&amp;gt; Either a b
right x = Either \_ c2 -&amp;gt; c2 x

newtype Parser a = Parser
  { parse ::
      String -&amp;gt;
      Either String (Pair a String)
  }

satisfy :: (Char -&amp;gt; Bool) -&amp;gt; Parser Char
satisfy p = Parser \case
  [] -&amp;gt; left &amp;quot;Unexpected EOF&amp;quot;
  (c : cs) -&amp;gt;
    if p c
      then right (pair c cs)
      else left (&amp;quot;Unexpected char: &amp;quot; ++ show c)

char :: Char -&amp;gt; Parser Char
char = satisfy . (==)

instance Functor Parser where
  fmap :: (a -&amp;gt; b) -&amp;gt; Parser a -&amp;gt; Parser b
  fmap f pa =
    Parser \str -&amp;gt;
      runEither (parse pa str)
        left
        (\p -&amp;gt; right (runPair p (pair . f)))

instance Applicative Parser where
  pure :: a -&amp;gt; Parser a
  pure a = Parser (right . pair a)

  (&amp;lt;*&amp;gt;) :: Parser (a -&amp;gt; b) -&amp;gt; Parser a -&amp;gt; Parser b
  pf &amp;lt;*&amp;gt; pa =
    Parser \str -&amp;gt;
      runEither (parse pf str)
        left
        (\p -&amp;gt; runPair p (\f -&amp;gt; parse (fmap f pa)))

instance Alternative Parser where
  empty :: Parser a
  empty = Parser (const (left &amp;quot;Empty&amp;quot;))

  (&amp;lt;|&amp;gt;) :: Parser a -&amp;gt; Parser a -&amp;gt; Parser a
  Parser l &amp;lt;|&amp;gt; Parser r =
    Parser \str -&amp;gt;
      runEither (l str)
        (const (r str))
        right

execParser :: Parser a -&amp;gt; String -&amp;gt; Either String a
execParser p str =
  runEither (parse p str)
    left
    (right . fst)

eval :: String -&amp;gt; Either String Natural
eval = execParser expression
  where
    expression :: Parser Natural
    expression = natural &amp;lt;|&amp;gt; application
    natural :: Parser Natural
    natural = read &amp;lt;$&amp;gt; some (satisfy isDigit)
    application :: Parser Natural
    application =
      char &amp;#39;(&amp;#39; *&amp;gt; operator &amp;lt;* space
        &amp;lt;*&amp;gt; expression &amp;lt;* space
        &amp;lt;*&amp;gt; expression &amp;lt;* char &amp;#39;)&amp;#39;
    operator :: Parser (Natural -&amp;gt; Natural -&amp;gt; Natural)
    operator = (+) &amp;lt;$ char &amp;#39;+&amp;#39; &amp;lt;|&amp;gt; (*) &amp;lt;$ char &amp;#39;*&amp;#39;
    space :: Parser Char
    space = char &amp;#39; &amp;#39;

main :: IO ()
main = do
  putStrLn &amp;quot;Enter an expression to evaluate. E.G.&amp;quot;
  putStrLn &amp;quot;(+ (* (+ 12 7) 100) 58)&amp;quot;
  forever $ do
    putStr &amp;quot;&amp;gt; &amp;quot;
    line &amp;lt;- getLine
    runEither (eval line)
      (putStrLn . (&amp;quot;Error: &amp;quot; ++))
      print&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can save that code into a file and execute it with &lt;code&gt;runhaskell&lt;/code&gt; if you want to see it in action.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ runhaskell HotAir.hs
Enter an expression to evaluate. E.G.
(+ (* (+ 12 7) 100) 58)
&amp;gt; (+ (* (+ 12 7) 100) 58)
1958
&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That was quite a whirlwind.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;I &lt;em&gt;know&lt;/em&gt; I really shouldn't be surprised that I could write my program with (more or less) only lambdas. Lambda calculus is &lt;a href="https://en.wikipedia.org/wiki/Lambda_calculus"&gt;"a universal model of computation"&lt;/a&gt; after all. I also shouldn't be surprised that translating lambda calculus terms into Haskell is so natural as Haskell based on a &lt;a href="https://gitlab.haskell.org/ghc/ghc/blob/master/docs/core-spec/core-spec.pdf"&gt;lambda calculus&lt;/a&gt;. But in this post I really wanted to focus on the wonder I feel when being able to &lt;em&gt;use&lt;/em&gt; abstract notions like lambda calculus to write runnable programs. My hope is that by writing this I might help someone find something they find wonderful, and encourage them to explore it.&lt;/p&gt;
&lt;p&gt;One possible avenue, which I might go into in a future post, is this: the above program still makes use of some pre-defined Haskell datatypes like &lt;code&gt;Bool&lt;/code&gt;, &lt;code&gt;Natural&lt;/code&gt;, &lt;code&gt;[a]&lt;/code&gt; and &lt;code&gt;Char&lt;/code&gt;. Does it have to? Could we build those entirely out of lambdas too? How far can we go?&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Huge thanks to &lt;a href="https://bradbow.com/"&gt;Brad Bow&lt;/a&gt; for his clarifying suggestions.&lt;/p&gt;</description><author>hi@bradparker.id.au (Brad Parker)</author><guid>https://bradparker.com/content/posts/2020-01-27-getting-close-to-the-conceptual-metal.html</guid><pubDate>Mon, 27 Jan 2020 00:00:00 UTC</pubDate></item><item><title>Deploying a fully automated Nix-based static website</title><link>https://bradparker.id.au/posts/deploying-a-fully-automated-nix-based-static-website</link><description>&lt;p&gt;My &lt;a href="https://bradparker.com"&gt;website&lt;/a&gt; has changed a bit over time. It was initially a WordPress blog, contorted to do double-duty as a folio for my design work. More recently it's been a static site, first generated by &lt;a href="https://metalsmith.io/"&gt;Metalsmith&lt;/a&gt; and later &lt;a href="https://jaspervdj.be/hakyll/"&gt;Hakyll&lt;/a&gt;. About a month ago I started to feel that hosting my site on Github pages was a little disconnected. I know this sounds odd, but I wanted to have a more active role in its deployment and take more responsibility for how it's run. Silly, right?&lt;/p&gt;
&lt;p&gt;Well, now here we are. If you're reading this at &lt;a href="https://bradparker.com"&gt;bradparker.com&lt;/a&gt; then you're getting the full experience. It's being served from a &lt;a href="https://www.digitalocean.com/"&gt;Digital Ocean&lt;/a&gt; droplet, running &lt;a href="https://nixos.org/"&gt;NixOs&lt;/a&gt; which has been configured to run a &lt;a href="https://hackage.haskell.org/package/warp"&gt;Warp&lt;/a&gt; web-server which is serving a static site built by &lt;a href="https://jaspervdj.be/hakyll/"&gt;Hakyll&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While researching how I might set all of this up I came across a great article on the Digital Ocean blog entitled &lt;a href="https://blog.digitalocean.com/deploying-a-fully-automated-git-based-static-website-in-under-5-minutes/"&gt;&lt;em&gt;Deploying a Fully-automated Git-based Static Website in Under 5 Minutes&lt;/em&gt;&lt;/a&gt;. The result seemed almost exactly what I wanted, a Github-pages-like experience but managed by me. The only thing that I felt it needed was a slightly more declarative approach.&lt;/p&gt;
&lt;h2 id="first-a-droplet"&gt;First, a Droplet&lt;/h2&gt;
&lt;p&gt;An important attribute of this setup for me is reproducibility. I should be able to stand a new server up in functionally same state as the current one by running one command. I don't want to have to access to server directly and configure anything by running a sequence of steps. This includes things like the security best practices outlined in another &lt;a href="https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-16-04"&gt;DigitalOcean blog article&lt;/a&gt; referenced in the aforementioned.&lt;/p&gt;
&lt;p&gt;To achieve this my server is running NixOs, a "completely declarative" operating system built on top of the &lt;a href="https://nixos.org/nix/"&gt;Nix&lt;/a&gt; package manager. Nix is one of those very powerful and very mysterious things, it's hard to fully explain because it can do so much. I use it as much as I can get away with, it &lt;a href="https://github.com/bradparker/dotfiles/blob/master/nixpkgs/home.nix"&gt;configures my work and personal machines&lt;/a&gt; and now the server which hosts my website.&lt;/p&gt;
&lt;p&gt;Chris Martin has a &lt;a href="https://chris-martin.org/2016/nixos-on-digitalocean"&gt;great post&lt;/a&gt; which outlines how to get a DigitalOcean droplet running NixOs. It is possible to extend those instructions slightly and get something more automated. To do this I took some advice from the &lt;a href="https://github.com/elitak/nixos-infect/blob/master/README.md"&gt;NixOs Infect README&lt;/a&gt; and made use of the fact that DigitalOcean images come with &lt;a href="https://cloud-init.io/"&gt;cloud-init&lt;/a&gt; installed. This makes it possible to run NixOs infect on the initial boot of a droplet without ever having to SSH into it. Using &lt;a href="https://github.com/digitalocean/doctl"&gt;&lt;code&gt;doctl&lt;/code&gt;&lt;/a&gt; you can create a droplet and have NixOs installed on it with one command.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/env bash

set -e

doctl compute droplet create \
  &amp;quot;bradparker.com&amp;quot; \
  --size s-1vcpu-3gb \
  --image ubuntu-16-04-x64 \
  --region sgp1 \
  --user-data &amp;quot;$(cat &amp;lt;&amp;lt;-EOF
    #cloud-config
    write_files:
    - path: /etc/nixos/host.nix
      permissions: &amp;#39;0644&amp;#39;
      content: |
        {pkgs, ...}:
        {
          # TODO: ... everything
        }
    runcmd:
      - curl https://raw.githubusercontent.com/elitak/nixos-infect/master/nixos-infect | PROVIDER=digitalocean NIXOS_IMPORT=./host.nix NIX_CHANNEL=nixos-19.09 bash 2&amp;gt;&amp;amp;1
    EOF
    )&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, the above command would not result in anything very useful. It's not running my website, and if I wanted to get the rest working I wouldn't even be able to SSH in to continue manually. I'm going to need a user who can SSH in and run commands as root if needs be.&lt;/p&gt;
&lt;pre class="nix"&gt;&lt;code&gt;{ config, pkgs, ... }:
{
  services.openssh = {
    passwordAuthentication = false;
    permitRootLogin = &amp;quot;no&amp;quot;;
  };

  users.mutableUsers = false;

  users.users.brad = {
    isNormalUser = true;
    hashedPassword = &amp;quot;$1$cmckqoXC$eBya/upETQKFbInZPz5y8.&amp;quot;;
    home = &amp;quot;/home/brad&amp;quot;;
    description = &amp;quot;Brad Parker&amp;quot;;
    extraGroups = [
      &amp;quot;wheel&amp;quot;
    ];
    openssh.authorizedKeys.keys = [
      &amp;quot;ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD8pPHsHkSNeX+YTVfbmrMltnWs+6dejWClomo2jBQuSv93WAzChWA1lhh8rUo9yxlud4FSV2iJ+3qQ6lpxgt8Dd9rS+xa8SS1rga/nTG5eqJqfq1fDyKXF+TpbHbNO09QdWZjRTcvv1DNCd51FyWUsFojECjoY0KmyjxJCmVyKgdvWjW/9DHiP0a1MS1ILtREr873D5SiQlKKj8T1AaVs7tToZNtZWxE2U4L4ibWYiWoJnVMi85t0nGj2NNBsVJsYhAb5fh5Uj5La9R3nR7RrkCLCHOKzuZu6VkWIQcObFCgb5G80DDt9Vp8uiNDCMwMLZA2HPi4CpGjWEfgHbvYEbgRNZIQcJhid12HscjEChLN4uvdp+9TiQwFsTm3kSBgflERFOdX4qbJMy/XQz8FEgUb2E8/lo3P3DMUeYhNXNGO6jmBvknNBv6XXjhhOFBa9xmT1jnjakSpKBWvICIWqLFmi8MByldqTW7oJKNpDH4qI4ML0goPaZ9ketlGs8PUwr1d4bCR/Dm79VTuiiUNw+i0J4sQrs2ufkEtuBQfBmHywVhl/sDS/3A7vUZWZ+2Cb+9qssAGjEy424anWRdkFx/x+m+9Zreb2tkXDlofEd18fCNbqAZzVTYAoDlQUmen1IJOEhWPpC724p3wyv8Y2SN1pMunPQ7ThmuPEB/hOSEQ== hi@bradparker.com&amp;quot;
    ];
  };
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above file describes a &lt;a href="https://nixos.wiki/wiki/Module"&gt;Nix module&lt;/a&gt; which will create a user able to log into the machine using SSH. I've also made sure that only key pairs can be used for SSH authentication and it's not possible to log in directly as the root user. In order to run commands as root I first have to SSH in and then elevate my privileges using &lt;code&gt;sudo&lt;/code&gt;. In order to do this I've given my user a password by providing the &lt;code&gt;hashedPassword&lt;/code&gt; option. I generated a value for this by using &lt;code&gt;openssl&lt;/code&gt; on my local machine.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ openssl passwd -1
Password: &amp;lt;Type a password&amp;gt;
Verifying - Password: &amp;lt;Type it again&amp;gt;
$1$JO1.bEGj$69.Gdj1/utBcmwRJYGu741&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;mutableUsers&lt;/code&gt; option means that users or groups created with &lt;code&gt;useradd&lt;/code&gt; or &lt;code&gt;groupadd&lt;/code&gt; won't be persisted when Nix rebuilds the system.&lt;/p&gt;
&lt;p&gt;Now, I'm going to want to &lt;em&gt;update&lt;/em&gt; an existing server after it's been created from time to time. The way I do this is by modifying a local &lt;code&gt;host.nix&lt;/code&gt; file, &lt;a href="https://rsync.samba.org/"&gt;&lt;code&gt;rsync&lt;/code&gt;&lt;/a&gt;-ing it up onto the server, using ssh to move it to &lt;code&gt;/etc/nixos/&lt;/code&gt; as root and running &lt;code&gt;nixos-rebuild switch&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="bash"&gt;&lt;code&gt;#!/usr/bin/env bash

set -exo pipefail

rsync host.nix bradparker.com:host.nix
ssh -t bradparker.com \
  &amp;#39;sudo mv host.nix /etc/nixos/host.nix &amp;amp;&amp;amp; sudo nixos-rebuild switch&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The whole server is administered using a local &lt;code&gt;host.nix&lt;/code&gt; file and the above script.&lt;/p&gt;
&lt;h2 id="next-a-static-site"&gt;Next, a static site&lt;/h2&gt;
&lt;p&gt;For the static site I wanted the "push to deploy" experience of Github pages. To achieve this firstly I built a Nix &lt;a href="https://github.com/bradparker/bradparker.com/blob/source/site/default.nix"&gt;derivation&lt;/a&gt; which describes, in full, how to build my static site. That derivation depends on &lt;a href="https://github.com/bradparker/bradparker.com/blob/source/builder/default.nix"&gt;another one&lt;/a&gt; which describes, in full, how to build the &lt;em&gt;builder&lt;/em&gt; for my site. As an aside, herein lies one of the killer features of Nix over similar tools: it composes. I'll only need to say that I want the site built and builder will be brought along for the ride. Once I had a derivation for my site I then defined a &lt;a href="https://freedesktop.org/wiki/Software/systemd/"&gt;systemd&lt;/a&gt; service to build it every five minutes.&lt;/p&gt;
&lt;pre class="nix"&gt;&lt;code&gt;{ options, lib, config, pkgs, ... }:
let
  serverName = &amp;quot;bradparker.com&amp;quot;;
  webRoot = &amp;quot;/var/www/${serverName}&amp;quot;;

  serviceConfig = config.services.&amp;quot;${serverName}&amp;quot;;
  options = {
    enable = lib.mkEnableOption &amp;quot;${serverName} service&amp;quot;;
  };
in
  {
    options.services.${serverName} = options;
    config = lib.mkIf serviceConfig.enable {
      systemd.services.&amp;quot;source-${serverName}&amp;quot; = {
        description = &amp;#39;&amp;#39;
          https://${serverName} source
        &amp;#39;&amp;#39;;
        serviceConfig = {
          Type = &amp;quot;oneshot&amp;quot;;
        };
        startAt = &amp;quot;*:0/5&amp;quot;;
        path = with pkgs; [ nix gnutar gzip curl jq ];
        script = &amp;#39;&amp;#39;
          set -ex

          rev=$(curl https://api.github.com/repos/bradparker/bradparker.com/git/ref/heads/source | jq -r .object.sha)
          result=$(nix-build https://github.com/bradparker/bradparker.com/archive/$rev.tar.gz -A bradparker-com.site)

          ln -sfT $result${webRoot} ${webRoot}
        &amp;#39;&amp;#39;;
      };
    };
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I curl the Github API to get the revision at the &lt;code&gt;HEAD&lt;/code&gt; of my "source" branch, and call &lt;code&gt;nix-build&lt;/code&gt; directly on the archive tarball for that revision. The web root symlink is then updated to point at the result. Fetching the latest revision rather than just using the tarball URL for the "source" branch means that Nix can still cache aggressively.&lt;/p&gt;
&lt;p&gt;To make it possible to update my host configuration and this service configuration separately I've put the service configuration in a separate file (&lt;a href="https://github.com/bradparker/bradparker.com/blob/source/module.nix"&gt;module.nix&lt;/a&gt;) that I fetch and import in host.nix.&lt;/p&gt;
&lt;pre class="nix"&gt;&lt;code&gt;{ config, pkgs, ... }:
let
  bradparker-source = builtins.fetchTarball {
    url = https://github.com/bradparker/bradparker.com/archive/355cf315becbf39ad7d3d032a88fe913ea0c4565.tar.gz;
  };
in
{
  imports = [&amp;quot;${bradparker-source}/module.nix&amp;quot;];

  # See above for user config.

  services.&amp;quot;bradparker.com&amp;quot;.enable = true;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="finally-a-web-server"&gt;Finally, a web server&lt;/h2&gt;
&lt;p&gt;At this stage the sensible thing to have done would have been to use the excellent &lt;a href="https://nixos.wiki/wiki/Nginx"&gt;Nginx NixOs module&lt;/a&gt;. I'd have auto-renewing SSL certificates (&lt;a href="https://tools.ietf.org/html/draft-ietf-acme-acme-18"&gt;ACME&lt;/a&gt;) and a speedy web server in six lines of code. But I didn't do that, I wanted to see what it'd be like to use the Haskell web-server &lt;a href="https://hackage.haskell.org/package/warp"&gt;Warp&lt;/a&gt; to serve my site, even including painless HTTPS.&lt;/p&gt;
&lt;p&gt;I needed to write some Haskell for both the application to &lt;a href="https://github.com/bradparker/bradparker.com/blob/source/server/Main.hs"&gt;serve the static site&lt;/a&gt; and one to &lt;a href="https://github.com/bradparker/bradparker.com/blob/source/acme/Main.hs"&gt;serve ACME challenges&lt;/a&gt; in order to get auto-renewing certificates. Being that I love writing Haskell this was OK with me.&lt;/p&gt;
&lt;p&gt;With those written I then needed some systemd services to run them. One for the static site.&lt;/p&gt;
&lt;pre class="nix"&gt;&lt;code&gt;{ options, lib, config, pkgs, ... }:
let
  package = import ./.;
  server = package.bradparker-com.server;

  serverName = &amp;quot;bradparker.com&amp;quot;;
  webRoot = &amp;quot;/var/www/${serverName}&amp;quot;;

  serviceConfig = config.services.&amp;quot;${serverName}&amp;quot;;
  options = {
    enable = lib.mkEnableOption &amp;quot;${serverName} service&amp;quot;;
  };
in
  {
    options.services.${serverName} = options;
    config = lib.mkIf serviceConfig.enable {
      # ... Source service definition

      systemd.services.${serverName} = {
        wantedBy = [ &amp;quot;multi-user.target&amp;quot; ];
        wants = [
          &amp;quot;acme-${serverName}.service&amp;quot;
          &amp;quot;acme-challenge-${serverName}.service&amp;quot;
        ];
        requires = [&amp;quot;source-${serverName}.service&amp;quot;];
        script = &amp;#39;&amp;#39;
          ${server}/bin/server \
            --port 443 \
            --directory /var/www/${serverName} \
            --https-cert-file /var/lib/acme/${serverName}/fullchain.pem \
            --https-key-file /var/lib/acme/${serverName}/key.pem
        &amp;#39;&amp;#39;;
        description = &amp;#39;&amp;#39;
          https://${serverName}
        &amp;#39;&amp;#39;;
        serviceConfig = {
          KillSignal=&amp;quot;INT&amp;quot;;
          Type = &amp;quot;simple&amp;quot;;
          Restart = &amp;quot;on-abort&amp;quot;;
          RestartSec = &amp;quot;10&amp;quot;;
        };
      };
    };
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; I've put all the Nix derivations into a &lt;a href="https://github.com/bradparker/bradparker.com/blob/source/default.nix"&gt;set&lt;/a&gt; so I can import them as a whole.&lt;/p&gt;
&lt;p&gt;And a service for the ACME challenges.&lt;/p&gt;
&lt;pre class="nix"&gt;&lt;code&gt;{ options, lib, config, pkgs, ... }:
let
  package = import ./.;
  acme = package.bradparker-com.acme;

  serverName = &amp;quot;bradparker.com&amp;quot;;
  acmeWebRoot =  &amp;quot;/var/lib/acme/acme-challenge&amp;quot;;

  serviceConfig = config.services.&amp;quot;${serverName}&amp;quot;;
  options = {
    enable = lib.mkEnableOption &amp;quot;${serverName} service&amp;quot;;
  };
in
  {
    options.services.${serverName} = options;
    config = lib.mkIf serviceConfig.enable {
      # ... Source service definition
      # ... Static site server service definition

      systemd.services.&amp;quot;acme-challenge-${serverName}&amp;quot; = {
        wantedBy = [ &amp;quot;multi-user.target&amp;quot; ];
        script = &amp;#39;&amp;#39;
          ${acme}/bin/acme \
            --port 80 \
            --directory ${acmeWebRoot}
        &amp;#39;&amp;#39;;
        description = &amp;#39;&amp;#39;
          The acme challenge server
        &amp;#39;&amp;#39;;
        serviceConfig = {
          KillSignal=&amp;quot;INT&amp;quot;;
          Type = &amp;quot;simple&amp;quot;;
          Restart = &amp;quot;on-abort&amp;quot;;
          RestartSec = &amp;quot;10&amp;quot;;
        };
      };
    };
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To go with that I needed to enable and configure the ACME service itself.&lt;/p&gt;
&lt;pre class="nix"&gt;&lt;code&gt;{ options, lib, config, pkgs, ... }:
let
  serverName = &amp;quot;bradparker.com&amp;quot;;
  acmeWebRoot =  &amp;quot;/var/lib/acme/acme-challenge&amp;quot;;

  serviceConfig = config.services.&amp;quot;${serverName}&amp;quot;;
  options = {
    enable = lib.mkEnableOption &amp;quot;${serverName} service&amp;quot;;
  };
in
  {
    options.services.${serverName} = options;
    config = lib.mkIf serviceConfig.enable {
      # ... Source service definition
      # ... Static site server service definition
      # ... ACME challenge server service definition

      security.acme.certs = {
        ${serverName} = {
          email = &amp;quot;hi@bradparker.com&amp;quot;;
          webroot = &amp;quot;${acmeWebRoot}&amp;quot;;
          extraDomains = { &amp;quot;bradparker.com.au&amp;quot; = null; };
          postRun = &amp;quot;systemctl restart ${serverName}.service&amp;quot;;
        };
      };
    };
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, I needed to open the default HTTP and HTTPS ports in NixOs' firewall. I did this in the host.nix file rather than the module file.&lt;/p&gt;
&lt;pre class="nix"&gt;&lt;code&gt;{ config, pkgs, ... }:
let
  # ... Fetching source
in
{
  # ... User config, importing the module

  networking.firewall.allowedTCPPorts = [ 80 443 ];

  # ... Enabling the service
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="hey-presto"&gt;Hey, presto&lt;/h2&gt;
&lt;p&gt;That's it. I'm pretty happy with the result thus far and will likely continue to tweak it. If you haven't yet checked out Nix or NixOs I encourage you to do so, I think it's great.&lt;/p&gt;</description><author>hi@bradparker.id.au (Brad Parker)</author><guid>https://bradparker.com/content/posts/2019-11-21-deploying-a-fully-automated-nix-based-static-website.html</guid><pubDate>Thu, 21 Nov 2019 00:00:00 UTC</pubDate></item><item><title>Servant's type-level domain specific language</title><link>https://bradparker.id.au/posts/servant-types</link><description>&lt;p&gt;This post is about some reasonably advanced type-level features of &lt;a href="https://www.haskell.org/ghc/"&gt;The Glasgow Haskell Compiler&lt;/a&gt; and as such I assume &lt;em&gt;some&lt;/em&gt; knowledge of Haskell. Despite this I've made an attempt to link to further resources on Haskell features as I introduce them. My hope is that even if &lt;em&gt;everything&lt;/em&gt; here doesn't make perfect sense then at least some part of it might still be helpful.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;I was shown &lt;a href="https://hackage.haskell.org/package/servant"&gt;Servant&lt;/a&gt; by a friend of mine not long after I'd started to learn Haskell. It was still new to me but one of the things that had really grabbed me about Haskell was its transparency. Without being very familiar with the language I found that I could tease out how some function or data structure worked just by poking around. Now I've spent a little time building &lt;a href="https://github.com/bradparker/servant-beam-realworld-example-app/"&gt;stuff&lt;/a&gt; with Servant I'd like to see what can be learned by having a closer look at some of &lt;em&gt;its&lt;/em&gt; functions and data structures. It's an interesting library, I think this'll be fun.&lt;/p&gt;
&lt;p&gt;Servant has you define your API as a type. You're not expected to define a wholly &lt;em&gt;new&lt;/em&gt; type, but rather combine existing types provided by the framework. These add up to a domain specific language, at the type level, for describing web APIs. This was quite a mental shift for me, that the type comes first, and drives the implementation. It's just so great that Servant's DSL is expressive enough to describe almost any API you might want to implement.&lt;/p&gt;
&lt;p&gt;Our aim here will be to understand &lt;em&gt;how&lt;/em&gt; Servant can take so many varied API descriptions and guide us to a corresponding implementation.&lt;/p&gt;
&lt;h2 id="the-example-type"&gt;The example type&lt;/h2&gt;
&lt;p&gt;The example we'll use is close to the one used in Servant's introductory tutorial. We're going to describe an API which has two endpoints: &lt;code&gt;GET /users&lt;/code&gt; which returns a JSON-encoded list of users and &lt;code&gt;GET /users/:username&lt;/code&gt; which returns the user, again JSON-encoded, for a corresponding username.&lt;/p&gt;
&lt;p&gt;We'll make use of &lt;a href="https://wiki.haskell.org/Type_synonym"&gt;type synonyms&lt;/a&gt; to group and give logical names to our API's sub-components.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}

import Servant
  ( (:&amp;lt;|&amp;gt;)
  , (:&amp;gt;)
  , Capture
  , Get
  , JSON
  )

type UsersIndex =
  Get &amp;#39;[JSON] [User]

type UsersShow =
  Capture &amp;quot;username&amp;quot; String
    :&amp;gt; Get &amp;#39;[JSON] User

type UsersAPI =
  &amp;quot;users&amp;quot;
    :&amp;gt; (UsersIndex :&amp;lt;|&amp;gt; UsersShow)&lt;/code&gt;&lt;/pre&gt;
&lt;figcaption&gt;
  &lt;a target="_blank" href="https://github.com/bradparker/how-does-servants-type-dsl-work/commit/01-users-api-type"&gt;
    Commit
  &lt;/a&gt;
&lt;/figcaption&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; for each code example I'll try to show only the bits of the finished module which are relevant to what's being currently discussed. Below some code samples you'll see a "commit" annotation which will link to a matching diff in the example &lt;a href="https://github.com/bradparker/how-does-servants-type-dsl-work"&gt;repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This first code example already contains a few type-level features that likely look interesting. Let's take a closer look.&lt;/p&gt;
&lt;h2 id="type-literals"&gt;Type literals&lt;/h2&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;Capture &amp;quot;username&amp;quot; String
        ~~~~~~~~~~&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;GHC supports both &lt;a href="https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-TypeLits.html#t:Nat"&gt;numeric&lt;/a&gt; and &lt;a href="https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-TypeLits.html#t:Symbol"&gt;string-like&lt;/a&gt; &lt;a href="https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#type-level-literals"&gt;type level literals&lt;/a&gt;. Of the greatest interest to us are the string-like type literals.&lt;/p&gt;
&lt;p&gt;The first thing to note about these are that unlike most types we encounter in Haskell type-level string literals are not of kind &lt;code&gt;Type&lt;/code&gt; but rather &lt;code&gt;Symbol&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; I'm using the extension &lt;code&gt;NoStarIsType&lt;/code&gt; to replace &lt;code&gt;*&lt;/code&gt; with &lt;code&gt;Type&lt;/code&gt; when talking about kinds.&lt;/p&gt;
&lt;p&gt;Another important thing to keep in mind is that each unique value is a different type. Or put another way, the &lt;em&gt;type&lt;/em&gt; &lt;code&gt;"foo"&lt;/code&gt; is distinct from the &lt;em&gt;type&lt;/em&gt; &lt;code&gt;"bar"&lt;/code&gt;. When talking about these types as a whole it's helpful to step up to the kind layer and refer to them as &lt;code&gt;Symbol&lt;/code&gt;s. For example: &lt;code&gt;"foo"&lt;/code&gt; and &lt;code&gt;"bar"&lt;/code&gt; are different types, but they're both &lt;code&gt;Symbol&lt;/code&gt;s.&lt;/p&gt;
&lt;p&gt;When working with Servant, &lt;code&gt;Symbol&lt;/code&gt;s are used to easily define things like static route segments, as well as named route and query parameters. &lt;code&gt;Symbol&lt;/code&gt;s can be brought down from the type level to strings at the value level. This means that Servant is able to extract &lt;em&gt;data&lt;/em&gt; from API types for use at run time. More on this later.&lt;/p&gt;
&lt;h2 id="data-type-promotion"&gt;Data type promotion&lt;/h2&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;Get &amp;#39;[JSON] [User]
    ~~~~~~~&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We don't have to be content with only strings and numbers moving up to the type level, by enabling the &lt;a href="https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-DataKinds"&gt;&lt;code&gt;DataKinds&lt;/code&gt;&lt;/a&gt; language extension many other data types will become available for use up there too. Servant makes use of type level lists in some parts of its API.&lt;/p&gt;
&lt;p&gt;The "tick" (&lt;code&gt;'&lt;/code&gt;) prefix is used to disambiguate type-level lists and the type of value-level lists. This is required in situations where GHC might need a hint to tell what is meant by, say:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;[Int]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Is that the type for a list of &lt;code&gt;Int&lt;/code&gt;, or is that a type level list with only one element, &lt;code&gt;Int&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;Similar to &lt;code&gt;Symbol&lt;/code&gt; types like &lt;code&gt;'[Int]&lt;/code&gt; and &lt;code&gt;'[Bool]&lt;/code&gt; are not of kind &lt;code&gt;Type&lt;/code&gt;. Those particular examples are of kind &lt;code&gt;[Type]&lt;/code&gt;. It's worth noting, however, that the contents of a type level list need not always be of kind &lt;code&gt;Type&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; &amp;gt; :kind &amp;#39;[Maybe]
&amp;#39;[Maybe] :: [Type -&amp;gt; Type]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we ask GHCi for the kind of &lt;code&gt;'[]&lt;/code&gt; we see something interesting.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; &amp;gt; :kind &amp;#39;[]
&amp;#39;[] :: [k]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This shows us that type level lists are &lt;a href="https://downloads.haskell.org/~ghc/7.8.4/docs/html/users_guide/kind-polymorphism.html"&gt;kind polymorphic&lt;/a&gt;. That &lt;code&gt;k&lt;/code&gt; is a kind variable, as with &lt;a href="https://wiki.haskell.org/Type_variables_instead_of_concrete_types"&gt;type variables&lt;/a&gt; these are introduced by an implicit &lt;code&gt;forall&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;&amp;#39;[] :: forall k. &amp;#39;[k]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Just as the &lt;em&gt;type&lt;/em&gt; for value-level lists is parameterized over some arbitrary other type.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; &amp;gt; :type []
[] :: [a]

 &amp;gt; :type [1, 2, 3]
[1, 2, 3] :: Num a =&amp;gt; [a]

 &amp;gt; :type [(+ 1), (+ 2), (+ 3)]
[(+ 1), (+ 2), (+ 3)] :: Num a =&amp;gt; [a -&amp;gt; a]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;em&gt;kind&lt;/em&gt; for type-level lists is parameterized over some arbitrary other kind.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; &amp;gt; :kind &amp;#39;[]
&amp;#39;[] :: [k]

 &amp;gt; :kind &amp;#39;[(), Bool, Ordering]
&amp;#39;[(), Bool, Ordering] :: [Type]

 &amp;gt; :kind &amp;#39;[Either (), Either Bool, Either Ordering]
&amp;#39;[Either (), Either Bool, Either Ordering] :: [Type -&amp;gt; Type]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Servant uses type level lists for a couple of purposes. In this post we'll see how they can help us specify the set of content types a given API can accept and return.&lt;/p&gt;
&lt;h2 id="type-operators"&gt;Type operators&lt;/h2&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;type UsersAPI =
  &amp;quot;users&amp;quot;
    :&amp;gt; (UsersIndex :&amp;lt;|&amp;gt; UsersShow)
    ~~             ~~~~&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By enabling the &lt;a href="https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-TypeOperators"&gt;&lt;code&gt;TypeOperators&lt;/code&gt;&lt;/a&gt; extension we can write infix &lt;a href="https://wiki.haskell.org/Constructor#Type_constructor"&gt;type constructors&lt;/a&gt; in much same the way that we can &lt;a href="https://wiki.haskell.org/Infix_operator"&gt;value-level infix functions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As with value-level infix operators, type operators have a &lt;a href="https://en.wikipedia.org/wiki/Order_of_operations"&gt;precedence&lt;/a&gt; relative to other operators and can &lt;a href="https://en.wikipedia.org/wiki/Operator_associativity"&gt;associate&lt;/a&gt; to the left or right. The syntax for defining these properties for a given type operator is the same as for value-level operators.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;(f . g) a = f (g a)

infixr 9 .

type (f ∘ g) a = f (g a)

infixr 9 ∘&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="putting-it-to-use"&gt;Putting it to use&lt;/h2&gt;
&lt;p&gt;As &lt;code&gt;UsersAPI&lt;/code&gt; is the type for an API which serves users we'll need to define what a &lt;code&gt;User&lt;/code&gt; is.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;{-# LANGUAGE DeriveGeneric #-}

import Data.Time (Day)
import GHC.Generics (Generic)

data User = User
  { name :: String
  , age :: Int
  , email :: String
  , username :: String
  , registrationDate :: Day
  } deriving (Generic)&lt;/code&gt;&lt;/pre&gt;
&lt;figcaption&gt;
  &lt;a target="_blank" href="https://github.com/bradparker/how-does-servants-type-dsl-work/commit/02-user-type"&gt;
    Commit
  &lt;/a&gt;
&lt;/figcaption&gt;

&lt;p&gt;We're deriving a &lt;a href="https://wiki.haskell.org/GHC.Generics"&gt;&lt;code&gt;Generic&lt;/code&gt;&lt;/a&gt; instance for use later, it just helps to get it out-of-the-way now.&lt;/p&gt;
&lt;p&gt;At the end of the day a runnable Haskell program is a value of type &lt;code&gt;IO ()&lt;/code&gt;. So how do we get from &lt;code&gt;UsersAPI&lt;/code&gt; to one of those? The &lt;a href="https://hackage.haskell.org/package/servant-server"&gt;servant-server&lt;/a&gt; package provides us a few functions for turning types like &lt;code&gt;UsersAPI&lt;/code&gt; into &lt;a href="https://hackage.haskell.org/package/wai"&gt;WAI&lt;/a&gt; &lt;code&gt;Application&lt;/code&gt;s. The simplest of these is &lt;a href="https://hackage.haskell.org/package/servant-server-0.16.2/docs/Servant-Server.html#v:serve"&gt;&lt;code&gt;serve&lt;/code&gt;&lt;/a&gt;, so that's what we'll go with.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;serve
  :: HasServer api &amp;#39;[]
  =&amp;gt; Proxy api
  -&amp;gt; ServerT api Handler
  -&amp;gt; Application&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;a href="https://hackage.haskell.org/package/warp"&gt;warp&lt;/a&gt; package provides a &lt;code&gt;run&lt;/code&gt; function which gets us from an &lt;code&gt;Application&lt;/code&gt; to a &lt;code&gt;IO ()&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;run :: Port -&amp;gt; Application -&amp;gt; IO ()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In order for &lt;code&gt;serve&lt;/code&gt; to return an &lt;code&gt;Application&lt;/code&gt; we'll need to give it two things. The first is a &lt;code&gt;Proxy&lt;/code&gt; of our &lt;code&gt;UsersAPI&lt;/code&gt; type. If you've seen types like &lt;code&gt;Map a&lt;/code&gt; or &lt;code&gt;Set a&lt;/code&gt; before you might think that a &lt;code&gt;Proxy a&lt;/code&gt; is some sort of container. &lt;code&gt;Proxy&lt;/code&gt; is &lt;em&gt;sort&lt;/em&gt; of a container, but rather a than for carrying around values it's for carrying around types.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;data Proxy (t :: k) = Proxy&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;See that the only data constructor, also called &lt;code&gt;Proxy&lt;/code&gt;, is nullary. At the value level it's empty, but at the type level it contains some &lt;code&gt;t&lt;/code&gt; of kind &lt;code&gt;k&lt;/code&gt;. Values of &lt;code&gt;Proxy&lt;/code&gt; are made easier to construct with the help of the &lt;code&gt;TypeApplications&lt;/code&gt; language extension. Using &lt;code&gt;TypeApplications&lt;/code&gt; we can make explicit the types which are inferred and applied to our expressions.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; &amp;gt; :t Proxy
Proxy :: Proxy t
 &amp;gt; :t Proxy @Int
Proxy @Int :: Proxy Int
 &amp;gt; :t Proxy @UsersAPI
Proxy @UsersAPI :: Proxy UsersAPI&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;Proxy @UsersAPI&lt;/code&gt; argument is needed by &lt;code&gt;serve&lt;/code&gt; for slightly obscure reasons, but for our purposes it's enough to say that it's a value which carries the &lt;code&gt;UsersAPI&lt;/code&gt; type around.&lt;/p&gt;
&lt;p&gt;Producing a value for the second argument will be the topic of this post. We can use a &lt;a href="https://downloads.haskell.org/~ghc/7.10.1/docs/html/users_guide/typed-holes.html"&gt;typed hole&lt;/a&gt; for now, giving us enough for a skeleton &lt;code&gt;main&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;{-# LANGUAGE TypeApplications #-}

import Data.Proxy (Proxy(Proxy))
import Network.Wai (Application)
import Network.Wai.Handler.Warp (run)
import Servant (serve)

usersApp :: Application
usersApp = serve (Proxy @UsersAPI) _usersServer

main :: IO ()
main = run 8080 usersApp&lt;/code&gt;&lt;/pre&gt;
&lt;figcaption&gt;
  &lt;a target="_blank" href="https://github.com/bradparker/how-does-servants-type-dsl-work/commit/03-main"&gt;
    Commit
  &lt;/a&gt;
&lt;/figcaption&gt;

&lt;p&gt;Trying to compile what we have so far will result in two errors. The first is complaining about a missing instance.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;• No instance for (ToJSON User) arising from a use of ‘serve’
• In the expression: serve (Proxy @Users) _usersServer
  In an equation for ‘usersApp’:
      usersApp = serve (Proxy @Users) _usersServer&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The second tells us the type of the &lt;code&gt;_usersServer&lt;/code&gt; value we've yet to define.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;• Found hole:
    _usersServer
      :: Handler [User] :&amp;lt;|&amp;gt; ([Char] -&amp;gt; Handler User)
  Or perhaps ‘_usersServer’ is mis-spelled, or not in scope
• In the second argument of ‘serve’, namely ‘_usersServer’
  In the expression: serve (Proxy @Users) _usersServer
  In an equation for ‘usersApp’:
      usersApp = serve (Proxy @Users) _usersServer&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We'll come back to why we're being asked about &lt;a href="https://hackage.haskell.org/package/aeson-1.4.5.0/docs/Data-Aeson.html#t:ToJSON"&gt;&lt;code&gt;ToJSON&lt;/code&gt;&lt;/a&gt; instances but for now we'll just give Servant what it wants.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;import Data.Aeson (ToJSON)

instance ToJSON User&lt;/code&gt;&lt;/pre&gt;
&lt;figcaption&gt;
  &lt;a target="_blank" href="https://github.com/bradparker/how-does-servants-type-dsl-work/commit/04-to-json-instance"&gt;
    Commit
  &lt;/a&gt;
&lt;/figcaption&gt;

&lt;h2 id="a-servers-type"&gt;A Server's type&lt;/h2&gt;
&lt;p&gt;We will try to understand where that &lt;code&gt;ToJSON&lt;/code&gt; requirement came from but first we're going to focus on the typed hole. I think asking GHCi what the type of &lt;code&gt;serve&lt;/code&gt; is when partially applied with a &lt;code&gt;Proxy UsersAPI&lt;/code&gt; is instructive here.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; &amp;gt; :t serve (Proxy @UsersAPI)
serve (Proxy @UsersAPI)
  :: (Handler [User] :&amp;lt;|&amp;gt; ([Char] -&amp;gt; Handler User))
     -&amp;gt; Application&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is interesting. In the type of &lt;code&gt;serve&lt;/code&gt; where previously there was a &lt;code&gt;ServerT api Handler&lt;/code&gt; there is now a &lt;code&gt;Handler [User] :&amp;lt;|&amp;gt; ([Char] -&amp;gt; Handler User)&lt;/code&gt;. Where did it come from?&lt;/p&gt;
&lt;p&gt;Recall that &lt;code&gt;serve&lt;/code&gt; has the following type.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;serve
  :: forall api
   . HasServer api &amp;#39;[]
  =&amp;gt; Proxy api
  -&amp;gt; ServerT api Handler
  -&amp;gt; Application&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There's a type variable &lt;code&gt;api&lt;/code&gt;, which is constrained to be types with a &lt;code&gt;HasServer&lt;/code&gt; instance. There's then two arguments, both referring to that constrained &lt;code&gt;api&lt;/code&gt; type. We've been able to produce a value for the first using &lt;code&gt;Proxy @UserAPI&lt;/code&gt;, a value for the second will take a little more doing.&lt;/p&gt;
&lt;p&gt;I mean, what is &lt;code&gt;ServerT&lt;/code&gt;? Why does it disappear when &lt;code&gt;UsersAPI&lt;/code&gt; is substituted for &lt;code&gt;api&lt;/code&gt;? It can't be a type constructor, type constructors don't just disappear. What does GHCi have to say about it?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; &amp;gt; :info ServerT
class HasServer (api :: k)
                (context :: [Type]) where
  type family ServerT (api :: k) (m :: Type -&amp;gt; Type) :: Type
  ...
        -- Defined in ‘Servant.Server.Internal’&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;ServerT&lt;/code&gt; is a &lt;a href="https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#type-families"&gt;type family&lt;/a&gt;. Type families look quite like type constructors. Like type constructors they accept types as arguments, unlike type constructors they're able to return different types depending on those arguments. It ends up looking something like a function which &lt;a href="https://en.wikibooks.org/wiki/Haskell/Pattern_matching"&gt;pattern matches&lt;/a&gt; on types.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ServerT&lt;/code&gt; is part of the &lt;code&gt;HasServer&lt;/code&gt; &lt;a href="https://en.wikibooks.org/wiki/Haskell/Classes_and_types"&gt;type class&lt;/a&gt;, therefore it will be defined for any type which has a &lt;code&gt;HasServer&lt;/code&gt; instance. It accepts the poly kinded &lt;code&gt;api&lt;/code&gt; type &lt;code&gt;HasServer&lt;/code&gt; is parameterized over as its first argument and some type constructor &lt;code&gt;m&lt;/code&gt; of kind &lt;code&gt;Type -&amp;gt; Type&lt;/code&gt; as its second. It then returns some type of kind &lt;code&gt;Type&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;GHCi allows us to evaluate type families, to see what the resulting type is at different type arguments.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; &amp;gt; :kind! ServerT Users Handler
ServerT UsersAPI Handler :: Type
= Handler [User] :&amp;lt;|&amp;gt; ([Char] -&amp;gt; Handler User)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we can see how &lt;code&gt;UsersAPI&lt;/code&gt; becomes &lt;code&gt;Handler [User] :&amp;lt;|&amp;gt; ([Char] -&amp;gt; Handler User)&lt;/code&gt; when substituted for &lt;code&gt;api&lt;/code&gt; in the type of &lt;code&gt;serve&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But that's not super satisfying to me. I feel like we're skipping a few steps. I'd like to see if we can find out what those steps are.&lt;/p&gt;
&lt;p&gt;One of the great advantages of referentially transparent languages like Haskell is that if we want to &lt;em&gt;see&lt;/em&gt; how an expression is evaluated we can do the evaluating ourselves, manually. We can substitute values for function parameters and continue evaluating the resulting expressions until we're only left with values. We'll attempt to apply this strategy to see what happens when &lt;code&gt;UsersAPI&lt;/code&gt; is applied to &lt;code&gt;ServerT&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="stepping-through"&gt;Stepping through&lt;/h3&gt;
&lt;p&gt;When &lt;code&gt;UsersAPI&lt;/code&gt; is substituted for &lt;code&gt;api&lt;/code&gt; in the type of &lt;code&gt;serve&lt;/code&gt; the &lt;code&gt;ServerT&lt;/code&gt; type family is evaluated with it as its first argument and the &lt;code&gt;Handler&lt;/code&gt; type as its second.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;ServerT UsersAPI Handler&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As &lt;code&gt;ServerT&lt;/code&gt; is part of the &lt;code&gt;HasServer&lt;/code&gt; type class there is a &lt;code&gt;ServerT&lt;/code&gt; implementation for each &lt;code&gt;HasServer&lt;/code&gt; instance. For us to figure out which &lt;code&gt;ServerT&lt;/code&gt; to use we'll need to know which &lt;code&gt;HasServer&lt;/code&gt; instance to grab it from. This means that not only are we going to be evaluating calls to &lt;code&gt;ServerT&lt;/code&gt; ourselves, but we're also going to have to resolve type class instances too. How do we find the right &lt;code&gt;HasServer&lt;/code&gt; instance for &lt;code&gt;UsersAPI&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;We can start by asking &lt;code&gt;GHCi&lt;/code&gt; to tell us everything is knows about &lt;code&gt;UsersAPI&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; &amp;gt; :info UsersAPI
type UsersAPI = &amp;quot;users&amp;quot; :&amp;gt; (UsersIndex :&amp;lt;|&amp;gt; UsersShow)
        -- Defined at src/Main.hs:75:1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;GHCi knows that &lt;code&gt;UsersAPI&lt;/code&gt; is a type synonym and helpfully shows us its definition.&lt;/p&gt;
&lt;p&gt;We still don't have a &lt;code&gt;HasServer&lt;/code&gt; instance, so we'll ask GHCi what it knows about the type that &lt;code&gt;UsersAPI&lt;/code&gt; is a synonym &lt;em&gt;for&lt;/em&gt;. Sadly, we can't pass the whole type to &lt;code&gt;:info&lt;/code&gt;, we can only ask about things like type families or type constructors when unapplied. So we'll need to start with the outermost type constructor, &lt;code&gt;(:&amp;gt;)&lt;/code&gt;, and go from there.&lt;/p&gt;
&lt;p&gt;The instance we're interested in will only show up if we import a couple of modules first.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; &amp;gt; import GHC.TypeLits
 &amp;gt; import Servant (HasServer)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can now expect &lt;code&gt;:info&lt;/code&gt; to tell us about the &lt;code&gt;HasServer&lt;/code&gt; instances relevant to &lt;code&gt;Symbol&lt;/code&gt;s and &lt;code&gt;(:&amp;gt;)&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; &amp;gt; :info (:&amp;gt;)
type role (:&amp;gt;) phantom phantom
data (:&amp;gt;) (path :: k) a
        -- Defined in ‘Servant.API.Sub’
infixr 4 :&amp;gt;
instance (KnownSymbol path, HasServer api context) =&amp;gt;
         HasServer (path :&amp;gt; api) context
  -- Defined in ‘Servant.Server.Internal’
instance forall k l (arr :: k -&amp;gt; l) api (context :: [Type]).
         (TypeError ...) =&amp;gt;
         HasServer (arr :&amp;gt; api) context
  -- Defined in ‘Servant.Server.Internal’&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that we're being shown &lt;em&gt;two&lt;/em&gt; &lt;code&gt;HasServer&lt;/code&gt; instances for &lt;code&gt;(:&amp;gt;)&lt;/code&gt;, and it actually has many more than these, but for now we're only interested in one of them.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;instance
  ( KnownSymbol path
  , HasServer api context
  ) =&amp;gt;
    HasServer (path :&amp;gt; api) context&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;How do I know that &lt;em&gt;this&lt;/em&gt; is the relevant instance?&lt;/p&gt;
&lt;p&gt;&lt;a href="https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-TypeLits.html#t:KnownSymbol"&gt;&lt;code&gt;KnownSymbol&lt;/code&gt;&lt;/a&gt; is a special type class definable only for types of kind &lt;code&gt;Symbol&lt;/code&gt;. It allows us to "read" type-level &lt;code&gt;Symbol&lt;/code&gt;s into value-level &lt;code&gt;String&lt;/code&gt;s.&lt;/p&gt;
&lt;p&gt;Seeing it in that instance head tells me that &lt;code&gt;path&lt;/code&gt; is a &lt;code&gt;Symbol&lt;/code&gt;, it couldn't have a &lt;code&gt;KnownSymbol&lt;/code&gt; instance if it were anything else. &lt;code&gt;UsersAPI&lt;/code&gt; has the &lt;code&gt;Symbol&lt;/code&gt; &lt;code&gt;"users"&lt;/code&gt; to the left of &lt;code&gt;(:&amp;gt;)&lt;/code&gt; so it's a good match.&lt;/p&gt;
&lt;p&gt;GHCi is able to tell us about type family instances for types, however in our case the output doesn't emphasize that &lt;code&gt;ServerT&lt;/code&gt; instances &lt;em&gt;belong to&lt;/em&gt; &lt;code&gt;HasServer&lt;/code&gt; instances. To find the relevant &lt;code&gt;ServerT&lt;/code&gt; it helps to look at &lt;code&gt;HasServer&lt;/code&gt;'s &lt;a href="https://hackage.haskell.org/package/servant-server-0.16.2/docs/Servant-Server-Internal.html#t:HasServer"&gt;documentation&lt;/a&gt; and the &lt;a href="https://hackage.haskell.org/package/servant-server-0.16.2/docs/src/Servant.Server.Internal.html#line-643"&gt;linked source&lt;/a&gt; for the instance in question.&lt;/p&gt;
&lt;p&gt;Now we know which &lt;code&gt;ServerT&lt;/code&gt; will be applied.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;type instance
  ServerT (path :&amp;gt; api) m =
    ServerT api m&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can take that, substitute &lt;code&gt;"users"&lt;/code&gt; for &lt;code&gt;path&lt;/code&gt;, &lt;code&gt;UsersIndex :&amp;lt;|&amp;gt; UsersShow&lt;/code&gt; for &lt;code&gt;api&lt;/code&gt; and &lt;code&gt;Handler&lt;/code&gt; for &lt;code&gt;m&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;ServerT (UsersIndex :&amp;lt;|&amp;gt; UsersShow) Handler&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice that &lt;code&gt;ServerT&lt;/code&gt; is being called again in this substituted body. It recurses, having now peeled off the &lt;code&gt;"users" :&amp;gt;&lt;/code&gt; part of the type. We have a new &lt;code&gt;ServerT&lt;/code&gt; to find, this time for &lt;code&gt;(:&amp;lt;|&amp;gt;)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can again ask GHCi using &lt;code&gt;:info&lt;/code&gt; to tell us what it knows about &lt;code&gt;(:&amp;lt;|&amp;gt;)&lt;/code&gt;. Fortunately there's only one &lt;code&gt;HasServer&lt;/code&gt; instance and therefore only one &lt;code&gt;ServerT&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;type instance
  ServerT (a :&amp;lt;|&amp;gt; b) m =
    ServerT a m :&amp;lt;|&amp;gt; ServerT b m&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Substituting &lt;code&gt;UsersIndex&lt;/code&gt; for &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;UsersShow&lt;/code&gt; for &lt;code&gt;b&lt;/code&gt; and &lt;code&gt;Handler&lt;/code&gt; for &lt;code&gt;m&lt;/code&gt; gets us the following.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;ServerT UsersIndex Handler :&amp;lt;|&amp;gt; ServerT UsersShow Handler&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We're faced with &lt;em&gt;two&lt;/em&gt; recursive calls to &lt;code&gt;ServerT&lt;/code&gt; in this substituted body. For the next step we'll need to choose which branch to evaluate first. Let's begin on the left.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;ServerT UsersIndex Handler&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which is the relevant &lt;code&gt;ServerT&lt;/code&gt; for &lt;code&gt;UsersIndex&lt;/code&gt;? Let's find out.&lt;/p&gt;
&lt;p&gt;First &lt;code&gt;UsersIndex&lt;/code&gt; is a synonym.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;type UsersIndex =
  Get &amp;#39;[JSON] [User]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Asking GHCi what &lt;code&gt;Get&lt;/code&gt; is will reveal that it too is a synonym.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; &amp;gt; :info Get
type Get =
  Servant.API.Verbs.Verb &amp;#39;Network.HTTP.Types.Method.GET 200
  :: [Type] -&amp;gt; Type -&amp;gt; Type
        -- Defined in ‘Servant.API.Verbs’&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Fortunately &lt;code&gt;Verb&lt;/code&gt; is the end of the line.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; &amp;gt; :info Servant.API.Verbs.Verb
type role Servant.API.Verbs.Verb phantom phantom phantom phantom
data Servant.API.Verbs.Verb (method :: k1)
                            (statusCode :: Nat)
                            (contentTypes :: [Type])
                            a
        -- Defined in ‘Servant.API.Verbs’
instance [safe] forall k1 (method :: k1) (statusCode :: Nat) (contentTypes :: [Type]) a.
                Generic (Servant.API.Verbs.Verb method statusCode contentTypes a)
  -- Defined in ‘Servant.API.Verbs’
instance [overlappable] forall k1 (ctypes :: [Type]) a (method :: k1) (status :: Nat) (context :: [Type]).
                        (Servant.API.ContentTypes.AllCTRender ctypes a,
                         Servant.API.Verbs.ReflectMethod method, KnownNat status) =&amp;gt;
                        HasServer (Servant.API.Verbs.Verb method status ctypes a) context
  -- Defined in ‘Servant.Server.Internal’&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There's our &lt;code&gt;HasServer&lt;/code&gt; instance, and so we're able to find the corresponding &lt;code&gt;ServerT&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;type instance
  ServerT (Verb method status ctypes a) m =
    m a&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Verb&lt;/code&gt;s are very general, we can make this look a bit simpler by inlining all the arguments that have been applied in the &lt;code&gt;UsersShow&lt;/code&gt; type.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;UsersShow
  =
Get &amp;#39;[JSON] [User]
  =
Verb GET 200 &amp;#39;[JSON] [User]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We now see that we can substitute &lt;code&gt;[User]&lt;/code&gt; for &lt;code&gt;a&lt;/code&gt;. Because we're tracing the evaluation of &lt;code&gt;ServerT&lt;/code&gt; as it's used in &lt;code&gt;serve&lt;/code&gt; we'll always be substituting &lt;code&gt;Handler&lt;/code&gt; for &lt;code&gt;m&lt;/code&gt;. Making those two substitutions in the body of the type family instance above will result in the following.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;Handler [User]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That's the left branch of &lt;code&gt;(:&amp;lt;|&amp;gt;)&lt;/code&gt; done.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;Handler [User] :&amp;lt;|&amp;gt; ServerT UsersIndex Handler&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On to the right.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;ServerT UsersShow Handler&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What was &lt;code&gt;UsersShow&lt;/code&gt; a synonym for?&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;type UsersShow =
  Capture &amp;quot;username&amp;quot; String
    :&amp;gt; Get &amp;#39;[JSON] User&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It's outermost type constructor is &lt;code&gt;(:&amp;gt;)&lt;/code&gt;, which we've seen before. Despite this we haven't yet seen the &lt;code&gt;ServerT&lt;/code&gt; that we'll need to evaluate this next step.&lt;/p&gt;
&lt;p&gt;Remember that the instance we last saw required that the first argument to &lt;code&gt;(:&amp;gt;)&lt;/code&gt; be of kind &lt;code&gt;Symbol&lt;/code&gt;. The first argument to &lt;code&gt;(:&amp;gt;)&lt;/code&gt; in &lt;code&gt;UsersShow&lt;/code&gt;, however, isn't. It's a bad match, we'll have to find another instance.&lt;/p&gt;
&lt;p&gt;Let's try asking about &lt;code&gt;Capture&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; &amp;gt; :info Capture
type Capture = Servant.API.Capture.Capture&amp;#39; &amp;#39;[] :: Symbol -&amp;gt; Type -&amp;gt; Type
        -- Defined in ‘Servant.API.Capture’&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We're told it's a synonym for &lt;code&gt;Capture'&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; &amp;gt; import Servant.API.Capture (Capture&amp;#39;)
 &amp;gt; :info Capture&amp;#39;
type role Capture&amp;#39; phantom phantom phantom
data Capture&amp;#39; (mods :: [Type]) (sym :: Symbol) a
        -- Defined in ‘Servant.API.Capture’
instance (KnownSymbol capture,
          Web.Internal.HttpApiData.FromHttpApiData a,
          HasServer api context) =&amp;gt;
         HasServer (Capture&amp;#39; mods capture a :&amp;gt; api) context
  -- Defined in ‘Servant.Server.Internal’&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Capture'&lt;/code&gt; has only one &lt;code&gt;HasServer&lt;/code&gt; instance, and it's defined only for &lt;code&gt;Capture'&lt;/code&gt;s which appear on the left-hand side of &lt;code&gt;(:&amp;gt;)&lt;/code&gt;. This looks like a good match.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;ServerT&lt;/code&gt; for this instance is, I think, the most interesting we've seen.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;type instance
  ServerT (Capture&amp;#39; mods capture a :&amp;gt; api) m =
    a -&amp;gt; ServerT api m&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Substituting &lt;code&gt;'[]&lt;/code&gt; for &lt;code&gt;mods&lt;/code&gt;, &lt;code&gt;"username"&lt;/code&gt; for &lt;code&gt;capture&lt;/code&gt;, &lt;code&gt;String&lt;/code&gt; for &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;Get '[JSON] User&lt;/code&gt; for &lt;code&gt;api&lt;/code&gt; and &lt;code&gt;Handler&lt;/code&gt; for &lt;code&gt;m&lt;/code&gt; gives us a function.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;String -&amp;gt; ServerT (Get &amp;#39;[JSON] User) Handler&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is magical. A &lt;code&gt;Capture&lt;/code&gt; is transformed into a function which accepts the path parameter it represents.&lt;/p&gt;
&lt;p&gt;We're nearly finished evaluating, we have one more call to &lt;code&gt;ServerT&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;ServerT (Get &amp;#39;[JSON] User) Handler&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Fortunately we already know the &lt;code&gt;ServerT&lt;/code&gt; to use here.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;type instance
  ServerT (Verb method status ctypes a) m =
    m a&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So let's apply it.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;Handler User&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we're finished evaluating &lt;code&gt;ServerT UsersShow Hander&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;String -&amp;gt; Handler User&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which means we're finished evaluating &lt;code&gt;ServerT UsersIndex Handler :&amp;lt;|&amp;gt; ServerT UsersShow Handler&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Which means we're finished evaluating &lt;code&gt;ServerT UsersAPI Handler&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;Handler [User] :&amp;lt;|&amp;gt; (String -&amp;gt; Handler User)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here's all of those steps together.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;ServerT UsersAPI Handler
ServerT (&amp;quot;users&amp;quot; :&amp;gt; (UsersIndex :&amp;lt;|&amp;gt; UsersShow)) Handler
ServerT (UsersIndex :&amp;lt;|&amp;gt; UsersShow) Handler
ServerT UsersIndex Handler :&amp;lt;|&amp;gt; ServerT UsersShow Handler
ServerT (Get &amp;#39;[JSON] [User]) Handler :&amp;lt;|&amp;gt; ServerT UsersShow Handler
ServerT (Verb GET 200 &amp;#39;[JSON] [User]) Handler :&amp;lt;|&amp;gt; ServerT UsersShow Handler
Handler [User] :&amp;lt;|&amp;gt; ServerT UsersShow Handler
Handler [User] :&amp;lt;|&amp;gt; ServerT (Capture &amp;quot;username&amp;quot; String :&amp;gt; Get &amp;#39;[JSON] User) Handler
Handler [User] :&amp;lt;|&amp;gt; (String -&amp;gt; ServerT (Get &amp;#39;[JSON] User)) Handler
Handler [User] :&amp;lt;|&amp;gt; (String -&amp;gt; ServerT (Verb GET 200 &amp;#39;[JSON] User)) Handler
Handler [User] :&amp;lt;|&amp;gt; (String -&amp;gt; Handler User)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So this is how Servant goes about transforming the &lt;code&gt;UsersAPI&lt;/code&gt; type into the type for a server. We first declared a reasonable looking shape for our API as a type and now Servant is letting us know how we can implement a server for it.&lt;/p&gt;
&lt;p&gt;Before we do that, however, we had another type error we were going to look into.&lt;/p&gt;
&lt;h2 id="content-types"&gt;Content types&lt;/h2&gt;
&lt;p&gt;Why did we need to define a &lt;code&gt;ToJSON&lt;/code&gt; instance for &lt;code&gt;User&lt;/code&gt;? Where did that constraint come from?&lt;/p&gt;
&lt;p&gt;We mention JSON twice in the type of &lt;code&gt;UsersAPI&lt;/code&gt;, in both instances it's as an argument to the &lt;code&gt;Get&lt;/code&gt; type constructor. Recall from above that &lt;code&gt;Get&lt;/code&gt; is an alias for &lt;code&gt;Verb&lt;/code&gt;, recall also that the only constraint on &lt;code&gt;serve&lt;/code&gt; is that the provided &lt;code&gt;api&lt;/code&gt; type has a &lt;code&gt;HasServer&lt;/code&gt; instance. Is there anything interesting about the &lt;code&gt;HasServer&lt;/code&gt; instance for &lt;code&gt;Verb&lt;/code&gt;?&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;instance
  forall
    k1
    (ctypes :: [Type])
    a
    (method :: k1)
    (status :: Nat)
    (context :: [Type]).
  ( AllCTRender ctypes a
  , ReflectMethod method
  , KnownNat status
  ) =&amp;gt;
    HasServer (Verb method status ctypes a) context&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;HasServer&lt;/code&gt; instance for &lt;code&gt;Verb&lt;/code&gt; constrains the &lt;code&gt;a&lt;/code&gt; type parameter to be an instance of a type class called &lt;code&gt;AllCTRender&lt;/code&gt;. If we go looking for instances of this type class we're faced with something that might seem a little strange.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;instance
  (TypeError ...) =&amp;gt;
    AllCTRender &amp;#39;[] ()

instance
  ( Accept ct
  , AllMime cts
  , AllMimeRender (ct : cts) a
  ) =&amp;gt;
    AllCTRender (ct : cts) a&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It has two instances. One instance which will throw a custom type error when applied to an empty list and &lt;code&gt;()&lt;/code&gt;, and one that doesn't refer to any concrete types, strange stuff.&lt;/p&gt;
&lt;p&gt;Notice that type level lists can be pattern-matched and de-structured quite like value level lists, here in the constraints of this type class instance. This means that were able to iterate over type level lists in much the same way that we do for those at the value level. The iteration splits off into three more type classes: &lt;code&gt;Accept&lt;/code&gt;, &lt;code&gt;AllMime&lt;/code&gt; and &lt;code&gt;AllMimeRender&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;AllMimeRender&lt;/code&gt; has two instances, and with these this &lt;em&gt;really&lt;/em&gt; starts to look like value level list iteration.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;instance
  ( MimeRender ctyp a
  ) =&amp;gt;
    AllMimeRender &amp;#39;[ctyp] a

instance
  ( MimeRender ctyp a
  , AllMimeRender (ctyp&amp;#39; : ctyps) a
  ) =&amp;gt;
    AllMimeRender (ctyp : ctyp&amp;#39; : ctyps) a&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We have a base case where there's only one element in the list. The other instance asserts that the head of the list has an instance of &lt;code&gt;MimeRender&lt;/code&gt; and the (non-empty) tail has one for &lt;code&gt;AllMimeRender&lt;/code&gt;, that is: it recurses.&lt;/p&gt;
&lt;p&gt;Our API only speaks JSON, represented by its content-types list being &lt;code&gt;'[JSON]&lt;/code&gt;, so the first instance of &lt;code&gt;AllMimeRender&lt;/code&gt; is used. This means that there needs to be an instance of &lt;code&gt;MimeRender&lt;/code&gt; for &lt;code&gt;JSON&lt;/code&gt;. By looking for that instance we see what we've been looking for.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;instance ToJSON a =&amp;gt; MimeRender JSON a&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here's how it all goes.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In order for there to be an instance of &lt;code&gt;HasServer&lt;/code&gt; for &lt;code&gt;Verb GET 200 '[JSON] User&lt;/code&gt; there has to be an instance of &lt;code&gt;AllCTRender&lt;/code&gt; for &lt;code&gt;'[JSON]&lt;/code&gt; and &lt;code&gt;User&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;In order for there to be an instance of &lt;code&gt;AllCTRender&lt;/code&gt; for &lt;code&gt;'[JSON]&lt;/code&gt; and &lt;code&gt;User&lt;/code&gt; there has to be an instance of &lt;code&gt;AllMimeRender&lt;/code&gt; for &lt;code&gt;'[JSON]&lt;/code&gt; and &lt;code&gt;User&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;In order for there to be an instance of &lt;code&gt;AllMimeRender&lt;/code&gt; for &lt;code&gt;'[JSON]&lt;/code&gt; and &lt;code&gt;User&lt;/code&gt; there has to be an instance of &lt;code&gt;MimeRender&lt;/code&gt; for &lt;code&gt;JSON&lt;/code&gt; and &lt;code&gt;User&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;In order for there to be an instance of &lt;code&gt;MimeRender&lt;/code&gt; for &lt;code&gt;JSON&lt;/code&gt; and &lt;code&gt;User&lt;/code&gt; there has to be an instance of Aeson's &lt;code&gt;ToJSON&lt;/code&gt; for &lt;code&gt;User&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So that's why when we tried to apply &lt;code&gt;UsersAPI&lt;/code&gt; to &lt;code&gt;serve&lt;/code&gt; we needed to define a &lt;code&gt;ToJSON&lt;/code&gt; instance for &lt;code&gt;User&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="implementing-a-server-for-our-type"&gt;Implementing a server for our type&lt;/h2&gt;
&lt;p&gt;Now we know how the typed hole &lt;code&gt;_usersServer&lt;/code&gt; ends up with the type it does.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;Handler [User] :&amp;lt;|&amp;gt; (String -&amp;gt; Handler User)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let's go about creating a value of this type. We might start from the outside, in much the same order as we traced the evaluation of &lt;code&gt;ServerT&lt;/code&gt;. This means first figuring out how to construct a value of type &lt;code&gt;a :&amp;lt;|&amp;gt; b&lt;/code&gt;. Using GHCi we're able to view the definition of this type.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;data (:&amp;lt;|&amp;gt;) a b = a :&amp;lt;|&amp;gt; b&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It's pretty much a pair.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;data (,) a b = (a, b)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It has only one data constructor, which happens to share the type's name. There's only one thing we can do, provide that constructor two values. Now, we don't actually &lt;em&gt;have&lt;/em&gt; those values yet, so let's use typed holes for now.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;usersServer :: Server UsersAPI
usersServer = _usersIndex :&amp;lt;|&amp;gt; _usersShow&lt;/code&gt;&lt;/pre&gt;
&lt;figcaption&gt;
  &lt;a target="_blank" href="https://github.com/bradparker/how-does-servants-type-dsl-work/commit/05-usersServer"&gt;
    Commit
  &lt;/a&gt;
&lt;/figcaption&gt;

&lt;p&gt;Applying this to &lt;code&gt;serve&lt;/code&gt; will let us know if we're on the right track.&lt;/p&gt;
&lt;pre class="diff"&gt;&lt;code&gt;  usersApp :: Application
- usersApp = serve (Proxy @UsersAPI) _usersServer
+ usersApp = serve (Proxy @UsersAPI) usersServer&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Trying to compile should give us something like the following.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;src/Main.hs:86:15: error:
    • Found hole: _usersIndex :: Handler [User]
      Or perhaps ‘_usersIndex’ is mis-spelled, or not in scope
    • In the first argument of ‘(:&amp;lt;|&amp;gt;)’, namely ‘_usersIndex’
      In the expression: _usersIndex :&amp;lt;|&amp;gt; _usersShow
      In an equation for ‘usersServer’:
          usersServer = _usersIndex :&amp;lt;|&amp;gt; _usersShow
    • Relevant bindings include
        usersServer :: Server UsersAPI (bound at src/Main.hs:86:1)
   |
86 | usersServer = _usersIndex :&amp;lt;|&amp;gt; _usersShow
   |               ^^^^^^^^^^^

src/Main.hs:86:32: error:
    • Found hole: _usersShow :: [Char] -&amp;gt; Handler User
      Or perhaps ‘_usersShow’ is mis-spelled, or not in scope
    • In the second argument of ‘(:&amp;lt;|&amp;gt;)’, namely ‘_usersShow’
      In the expression: _usersIndex :&amp;lt;|&amp;gt; _usersShow
      In an equation for ‘usersServer’:
          usersServer = _usersIndex :&amp;lt;|&amp;gt; _usersShow
    • Relevant bindings include
        usersServer :: Server UsersAPI (bound at src/Main.hs:86:1)
   |
86 | usersServer = _usersIndex :&amp;lt;|&amp;gt; _usersShow
   |                                ^^^^^^^^^^&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Amongst that we're being told that we have two values we need to conjure up.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;usersIndex :: Handler [User]
usersIndex = _

usersShow :: String -&amp;gt; Handler User
usersShow _uname = _&lt;/code&gt;&lt;/pre&gt;
&lt;figcaption&gt;
  &lt;a target="_blank" href="https://github.com/bradparker/how-does-servants-type-dsl-work/commit/06-usersShow-and-usersIndex-placeholders"&gt;
    Commit
  &lt;/a&gt;
&lt;/figcaption&gt;

&lt;p&gt;We'll start with &lt;code&gt;usersIndex&lt;/code&gt;, which is a value of type &lt;code&gt;Handler [User]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For the sake of this example our collection of users will be some static, sample data. I might do another post on my experience of using &lt;a href="https://tathougies.github.io/beam/"&gt;Beam&lt;/a&gt; in a Servant application, but for now let's keep it simple.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;users :: [User]
users =
  [ User
    { name             = &amp;quot;Isaac Newton&amp;quot;
    , age              = 372
    , email            = &amp;quot;isaac@newton.co.uk&amp;quot;
    , username         = &amp;quot;isaac&amp;quot;
    , registrationDate = fromGregorian 1683 3 1
    }
  , User
    { name             = &amp;quot;Albert Einstein&amp;quot;
    , age              = 136
    , email            = &amp;quot;ae@mc2.org&amp;quot;
    , username         = &amp;quot;albert&amp;quot;
    , registrationDate = fromGregorian 1905 12 1
    }
  ]&lt;/code&gt;&lt;/pre&gt;
&lt;figcaption&gt;
  &lt;a target="_blank" href="https://github.com/bradparker/how-does-servants-type-dsl-work/commit/07-sample-users"&gt;
    Commit
  &lt;/a&gt;
&lt;/figcaption&gt;

&lt;p&gt;Now that we have a value of &lt;code&gt;[User]&lt;/code&gt; we need a function which can wrap it in a &lt;code&gt;Handler&lt;/code&gt;. Looking at the &lt;a href="https://hackage.haskell.org/package/servant-server-0.16.2/docs/Servant-Server-Internal-Handler.html#t:Handler"&gt;documentation for &lt;code&gt;Handler&lt;/code&gt;&lt;/a&gt; we see that it has an &lt;code&gt;Applicative&lt;/code&gt; instance which will provide us &lt;a href="https://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Applicative.html#v:pure"&gt;just what we need&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; &amp;gt; :type pure @Handler
pure @Handler :: a -&amp;gt; Handler a&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So there we have it.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;usersIndex :: Handler [User]
usersIndex = pure users&lt;/code&gt;&lt;/pre&gt;
&lt;figcaption&gt;
  &lt;a target="_blank" href="https://github.com/bradparker/how-does-servants-type-dsl-work/commit/08-usersIndex"&gt;
    Commit
  &lt;/a&gt;
&lt;/figcaption&gt;

&lt;p&gt;For &lt;code&gt;UsersShow&lt;/code&gt; we'll have a little more work to do. We're supplied the user name of the user we'd like returned, we should use it to look for that user in &lt;code&gt;users&lt;/code&gt;. The function we'll need for finding elements of lists is &lt;code&gt;find&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;find :: Foldable t =&amp;gt; (a -&amp;gt; Bool) -&amp;gt; t a -&amp;gt; Maybe a&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or more specifically.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; &amp;gt; :t find @[] @User
find @[] @User :: (User -&amp;gt; Bool) -&amp;gt; [User] -&amp;gt; Maybe User&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We'll need a function &lt;code&gt;User -&amp;gt; Bool&lt;/code&gt; and in our case the &lt;code&gt;Bool&lt;/code&gt; should indicate whether a provided &lt;code&gt;String&lt;/code&gt; matches a given &lt;code&gt;User&lt;/code&gt;s &lt;code&gt;username&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;matchesUsername :: String -&amp;gt; User -&amp;gt; Bool
matchesUsername uname = (uname ==) . username&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We're nearly there.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; &amp;gt; :t \uname -&amp;gt; find @[] (matchesUsername uname)
\uname -&amp;gt; find @[] (matchesUsername uname)
  :: String -&amp;gt; [User] -&amp;gt; Maybe User

 &amp;gt; :t \uname -&amp;gt; find @[] (matchesUsername uname) users
\uname -&amp;gt; find @[] (matchesUsername uname) users
  :: String -&amp;gt; Maybe User&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The final step is to turn a &lt;code&gt;Maybe User&lt;/code&gt; into a &lt;code&gt;Handler User&lt;/code&gt;. For the &lt;code&gt;Just&lt;/code&gt; case we have a &lt;code&gt;User&lt;/code&gt; and are able to use &lt;code&gt;pure @Handler&lt;/code&gt; to wrap it in a &lt;code&gt;Handler&lt;/code&gt;, but for the &lt;code&gt;Nothing&lt;/code&gt; case, what should we do?&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;usersShow :: String -&amp;gt; Handler User
usersShow uname =
  case find (matchesUsername uname) users of
    Nothing   -&amp;gt; _
    Just user -&amp;gt; pure user&lt;/code&gt;&lt;/pre&gt;
&lt;figcaption&gt;
  &lt;a target="_blank" href="https://github.com/bradparker/how-does-servants-type-dsl-work/commit/09-most-of-usersShow"&gt;
    Commit
  &lt;/a&gt;
&lt;/figcaption&gt;

&lt;p&gt;Ordinarily when you ask a web server for a resource it can't find you get a 404 response back. How can we produce a value of &lt;code&gt;Handler User&lt;/code&gt; that results in a 404?&lt;/p&gt;
&lt;p&gt;By looking at the docs for &lt;code&gt;Handler&lt;/code&gt; again we can see that it has a &lt;a href="https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Error-Class.html#t:MonadError"&gt;&lt;code&gt;MonadError&lt;/code&gt;&lt;/a&gt; instance, this suggests that we can use &lt;code&gt;throwError&lt;/code&gt; when we need to return &lt;em&gt;something&lt;/em&gt; but can't return a &lt;code&gt;User&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;By looking at &lt;code&gt;Handler&lt;/code&gt;'s instance for &lt;code&gt;MonadError&lt;/code&gt; we see that it's defined for a &lt;code&gt;ServantErr&lt;/code&gt; type. So in our case &lt;code&gt;throwError&lt;/code&gt; has the following type.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; &amp;gt; :t throwError @ServantErr @Handler
throwError @ServantErr @Handler :: ServantErr -&amp;gt; Handler a&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now it helps to look at the &lt;a href="https://hackage.haskell.org/package/servant-server-0.15/docs/Servant-Server-Internal-ServantErr.html"&gt;documentation for &lt;code&gt;ServantErr&lt;/code&gt;&lt;/a&gt;. There we see quite a few values of the type, including a quite relevant-looking &lt;code&gt;err404&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;usersShow :: String -&amp;gt; Handler User
usersShow uname =
  case find (matchesUsername uname) users of
    Nothing   -&amp;gt; throwError err404
    Just user -&amp;gt; pure user&lt;/code&gt;&lt;/pre&gt;
&lt;figcaption&gt;
  &lt;a target="_blank" href="https://github.com/bradparker/how-does-servants-type-dsl-work/commit/10-return-404-when-no-matching-user"&gt;
    Commit
  &lt;/a&gt;
&lt;/figcaption&gt;

&lt;p&gt;We've now defined everything we need and should have a runnable server.&lt;/p&gt;
&lt;p&gt;Start it up.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ runhaskell src/Main.hs&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And try it out.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ curl -sD /dev/stderr http://localhost:8080/users | jq .
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Date: Sat, 21 Sep 2019 05:26:33 GMT
Server: Warp/3.2.28
Content-Type: application/json;charset=utf-8

[
  {
    &amp;quot;email&amp;quot;: &amp;quot;isaac@newton.co.uk&amp;quot;,
    &amp;quot;registrationDate&amp;quot;: &amp;quot;1683-03-01&amp;quot;,
    &amp;quot;age&amp;quot;: 372,
    &amp;quot;username&amp;quot;: &amp;quot;isaac&amp;quot;,
    &amp;quot;name&amp;quot;: &amp;quot;Isaac Newton&amp;quot;
  },
  {
    &amp;quot;email&amp;quot;: &amp;quot;ae@mc2.org&amp;quot;,
    &amp;quot;registrationDate&amp;quot;: &amp;quot;1905-12-01&amp;quot;,
    &amp;quot;age&amp;quot;: 136,
    &amp;quot;username&amp;quot;: &amp;quot;albert&amp;quot;,
    &amp;quot;name&amp;quot;: &amp;quot;Albert Einstein&amp;quot;
  }
]

$ curl -sD /dev/stderr http://localhost:8080/users/albert | jq .
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Date: Sat, 21 Sep 2019 05:25:09 GMT
Server: Warp/3.2.28
Content-Type: application/json;charset=utf-8

{
  &amp;quot;email&amp;quot;: &amp;quot;ae@mc2.org&amp;quot;,
  &amp;quot;registrationDate&amp;quot;: &amp;quot;1905-12-01&amp;quot;,
  &amp;quot;age&amp;quot;: 136,
  &amp;quot;username&amp;quot;: &amp;quot;albert&amp;quot;,
  &amp;quot;name&amp;quot;: &amp;quot;Albert Einstein&amp;quot;
}

$ curl -sD /dev/stderr http://localhost:8080/users/unknown | jq .
HTTP/1.1 404 Not Found
Transfer-Encoding: chunked
Date: Sat, 21 Sep 2019 05:26:00 GMT
Server: Warp/3.2.28
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="whats-it-all-for"&gt;What's it all for?&lt;/h2&gt;
&lt;p&gt;My hope when planning this post was that I'd become a little more familiar with the type level programming features of GHC Haskell. I wasn't sure which features or to what extent. Having finished I'd say that I've &lt;em&gt;started&lt;/em&gt; to understand this topic. At the very least I've spent a bit of time becoming more familiar with a library that makes great use of GHC's type level features.&lt;/p&gt;
&lt;p&gt;The DSL provided by Servant allows us to construct types which specify an API contract. With it we were able to specify static route segments and named route parameters using &lt;code&gt;Symbol&lt;/code&gt;s. We could associate those routes with HTTP verbs which could accept and return many content-types using type level lists. Combining these components was made easy with infix type constructors.&lt;/p&gt;
&lt;p&gt;The way Servant has us think "specification first" is very appealing to me, and the more time I spend with Haskell the more this method of designing and implementing software just &lt;em&gt;feels right&lt;/em&gt;. The type level feels much more declarative: you don't talk as much about what you want to happen, instead you talk more about what things you would like to exist. Then it's up to you and the compiler to figure out how that might be possible.&lt;/p&gt;
&lt;p&gt;There's another, more practical, benefit to this in Servant's case however. We've seen that specifications can be turned into the types of servers which implement them, however we didn't explore how we can also use them to automatically produce &lt;a href="https://hackage.haskell.org/package/servant-client"&gt;clients&lt;/a&gt;, &lt;a href="https://hackage.haskell.org/package/servant-swagger"&gt;documentation&lt;/a&gt;, and even &lt;a href="https://hackage.haskell.org/package/servant-quickcheck"&gt;property tests&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I imagine investigating those packages would be good for even more type level learnings.&lt;/p&gt;</description><author>hi@bradparker.id.au (Brad Parker)</author><guid>https://bradparker.com/content/posts/2019-10-05-servant-types.html</guid><pubDate>Sat,  5 Oct 2019 00:00:00 UTC</pubDate></item><item><title>Let's learn about lenses</title><link>https://bradparker.id.au/posts/lets-learn-about-lenses</link><description>&lt;p&gt;Before we begin: in order to understand a lot of the following you'll first need some familiarity with &lt;a href="https://haskell.org"&gt;Haskell&lt;/a&gt; syntax and be somewhat comfortable with what a Functor is.&lt;/p&gt;
&lt;p&gt;OK, now firstly: why learn about lenses? Every time I've seen lenses in action it's looked like wizardry. I mean, just look at these examples of using &lt;a href="https://hackage.haskell.org/package/lens-aeson"&gt;&lt;code&gt;lens-aeson&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;someJson =
  [json| {
    packages: [
      { version: 1 },
      { version: 5 }
    ]
  }|]

versions =
  key &amp;quot;packages&amp;quot;
    . _Array
    . traverse
    . key &amp;quot;version&amp;quot;
    . _Number

print $ someJson ^.. versions
-- [1.0,5.0]

BS.putStrLn $ someJson &amp;amp; versions %~ (+ 2)
-- {
--   &amp;quot;packages&amp;quot;: [
--     { &amp;quot;version&amp;quot;: 3 },
--     { &amp;quot;version&amp;quot;: 7 }
--   ]
-- }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;What?&lt;/em&gt; Reaching into some JSON, transforming it and just putting it back together, there's no way it can be so easy? Right?&lt;/p&gt;
&lt;p&gt;Let's try to understand what's going on here. We should probably start with something a little simpler than the JSON example above, how about tuples?&lt;/p&gt;
&lt;p&gt;OK, imagine we have these two magic functions. &lt;code&gt;_1&lt;/code&gt; for doing &lt;em&gt;stuff&lt;/em&gt; to the first element of a tuple and &lt;code&gt;_2&lt;/code&gt; for doing &lt;em&gt;stuff&lt;/em&gt; to the second.&lt;/p&gt;
&lt;p&gt;We can compose them &lt;code&gt;_1 . _2&lt;/code&gt;, which lets us do &lt;em&gt;stuff&lt;/em&gt; to the second element of a tuple which is itself the first element of a tuple.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;((a, b), c)
--   ^
--   This thing, here.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What kind of stuff?&lt;/p&gt;
&lt;p&gt;We can "view" (&lt;code&gt;^.&lt;/code&gt;) the value:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;&amp;gt; ((2, True), &amp;#39;b&amp;#39;) ^. _1 . _2
True&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can "modify" (&lt;code&gt;%~&lt;/code&gt;) the value:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;&amp;gt; ((2, True), &amp;#39;b&amp;#39;) &amp;amp; _1 . _2 %~ not
((2,False),&amp;#39;b&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can traverse over a list of these tuples and view the value of each as a list (&lt;code&gt;^..&lt;/code&gt; with &lt;code&gt;traverse&lt;/code&gt;):&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;&amp;gt; [((2, True), &amp;#39;b&amp;#39;), ((3, False), &amp;#39;b&amp;#39;)] ^.. traverse . _1 . _2
[True,False]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While we traverse (this time over any Traversable thing), instead of viewing we can modify:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;&amp;gt; [((2, True), &amp;#39;b&amp;#39;), ((3, False), &amp;#39;b&amp;#39;)] &amp;amp; traverse . _1 . _2 %~ not
[((2,False),&amp;#39;b&amp;#39;),((3,True),&amp;#39;b&amp;#39;)]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That looks pretty useful to me. What do you reckon?&lt;/p&gt;
&lt;p&gt;To understand how this all works we should probably move step by step. Let's try this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First we're going to define &lt;em&gt;slightly&lt;/em&gt; simplified versions of &lt;code&gt;_1&lt;/code&gt; and &lt;code&gt;_2&lt;/code&gt;, as &lt;code&gt;one&lt;/code&gt; and &lt;code&gt;two&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Then we'll move on to define similarly simplified versions of &lt;code&gt;^.&lt;/code&gt; (as &lt;code&gt;view&lt;/code&gt;) and &lt;code&gt;%~&lt;/code&gt; (as &lt;code&gt;modify&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Finally we'll adapt &lt;code&gt;_1&lt;/code&gt; and &lt;code&gt;_2&lt;/code&gt; to be a little closer to their definitions in the &lt;a href="https://hackage.haskell.org/package/lens"&gt;&lt;code&gt;lens&lt;/code&gt;&lt;/a&gt; library.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We might seek to explore &lt;code&gt;^..&lt;/code&gt; and how it interacts with &lt;code&gt;traverse&lt;/code&gt; in another post. It's super cool, but we'll likely need to get there via some other concepts.&lt;/p&gt;
&lt;h2 id="lenses-_1-one-and-_2-two"&gt;Lenses &lt;code&gt;_1&lt;/code&gt; (one) and &lt;code&gt;_2&lt;/code&gt; (two)&lt;/h2&gt;
&lt;p&gt;What are these two magic functions? How do they work?&lt;/p&gt;
&lt;p&gt;We'll start by describing "functional references" al la &lt;a href="https://www.twanvl.nl/blog/haskell/cps-functional-references"&gt;Twan van Laarhoven&lt;/a&gt;, a precursor to what we now call lenses. For the sake of simplicity we're still going to refer to these as "lenses".&lt;/p&gt;
&lt;p&gt;In the above article a lens is defined as something with this type:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;Functor f =&amp;gt; (a -&amp;gt; f a) -&amp;gt; s -&amp;gt; f s&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let's make an alias for use later.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;type Lens&amp;#39; s a =
  forall f. Functor f =&amp;gt;
    (a -&amp;gt; f a) -&amp;gt; s -&amp;gt; f s&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The goal of this section is going to be implementing functions that satisfy this type. In the next section we'll seek to understand &lt;em&gt;why&lt;/em&gt; this type is the way it is.&lt;/p&gt;
&lt;p&gt;Imagine that &lt;code&gt;s&lt;/code&gt; stands for "structure", this will become clearer a little later.&lt;/p&gt;
&lt;p&gt;Something bothered me when I first saw this type, it looks like it's missing two functions: &lt;code&gt;s -&amp;gt; a&lt;/code&gt;, &lt;code&gt;a -&amp;gt; s&lt;/code&gt;. If we had an &lt;code&gt;s -&amp;gt; a&lt;/code&gt; we could turn the &lt;code&gt;s&lt;/code&gt; we get as a second argument into the &lt;code&gt;a&lt;/code&gt; we need to supply to the &lt;code&gt;a -&amp;gt; f a&lt;/code&gt; we receive as the first argument. If we had an &lt;code&gt;a -&amp;gt; s&lt;/code&gt; we could use &lt;code&gt;fmap&lt;/code&gt; to transform the &lt;code&gt;f a&lt;/code&gt; to an &lt;code&gt;f s&lt;/code&gt; ready to return it.&lt;/p&gt;
&lt;p&gt;We could write a function which accepts an &lt;code&gt;s -&amp;gt; a&lt;/code&gt; and an &lt;code&gt;a -&amp;gt; s&lt;/code&gt; in order to build a lens, something like this:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;makeLens
  :: (s -&amp;gt; a)
  -&amp;gt; (a -&amp;gt; s)
  -&amp;gt; Lens&amp;#39; s a
makeLens sToA aToS aToFa s =
  fmap aToS (aToFa (sToA s))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It ends up those functions are &lt;em&gt;precisely&lt;/em&gt; what we need to provide to make a lens. The first function is the "getter", the second the "setter".&lt;/p&gt;
&lt;p&gt;What might a getter for the first element of a tuple look like?&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;getOne :: (a, c) -&amp;gt; a
getOne (a, _) = a&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Looks about right. How about the setter?&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;setOne :: (a, c) -&amp;gt; a -&amp;gt; (a, c)
setOne (_, c) a = (a, c)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That should work.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;one :: Lens&amp;#39; (a, c) a
one aToFa ac =
  makeLens getOne (setOne ac) aToFa ac&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We don't really &lt;em&gt;need&lt;/em&gt; this &lt;code&gt;makeLens&lt;/code&gt; function, so let's get rid of it.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;one :: Lens&amp;#39; (a, c) a
one aToFa (a, c) =
  fmap (\a&amp;#39; -&amp;gt; (a&amp;#39;, c)) (aToFa a)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We now do the getting by pattern matching and the setting with an anonymous function: &lt;code&gt;\a' -&amp;gt; (a', c)&lt;/code&gt;. We don't need separate functions &lt;em&gt;necessarily&lt;/em&gt; for getting and setting, which might explain why they're not mentioned in the type.&lt;/p&gt;
&lt;p&gt;Let's compare the type of &lt;code&gt;one&lt;/code&gt; to the lens type above.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;       Functor f =&amp;gt; (a -&amp;gt; f a) -&amp;gt; s      -&amp;gt; f s
one :: Functor f =&amp;gt; (a -&amp;gt; f a) -&amp;gt; (a, c) -&amp;gt; f (a, c)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So &lt;code&gt;s&lt;/code&gt; in the lens type is &lt;code&gt;(a, c)&lt;/code&gt; in the type for &lt;code&gt;one&lt;/code&gt;. The getter function &lt;code&gt;s -&amp;gt; a&lt;/code&gt; is generic enough to say that "&lt;code&gt;a&lt;/code&gt; is some part of &lt;code&gt;s&lt;/code&gt;", without being specific about what &lt;code&gt;s&lt;/code&gt; is at all.&lt;/p&gt;
&lt;p&gt;OK, now &lt;code&gt;two&lt;/code&gt; is going to be pretty much the same, except that we'll focus on the second element of the tuple.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;two :: Lens&amp;#39; (c, a) a
two aToFa (c, a) =
  fmap (\a&amp;#39; -&amp;gt; (c, a&amp;#39;)) (aToFa a)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we compare it with the lens type:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;       Functor f =&amp;gt; (a -&amp;gt; f a) -&amp;gt; s      -&amp;gt; f s
two :: Functor f =&amp;gt; (a -&amp;gt; f a) -&amp;gt; (c, a) -&amp;gt; f (c, a)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All together now:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;       Functor f =&amp;gt; (a -&amp;gt; f a) -&amp;gt; s      -&amp;gt; f s
one :: Functor f =&amp;gt; (a -&amp;gt; f a) -&amp;gt; (a, c) -&amp;gt; f (a, c)
two :: Functor f =&amp;gt; (a -&amp;gt; f a) -&amp;gt; (c, a) -&amp;gt; f (c, a)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I reckon we've got a reasonable idea now how the functions &lt;code&gt;one&lt;/code&gt; and &lt;code&gt;two&lt;/code&gt; are lenses. That is to say: we can see how the types line up.&lt;/p&gt;
&lt;p&gt;The next step is to understand how we can use each of these functions as both a getter and a setter.&lt;/p&gt;
&lt;h2 id="lens-interpreters--view-and--modify"&gt;Lens interpreters &lt;code&gt;(^.)&lt;/code&gt; (view) and &lt;code&gt;(%~)&lt;/code&gt; (modify)&lt;/h2&gt;
&lt;p&gt;We've made the types line up, but to what end? What is this crazy type up to anyway? The genius here lies largely in the &lt;code&gt;Functor f&lt;/code&gt; constraint.&lt;/p&gt;
&lt;p&gt;To start with we'll pick a very boring Functor to stand in for &lt;code&gt;f&lt;/code&gt;: &lt;code&gt;Identity&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;newtype Identity a = Identity { runIdentity :: a }

instance Functor Identity where
  fmap :: (a -&amp;gt; b) -&amp;gt; Identity a -&amp;gt; Identity b
  fmap f (Identity a) = Identity (f a)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;See how boring this thing is? It's just a container for a single value, all &lt;code&gt;fmap&lt;/code&gt; can do is unpack it to get at the &lt;code&gt;a&lt;/code&gt; inside, apply &lt;code&gt;f&lt;/code&gt; to &lt;code&gt;a&lt;/code&gt; and pack it back up again.&lt;/p&gt;
&lt;p&gt;Note that our lenses expect a &lt;code&gt;a -&amp;gt; f a&lt;/code&gt;, which in this case will be &lt;code&gt;a -&amp;gt; Identity a&lt;/code&gt;. We have a function already which can fulfil that type, &lt;code&gt;Identity&lt;/code&gt;'s only data constructor:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;Identity :: a -&amp;gt; Identity a&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So we can pass the &lt;code&gt;Identity&lt;/code&gt; data constructor as the first argument to &lt;code&gt;one&lt;/code&gt; and see what we get.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;&amp;gt; :t one Identity
one Identity :: (a, c) -&amp;gt; Identity (a, c)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hmm, and if we pass it some value?&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;&amp;gt; one Identity (1, &amp;#39;a&amp;#39;)
Identity (1,&amp;#39;a&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Makes sense, and I guess all we can do now is unpack it using &lt;code&gt;runIdentity :: Identity a -&amp;gt; a&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;&amp;gt; runIdentity (one Identity (1, &amp;#39;a&amp;#39;))
(1,&amp;#39;a&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wait, this looks familiar.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;&amp;gt; familiar = runIdentity . one Identity
&amp;gt; familiar (1, &amp;#39;a&amp;#39;)
(1,&amp;#39;a&amp;#39;)
&amp;gt; id (1, &amp;#39;a&amp;#39;)
(1,&amp;#39;a&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Right, right. Cool. So absolutely nothing happens but in a fairly involved way.&lt;/p&gt;
&lt;p&gt;We &lt;em&gt;can&lt;/em&gt; make something happen though.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;&amp;gt; one (Identity . (+ 2)) (1, &amp;#39;a&amp;#39;)
Identity (3,&amp;#39;a&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can compose &lt;code&gt;Identity :: a -&amp;gt; Identity a&lt;/code&gt; with some &lt;code&gt;a -&amp;gt; a&lt;/code&gt;. We can write a pretty general function for this:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;&amp;gt; modifyOne f tuple = runIdentity (one (Identity . f) tuple)
&amp;gt; modifyOne (+ 2) (1, &amp;#39;a&amp;#39;)
(3,&amp;#39;a&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;... an even &lt;em&gt;more&lt;/em&gt; general function:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;&amp;gt; modify lens modification value = runIdentity (lens (Identity . modification) value)
&amp;gt; modify one (+ 2) (1, &amp;#39;a&amp;#39;)
(3,&amp;#39;a&amp;#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wow, what's the type of &lt;code&gt;modify&lt;/code&gt; then?&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;&amp;gt; :t modify
modify :: ((a -&amp;gt; Identity a) -&amp;gt; s -&amp;gt; Identity s) -&amp;gt; (a -&amp;gt; a) -&amp;gt; s -&amp;gt; s&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Modify takes a lens:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;&amp;gt; :t modify one
modify one :: (a -&amp;gt; a) -&amp;gt; (a, c) -&amp;gt; (a, c)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;An &lt;code&gt;a -&amp;gt; a&lt;/code&gt;, which will be composed with &lt;code&gt;Identity :: a -&amp;gt; Identity a&lt;/code&gt;, still giving us the &lt;code&gt;a -&amp;gt; Identity a&lt;/code&gt; we need:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;&amp;gt; :t modify one (+ 2)
modify one (+ 2) :: Num a =&amp;gt; (a, c) -&amp;gt; (a, c)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And some value the lens can act on:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;&amp;gt; :t modify one (+ 2) (1, &amp;#39;a&amp;#39;)
modify one (+ 2) (1, &amp;#39;a&amp;#39;) :: Num a =&amp;gt; (a, Char)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we make things less generic for a second it might be a bit clearer:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;one :: (a -&amp;gt; Identity a) -&amp;gt; (a, c) -&amp;gt; Identity (a, c)
one aToFa (a, c) = fmap (\a&amp;#39; -&amp;gt; (a&amp;#39;, c)) (aToFa a)
--  ^^^^^          ^^^^^^^^^^^^^^^^^^^^^
--  |              All this does is put the
--  |              modified a back in the tuple:
--  |              Identity a -&amp;gt; Identity (a, c)
--  |
--  |
--  This is the Identity data constructor composed
--  with some function a -&amp;gt; a, the modification&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is all pretty interesting but still doesn't answer why we have the &lt;code&gt;Functor f&lt;/code&gt; constraint, &lt;code&gt;Identity&lt;/code&gt; here just makes getting to the value kinda obscure.&lt;/p&gt;
&lt;p&gt;Let's put another weird Functor in place of &lt;code&gt;f&lt;/code&gt;: &lt;code&gt;Const&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;newtype Const c a = Const { getConst :: c }

instance Functor (Const c) where
  fmap :: (a -&amp;gt; b) -&amp;gt; Const c a -&amp;gt; Const c b
  fmap _ (Const c) = Const c&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This was pretty mind-bending for me at first. What possible use could this thing have? It looks like it's a Functor where &lt;code&gt;fmap&lt;/code&gt; doesn't &lt;em&gt;do&lt;/em&gt; anything, the function argument is totally ignored.&lt;/p&gt;
&lt;p&gt;It's worth having another look at the signature for &lt;code&gt;fmap&lt;/code&gt; in that last code block. The function argument isn't applied, but the type &lt;em&gt;does&lt;/em&gt; change. We've still gone from &lt;code&gt;f a&lt;/code&gt; to &lt;code&gt;f b&lt;/code&gt; after we've &lt;code&gt;fmap&lt;/code&gt;ed.&lt;/p&gt;
&lt;p&gt;Let's look at these &lt;code&gt;fmap&lt;/code&gt;s side by side.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;fmap :: (a -&amp;gt; b) -&amp;gt; f        a -&amp;gt; f        b
fmap :: (a -&amp;gt; b) -&amp;gt; Identity a -&amp;gt; Identity b
fmap :: (a -&amp;gt; b) -&amp;gt; Const c  a -&amp;gt; Const c  b&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What happens when we use &lt;code&gt;Const :: a -&amp;gt; Const a a&lt;/code&gt; as our &lt;code&gt;a -&amp;gt; f a&lt;/code&gt; in &lt;code&gt;one&lt;/code&gt;?&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;&amp;gt; one Const (1, &amp;#39;a&amp;#39;)
Const 1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Huh? Weird. Wonder what the type is.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;&amp;gt; :t one Const (1, &amp;#39;a&amp;#39;)
one Const (1, &amp;#39;a&amp;#39;) :: Num a =&amp;gt; Const a (a, Char)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Right, so we &lt;em&gt;do&lt;/em&gt; have a &lt;code&gt;Const a (a, c)&lt;/code&gt;, which fits the &lt;code&gt;f (a, c)&lt;/code&gt; returned by &lt;code&gt;one&lt;/code&gt;. The really interesting thing is that the "setter" part of &lt;code&gt;one&lt;/code&gt; didn't actually get applied. &lt;code&gt;Const&lt;/code&gt;'s &lt;code&gt;fmap&lt;/code&gt; ignores that function argument.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;one :: Functor f =&amp;gt; (a -&amp;gt; f a) -&amp;gt; (a, c) -&amp;gt; f (a, c)
one aToFa (a, c) = fmap (\a&amp;#39; -&amp;gt; (a&amp;#39;, c)) (aToFa a)
--                      ^^^^^^^^^^^^^^^^
--                      This is never run&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once more, if we make things less generic for a second it might be a bit clearer:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;one :: (a -&amp;gt; Const a a) -&amp;gt; (a, c) -&amp;gt; Const a (a, c)
one aToFa (a, c) = fmap (\a&amp;#39; -&amp;gt; (a&amp;#39;, c)) (aToFa a)
--  ^^^^^          ^^^^^^^^^^^^^^^^^^^^^
--  |              All this does is
--  |              change the type:
--  |              Const a a -&amp;gt; Const a (a, c)
--  |
--  |
--  This is the Const data constructor.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The Functor constraint is satisfied, so we're able to use &lt;code&gt;Identity&lt;/code&gt; and &lt;code&gt;Const&lt;/code&gt; interchangeably. When we use &lt;code&gt;Identity&lt;/code&gt; the setter function is run and so the updated value is popped back into our tuple, when we use &lt;code&gt;Const&lt;/code&gt; the setter is skipped.&lt;/p&gt;
&lt;p&gt;Once again there's little more we can do than unwrap the Functor:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;&amp;gt; getConst (one Const (1, &amp;#39;a&amp;#39;))
1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Also once again, we can write a very generic version of this:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;&amp;gt; view lens value = getConst (lens Const value)
&amp;gt; :t view
view :: ((a -&amp;gt; Const a a) -&amp;gt; s -&amp;gt; Const a s) -&amp;gt; s -&amp;gt; a
&amp;gt; view one (1, &amp;#39;a&amp;#39;)
1&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="polymorphism"&gt;Polymorphism?&lt;/h2&gt;
&lt;p&gt;So far &lt;code&gt;modify&lt;/code&gt; is somewhat limited, we can only provide it functions that accept and return values of the same type (&lt;code&gt;a -&amp;gt; a&lt;/code&gt;). What might it take to adapt &lt;code&gt;one&lt;/code&gt;, &lt;code&gt;two&lt;/code&gt; and &lt;code&gt;modify&lt;/code&gt; to work with functions that accept one type and return another?&lt;/p&gt;
&lt;p&gt;The answer is: nothing. All we need to do is change some type signatures and variable names. The actual functions are already good to go.&lt;/p&gt;
&lt;p&gt;Our current lens type becomes the same as the lens library type by adding two more type variables: &lt;code&gt;b&lt;/code&gt; and &lt;code&gt;t&lt;/code&gt;. When we allow the value yanked out of &lt;code&gt;s&lt;/code&gt; to have it's type changed from &lt;code&gt;a&lt;/code&gt; to &lt;code&gt;b&lt;/code&gt;, putting it back must be allowed to change the type of &lt;code&gt;s&lt;/code&gt;, and so we return &lt;code&gt;f t&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;Functor f =&amp;gt; (a -&amp;gt; f a) -&amp;gt; s -&amp;gt; f s
Functor f =&amp;gt; (a -&amp;gt; f b) -&amp;gt; s -&amp;gt; f t&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can define another handy alias.&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;type Lens s t a b =
  forall f. Functor f =&amp;gt;
    (a -&amp;gt; f b) -&amp;gt; s -&amp;gt; f t&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;one&lt;/code&gt; becomes &lt;code&gt;_1&lt;/code&gt; with only some type and value variable renaming:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;one :: Lens&amp;#39; (a, c) a
one aToFa (a, c) =
  fmap (\a&amp;#39; -&amp;gt; (a&amp;#39;, c)) (aToFa a)

_1 :: Lens (a, c) (b, c) a b
_1 aToFb (a, c) =
  fmap (\b -&amp;gt; (b, c)) (aToFb a)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As with &lt;code&gt;two&lt;/code&gt; to &lt;code&gt;_2&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;two :: Lens&amp;#39; (c, a) a
two aToFa (c, a) =
  fmap (\a&amp;#39; -&amp;gt; (c, a&amp;#39;)) (aToFa a)

_2 :: Lens (c, a) (c, b) a b
_2 aToFb (c, a) =
  fmap (\b -&amp;gt; (c, b)) (aToFb a)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;modify&lt;/code&gt; becomes &lt;code&gt;%~&lt;/code&gt; thusly&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;modify :: Lens&amp;#39; s a -&amp;gt; (a -&amp;gt; a) -&amp;gt; s -&amp;gt; s
modify lens modification value =
  runIdentity $
    lens (Identity . modification) value

(%~) :: Lens s t a b -&amp;gt; (a -&amp;gt; b) -&amp;gt; s -&amp;gt; t
(%~) lens modification value =
  runIdentity $
    lens (Identity . modification) value

infixr 7 %~&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;view&lt;/code&gt; gets much the same treatment, we also flip the args to make it match &lt;code&gt;^.&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;view :: Lens&amp;#39; s a -&amp;gt; s -&amp;gt; a
view lens value = getConst (lens Const value)

(^.) :: s -&amp;gt; Lens s t a b -&amp;gt; a
(^.) value lens = getConst (lens Const value)

infixr 7 ^.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And hey presto we have polymorphic lenses, quite like those in &lt;code&gt;Control.Lens&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;Some more fun examples to see what we've done in action:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;&amp;gt; (&amp;#39;a&amp;#39;, 4) &amp;amp; _1 %~ (: &amp;quot;bc&amp;quot;)
(&amp;quot;abc&amp;quot;,4)
&amp;gt; (&amp;#39;a&amp;#39;, 4) &amp;amp; _2 %~ show
(&amp;#39;a&amp;#39;,&amp;quot;4&amp;quot;)
&amp;gt; (&amp;#39;a&amp;#39;, 4) ^. _1
&amp;#39;a&amp;#39;
&amp;gt; (&amp;#39;a&amp;#39;, 4) ^. _2
4
-- Let&amp;#39;s get crazy
&amp;gt; (&amp;#39;a&amp;#39;, 4) &amp;amp; _1 %~ (: &amp;quot;bc&amp;quot;) &amp;amp; _2 %~ (show . subtract 4)
(&amp;quot;abc&amp;quot;,&amp;quot;0&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This type didn't make a heap of sense to me when I first saw it:&lt;/p&gt;
&lt;pre class="haskell"&gt;&lt;code&gt;type Lens s t a b =
  forall f. Functor f =&amp;gt;
    (a -&amp;gt; f b) -&amp;gt; s -&amp;gt; f t&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After having gone through all of the implementations above, I reckon I get it now. This is not to say I understand all the weird and wonderful things in &lt;a href="https://hackage.haskell.org/package/lens"&gt;lens&lt;/a&gt;, but I feel like I'm on the way. With any luck this may have helped you too.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Further reading:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The lens wiki has &lt;a href="https://github.com/ekmett/lens/wiki/History-of-Lenses"&gt;this awesome page&lt;/a&gt; full of links that really helped me with the above.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Most of the code samples from this article can be found in &lt;a href="https://gist.github.com/bradparker/205a8ff1f6bcbc9a2d3249e1d8ba5af1#file-lens-hs"&gt;this gist&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>hi@bradparker.id.au (Brad Parker)</author><guid>https://bradparker.com/content/posts/2018-08-21-lets-learn-about-lenses.html</guid><pubDate>Tue, 21 Aug 2018 00:00:00 UTC</pubDate></item><item><title>You already know what Monads are</title><link>https://bradparker.id.au/posts/you-already-know-what-monads-are</link><description>&lt;p&gt;Assuming you're a javascript dev who's had to deal with anything aysncronous.&lt;/p&gt;
&lt;p&gt;Firstly, we're going to talk about promises, so:&lt;/p&gt;
&lt;h2 id="what-do-we-talk-about-when-we-talk-about-promises"&gt;What do we talk about when we talk about Promises?&lt;/h2&gt;
&lt;p&gt;It's very likely you've done something like this:&lt;/p&gt;
&lt;pre class="javascript"&gt;&lt;code&gt;doSomethingAsync(function (resultOfAsyncThing) {
  console.log(resultOfAsyncThing)
})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There's an interesting concept highlighted in that code above.&lt;/p&gt;
&lt;p&gt;What if we tried to do the following:&lt;/p&gt;
&lt;pre class="javascript"&gt;&lt;code&gt;let resultOutsideCallback

doSomethingAsync(function (resultOfAsyncThing) {
  resultOutsideCallback = resultOfAsyncThing
})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;How will we get to use &lt;code&gt;resultOutsideCallback&lt;/code&gt;?&lt;/p&gt;
&lt;pre class="javascript"&gt;&lt;code&gt;let resultOutsideCallback

doSomethingAsync(function (resultOfAsyncThing) {
  resultOutsideCallback = resultOfAsyncThing
})

while(true) {
  if (resultOutsideCallback) {
    console.log(resultOutsideCallback)
    break
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That's... not awesome. Everything we try to execute after that while loop is blocked until the async function's callback is called. But if we want to work with that value "outside" of the callback, that's kind of how we'd have to do it.&lt;/p&gt;
&lt;p&gt;So, it appears that the &lt;code&gt;resultOfAsyncThing&lt;/code&gt; value is best left "inside" the callback. This is something that just kind of &lt;em&gt;happens&lt;/em&gt; when working with callbacks. A callback creates an (almost) inescapable context.&lt;/p&gt;
&lt;pre class="javascript"&gt;&lt;code&gt;someAsyncAction(function (a) {
  someOtherAsyncAction(function (b) {
    console.log(a + b)
  })
})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Promises are a way of turning this concept of "the eventual value of an async action" into an object we can interact with. The object is a container for this future value that grants you access to it through the &lt;code&gt;then&lt;/code&gt; method. The &lt;code&gt;then&lt;/code&gt; method is a way to get into the context in which the eventual value exists.&lt;/p&gt;
&lt;pre class="javascript"&gt;&lt;code&gt;someAsyncAction().then(function (resultOfAsyncAction) {
  console.log(resultOfAsyncAction)
})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, the example above doesn't really offer anything over using callbacks. But there is an aspect of promises that makes them very handy:&lt;/p&gt;
&lt;pre class="javascript"&gt;&lt;code&gt;someAsyncAction().then(function (value) {
  return value.toUppercase()
}).then(function (uppercaseValue) {
  return uppercaseValue.split(&amp;#39;&amp;#39;).reverse().join()
}).then(function (uppercaseAndReversedValue) {
  console.log(uppercaseAndReversed)
})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each time we call &lt;code&gt;then&lt;/code&gt; we get a new promise back. The new promise now "contains" the value returned by the function we passed in. So the above could be re-written as:&lt;/p&gt;
&lt;pre class="javascript"&gt;&lt;code&gt;const uppercased = someAsyncAction().then(function (value) {
  return value.toUppercase()
})

const uppercasedAndReversed = uppercased.then(function (uppercaseValue) {
  return uppercaseValue.split(&amp;#39;&amp;#39;).reverse().join()
})

uppercasedAndReversed.then(function (uppercasedAndReversedValue) {
  console.log(uppercasedAndReversedValue)
})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It looks a lot like performing a chain of transformations on an array to me:&lt;/p&gt;
&lt;pre class="javascript"&gt;&lt;code&gt;[1, 2, 3].map(function (value) {
  return value * 2
}).map(function (value) {
  return value + 2
})&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="ok-so-what-does-this-have-to-do-with-monads"&gt;Ok, so what does this have to do with Monads?&lt;/h2&gt;
&lt;p&gt;Here we should highlight that &lt;code&gt;Array#map&lt;/code&gt; is a lot like &lt;code&gt;Promise#then&lt;/code&gt;. Where &lt;code&gt;then&lt;/code&gt; is something you call on a container for a future value, &lt;code&gt;map&lt;/code&gt; is something you call on a container for many values. They both kind of work the same way, you pass a function which will return a new value which goes back into the container.&lt;/p&gt;
&lt;pre class="javascript"&gt;&lt;code&gt;const a = Promise.resolve(1)
// Promise { 1 }
const b = a.then(function (a) { return a + 2 })
// Promise { 3 }

const as = [ 1, 1, 1 ]
// [ 1, 1, 1 ]
const bs = as.map(function (a) { return a + 2 })
// [ 3, 3, 3 ]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This concept of a container for a value which can have that value transformed by passing a function to the container has a name: Functor. That's a bit of a mouthful so let's pull it apart. Array is a functor because it has a &lt;code&gt;map&lt;/code&gt; method which allows you to operate on and transform its contents. Promise is a functor because it has a &lt;code&gt;then&lt;/code&gt; method which allows you to operate on and transform its eventual value.&lt;/p&gt;
&lt;p&gt;The functions passed to &lt;code&gt;Array#map&lt;/code&gt; and &lt;code&gt;Promise#then&lt;/code&gt; both return the new contents of their respective containers. So you pass in a fuction which returns a "normal" value and when it's called that value will be wrapped up in a container for us.&lt;/p&gt;
&lt;pre class="javascript"&gt;&lt;code&gt;Promise.resolve(1).then(function (a) {
  return a + 2
//       ^^^^^
//       normal, un-wrapped value
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is not always what you want. Say, for example, that you need to perform two async actions in series, one will pass data to the next.&lt;/p&gt;
&lt;pre class="javascript"&gt;&lt;code&gt;readAFile().then(function (content) {
  return writeAFile(content)
}).then(function (report) {
  console.log(report)
})&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;See that? Interesting, right? You can return a new Promise from the function passed to &lt;code&gt;then&lt;/code&gt;, when you do you get a new promise back, but it has the same contents as the one you returned.&lt;/p&gt;
&lt;pre class="javascript"&gt;&lt;code&gt;const a = Promise.resolve(1)
// Promise { 1 }

const b = Promise.resolve(2)
// Promise { 2 }

const c = a.then(function () {
  return b
})
// Promise { 2 }

c === b
// false&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So you either return a "normal" value and it'll get wrapped up in a Promise for you, or you can return a Promise and its content will be the content of the new promise returned.&lt;/p&gt;
&lt;p&gt;This second version of the function passed to &lt;code&gt;then&lt;/code&gt;, where it accepts a normal value but returns a Promise has an array equivelant: &lt;code&gt;flatMap&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="javascript"&gt;&lt;code&gt;flatMap([1, 2, 3], function (elem) {
  return [elem, &amp;#39;-&amp;#39;]
})
// [ 1, &amp;#39;-&amp;#39;, 2, &amp;#39;-&amp;#39;, 3, &amp;#39;-&amp;#39; ]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The function passed to &lt;code&gt;flatMap&lt;/code&gt; takes a normal value but returns an Array. We don't get an array of arrays back because something happens to that returned value so that it results in a flattened array.&lt;/p&gt;
&lt;p&gt;This extension to the idea of a functor, whereby the function passed to it returns a container of the same type has a name: Monad.&lt;/p&gt;
&lt;p&gt;With the value-extracting and container-flattening parts of these operations abstracted away composing functions which return containers is made simpler. We can chain together async operations easily because the plumbing for “where did this value come from?” and “where should this new Promise go?” happens inside the then method. That’s what we get through good, composable abstractions.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;This was intended as something of a practical introduction to the concept of a Monad, there is more to it than I’ve outlined here. If you’d like to dive deeper have a look at http://learnyouahaskell.com/a-fistful-of-monads. You may want to start from the begining of the book to gain some familiarity with Haskell.&lt;/p&gt;
&lt;p&gt;[1] For more info on how promises perform their flattening: http://www.mattgreer.org/articles/promises-in-wicked-detail/&lt;/p&gt;
&lt;p&gt;[2] A simple implementation of flatMap might look like: https://gist.github.com/bradparker/34c7bd8d627809333adcc3e02cd7f755&lt;/p&gt;</description><author>hi@bradparker.id.au (Brad Parker)</author><guid>https://bradparker.com/content/posts/2017-01-06-you-already-know-what-monads-are.html</guid><pubDate>Fri,  6 Jan 2017 00:00:00 UTC</pubDate></item><item><title>Petrichor Ensemble — Gig Poster</title><link>https://bradparker.id.au/posts/petrichor</link><description>&lt;p&gt;&lt;img src="https://bradparker.id.au/assets/images/petrichor-full.jpg" alt="Petrichor Ensemble — Gig Poster Full" /&gt;&lt;/p&gt;</description><author>hi@bradparker.id.au (Brad Parker)</author><guid>https://bradparker.com/content/posts/2013-02-08-petrichor.html</guid><pubDate>Fri,  8 Feb 2013 00:00:00 UTC</pubDate></item><item><title>Brisbane Bicycle Film Festival 2012 — Poster</title><link>https://bradparker.id.au/posts/brisbane-bicycle-film-festival</link><description>&lt;p&gt;&lt;img src="https://bradparker.id.au/assets/images/bbff-2012-full.jpg" alt="Bicycle Film Festival — Poster Full" /&gt;&lt;/p&gt;</description><author>hi@bradparker.id.au (Brad Parker)</author><guid>https://bradparker.com/content/posts/2012-10-03-brisbane-bicycle-film-festival.html</guid><pubDate>Wed,  3 Oct 2012 00:00:00 UTC</pubDate></item><item><title>Design futures — Typography</title><link>https://bradparker.id.au/posts/design-futures</link><description>&lt;p&gt;&lt;img src="https://bradparker.id.au/assets/images/design-futures-full.jpg" alt="Design Futures — Full" /&gt;&lt;/p&gt;</description><author>hi@bradparker.id.au (Brad Parker)</author><guid>https://bradparker.com/content/posts/2011-06-01-design-futures.html</guid><pubDate>Wed,  1 Jun 2011 00:00:00 UTC</pubDate></item><lastBuildDate>Sat, 21 Jun 2025 00:00:00 UTC</lastBuildDate></channel></rss>