<?xml version="1.0" encoding="UTF-8"?><rss dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>in Code — Entries</title><link>https://blog.jle.im/</link><description>Weblog of Justin Le, covering various adventures in programming and explorations in the worlds of computation physics, and knowledge.
</description><item><title>Extreme Haskell: Typed Expression EDSLs (Part 1)</title><link>https://blog.jle.im/entry/extreme-haskell-typed-expression-edsls-1.html</link><description>&lt;p&gt;I always say, inside every Haskeller there are two wolves, living on opposite
ends of the Haskell Fancy Code Spectrum. Are you going to write “simple
Haskell”, using basic GHC 2010 tools and writing universal Haskell that every
introductory course offers, trying to keep the code as immediately
understandable and accessible? Or are you going to pile in all of the Haskell
type system and evaluation tricks you can find and turn on all the extensions,
and go full fancy?&lt;/p&gt;
&lt;p&gt;In my &lt;a
href="https://blog.jle.im/entry/levels-of-type-safety-haskell-lists.html"&gt;Seven
Levels of Type Safety&lt;/a&gt; post, I described different extremes of type safety
and fancy code. I talked about how writing effective code was finding the
correct compromise for the level of communication and safety you need.&lt;/p&gt;
&lt;p&gt;But this is not that kind of blog post. This is the kind of blog post where
we celebrate terrifying type-safety, facetious fanciness, and masochistic
meta-analysis. This series is about what happens when we dare to go full fancy.
Let’s write code that is so inscrutable, so painful and torturous to write, yet
so &lt;em&gt;undeniably useful&lt;/em&gt; that you can’t help but try to throw it into every
single thing you write and will feel a gnawing emptiness in your soul until you
do.&lt;/p&gt;
&lt;p&gt;As our example, let’s write a type-safe method to specify your program as a
series of states, with triggered transitions between them: a type-safe state
machine graph using a type-safe lambda calculus. We want to specify this in a
way that we can write once and then:&lt;/p&gt;
&lt;ol type="1"&gt;
&lt;li&gt;be interpretable in a type-safe way within Haskell.&lt;/li&gt;
&lt;li&gt;be inspectable with visualizable control flow.&lt;/li&gt;
&lt;li&gt;be compilable to multiple actual back-ends, letting you run the same
function under multiple implementations.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This exact thing is something I’ve needed and used multiple times now in
projects. I want to specify one program graph within Haskell, but in a way that
can compile both in C and javascript while also being visualizable and
interactively explorable.&lt;/p&gt;
&lt;p&gt;Once you go down this road, everything you ever write will feel woefully
unsafe and limited. And everything you want to write will be hopelessly
inscrutable by normal humans and borderline unusable. But such is the curse we
all bear. Turn around now, you have been warned.&lt;/p&gt;
&lt;p&gt;This post will build up the embedded typed expression language. Part 2 will
use that expression language to define typed state machines with embedded
predicates and visualize them, and Part 3 will compile those machines to
different languages and verify they execute identically, with some live
demos.&lt;/p&gt;
&lt;p&gt;All of the code here is &lt;a
href="https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/flake.nix"&gt;available
online&lt;/a&gt;, and if you check out the repo and run &lt;code&gt;nix develop&lt;/code&gt; you
should be able to load it all in ghci:&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode bash"&gt;&lt;code class="sourceCode bash"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;$&lt;/span&gt; cd code-samples/typed-sm-lc&lt;/span&gt;
&lt;span id="cb1-2"&gt;&lt;a href="#cb1-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;$&lt;/span&gt; nix develop&lt;/span&gt;
&lt;span id="cb1-3"&gt;&lt;a href="#cb1-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;$&lt;/span&gt; ghci&lt;/span&gt;
&lt;span id="cb1-4"&gt;&lt;a href="#cb1-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ex"&gt;ghci&lt;/span&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; :load ExprStage1.hs&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="the-lambda-calculus"&gt;The Lambda Calculus&lt;/h2&gt;
&lt;p&gt;Let’s derive a way to express an algorithm or expression in Haskell that can
be reified and analyzed within Haskell, and eventually be a form we can compile
to different backends, interpret in Haskell, or generate Graphviz visualizations
for.&lt;/p&gt;
&lt;h3 id="a-first-pass"&gt;A First Pass&lt;/h3&gt;
&lt;p&gt;One basic thing we can do is start with:&lt;/p&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb2-1"&gt;&lt;a href="#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage1.hs#L18-L34&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb2-3"&gt;&lt;a href="#cb2-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Prim&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;PBool&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt; &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;PString&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-4"&gt;&lt;a href="#cb2-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="kw"&gt;deriving&lt;/span&gt; (&lt;span class="dt"&gt;Eq&lt;/span&gt;, &lt;span class="dt"&gt;Show&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb2-5"&gt;&lt;a href="#cb2-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb2-6"&gt;&lt;a href="#cb2-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Op&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;OPlus&lt;/span&gt; &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;OTimes&lt;/span&gt; &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;OLte&lt;/span&gt; &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;OAnd&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-7"&gt;&lt;a href="#cb2-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="kw"&gt;deriving&lt;/span&gt; (&lt;span class="dt"&gt;Eq&lt;/span&gt;, &lt;span class="dt"&gt;Show&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb2-8"&gt;&lt;a href="#cb2-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb2-9"&gt;&lt;a href="#cb2-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-10"&gt;&lt;a href="#cb2-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;EPrim&lt;/span&gt; &lt;span class="dt"&gt;Prim&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-11"&gt;&lt;a href="#cb2-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;EVar&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-12"&gt;&lt;a href="#cb2-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;ELambda&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-13"&gt;&lt;a href="#cb2-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;EApply&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-14"&gt;&lt;a href="#cb2-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;Op&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-15"&gt;&lt;a href="#cb2-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;ERecord&lt;/span&gt; (&lt;span class="dt"&gt;Map&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb2-16"&gt;&lt;a href="#cb2-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;EAccess&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-17"&gt;&lt;a href="#cb2-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;EChoice&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-18"&gt;&lt;a href="#cb2-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;ECase&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; (&lt;span class="dt"&gt;Map&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; (&lt;span class="dt"&gt;String&lt;/span&gt;, &lt;span class="dt"&gt;Expr&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb2-19"&gt;&lt;a href="#cb2-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="kw"&gt;deriving&lt;/span&gt; (&lt;span class="dt"&gt;Eq&lt;/span&gt;, &lt;span class="dt"&gt;Show&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And you can write &lt;code&gt;(\x -&amp;gt; x * 3) 5&lt;/code&gt; as:&lt;/p&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb3-1"&gt;&lt;a href="#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage1.hs#L36-L37&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a href="#cb3-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;fifteen ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-4"&gt;&lt;a href="#cb3-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fifteen &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;ELambda&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OTimes&lt;/span&gt; (&lt;span class="dt"&gt;EVar&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt;) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;))) &lt;span class="ot"&gt;`EApply`&lt;/span&gt; &lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;5&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The strings in &lt;code&gt;ELambda&lt;/code&gt; introduce variables, and
&lt;code&gt;EVar&lt;/code&gt; refers to the bound variable. As you can see, this is…pretty
untyped. We could easily write something that is meaningless:&lt;/p&gt;
&lt;div class="sourceCode" id="cb4"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb4-1"&gt;&lt;a href="#cb4-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage1.hs#L67-L69&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-2"&gt;&lt;a href="#cb4-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb4-3"&gt;&lt;a href="#cb4-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;badTypeExample ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-4"&gt;&lt;a href="#cb4-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;badTypeExample &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-5"&gt;&lt;a href="#cb4-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OAnd&lt;/span&gt; (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;)) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Of course, GHC can typecheck our code if we literally write
&lt;code&gt;\x -&amp;gt; x + 3&lt;/code&gt; and reject &lt;code&gt;1 &amp;amp;&amp;amp; 2&lt;/code&gt;. But we
aren’t trying to build opaque Haskell code here, we’re trying to represent our
expression as an ADT that we can analyze &lt;em&gt;within&lt;/em&gt; the language.&lt;/p&gt;
&lt;p&gt;If we want a record projection and one labeled choice with a case analysis
over it:&lt;/p&gt;
&lt;div class="sourceCode" id="cb5"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb5-1"&gt;&lt;a href="#cb5-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage1.hs#L39-L62&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-2"&gt;&lt;a href="#cb5-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb5-3"&gt;&lt;a href="#cb5-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;recordExample ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-4"&gt;&lt;a href="#cb5-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;recordExample &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-5"&gt;&lt;a href="#cb5-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EOp&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-6"&gt;&lt;a href="#cb5-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;OPlus&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-7"&gt;&lt;a href="#cb5-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ( &lt;span class="dt"&gt;EAccess&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-8"&gt;&lt;a href="#cb5-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ( &lt;span class="dt"&gt;ERecord&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-9"&gt;&lt;a href="#cb5-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            M.fromList&lt;/span&gt;
&lt;span id="cb5-10"&gt;&lt;a href="#cb5-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              [ (&lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;, &lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;7&lt;/span&gt;)),&lt;/span&gt;
&lt;span id="cb5-11"&gt;&lt;a href="#cb5-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                (&lt;span class="st"&gt;&amp;quot;label&amp;quot;&lt;/span&gt;, &lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PString&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;found&amp;quot;&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb5-12"&gt;&lt;a href="#cb5-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              ]&lt;/span&gt;
&lt;span id="cb5-13"&gt;&lt;a href="#cb5-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        )&lt;/span&gt;
&lt;span id="cb5-14"&gt;&lt;a href="#cb5-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-15"&gt;&lt;a href="#cb5-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb5-16"&gt;&lt;a href="#cb5-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb5-17"&gt;&lt;a href="#cb5-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb5-18"&gt;&lt;a href="#cb5-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;sumExample ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-19"&gt;&lt;a href="#cb5-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sumExample &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-20"&gt;&lt;a href="#cb5-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ECase&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-21"&gt;&lt;a href="#cb5-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    (&lt;span class="dt"&gt;EChoice&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;7&lt;/span&gt;)))&lt;/span&gt;
&lt;span id="cb5-22"&gt;&lt;a href="#cb5-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ( M.fromList&lt;/span&gt;
&lt;span id="cb5-23"&gt;&lt;a href="#cb5-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        [ (&lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt;, (&lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;, &lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OPlus&lt;/span&gt; (&lt;span class="dt"&gt;EVar&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;)))),&lt;/span&gt;
&lt;span id="cb5-24"&gt;&lt;a href="#cb5-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          (&lt;span class="st"&gt;&amp;quot;Missing&amp;quot;&lt;/span&gt;, (&lt;span class="st"&gt;&amp;quot;message&amp;quot;&lt;/span&gt;, &lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;)))&lt;/span&gt;
&lt;span id="cb5-25"&gt;&lt;a href="#cb5-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ]&lt;/span&gt;
&lt;span id="cb5-26"&gt;&lt;a href="#cb5-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, for the entire point of &lt;code&gt;Expr&lt;/code&gt;, we can write a function to
pretty-print it, using the &lt;em&gt;&lt;a
href="https://hackage.haskell.org/package/prettyprinter"&gt;prettyprinter&lt;/a&gt;&lt;/em&gt;
library:&lt;/p&gt;
&lt;div class="sourceCode" id="cb6"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb6-1"&gt;&lt;a href="#cb6-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage1.hs#L253-L299&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-2"&gt;&lt;a href="#cb6-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb6-3"&gt;&lt;a href="#cb6-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;ppPrim ::&lt;/span&gt; &lt;span class="dt"&gt;Prim&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;PP.Doc&lt;/span&gt; ann&lt;/span&gt;
&lt;span id="cb6-4"&gt;&lt;a href="#cb6-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ppPrim &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-5"&gt;&lt;a href="#cb6-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;PInt&lt;/span&gt; n &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; PP.pretty n&lt;/span&gt;
&lt;span id="cb6-6"&gt;&lt;a href="#cb6-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;PBool&lt;/span&gt; &lt;span class="dt"&gt;True&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-7"&gt;&lt;a href="#cb6-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;PBool&lt;/span&gt; &lt;span class="dt"&gt;False&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;false&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-8"&gt;&lt;a href="#cb6-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;PString&lt;/span&gt; s &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; PP.pretty (&lt;span class="fu"&gt;show&lt;/span&gt; s)&lt;/span&gt;
&lt;span id="cb6-9"&gt;&lt;a href="#cb6-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb6-10"&gt;&lt;a href="#cb6-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;ppOp ::&lt;/span&gt; &lt;span class="dt"&gt;Op&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;PP.Doc&lt;/span&gt; ann&lt;/span&gt;
&lt;span id="cb6-11"&gt;&lt;a href="#cb6-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ppOp &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-12"&gt;&lt;a href="#cb6-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;OPlus&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;+&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-13"&gt;&lt;a href="#cb6-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;OTimes&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;*&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-14"&gt;&lt;a href="#cb6-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;OLte&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;&amp;lt;=&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-15"&gt;&lt;a href="#cb6-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;OAnd&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;&amp;amp;&amp;amp;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-16"&gt;&lt;a href="#cb6-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb6-17"&gt;&lt;a href="#cb6-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;ppExpr ::&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;PP.Doc&lt;/span&gt; ann&lt;/span&gt;
&lt;span id="cb6-18"&gt;&lt;a href="#cb6-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ppExpr paren &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-19"&gt;&lt;a href="#cb6-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EPrim&lt;/span&gt; p &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; ppPrim p&lt;/span&gt;
&lt;span id="cb6-20"&gt;&lt;a href="#cb6-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVar&lt;/span&gt; v &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; PP.pretty v&lt;/span&gt;
&lt;span id="cb6-21"&gt;&lt;a href="#cb6-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ELambda&lt;/span&gt; n body &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-22"&gt;&lt;a href="#cb6-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    wrap &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;\\&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; PP.pretty n &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;-&amp;gt;&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr &lt;span class="dt"&gt;False&lt;/span&gt; body&lt;/span&gt;
&lt;span id="cb6-23"&gt;&lt;a href="#cb6-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EApply&lt;/span&gt; f x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-24"&gt;&lt;a href="#cb6-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    wrap &lt;span class="op"&gt;$&lt;/span&gt; ppExpr &lt;span class="dt"&gt;True&lt;/span&gt; f &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr &lt;span class="dt"&gt;True&lt;/span&gt; x&lt;/span&gt;
&lt;span id="cb6-25"&gt;&lt;a href="#cb6-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EOp&lt;/span&gt; o x y &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-26"&gt;&lt;a href="#cb6-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    wrap &lt;span class="op"&gt;$&lt;/span&gt; ppExpr &lt;span class="dt"&gt;True&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppOp o &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr &lt;span class="dt"&gt;True&lt;/span&gt; y&lt;/span&gt;
&lt;span id="cb6-27"&gt;&lt;a href="#cb6-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ERecord&lt;/span&gt; xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-28"&gt;&lt;a href="#cb6-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    PP.encloseSep &lt;span class="st"&gt;&amp;quot;{ &amp;quot;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot; }&amp;quot;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;, &amp;quot;&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-29"&gt;&lt;a href="#cb6-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      [PP.pretty k &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;=&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr &lt;span class="dt"&gt;False&lt;/span&gt; v &lt;span class="op"&gt;|&lt;/span&gt; (k, v) &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; M.toList xs]&lt;/span&gt;
&lt;span id="cb6-30"&gt;&lt;a href="#cb6-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EAccess&lt;/span&gt; e k &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-31"&gt;&lt;a href="#cb6-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ppExpr &lt;span class="dt"&gt;True&lt;/span&gt; e &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;.&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; PP.pretty k&lt;/span&gt;
&lt;span id="cb6-32"&gt;&lt;a href="#cb6-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EChoice&lt;/span&gt; tag x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-33"&gt;&lt;a href="#cb6-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    wrap &lt;span class="op"&gt;$&lt;/span&gt; PP.pretty tag &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr &lt;span class="dt"&gt;True&lt;/span&gt; x&lt;/span&gt;
&lt;span id="cb6-34"&gt;&lt;a href="#cb6-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ECase&lt;/span&gt; x hs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-35"&gt;&lt;a href="#cb6-35" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    wrap &lt;span class="op"&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-36"&gt;&lt;a href="#cb6-36" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      PP.sep&lt;/span&gt;
&lt;span id="cb6-37"&gt;&lt;a href="#cb6-37" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        [ &lt;span class="st"&gt;&amp;quot;case&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr &lt;span class="dt"&gt;False&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;of&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-38"&gt;&lt;a href="#cb6-38" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        , PP.encloseSep &lt;span class="st"&gt;&amp;quot;{ &amp;quot;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot; }&amp;quot;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;; &amp;quot;&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-39"&gt;&lt;a href="#cb6-39" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            [ PP.pretty tag &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; PP.pretty n &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;-&amp;gt;&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr &lt;span class="dt"&gt;False&lt;/span&gt; body&lt;/span&gt;
&lt;span id="cb6-40"&gt;&lt;a href="#cb6-40" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;|&lt;/span&gt; (tag, (n, body)) &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; M.toList hs&lt;/span&gt;
&lt;span id="cb6-41"&gt;&lt;a href="#cb6-41" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            ]&lt;/span&gt;
&lt;span id="cb6-42"&gt;&lt;a href="#cb6-42" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ]&lt;/span&gt;
&lt;span id="cb6-43"&gt;&lt;a href="#cb6-43" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-44"&gt;&lt;a href="#cb6-44" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    wrap&lt;/span&gt;
&lt;span id="cb6-45"&gt;&lt;a href="#cb6-45" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="op"&gt;|&lt;/span&gt; paren &lt;span class="ot"&gt;=&lt;/span&gt; PP.parens&lt;/span&gt;
&lt;span id="cb6-46"&gt;&lt;a href="#cb6-46" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="fu"&gt;otherwise&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-47"&gt;&lt;a href="#cb6-47" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb6-48"&gt;&lt;a href="#cb6-48" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;prettyExpr ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;PP.Doc&lt;/span&gt; ann&lt;/span&gt;
&lt;span id="cb6-49"&gt;&lt;a href="#cb6-49" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;prettyExpr &lt;span class="ot"&gt;=&lt;/span&gt; ppExpr &lt;span class="dt"&gt;False&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb7"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb7-1"&gt;&lt;a href="#cb7-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; prettyExpr fifteen&lt;/span&gt;
&lt;span id="cb7-2"&gt;&lt;a href="#cb7-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(\x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; x &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;) &lt;span class="dv"&gt;5&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-3"&gt;&lt;a href="#cb7-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; prettyExpr badTypeExample&lt;/span&gt;
&lt;span id="cb7-4"&gt;&lt;a href="#cb7-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="op"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-5"&gt;&lt;a href="#cb7-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; prettyExpr recordExample&lt;/span&gt;
&lt;span id="cb7-6"&gt;&lt;a href="#cb7-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;{ label &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;found&amp;quot;&lt;/span&gt;, value &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;7&lt;/span&gt; }&lt;span class="op"&gt;.&lt;/span&gt;value &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-7"&gt;&lt;a href="#cb7-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; prettyExpr sumExample&lt;/span&gt;
&lt;span id="cb7-8"&gt;&lt;a href="#cb7-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;case&lt;/span&gt; &lt;span class="dt"&gt;Found&lt;/span&gt; &lt;span class="dv"&gt;7&lt;/span&gt; &lt;span class="kw"&gt;of&lt;/span&gt; { &lt;span class="dt"&gt;Found&lt;/span&gt; value &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; value &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;; &lt;span class="dt"&gt;Missing&lt;/span&gt; message &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt; }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, we can write a quick typechecker for this using a greedy type-checking
algorithm (&lt;a
href="https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage1.hs#L77-L89"&gt;written
out here&lt;/a&gt;), which is a fun exercise, but it’s beyond the point of this post.
For our purposes, we’re going to write the in-Haskell evaluator, which is one
sure-fire evidential/constructive way to prove an expression was valid
after-the-fact.&lt;/p&gt;
&lt;p&gt;So…how can you “evaluate” this to 15, within Haskell? What would the type
even be? The best we can do at this point is make the entire thing monadic by
returning &lt;code&gt;Maybe&lt;/code&gt; or &lt;code&gt;Either&lt;/code&gt;, and split out the
expressions we write from the values we can actually evaluate to:&lt;/p&gt;
&lt;div class="sourceCode" id="cb8"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb8-1"&gt;&lt;a href="#cb8-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage1.hs#L228-L330&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-2"&gt;&lt;a href="#cb8-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb8-3"&gt;&lt;a href="#cb8-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-4"&gt;&lt;a href="#cb8-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;EVInt&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-5"&gt;&lt;a href="#cb8-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;EVBool&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-6"&gt;&lt;a href="#cb8-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;EVString&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-7"&gt;&lt;a href="#cb8-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;EVFun&lt;/span&gt; (&lt;span class="dt"&gt;EValue&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb8-8"&gt;&lt;a href="#cb8-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;EVRecord&lt;/span&gt; (&lt;span class="dt"&gt;Map&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb8-9"&gt;&lt;a href="#cb8-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;EVChoice&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-10"&gt;&lt;a href="#cb8-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb8-11"&gt;&lt;a href="#cb8-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;eval ::&lt;/span&gt; &lt;span class="dt"&gt;Map&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-12"&gt;&lt;a href="#cb8-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;eval env &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-13"&gt;&lt;a href="#cb8-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EPrim&lt;/span&gt; p &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; evalPrim p&lt;/span&gt;
&lt;span id="cb8-14"&gt;&lt;a href="#cb8-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVar&lt;/span&gt; v &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; M.lookup v env&lt;/span&gt;
&lt;span id="cb8-15"&gt;&lt;a href="#cb8-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ELambda&lt;/span&gt; n body &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;pure&lt;/span&gt; (&lt;span class="dt"&gt;EVFun&lt;/span&gt; (\x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; eval (M.insert n x env) body))&lt;/span&gt;
&lt;span id="cb8-16"&gt;&lt;a href="#cb8-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EApply&lt;/span&gt; f x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; eval env f &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-17"&gt;&lt;a href="#cb8-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;EVFun&lt;/span&gt; f&amp;#39; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; eval env x &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; f&amp;#39;&lt;/span&gt;
&lt;span id="cb8-18"&gt;&lt;a href="#cb8-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-19"&gt;&lt;a href="#cb8-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EOp&lt;/span&gt; o x y &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-20"&gt;&lt;a href="#cb8-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    u &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env x&lt;/span&gt;
&lt;span id="cb8-21"&gt;&lt;a href="#cb8-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    v &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env y&lt;/span&gt;
&lt;span id="cb8-22"&gt;&lt;a href="#cb8-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;case&lt;/span&gt; (u, v) &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-23"&gt;&lt;a href="#cb8-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      (&lt;span class="dt"&gt;EVInt&lt;/span&gt; a, &lt;span class="dt"&gt;EVInt&lt;/span&gt; b) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;case&lt;/span&gt; o &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-24"&gt;&lt;a href="#cb8-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="dt"&gt;OPlus&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;pure&lt;/span&gt; (&lt;span class="dt"&gt;EVInt&lt;/span&gt; (a &lt;span class="op"&gt;+&lt;/span&gt; b))&lt;/span&gt;
&lt;span id="cb8-25"&gt;&lt;a href="#cb8-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="dt"&gt;OTimes&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;pure&lt;/span&gt; (&lt;span class="dt"&gt;EVInt&lt;/span&gt; (a &lt;span class="op"&gt;*&lt;/span&gt; b))&lt;/span&gt;
&lt;span id="cb8-26"&gt;&lt;a href="#cb8-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="dt"&gt;OLte&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;pure&lt;/span&gt; (&lt;span class="dt"&gt;EVBool&lt;/span&gt; (a &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; b))&lt;/span&gt;
&lt;span id="cb8-27"&gt;&lt;a href="#cb8-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="dt"&gt;OAnd&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-28"&gt;&lt;a href="#cb8-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      (&lt;span class="dt"&gt;EVBool&lt;/span&gt; a, &lt;span class="dt"&gt;EVBool&lt;/span&gt; b) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;case&lt;/span&gt; o &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-29"&gt;&lt;a href="#cb8-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="dt"&gt;OAnd&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;pure&lt;/span&gt; (&lt;span class="dt"&gt;EVBool&lt;/span&gt; (a &lt;span class="op"&gt;&amp;amp;&amp;amp;&lt;/span&gt; b))&lt;/span&gt;
&lt;span id="cb8-30"&gt;&lt;a href="#cb8-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-31"&gt;&lt;a href="#cb8-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-32"&gt;&lt;a href="#cb8-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ERecord&lt;/span&gt; xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EVRecord&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;traverse&lt;/span&gt; (eval env) xs&lt;/span&gt;
&lt;span id="cb8-33"&gt;&lt;a href="#cb8-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EAccess&lt;/span&gt; e k &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-34"&gt;&lt;a href="#cb8-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;EVRecord&lt;/span&gt; xs &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env e&lt;/span&gt;
&lt;span id="cb8-35"&gt;&lt;a href="#cb8-35" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    M.lookup k xs&lt;/span&gt;
&lt;span id="cb8-36"&gt;&lt;a href="#cb8-36" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EChoice&lt;/span&gt; tag x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EVChoice&lt;/span&gt; tag &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; eval env x&lt;/span&gt;
&lt;span id="cb8-37"&gt;&lt;a href="#cb8-37" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ECase&lt;/span&gt; x hs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-38"&gt;&lt;a href="#cb8-38" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;EVChoice&lt;/span&gt; tag payload &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env x&lt;/span&gt;
&lt;span id="cb8-39"&gt;&lt;a href="#cb8-39" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    (n, body) &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; M.lookup tag hs&lt;/span&gt;
&lt;span id="cb8-40"&gt;&lt;a href="#cb8-40" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    eval (M.insert n payload env) body&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This would properly evaluate:&lt;/p&gt;
&lt;div class="sourceCode" id="cb9"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb9-1"&gt;&lt;a href="#cb9-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; eval M.empty fifteen&lt;/span&gt;
&lt;span id="cb9-2"&gt;&lt;a href="#cb9-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Just&lt;/span&gt; (&lt;span class="dt"&gt;EVInt&lt;/span&gt; &lt;span class="dv"&gt;15&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can also produce closures as values:&lt;/p&gt;
&lt;div class="sourceCode" id="cb10"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb10-1"&gt;&lt;a href="#cb10-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage1.hs#L64-L65&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-2"&gt;&lt;a href="#cb10-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-3"&gt;&lt;a href="#cb10-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;plusThree ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-4"&gt;&lt;a href="#cb10-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plusThree &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;ELambda&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OPlus&lt;/span&gt; (&lt;span class="dt"&gt;EVar&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt;) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;)))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb11"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb11-1"&gt;&lt;a href="#cb11-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; for_ (eval M.empty plusThree) \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-2"&gt;&lt;a href="#cb11-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;EVFun&lt;/span&gt; f &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;print&lt;/span&gt; (f (&lt;span class="dt"&gt;EVInt&lt;/span&gt; &lt;span class="dv"&gt;4&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb11-3"&gt;&lt;a href="#cb11-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;putStrLn&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;not a function&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-4"&gt;&lt;a href="#cb11-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Just&lt;/span&gt; (&lt;span class="dt"&gt;EVInt&lt;/span&gt; &lt;span class="dv"&gt;7&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This kind of works if you remember to thread everything through
&lt;code&gt;Maybe&lt;/code&gt; (or &lt;code&gt;Either&lt;/code&gt;) or what have you. But this is not
ideal. You should be able to know, at compile-time, that your &lt;code&gt;Expr&lt;/code&gt;
is valid. After all, you want to be able to create one “valid”
&lt;code&gt;Expr&lt;/code&gt;, and run it at every context. It’s useless to you if every
single time you used an &lt;code&gt;Expr&lt;/code&gt;, you had to manually handle the
&lt;code&gt;Nothing&lt;/code&gt; case. Your diagram generator, your Haskell runner, your
code generator, will always be in &lt;code&gt;Either&lt;/code&gt; even though you know your
&lt;code&gt;Expr&lt;/code&gt; is valid, via tests or something. We want GHC to reject badly
typed expressions, so we never need to unwrap or handle a &lt;code&gt;Nothing&lt;/code&gt;
or &lt;code&gt;Left&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;No, no, this is not okay and not acceptable. We should be able to verify in
the types if an &lt;code&gt;Expr&lt;/code&gt; is valid.&lt;/p&gt;
&lt;h2 id="type-indexed-expressions"&gt;Type-Indexed Expressions&lt;/h2&gt;
&lt;h3 id="just-add-the-index"&gt;Just Add the Index&lt;/h3&gt;
&lt;p&gt;The next step you’ll see in posts online is to add a phantom index type to
&lt;code&gt;Expr&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb12"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb12-1"&gt;&lt;a href="#cb12-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage2.hs#L19-L49&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-2"&gt;&lt;a href="#cb12-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb12-3"&gt;&lt;a href="#cb12-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Ty&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-4"&gt;&lt;a href="#cb12-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-5"&gt;&lt;a href="#cb12-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;TBool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-6"&gt;&lt;a href="#cb12-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-7"&gt;&lt;a href="#cb12-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;Ty&lt;/span&gt; &lt;span class="op"&gt;:-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Ty&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-8"&gt;&lt;a href="#cb12-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb12-9"&gt;&lt;a href="#cb12-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Prim&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Ty&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-10"&gt;&lt;a href="#cb12-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;PInt&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Prim&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-11"&gt;&lt;a href="#cb12-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;PBool&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Prim&lt;/span&gt; &lt;span class="dt"&gt;TBool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-12"&gt;&lt;a href="#cb12-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;PString&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Prim&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-13"&gt;&lt;a href="#cb12-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb12-14"&gt;&lt;a href="#cb12-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Op&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Ty&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Ty&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Ty&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-15"&gt;&lt;a href="#cb12-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;OPlus&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Op&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-16"&gt;&lt;a href="#cb12-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;OTimes&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Op&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-17"&gt;&lt;a href="#cb12-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;OLte&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Op&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt; &lt;span class="dt"&gt;TBool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-18"&gt;&lt;a href="#cb12-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;OAnd&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Op&lt;/span&gt; &lt;span class="dt"&gt;TBool&lt;/span&gt; &lt;span class="dt"&gt;TBool&lt;/span&gt; &lt;span class="dt"&gt;TBool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-19"&gt;&lt;a href="#cb12-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb12-20"&gt;&lt;a href="#cb12-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Ty&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-21"&gt;&lt;a href="#cb12-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EPrim&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Prim&lt;/span&gt; t &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; t&lt;/span&gt;
&lt;span id="cb12-22"&gt;&lt;a href="#cb12-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVar&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; t &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; t&lt;/span&gt;
&lt;span id="cb12-23"&gt;&lt;a href="#cb12-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ELambda&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; (a &lt;span class="op"&gt;:-&amp;gt;&lt;/span&gt; b)&lt;/span&gt;
&lt;span id="cb12-24"&gt;&lt;a href="#cb12-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EApply&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; (a &lt;span class="op"&gt;:-&amp;gt;&lt;/span&gt; b) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; b&lt;/span&gt;
&lt;span id="cb12-25"&gt;&lt;a href="#cb12-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EOp&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Op&lt;/span&gt; a b c &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; c&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(We’ll explain each part of this declaration eventually)&lt;/p&gt;
&lt;p&gt;A phantom type is a type parameter that doesn’t represent any actual
&lt;em&gt;value&lt;/em&gt; “contained” inside the data type, but just serves to “tag” or
distinguish values for the compiler to reject or unify things in useful
ways.&lt;/p&gt;
&lt;p&gt;This introduces several new language features, so bear with me as I break
them down.&lt;/p&gt;
&lt;p&gt;First, we use &lt;code&gt;-XTypeData&lt;/code&gt; to define a data kind: &lt;code&gt;Ty&lt;/code&gt;
is a kind with types &lt;code&gt;TInt :: Ty&lt;/code&gt;, &lt;code&gt;TBool :: Ty&lt;/code&gt;, etc. And
in &lt;code&gt;Expr t&lt;/code&gt;, we have an expression tagged with &lt;code&gt;t&lt;/code&gt;, which
describes the result type. (In fact, &lt;em&gt;all&lt;/em&gt; data types are automatically
promoted to the type level with &lt;code&gt;-XDataKinds&lt;/code&gt;. You might see the
&lt;code&gt;'Nothing&lt;/code&gt; quote prefix syntax in cases where it’s ambiguous if
you’re talking about the data constructor or the type constructor, like
&lt;code&gt;'[]&lt;/code&gt; and &lt;code&gt;'(,)&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;For example, because we have &lt;code&gt;EPrim :: Prim t -&amp;gt; Expr t&lt;/code&gt;, and
&lt;code&gt;PInt 3 :: Prim TInt&lt;/code&gt;, we have
&lt;code&gt;EPrim (PInt 3) :: Expr TInt&lt;/code&gt;: a primitive 3 is an expression
describing an integer.&lt;/p&gt;
&lt;p&gt;And because
&lt;code&gt;EOp :: Op a b c -&amp;gt; Expr a -&amp;gt; Expr b -&amp;gt; Expr c&lt;/code&gt;, and
&lt;code&gt;OLte :: Op TInt TInt TBool&lt;/code&gt;, we have&lt;/p&gt;
&lt;div class="sourceCode" id="cb13"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb13-1"&gt;&lt;a href="#cb13-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OLte&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;TBool&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So we can write an operation on two &lt;code&gt;Expr&lt;/code&gt;s that typecheck how
we’d expect:&lt;/p&gt;
&lt;div class="sourceCode" id="cb14"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb14-1"&gt;&lt;a href="#cb14-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;:&lt;/span&gt;t &lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OLte&lt;/span&gt; (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;)) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;4&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb14-2"&gt;&lt;a href="#cb14-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;TBool&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We also have
&lt;code&gt;EOp OAnd :: Expr TBool -&amp;gt; Expr TBool -&amp;gt; Expr TBool&lt;/code&gt;, which
means the compiler will reject our previous &lt;code&gt;1 &amp;amp;&amp;amp; 2&lt;/code&gt;
example:&lt;/p&gt;
&lt;div class="sourceCode" id="cb15"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb15-1"&gt;&lt;a href="#cb15-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;:&lt;/span&gt;t &lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OAnd&lt;/span&gt; (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;)) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb15-2"&gt;&lt;a href="#cb15-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;interactive&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;error&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb15-3"&gt;&lt;a href="#cb15-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    • &lt;span class="dt"&gt;Couldn&amp;#39;t&lt;/span&gt; match &lt;span class="kw"&gt;type&lt;/span&gt; ‘&lt;span class="dt"&gt;TInt&lt;/span&gt;’ with ‘&lt;span class="dt"&gt;TBool&lt;/span&gt;’&lt;/span&gt;
&lt;span id="cb15-4"&gt;&lt;a href="#cb15-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;Expected&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;Prim&lt;/span&gt; &lt;span class="dt"&gt;TBool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb15-5"&gt;&lt;a href="#cb15-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="dt"&gt;Actual&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;Prim&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can write lambdas in this system too:&lt;/p&gt;
&lt;div class="sourceCode" id="cb16"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb16-1"&gt;&lt;a href="#cb16-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage2.hs#L51-L55&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-2"&gt;&lt;a href="#cb16-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb16-3"&gt;&lt;a href="#cb16-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;fifteen ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-4"&gt;&lt;a href="#cb16-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fifteen &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-5"&gt;&lt;a href="#cb16-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EApply&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-6"&gt;&lt;a href="#cb16-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    (&lt;span class="dt"&gt;ELambda&lt;/span&gt; &lt;span class="dt"&gt;STInt&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OTimes&lt;/span&gt; (&lt;span class="dt"&gt;EVar&lt;/span&gt; &lt;span class="dt"&gt;STInt&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt;) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;))))&lt;/span&gt;
&lt;span id="cb16-7"&gt;&lt;a href="#cb16-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;5&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Because of &lt;code&gt;Ty&lt;/code&gt;, we can also make a new indexed data type with
phantoms of “fully resolved” values:&lt;/p&gt;
&lt;div class="sourceCode" id="cb17"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb17-1"&gt;&lt;a href="#cb17-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage2.hs#L115-L119&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb17-2"&gt;&lt;a href="#cb17-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb17-3"&gt;&lt;a href="#cb17-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Ty&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb17-4"&gt;&lt;a href="#cb17-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVInt&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb17-5"&gt;&lt;a href="#cb17-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVBool&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt; &lt;span class="dt"&gt;TBool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb17-6"&gt;&lt;a href="#cb17-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVString&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb17-7"&gt;&lt;a href="#cb17-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVFun&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; (&lt;span class="dt"&gt;EValue&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; (&lt;span class="dt"&gt;EValue&lt;/span&gt; b)) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt; (a &lt;span class="op"&gt;:-&amp;gt;&lt;/span&gt; b)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is what we want to eventually &lt;code&gt;eval&lt;/code&gt; into, as we can
guarantee ourselves to get a value of the correct type based on the
&lt;code&gt;Ty&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb18"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb18-1"&gt;&lt;a href="#cb18-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;eValueToInt ::&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-2"&gt;&lt;a href="#cb18-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;eValueToInt &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-3"&gt;&lt;a href="#cb18-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;EVInt&lt;/span&gt; x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; x&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And GHC will verify this as a total pattern match because &lt;code&gt;EVInt&lt;/code&gt;
is the only possible way to create an &lt;code&gt;EValue TInt&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="singletons-and-existentials"&gt;Singletons and Existentials&lt;/h3&gt;
&lt;p&gt;We’ll keep our bound variables stored as an ambient map of variable names to
their evaluated values for now. But, to do this, we need to turn the
heterogeneous &lt;code&gt;EValue t&lt;/code&gt; into the homogeneous
&lt;code&gt;Map String SomeValue&lt;/code&gt; by wrapping the type variable as an
existential type.&lt;/p&gt;
&lt;p&gt;You might notice we have a &lt;a
href="https://blog.jle.im/entries/series/+introduction-to-singletons.html"&gt;singleton&lt;/a&gt;
for our &lt;code&gt;Ty&lt;/code&gt; type, &lt;code&gt;STy&lt;/code&gt;, that pops up in multiple
situations.&lt;/p&gt;
&lt;div class="sourceCode" id="cb19"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb19-1"&gt;&lt;a href="#cb19-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage2.hs#L27-L31&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-2"&gt;&lt;a href="#cb19-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb19-3"&gt;&lt;a href="#cb19-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Ty&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-4"&gt;&lt;a href="#cb19-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;STInt&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-5"&gt;&lt;a href="#cb19-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;STBool&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; &lt;span class="dt"&gt;TBool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-6"&gt;&lt;a href="#cb19-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;STString&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-7"&gt;&lt;a href="#cb19-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;STFun&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; (a &lt;span class="op"&gt;:-&amp;gt;&lt;/span&gt; b)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Firstly, it might help to recognize the general pattern where
&lt;code&gt;STy&lt;/code&gt; (the singleton) appears. It &lt;em&gt;usually&lt;/em&gt; pops up whenever
we have existentially scoped variables, like in
&lt;code&gt;data SomeValue = forall t. SomeValue (STy t) (EValue t)&lt;/code&gt;. In this
case, the &lt;code&gt;t&lt;/code&gt; is completely lost to the outside world, and
&lt;code&gt;STy t&lt;/code&gt; is used to allow us to recover a runtime witness to what
&lt;code&gt;t&lt;/code&gt; was, after pattern matching on &lt;code&gt;STy&lt;/code&gt;. This is the
&lt;em&gt;dependent sum&lt;/em&gt; pattern, and is similar to how &lt;code&gt;Typeable&lt;/code&gt; is
used in &lt;em&gt;Data.Dynamic&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In our case, because variables are still stored ambiently in the environment
and validated at runtime, we &lt;em&gt;do&lt;/em&gt; need singletons to implement
&lt;code&gt;eval&lt;/code&gt; . The type &lt;code&gt;Expr t&lt;/code&gt; only specifies the type of the
result, but the type information of the ambient variables is not available. So,
you can write &lt;code&gt;EVar STInt "myVar" :: Expr TInt&lt;/code&gt;, but:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;myVar&lt;/code&gt; might not be a variable in scope at all, so
&lt;code&gt;eval&lt;/code&gt; will fail at runtime&lt;/li&gt;
&lt;li&gt;&lt;code&gt;myVar&lt;/code&gt; might be in scope, but might be a &lt;code&gt;TString&lt;/code&gt;
and not a &lt;code&gt;TInt&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The first case is easy enough to deal with (&lt;code&gt;M.lookup&lt;/code&gt; returns
&lt;code&gt;Nothing&lt;/code&gt;), but the second one is a little more subtle. Let’s say we
&lt;em&gt;do&lt;/em&gt; have a &lt;code&gt;SomeValue&lt;/code&gt; under our key &lt;code&gt;myVar&lt;/code&gt;…how
do we make sure it has the correct type?&lt;/p&gt;
&lt;h3 id="runtime-type-equality"&gt;Runtime Type Equality&lt;/h3&gt;
&lt;p&gt;We can do ad-hoc pattern matching on &lt;code&gt;EValue&lt;/code&gt;, but that won’t get
us too far. Mostly because some of the &lt;code&gt;EValue&lt;/code&gt; constructors actually
don’t have enough information for us to validate their actual type (try it!
&lt;code&gt;EVFun&lt;/code&gt; will give you a lot of trouble). So, what we can do is write
a function that takes two &lt;code&gt;STy&lt;/code&gt; at runtime and &lt;em&gt;unifies&lt;/em&gt; them
conditionally if they are the same. We’ll write a function
&lt;code&gt;sameTy :: STy a -&amp;gt; STy b -&amp;gt; Maybe (a :~: b)&lt;/code&gt;, where&lt;/p&gt;
&lt;div class="sourceCode" id="cb20"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb20-1"&gt;&lt;a href="#cb20-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt;&lt;span class="ot"&gt; (:~:) ::&lt;/span&gt; k &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; k &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-2"&gt;&lt;a href="#cb20-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;Refl&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; a &lt;span class="op"&gt;:~:&lt;/span&gt; a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;pattern matching&lt;/em&gt; on a value of type &lt;code&gt;a :~: b&lt;/code&gt; will reveal
that &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; are the same type variable, because the
only way to construct it is with &lt;code&gt;Refl :: a :~: a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;With that, we can write &lt;code&gt;sameTy&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb21"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb21-1"&gt;&lt;a href="#cb21-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage2.hs#L133-L143&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-2"&gt;&lt;a href="#cb21-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb21-3"&gt;&lt;a href="#cb21-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;sameTy ::&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; (a &lt;span class="op"&gt;:~:&lt;/span&gt; b)&lt;/span&gt;
&lt;span id="cb21-4"&gt;&lt;a href="#cb21-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sameTy &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-5"&gt;&lt;a href="#cb21-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;STInt&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt; &lt;span class="dt"&gt;STInt&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Just&lt;/span&gt; &lt;span class="dt"&gt;Refl&lt;/span&gt;; _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-6"&gt;&lt;a href="#cb21-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;STBool&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt; &lt;span class="dt"&gt;STBool&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Just&lt;/span&gt; &lt;span class="dt"&gt;Refl&lt;/span&gt;; _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-7"&gt;&lt;a href="#cb21-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;STString&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt; &lt;span class="dt"&gt;STString&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Just&lt;/span&gt; &lt;span class="dt"&gt;Refl&lt;/span&gt;; _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-8"&gt;&lt;a href="#cb21-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;STFun&lt;/span&gt; a b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-9"&gt;&lt;a href="#cb21-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;STFun&lt;/span&gt; c d &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-10"&gt;&lt;a href="#cb21-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;Refl&lt;/span&gt; &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; sameTy a c&lt;/span&gt;
&lt;span id="cb21-11"&gt;&lt;a href="#cb21-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;Refl&lt;/span&gt; &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; sameTy b d&lt;/span&gt;
&lt;span id="cb21-12"&gt;&lt;a href="#cb21-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;Just&lt;/span&gt; &lt;span class="dt"&gt;Refl&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-13"&gt;&lt;a href="#cb21-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There’s a typeclass in &lt;em&gt;base&lt;/em&gt; (or rather, a “kindclass”),
&lt;code&gt;TestEquality&lt;/code&gt;, that encapsulates this pattern:&lt;/p&gt;
&lt;div class="sourceCode" id="cb22"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb22-1"&gt;&lt;a href="#cb22-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;class&lt;/span&gt; &lt;span class="dt"&gt;TestEquality&lt;/span&gt; f &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-2"&gt;&lt;a href="#cb22-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;    testEquality ::&lt;/span&gt; f a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; (a &lt;span class="op"&gt;:~:&lt;/span&gt; b)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In fact, we can write our &lt;code&gt;sameTy&lt;/code&gt; as an instance:&lt;/p&gt;
&lt;div class="sourceCode" id="cb23"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb23-1"&gt;&lt;a href="#cb23-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage2.hs#L130-L131&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-2"&gt;&lt;a href="#cb23-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb23-3"&gt;&lt;a href="#cb23-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;TestEquality&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-4"&gt;&lt;a href="#cb23-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  testEquality &lt;span class="ot"&gt;=&lt;/span&gt; sameTy&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We’re now at a higher fanciness level than before. But you might see the
problem here: &lt;code&gt;EVar STInt "x"&lt;/code&gt;. &lt;code&gt;x&lt;/code&gt; might not be defined,
and it also might not have the correct type. Soooo yes, we still have issues
here.&lt;/p&gt;
&lt;p&gt;But now at least we can write &lt;code&gt;eval&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb24"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb24-1"&gt;&lt;a href="#cb24-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage2.hs#L145-L176&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-2"&gt;&lt;a href="#cb24-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb24-3"&gt;&lt;a href="#cb24-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;eval ::&lt;/span&gt; &lt;span class="dt"&gt;Map&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="dt"&gt;SomeValue&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; t &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; (&lt;span class="dt"&gt;EValue&lt;/span&gt; t)&lt;/span&gt;
&lt;span id="cb24-4"&gt;&lt;a href="#cb24-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;eval env &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-5"&gt;&lt;a href="#cb24-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; n) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;pure&lt;/span&gt; (&lt;span class="dt"&gt;EVInt&lt;/span&gt; n)&lt;/span&gt;
&lt;span id="cb24-6"&gt;&lt;a href="#cb24-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PBool&lt;/span&gt; b) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;pure&lt;/span&gt; (&lt;span class="dt"&gt;EVBool&lt;/span&gt; b)&lt;/span&gt;
&lt;span id="cb24-7"&gt;&lt;a href="#cb24-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PString&lt;/span&gt; s) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;pure&lt;/span&gt; (&lt;span class="dt"&gt;EVString&lt;/span&gt; s)&lt;/span&gt;
&lt;span id="cb24-8"&gt;&lt;a href="#cb24-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVar&lt;/span&gt; t v &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-9"&gt;&lt;a href="#cb24-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;SomeValue&lt;/span&gt; t&amp;#39; v&amp;#39; &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; M.lookup v env&lt;/span&gt;
&lt;span id="cb24-10"&gt;&lt;a href="#cb24-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;Refl&lt;/span&gt; &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; sameTy t t&amp;#39;&lt;/span&gt;
&lt;span id="cb24-11"&gt;&lt;a href="#cb24-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="fu"&gt;pure&lt;/span&gt; v&amp;#39;&lt;/span&gt;
&lt;span id="cb24-12"&gt;&lt;a href="#cb24-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ELambda&lt;/span&gt; ta n body &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-13"&gt;&lt;a href="#cb24-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="fu"&gt;pure&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="dt"&gt;EVFun&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; \x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; eval (M.insert n (&lt;span class="dt"&gt;SomeValue&lt;/span&gt; ta x) env) body&lt;/span&gt;
&lt;span id="cb24-14"&gt;&lt;a href="#cb24-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EApply&lt;/span&gt; f x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-15"&gt;&lt;a href="#cb24-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;EVFun&lt;/span&gt; g &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env f&lt;/span&gt;
&lt;span id="cb24-16"&gt;&lt;a href="#cb24-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    x&amp;#39; &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env x&lt;/span&gt;
&lt;span id="cb24-17"&gt;&lt;a href="#cb24-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    g x&amp;#39;&lt;/span&gt;
&lt;span id="cb24-18"&gt;&lt;a href="#cb24-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EOp&lt;/span&gt; o x y &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;case&lt;/span&gt; o &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-19"&gt;&lt;a href="#cb24-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;OPlus&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-20"&gt;&lt;a href="#cb24-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EVInt&lt;/span&gt; a &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env x&lt;/span&gt;
&lt;span id="cb24-21"&gt;&lt;a href="#cb24-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EVInt&lt;/span&gt; b &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env y&lt;/span&gt;
&lt;span id="cb24-22"&gt;&lt;a href="#cb24-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="fu"&gt;pure&lt;/span&gt; (&lt;span class="dt"&gt;EVInt&lt;/span&gt; (a &lt;span class="op"&gt;+&lt;/span&gt; b))&lt;/span&gt;
&lt;span id="cb24-23"&gt;&lt;a href="#cb24-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;OTimes&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-24"&gt;&lt;a href="#cb24-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EVInt&lt;/span&gt; a &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env x&lt;/span&gt;
&lt;span id="cb24-25"&gt;&lt;a href="#cb24-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EVInt&lt;/span&gt; b &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env y&lt;/span&gt;
&lt;span id="cb24-26"&gt;&lt;a href="#cb24-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="fu"&gt;pure&lt;/span&gt; (&lt;span class="dt"&gt;EVInt&lt;/span&gt; (a &lt;span class="op"&gt;*&lt;/span&gt; b))&lt;/span&gt;
&lt;span id="cb24-27"&gt;&lt;a href="#cb24-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;OLte&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-28"&gt;&lt;a href="#cb24-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EVInt&lt;/span&gt; a &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env x&lt;/span&gt;
&lt;span id="cb24-29"&gt;&lt;a href="#cb24-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EVInt&lt;/span&gt; b &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env y&lt;/span&gt;
&lt;span id="cb24-30"&gt;&lt;a href="#cb24-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="fu"&gt;pure&lt;/span&gt; (&lt;span class="dt"&gt;EVBool&lt;/span&gt; (a &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; b))&lt;/span&gt;
&lt;span id="cb24-31"&gt;&lt;a href="#cb24-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;OAnd&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-32"&gt;&lt;a href="#cb24-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EVBool&lt;/span&gt; a &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env x&lt;/span&gt;
&lt;span id="cb24-33"&gt;&lt;a href="#cb24-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EVBool&lt;/span&gt; b &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env y&lt;/span&gt;
&lt;span id="cb24-34"&gt;&lt;a href="#cb24-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="fu"&gt;pure&lt;/span&gt; (&lt;span class="dt"&gt;EVBool&lt;/span&gt; (a &lt;span class="op"&gt;&amp;amp;&amp;amp;&lt;/span&gt; b))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This does seem to work:&lt;/p&gt;
&lt;div class="sourceCode" id="cb25"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb25-1"&gt;&lt;a href="#cb25-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; for_ (eval M.empty fifteen) \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb25-2"&gt;&lt;a href="#cb25-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;EVInt&lt;/span&gt; x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;print&lt;/span&gt; x&lt;/span&gt;
&lt;span id="cb25-3"&gt;&lt;a href="#cb25-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dv"&gt;15&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Our system also allows us to produce closures and functions as values:&lt;/p&gt;
&lt;div class="sourceCode" id="cb26"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb26-1"&gt;&lt;a href="#cb26-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage2.hs#L63-L64&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb26-2"&gt;&lt;a href="#cb26-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb26-3"&gt;&lt;a href="#cb26-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;plusThree ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; (&lt;span class="dt"&gt;TInt&lt;/span&gt; &lt;span class="op"&gt;:-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb26-4"&gt;&lt;a href="#cb26-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plusThree &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;ELambda&lt;/span&gt; &lt;span class="dt"&gt;STInt&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OPlus&lt;/span&gt; (&lt;span class="dt"&gt;EVar&lt;/span&gt; &lt;span class="dt"&gt;STInt&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt;) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;)))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb27"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb27-1"&gt;&lt;a href="#cb27-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; for_ (eval M.empty plusThree) \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb27-2"&gt;&lt;a href="#cb27-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;EVFun&lt;/span&gt; f &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; for_ (f (&lt;span class="dt"&gt;EVInt&lt;/span&gt; &lt;span class="dv"&gt;4&lt;/span&gt;)) \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb27-3"&gt;&lt;a href="#cb27-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EVInt&lt;/span&gt; x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;print&lt;/span&gt; x    &lt;span class="co"&gt;-- compiler-verified to always be EVInt&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb27-4"&gt;&lt;a href="#cb27-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dv"&gt;7&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We have a type-safe &lt;code&gt;eval&lt;/code&gt; now that will create a value of the
type we want. But we still have the same errors when looking at variables:
variables can still not be defined, or be defined as the wrong type.&lt;/p&gt;
&lt;h3 id="pretty-printing"&gt;Pretty-Printing&lt;/h3&gt;
&lt;p&gt;One nice consequence of this type-index method is that if you choose to
consume them into an untyped target, you can do it more or less in the same way
as the non-indexed untyped data.&lt;/p&gt;
&lt;div class="sourceCode" id="cb28"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb28-1"&gt;&lt;a href="#cb28-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage2.hs#L87-L113&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-2"&gt;&lt;a href="#cb28-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb28-3"&gt;&lt;a href="#cb28-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;ppPrim ::&lt;/span&gt; &lt;span class="dt"&gt;Prim&lt;/span&gt; t &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;PP.Doc&lt;/span&gt; ann&lt;/span&gt;
&lt;span id="cb28-4"&gt;&lt;a href="#cb28-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ppPrim &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-5"&gt;&lt;a href="#cb28-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;PInt&lt;/span&gt; n &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; PP.pretty n&lt;/span&gt;
&lt;span id="cb28-6"&gt;&lt;a href="#cb28-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;PBool&lt;/span&gt; b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;if&lt;/span&gt; b &lt;span class="kw"&gt;then&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span class="kw"&gt;else&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;false&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-7"&gt;&lt;a href="#cb28-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;PString&lt;/span&gt; s &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; PP.pretty (&lt;span class="fu"&gt;show&lt;/span&gt; s)&lt;/span&gt;
&lt;span id="cb28-8"&gt;&lt;a href="#cb28-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb28-9"&gt;&lt;a href="#cb28-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;ppOp ::&lt;/span&gt; &lt;span class="dt"&gt;Op&lt;/span&gt; a b c &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;PP.Doc&lt;/span&gt; ann&lt;/span&gt;
&lt;span id="cb28-10"&gt;&lt;a href="#cb28-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ppOp &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-11"&gt;&lt;a href="#cb28-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;OPlus&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;+&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-12"&gt;&lt;a href="#cb28-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;OTimes&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;*&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-13"&gt;&lt;a href="#cb28-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;OLte&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;&amp;lt;=&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-14"&gt;&lt;a href="#cb28-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;OAnd&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;&amp;amp;&amp;amp;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-15"&gt;&lt;a href="#cb28-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb28-16"&gt;&lt;a href="#cb28-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;ppExpr ::&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; t &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;PP.Doc&lt;/span&gt; ann&lt;/span&gt;
&lt;span id="cb28-17"&gt;&lt;a href="#cb28-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ppExpr paren &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-18"&gt;&lt;a href="#cb28-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EPrim&lt;/span&gt; p &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; ppPrim p&lt;/span&gt;
&lt;span id="cb28-19"&gt;&lt;a href="#cb28-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVar&lt;/span&gt; _ v &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; PP.pretty v&lt;/span&gt;
&lt;span id="cb28-20"&gt;&lt;a href="#cb28-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ELambda&lt;/span&gt; _ n body &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; wrap &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;\\&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; PP.pretty n &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;-&amp;gt;&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr &lt;span class="dt"&gt;False&lt;/span&gt; body&lt;/span&gt;
&lt;span id="cb28-21"&gt;&lt;a href="#cb28-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EApply&lt;/span&gt; f x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; wrap &lt;span class="op"&gt;$&lt;/span&gt; ppExpr &lt;span class="dt"&gt;True&lt;/span&gt; f &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr &lt;span class="dt"&gt;True&lt;/span&gt; x&lt;/span&gt;
&lt;span id="cb28-22"&gt;&lt;a href="#cb28-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EOp&lt;/span&gt; o x y &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; wrap &lt;span class="op"&gt;$&lt;/span&gt; ppExpr &lt;span class="dt"&gt;True&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppOp o &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr &lt;span class="dt"&gt;True&lt;/span&gt; y&lt;/span&gt;
&lt;span id="cb28-23"&gt;&lt;a href="#cb28-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-24"&gt;&lt;a href="#cb28-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    wrap&lt;/span&gt;
&lt;span id="cb28-25"&gt;&lt;a href="#cb28-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="op"&gt;|&lt;/span&gt; paren &lt;span class="ot"&gt;=&lt;/span&gt; PP.parens&lt;/span&gt;
&lt;span id="cb28-26"&gt;&lt;a href="#cb28-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="fu"&gt;otherwise&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-27"&gt;&lt;a href="#cb28-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb28-28"&gt;&lt;a href="#cb28-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;prettyExpr ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; t &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;PP.Doc&lt;/span&gt; ann&lt;/span&gt;
&lt;span id="cb28-29"&gt;&lt;a href="#cb28-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;prettyExpr &lt;span class="ot"&gt;=&lt;/span&gt; ppExpr &lt;span class="dt"&gt;False&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And they render the same way:&lt;/p&gt;
&lt;div class="sourceCode" id="cb29"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb29-1"&gt;&lt;a href="#cb29-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; prettyExpr fifteen&lt;/span&gt;
&lt;span id="cb29-2"&gt;&lt;a href="#cb29-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(\x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; x &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;) &lt;span class="dv"&gt;5&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-3"&gt;&lt;a href="#cb29-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; prettyExpr plusThree&lt;/span&gt;
&lt;span id="cb29-4"&gt;&lt;a href="#cb29-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;\x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; x &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-5"&gt;&lt;a href="#cb29-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; prettyExpr badVariable&lt;/span&gt;
&lt;span id="cb29-6"&gt;&lt;a href="#cb29-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(\x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; x &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;) true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="still-not-fully-verified"&gt;Still Not Fully Verified&lt;/h3&gt;
&lt;p&gt;Implicit in the previous section was the admission of failure: this system
lets us use indexed types to help propagate unification (the result types of
&lt;code&gt;OLte&lt;/code&gt;, &lt;code&gt;OAnd&lt;/code&gt;, &lt;code&gt;OPlus&lt;/code&gt;, etc.), but it can’t
prevent all ill-defined programs from compiling.&lt;/p&gt;
&lt;p&gt;The issue is &lt;code&gt;EVar&lt;/code&gt;: its type
&lt;code&gt;EVar :: STy t -&amp;gt; String -&amp;gt; Expr t&lt;/code&gt; lets us bind &lt;em&gt;any&lt;/em&gt;
variable name as &lt;em&gt;any&lt;/em&gt; type, and it’ll still typecheck. Even with the
help of everything we have, we can just straight-up declare a reference to an
unbound variable&lt;/p&gt;
&lt;div class="sourceCode" id="cb30"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb30-1"&gt;&lt;a href="#cb30-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage2.hs#L71-L72&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb30-2"&gt;&lt;a href="#cb30-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb30-3"&gt;&lt;a href="#cb30-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;unboundVariable ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb30-4"&gt;&lt;a href="#cb30-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;unboundVariable &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;EVar&lt;/span&gt; &lt;span class="dt"&gt;STInt&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;missing&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This typechecks in GHC even though it’s meaningless in the domain. We can
also reference the variable under any &lt;em&gt;type&lt;/em&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb31"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb31-1"&gt;&lt;a href="#cb31-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage2.hs#L57-L61&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-2"&gt;&lt;a href="#cb31-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb31-3"&gt;&lt;a href="#cb31-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;badVariable ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-4"&gt;&lt;a href="#cb31-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;badVariable &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-5"&gt;&lt;a href="#cb31-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EApply&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-6"&gt;&lt;a href="#cb31-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    (&lt;span class="dt"&gt;ELambda&lt;/span&gt; &lt;span class="dt"&gt;STBool&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OPlus&lt;/span&gt; (&lt;span class="dt"&gt;EVar&lt;/span&gt; &lt;span class="dt"&gt;STInt&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt;) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;))))&lt;/span&gt;
&lt;span id="cb31-7"&gt;&lt;a href="#cb31-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PBool&lt;/span&gt; &lt;span class="dt"&gt;True&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That’s because &lt;code&gt;EVar&lt;/code&gt; can freely take any &lt;code&gt;STy&lt;/code&gt; without
any restriction, and no association with the binder name, so there’s no way for
GHC to stop us.&lt;/p&gt;
&lt;p&gt;So, again, we cannot create a &lt;em&gt;fully&lt;/em&gt; type-checked &lt;code&gt;Expr&lt;/code&gt;.
We still have to deal with &lt;em&gt;most&lt;/em&gt; of the same errors. This is noble, but
clearly not good enough. We have to go deeper.&lt;/p&gt;
&lt;h2 id="typed-records-and-sums"&gt;Typed Records and Sums&lt;/h2&gt;
&lt;p&gt;A quick detour: you might have noticed that this past implementation dropped
records and sums. Before we move on, let’s go ahead and add those. Introducing
records and sums at the same time as type-indexed &lt;code&gt;Expr&lt;/code&gt; is a bit
&lt;em&gt;too&lt;/em&gt; much of a jump to fit into a single section.&lt;/p&gt;
&lt;p&gt;Let’s add sums and records, which can use pretty similar mechanisms (via
duality) for implementation.&lt;/p&gt;
&lt;div class="sourceCode" id="cb32"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb32-1"&gt;&lt;a href="#cb32-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L31-L79&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb32-2"&gt;&lt;a href="#cb32-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb32-3"&gt;&lt;a href="#cb32-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Ty&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb32-4"&gt;&lt;a href="#cb32-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb32-5"&gt;&lt;a href="#cb32-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;TBool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb32-6"&gt;&lt;a href="#cb32-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb32-7"&gt;&lt;a href="#cb32-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;TRecord&lt;/span&gt; [(&lt;span class="dt"&gt;Symbol&lt;/span&gt;, &lt;span class="dt"&gt;Ty&lt;/span&gt;)]&lt;/span&gt;
&lt;span id="cb32-8"&gt;&lt;a href="#cb32-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;TSum&lt;/span&gt; [(&lt;span class="dt"&gt;Symbol&lt;/span&gt;, &lt;span class="dt"&gt;Ty&lt;/span&gt;)]&lt;/span&gt;
&lt;span id="cb32-9"&gt;&lt;a href="#cb32-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;Ty&lt;/span&gt; &lt;span class="op"&gt;:-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Ty&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb32-10"&gt;&lt;a href="#cb32-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb32-11"&gt;&lt;a href="#cb32-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Ty&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb32-12"&gt;&lt;a href="#cb32-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;STInt&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb32-13"&gt;&lt;a href="#cb32-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;STBool&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; &lt;span class="dt"&gt;TBool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb32-14"&gt;&lt;a href="#cb32-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;STString&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb32-15"&gt;&lt;a href="#cb32-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;STRecord&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; &lt;span class="dt"&gt;STyField&lt;/span&gt; as &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; (&lt;span class="dt"&gt;TRecord&lt;/span&gt; as)&lt;/span&gt;
&lt;span id="cb32-16"&gt;&lt;a href="#cb32-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;STSum&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; &lt;span class="dt"&gt;STyField&lt;/span&gt; as &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; (&lt;span class="dt"&gt;TSum&lt;/span&gt; as)&lt;/span&gt;
&lt;span id="cb32-17"&gt;&lt;a href="#cb32-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;STFun&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; (a &lt;span class="op"&gt;:-&amp;gt;&lt;/span&gt; b)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Ty&lt;/code&gt; now includes &lt;code&gt;TRecord [(Symbol, Ty)]&lt;/code&gt; and
&lt;code&gt;TSum [(Symbol, Ty)]&lt;/code&gt;, which represent the field names and
constructor payloads (&lt;code&gt;Symbol&lt;/code&gt; being a type-level string). So, for
example, &lt;code&gt;TRecord ["value" ::: TInt, "label" ::: TString]&lt;/code&gt; would be
the type of a record with ordered fields &lt;code&gt;value&lt;/code&gt; and
&lt;code&gt;label&lt;/code&gt; of integers and strings, respectively.
&lt;code&gt;TSum ["Found" ::: TInt, "Missing" ::: TString]&lt;/code&gt; would be the type of
a sum between &lt;code&gt;Found&lt;/code&gt; containing an integer and &lt;code&gt;Missing&lt;/code&gt;
containing a string. Note we take a page out of &lt;a
href="https://hackage.haskell.org/package/vinyl"&gt;vinyl&lt;/a&gt; by defining the type
alias &lt;code&gt;(:::) = '(,)&lt;/code&gt; to make things syntactically nicer.&lt;/p&gt;
&lt;h3 id="record-access"&gt;Record Access&lt;/h3&gt;
&lt;p&gt;We need the fields and types at the type level because we have to answer what
the &lt;code&gt;Expr&lt;/code&gt; phantom type of field access is. If we had an
&lt;code&gt;x :: Expr (TRecord ["value" ::: TInt, "label" ::: TString])&lt;/code&gt;, we
want the type of &lt;code&gt;x.value&lt;/code&gt; to be &lt;code&gt;Expr TInt&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To do this, we need to have a &lt;em&gt;value&lt;/em&gt; in our &lt;code&gt;Expr&lt;/code&gt; for
field access that can “point” at a specific field in the type. One way to do
that is to take a field of type &lt;code&gt;Index&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb33"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb33-1"&gt;&lt;a href="#cb33-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L47-L49&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb33-2"&gt;&lt;a href="#cb33-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb33-3"&gt;&lt;a href="#cb33-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Index&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; [k] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; k &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb33-4"&gt;&lt;a href="#cb33-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;IZ&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Index&lt;/span&gt; (x &lt;span class="op"&gt;:&lt;/span&gt; xs) x&lt;/span&gt;
&lt;span id="cb33-5"&gt;&lt;a href="#cb33-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;IS&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Index&lt;/span&gt; xs x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Index&lt;/span&gt; (y &lt;span class="op"&gt;:&lt;/span&gt; xs) x&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can read this as: “&lt;code&gt;IZ&lt;/code&gt; is an index to the head of the
type-level list, and &lt;code&gt;IS n&lt;/code&gt; is an index to the n-th item of the
tail”. So, &lt;code&gt;IS IZ&lt;/code&gt; is an index into the second element,
&lt;code&gt;IS (IS IZ)&lt;/code&gt; is an index into the third, etc.&lt;/p&gt;
&lt;p&gt;If we have &lt;code&gt;["value" ::: TInt, "label" ::: TString]&lt;/code&gt;, then we have
values:&lt;/p&gt;
&lt;div class="sourceCode" id="cb34"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb34-1"&gt;&lt;a href="#cb34-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;IZ&lt;/span&gt;&lt;span class="ot"&gt;    ::&lt;/span&gt; &lt;span class="dt"&gt;Index&lt;/span&gt; [&lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;, &lt;span class="st"&gt;&amp;quot;label&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;] (&lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb34-2"&gt;&lt;a href="#cb34-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;IS&lt;/span&gt; &lt;span class="dt"&gt;IZ&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Index&lt;/span&gt; [&lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;, &lt;span class="st"&gt;&amp;quot;label&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;] (&lt;span class="st"&gt;&amp;quot;label&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that the way this is constructed, it’s impossible for
&lt;code&gt;IS (IS IZ) :: Index ["value" ::: TInt, "label" ::: TString] _&lt;/code&gt; to
typecheck as anything!&lt;/p&gt;
&lt;p&gt;In this way, we have a well-typed field accessor syntax, which takes an
&lt;code&gt;Expr&lt;/code&gt; of a record of fields and indexes it to get an
&lt;code&gt;Expr&lt;/code&gt; of the type at that index:&lt;/p&gt;
&lt;div class="sourceCode" id="cb35"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb35-1"&gt;&lt;a href="#cb35-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L105-L105&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb35-2"&gt;&lt;a href="#cb35-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb35-3"&gt;&lt;a href="#cb35-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EAccess&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;KnownSymbol&lt;/span&gt; l &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; (&lt;span class="dt"&gt;TRecord&lt;/span&gt; as) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Index&lt;/span&gt; as (l &lt;span class="op"&gt;:::&lt;/span&gt; a) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Which is typed as:&lt;/p&gt;
&lt;div class="sourceCode" id="cb36"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb36-1"&gt;&lt;a href="#cb36-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(&lt;span class="ot"&gt;`EAccess`&lt;/span&gt; &lt;span class="dt"&gt;IZ&lt;/span&gt;)&lt;span class="ot"&gt;    ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; (&lt;span class="dt"&gt;TRecord&lt;/span&gt; [&lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;, &lt;span class="st"&gt;&amp;quot;label&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;]) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-2"&gt;&lt;a href="#cb36-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(&lt;span class="ot"&gt;`EAccess`&lt;/span&gt; &lt;span class="dt"&gt;IS&lt;/span&gt; &lt;span class="dt"&gt;IZ&lt;/span&gt;)&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; (&lt;span class="dt"&gt;TRecord&lt;/span&gt; [&lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;, &lt;span class="st"&gt;&amp;quot;label&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;]) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To &lt;em&gt;create&lt;/em&gt; an &lt;code&gt;Expr&lt;/code&gt; of a record, we can use
&lt;code&gt;Rec&lt;/code&gt; from &lt;em&gt;&lt;a
href="https://hackage.haskell.org/package/vinyl"&gt;vinyl&lt;/a&gt;&lt;/em&gt; or
&lt;code&gt;NP&lt;/code&gt; from &lt;em&gt;&lt;a
href="https://hackage.haskell.org/package/sop-core"&gt;sop-core&lt;/a&gt;&lt;/em&gt;: a
heterogeneous list indexed by a type-level list.&lt;/p&gt;
&lt;div class="sourceCode" id="cb37"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb37-1"&gt;&lt;a href="#cb37-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L43-L45&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb37-2"&gt;&lt;a href="#cb37-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb37-3"&gt;&lt;a href="#cb37-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; (k &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt;) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; [k] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb37-4"&gt;&lt;a href="#cb37-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;RNil&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; f &amp;#39;[]&lt;/span&gt;
&lt;span id="cb37-5"&gt;&lt;a href="#cb37-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;  (:&amp;amp;) ::&lt;/span&gt; f x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; f xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; f (x &lt;span class="op"&gt;:&lt;/span&gt; xs)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you haven’t seen &lt;code&gt;Rec&lt;/code&gt; before, basically
&lt;code&gt;Rec f [a,b,c]&lt;/code&gt; is a tuple of &lt;code&gt;f a&lt;/code&gt;, &lt;code&gt;f b&lt;/code&gt;, and
&lt;code&gt;f c&lt;/code&gt;. For example:&lt;/p&gt;
&lt;div class="sourceCode" id="cb38"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb38-1"&gt;&lt;a href="#cb38-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;:&lt;/span&gt;t &lt;span class="dt"&gt;Identity&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt; &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; &lt;span class="dt"&gt;Identity&lt;/span&gt; &lt;span class="dt"&gt;True&lt;/span&gt; &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; &lt;span class="dt"&gt;Identity&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; &lt;span class="dt"&gt;RNil&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb38-2"&gt;&lt;a href="#cb38-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Rec&lt;/span&gt; &lt;span class="dt"&gt;Identity&lt;/span&gt; [&lt;span class="dt"&gt;Int&lt;/span&gt;, &lt;span class="dt"&gt;Bool&lt;/span&gt;, &lt;span class="dt"&gt;String&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb38-3"&gt;&lt;a href="#cb38-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;:&lt;/span&gt;t &lt;span class="dt"&gt;Const&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; &lt;span class="dt"&gt;Const&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;y&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; &lt;span class="dt"&gt;RNil&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb38-4"&gt;&lt;a href="#cb38-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Rec&lt;/span&gt; (&lt;span class="dt"&gt;Const&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;) [x1, x2]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Keeping &lt;code&gt;Rec f as&lt;/code&gt; instead of a direct heterogeneous list of
&lt;code&gt;a&lt;/code&gt;s lets us store more interesting things than just
&lt;code&gt;Type&lt;/code&gt;-kinded things. For example, since our lists here are lists of
&lt;code&gt;(Symbol, Ty)&lt;/code&gt;, we can create a container to hold fields:&lt;/p&gt;
&lt;div class="sourceCode" id="cb39"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb39-1"&gt;&lt;a href="#cb39-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L109-L110&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb39-2"&gt;&lt;a href="#cb39-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb39-3"&gt;&lt;a href="#cb39-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;ExprField&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; (&lt;span class="dt"&gt;Symbol&lt;/span&gt;, &lt;span class="dt"&gt;Ty&lt;/span&gt;) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb39-4"&gt;&lt;a href="#cb39-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EField&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;KnownSymbol&lt;/span&gt; l &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;ExprField&lt;/span&gt; (l &lt;span class="op"&gt;:::&lt;/span&gt; a)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The field constructor keeps a &lt;code&gt;KnownSymbol l&lt;/code&gt; constraint, so the
type-level label is still available later when we need to render it:&lt;/p&gt;
&lt;div class="sourceCode" id="cb40"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb40-1"&gt;&lt;a href="#cb40-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;:&lt;/span&gt;t &lt;span class="dt"&gt;EField&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;&lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;7&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb40-2"&gt;&lt;a href="#cb40-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; &lt;span class="dt"&gt;EField&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;&lt;span class="st"&gt;&amp;quot;label&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PString&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;found&amp;quot;&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb40-3"&gt;&lt;a href="#cb40-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; &lt;span class="dt"&gt;RNil&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb40-4"&gt;&lt;a href="#cb40-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Rec&lt;/span&gt; &lt;span class="dt"&gt;ExprField&lt;/span&gt; [&lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;, &lt;span class="st"&gt;&amp;quot;label&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So, we can create
&lt;code&gt;Expr (TRecord ["value" ::: TInt, "label" ::: TString])&lt;/code&gt; by taking a
&lt;code&gt;Rec&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb41"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb41-1"&gt;&lt;a href="#cb41-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L104-L104&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb41-2"&gt;&lt;a href="#cb41-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb41-3"&gt;&lt;a href="#cb41-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ERecord&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; &lt;span class="dt"&gt;ExprField&lt;/span&gt; as &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; (&lt;span class="dt"&gt;TRecord&lt;/span&gt; as)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can make this a little more ergonomic by using
&lt;code&gt;-XRequiredTypeArguments&lt;/code&gt; (as of GHC 9.10) to get rid of the
&lt;code&gt;-XTypeApplication&lt;/code&gt; ugliness:&lt;/p&gt;
&lt;div class="sourceCode" id="cb42"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb42-1"&gt;&lt;a href="#cb42-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L115-L150&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-2"&gt;&lt;a href="#cb42-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-3"&gt;&lt;a href="#cb42-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;eField ::&lt;/span&gt; &lt;span class="kw"&gt;forall&lt;/span&gt; l &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;KnownSymbol&lt;/span&gt; l &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;ExprField&lt;/span&gt; (l &lt;span class="op"&gt;:::&lt;/span&gt; a)&lt;/span&gt;
&lt;span id="cb42-4"&gt;&lt;a href="#cb42-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;eField l &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;EField&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l&lt;/span&gt;
&lt;span id="cb42-5"&gt;&lt;a href="#cb42-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-6"&gt;&lt;a href="#cb42-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;makeRecordExample ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; (&lt;span class="dt"&gt;TRecord&lt;/span&gt; [&lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;, &lt;span class="st"&gt;&amp;quot;label&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb42-7"&gt;&lt;a href="#cb42-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;makeRecordExample &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-8"&gt;&lt;a href="#cb42-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ERecord&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-9"&gt;&lt;a href="#cb42-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ( eField &lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;7&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb42-10"&gt;&lt;a href="#cb42-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; eField &lt;span class="st"&gt;&amp;quot;label&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PString&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;found&amp;quot;&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb42-11"&gt;&lt;a href="#cb42-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; &lt;span class="dt"&gt;RNil&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-12"&gt;&lt;a href="#cb42-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb42-13"&gt;&lt;a href="#cb42-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-14"&gt;&lt;a href="#cb42-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;recordExample ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-15"&gt;&lt;a href="#cb42-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;recordExample &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OPlus&lt;/span&gt; (&lt;span class="dt"&gt;EAccess&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;&lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt; makeRecordExample &lt;span class="dt"&gt;IZ&lt;/span&gt;) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="sum-injection-and-case-analysis"&gt;Sum Injection and Case Analysis&lt;/h3&gt;
&lt;p&gt;We also need a type-level list witness for &lt;em&gt;sum&lt;/em&gt; types, because we
need to be able to implement the correct continuations for pattern matches: How
do we know &lt;em&gt;what&lt;/em&gt; thing to handle in each pattern match, unless the sum
type has that information in its type?&lt;/p&gt;
&lt;p&gt;Luckily due to the magic of duality, we can use the same tools, for the most
part! We can inject into a sum with an &lt;code&gt;Index&lt;/code&gt;, let’s say for a
&lt;code&gt;Expr (TSum ["Found" ::: TInt, "Missing" ::: TString])&lt;/code&gt;: sum type
with &lt;code&gt;Found&lt;/code&gt; containing an integer and &lt;code&gt;Missing&lt;/code&gt;
containing a string:&lt;/p&gt;
&lt;div class="sourceCode" id="cb43"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb43-1"&gt;&lt;a href="#cb43-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L106-L106&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb43-2"&gt;&lt;a href="#cb43-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb43-3"&gt;&lt;a href="#cb43-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EChoice&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;KnownSymbol&lt;/span&gt; l &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Index&lt;/span&gt; as (l &lt;span class="op"&gt;:::&lt;/span&gt; a) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; (&lt;span class="dt"&gt;TSum&lt;/span&gt; as)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb44"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb44-1"&gt;&lt;a href="#cb44-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;EChoice&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;&lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; &lt;span class="dt"&gt;IZ&lt;/span&gt;&lt;span class="ot"&gt;        ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; (&lt;span class="dt"&gt;TSum&lt;/span&gt; [&lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;, &lt;span class="st"&gt;&amp;quot;Missing&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb44-2"&gt;&lt;a href="#cb44-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;EChoice&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;&lt;span class="st"&gt;&amp;quot;Missing&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;IS&lt;/span&gt; &lt;span class="dt"&gt;IZ&lt;/span&gt;)&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; (&lt;span class="dt"&gt;TSum&lt;/span&gt; [&lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;, &lt;span class="st"&gt;&amp;quot;Missing&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb45"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb45-1"&gt;&lt;a href="#cb45-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L181-L182&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-2"&gt;&lt;a href="#cb45-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb45-3"&gt;&lt;a href="#cb45-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;makeSumExample ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; (&lt;span class="dt"&gt;TSum&lt;/span&gt; [&lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;, &lt;span class="st"&gt;&amp;quot;Missing&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb45-4"&gt;&lt;a href="#cb45-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;makeSumExample &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;EChoice&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;&lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; &lt;span class="dt"&gt;IZ&lt;/span&gt; (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;7&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we can re-use &lt;code&gt;Rec&lt;/code&gt; to define a type that can &lt;em&gt;handle&lt;/em&gt;
a &lt;code&gt;["Found" ::: TInt, "Missing" ::: TString]&lt;/code&gt; sum:&lt;/p&gt;
&lt;div class="sourceCode" id="cb46"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb46-1"&gt;&lt;a href="#cb46-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L112-L133&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb46-2"&gt;&lt;a href="#cb46-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb46-3"&gt;&lt;a href="#cb46-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;ExprHandler&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Ty&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; (&lt;span class="dt"&gt;Symbol&lt;/span&gt;, &lt;span class="dt"&gt;Ty&lt;/span&gt;) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb46-4"&gt;&lt;a href="#cb46-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EHandler&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;KnownSymbol&lt;/span&gt; l &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;ExprHandler&lt;/span&gt; b (l &lt;span class="op"&gt;:::&lt;/span&gt; a)&lt;/span&gt;
&lt;span id="cb46-5"&gt;&lt;a href="#cb46-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb46-6"&gt;&lt;a href="#cb46-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;eHandler ::&lt;/span&gt; &lt;span class="kw"&gt;forall&lt;/span&gt; l &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;KnownSymbol&lt;/span&gt; l &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;ExprHandler&lt;/span&gt; b (l &lt;span class="op"&gt;:::&lt;/span&gt; a)&lt;/span&gt;
&lt;span id="cb46-7"&gt;&lt;a href="#cb46-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;eHandler l &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;EHandler&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb47"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb47-1"&gt;&lt;a href="#cb47-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;:&lt;/span&gt;t eHandler &lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; &lt;span class="dt"&gt;STInt&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OPlus&lt;/span&gt; (&lt;span class="dt"&gt;EVar&lt;/span&gt; &lt;span class="dt"&gt;STInt&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;)))&lt;/span&gt;
&lt;span id="cb47-2"&gt;&lt;a href="#cb47-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;ExprHandler&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt; (&lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb47-3"&gt;&lt;a href="#cb47-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;         &lt;span class="co"&gt;-- ^ result           ^ payload&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we can put these into a &lt;code&gt;Rec&lt;/code&gt; to handle each option in the
list:&lt;/p&gt;
&lt;div class="sourceCode" id="cb48"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb48-1"&gt;&lt;a href="#cb48-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;:&lt;/span&gt;t eHandler &lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; &lt;span class="dt"&gt;STInt&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OPlus&lt;/span&gt; (&lt;span class="dt"&gt;EVar&lt;/span&gt; &lt;span class="dt"&gt;STInt&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;)))&lt;/span&gt;
&lt;span id="cb48-2"&gt;&lt;a href="#cb48-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; eHandler &lt;span class="st"&gt;&amp;quot;Missing&amp;quot;&lt;/span&gt; &lt;span class="dt"&gt;STString&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;message&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb48-3"&gt;&lt;a href="#cb48-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; &lt;span class="dt"&gt;RNil&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb48-4"&gt;&lt;a href="#cb48-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Rec&lt;/span&gt; (&lt;span class="dt"&gt;ExprHandler&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;) [&lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;, &lt;span class="st"&gt;&amp;quot;Missing&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And that’s exactly what a case statement is:&lt;/p&gt;
&lt;div class="sourceCode" id="cb49"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb49-1"&gt;&lt;a href="#cb49-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L107-L107&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb49-2"&gt;&lt;a href="#cb49-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb49-3"&gt;&lt;a href="#cb49-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ECase&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; (&lt;span class="dt"&gt;TSum&lt;/span&gt; as) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; (&lt;span class="dt"&gt;ExprHandler&lt;/span&gt; b) as &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; b&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb50"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb50-1"&gt;&lt;a href="#cb50-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L184-L191&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb50-2"&gt;&lt;a href="#cb50-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb50-3"&gt;&lt;a href="#cb50-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;sumExample ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb50-4"&gt;&lt;a href="#cb50-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sumExample &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb50-5"&gt;&lt;a href="#cb50-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ECase&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb50-6"&gt;&lt;a href="#cb50-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    makeSumExample&lt;/span&gt;
&lt;span id="cb50-7"&gt;&lt;a href="#cb50-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ( eHandler &lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; &lt;span class="dt"&gt;STInt&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OPlus&lt;/span&gt; (&lt;span class="dt"&gt;EVar&lt;/span&gt; &lt;span class="dt"&gt;STInt&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;)))&lt;/span&gt;
&lt;span id="cb50-8"&gt;&lt;a href="#cb50-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; eHandler &lt;span class="st"&gt;&amp;quot;Missing&amp;quot;&lt;/span&gt; &lt;span class="dt"&gt;STString&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;message&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb50-9"&gt;&lt;a href="#cb50-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; &lt;span class="dt"&gt;RNil&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb50-10"&gt;&lt;a href="#cb50-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that we’re still using string binders, so there’s still an element of
unsafety here… we say that the variable name is &lt;code&gt;"value"&lt;/code&gt; and that it
is a &lt;code&gt;TInt&lt;/code&gt;, but when we later refer to the variable with
&lt;code&gt;EVar STInt "value"&lt;/code&gt;, it isn’t type-checked that later references use
the same type. The compiler would be just as happy with
&lt;code&gt;EVar STString "value"&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here’s an example demonstrating both failure modes: the first handler
references a variable that doesn’t exist, and the second handler references a
variable that does exist as an incorrect type! How unfortunate.&lt;/p&gt;
&lt;div class="sourceCode" id="cb51"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb51-1"&gt;&lt;a href="#cb51-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L202-L209&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb51-2"&gt;&lt;a href="#cb51-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb51-3"&gt;&lt;a href="#cb51-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;badCaseBranchExample ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb51-4"&gt;&lt;a href="#cb51-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;badCaseBranchExample &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb51-5"&gt;&lt;a href="#cb51-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ECase&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb51-6"&gt;&lt;a href="#cb51-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    (&lt;span class="dt"&gt;EChoice&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;&lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; &lt;span class="dt"&gt;IZ&lt;/span&gt; (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;7&lt;/span&gt;)))&lt;/span&gt;
&lt;span id="cb51-7"&gt;&lt;a href="#cb51-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ( eHandler &lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; &lt;span class="dt"&gt;STInt&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OPlus&lt;/span&gt; (&lt;span class="dt"&gt;EVar&lt;/span&gt; &lt;span class="dt"&gt;STInt&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;missing&amp;quot;&lt;/span&gt;) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;)))&lt;/span&gt;
&lt;span id="cb51-8"&gt;&lt;a href="#cb51-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; eHandler &lt;span class="st"&gt;&amp;quot;Missing&amp;quot;&lt;/span&gt; &lt;span class="dt"&gt;STString&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;message&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OPlus&lt;/span&gt; (&lt;span class="dt"&gt;EVar&lt;/span&gt; &lt;span class="dt"&gt;STInt&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;message&amp;quot;&lt;/span&gt;) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;)))&lt;/span&gt;
&lt;span id="cb51-9"&gt;&lt;a href="#cb51-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; &lt;span class="dt"&gt;RNil&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb51-10"&gt;&lt;a href="#cb51-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="runtime-equality-for-records-and-sums"&gt;Runtime Equality for Records and
Sums&lt;/h3&gt;
&lt;p&gt;One complication is that we need to update the &lt;code&gt;TestEquality&lt;/code&gt;
instance for &lt;code&gt;STy&lt;/code&gt;. The record and sum labels are type-level
&lt;code&gt;Symbol&lt;/code&gt;s, so we compare those with the &lt;code&gt;sameSymbol&lt;/code&gt; (kind
of like &lt;code&gt;testEquality&lt;/code&gt; for any &lt;code&gt;KnownSymbol&lt;/code&gt; instance) and
then compare the payload types recursively.&lt;/p&gt;
&lt;div class="sourceCode" id="cb52"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb52-1"&gt;&lt;a href="#cb52-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L284-L324&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-2"&gt;&lt;a href="#cb52-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb52-3"&gt;&lt;a href="#cb52-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;TestEquality&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-4"&gt;&lt;a href="#cb52-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    testEquality &lt;span class="ot"&gt;=&lt;/span&gt; sameTy&lt;/span&gt;
&lt;span id="cb52-5"&gt;&lt;a href="#cb52-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb52-6"&gt;&lt;a href="#cb52-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;TestEquality&lt;/span&gt; &lt;span class="dt"&gt;STyField&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-7"&gt;&lt;a href="#cb52-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    testEquality &lt;span class="ot"&gt;=&lt;/span&gt; sameField&lt;/span&gt;
&lt;span id="cb52-8"&gt;&lt;a href="#cb52-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb52-9"&gt;&lt;a href="#cb52-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;sameTy ::&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;STy&lt;/span&gt; b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; (a &lt;span class="op"&gt;:~:&lt;/span&gt; b)&lt;/span&gt;
&lt;span id="cb52-10"&gt;&lt;a href="#cb52-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sameTy &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-11"&gt;&lt;a href="#cb52-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;STInt&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt; &lt;span class="dt"&gt;STInt&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Just&lt;/span&gt; &lt;span class="dt"&gt;Refl&lt;/span&gt;; _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-12"&gt;&lt;a href="#cb52-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;STBool&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt; &lt;span class="dt"&gt;STBool&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Just&lt;/span&gt; &lt;span class="dt"&gt;Refl&lt;/span&gt;; _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-13"&gt;&lt;a href="#cb52-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;STString&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt; &lt;span class="dt"&gt;STString&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Just&lt;/span&gt; &lt;span class="dt"&gt;Refl&lt;/span&gt;; _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-14"&gt;&lt;a href="#cb52-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;STRecord&lt;/span&gt; as &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-15"&gt;&lt;a href="#cb52-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;STRecord&lt;/span&gt; bs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-16"&gt;&lt;a href="#cb52-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;Refl&lt;/span&gt; &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; sameFields as bs&lt;/span&gt;
&lt;span id="cb52-17"&gt;&lt;a href="#cb52-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;Just&lt;/span&gt; &lt;span class="dt"&gt;Refl&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-18"&gt;&lt;a href="#cb52-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-19"&gt;&lt;a href="#cb52-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;STSum&lt;/span&gt; as &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-20"&gt;&lt;a href="#cb52-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;STSum&lt;/span&gt; bs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-21"&gt;&lt;a href="#cb52-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;Refl&lt;/span&gt; &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; sameFields as bs&lt;/span&gt;
&lt;span id="cb52-22"&gt;&lt;a href="#cb52-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;Just&lt;/span&gt; &lt;span class="dt"&gt;Refl&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-23"&gt;&lt;a href="#cb52-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-24"&gt;&lt;a href="#cb52-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;STFun&lt;/span&gt; a b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-25"&gt;&lt;a href="#cb52-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;STFun&lt;/span&gt; c d &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-26"&gt;&lt;a href="#cb52-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;Refl&lt;/span&gt; &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; sameTy a c&lt;/span&gt;
&lt;span id="cb52-27"&gt;&lt;a href="#cb52-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;Refl&lt;/span&gt; &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; sameTy b d&lt;/span&gt;
&lt;span id="cb52-28"&gt;&lt;a href="#cb52-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;Just&lt;/span&gt; &lt;span class="dt"&gt;Refl&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-29"&gt;&lt;a href="#cb52-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-30"&gt;&lt;a href="#cb52-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb52-31"&gt;&lt;a href="#cb52-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;sameFields ::&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; &lt;span class="dt"&gt;STyField&lt;/span&gt; xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; &lt;span class="dt"&gt;STyField&lt;/span&gt; ys &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; (xs &lt;span class="op"&gt;:~:&lt;/span&gt; ys)&lt;/span&gt;
&lt;span id="cb52-32"&gt;&lt;a href="#cb52-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sameFields &lt;span class="dt"&gt;RNil&lt;/span&gt; &lt;span class="dt"&gt;RNil&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Just&lt;/span&gt; &lt;span class="dt"&gt;Refl&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-33"&gt;&lt;a href="#cb52-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sameFields (x &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; xs) (y &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; ys) &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-34"&gt;&lt;a href="#cb52-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Refl&lt;/span&gt; &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; sameField x y&lt;/span&gt;
&lt;span id="cb52-35"&gt;&lt;a href="#cb52-35" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Refl&lt;/span&gt; &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; sameFields xs ys&lt;/span&gt;
&lt;span id="cb52-36"&gt;&lt;a href="#cb52-36" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Just&lt;/span&gt; &lt;span class="dt"&gt;Refl&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-37"&gt;&lt;a href="#cb52-37" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sameFields _ _ &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-38"&gt;&lt;a href="#cb52-38" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb52-39"&gt;&lt;a href="#cb52-39" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;sameField ::&lt;/span&gt; &lt;span class="dt"&gt;STyField&lt;/span&gt; x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;STyField&lt;/span&gt; y &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; (x &lt;span class="op"&gt;:~:&lt;/span&gt; y)&lt;/span&gt;
&lt;span id="cb52-40"&gt;&lt;a href="#cb52-40" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sameField (&lt;span class="dt"&gt;STyField&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l tx) (&lt;span class="dt"&gt;STyField&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;m ty) &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-41"&gt;&lt;a href="#cb52-41" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;Refl&lt;/span&gt; &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; sameSymbol (&lt;span class="dt"&gt;Proxy&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l) (&lt;span class="dt"&gt;Proxy&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;m)&lt;/span&gt;
&lt;span id="cb52-42"&gt;&lt;a href="#cb52-42" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;Refl&lt;/span&gt; &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; sameTy tx ty&lt;/span&gt;
&lt;span id="cb52-43"&gt;&lt;a href="#cb52-43" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;Just&lt;/span&gt; &lt;span class="dt"&gt;Refl&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="the-full-eval"&gt;The Full Eval&lt;/h3&gt;
&lt;p&gt;Before we write the final &lt;code&gt;eval&lt;/code&gt;, let’s practice using
&lt;code&gt;Index&lt;/code&gt; and &lt;code&gt;Rec&lt;/code&gt; together. If we have an index
&lt;code&gt;Index as a&lt;/code&gt; that picks out a value &lt;code&gt;a&lt;/code&gt; in
&lt;code&gt;as&lt;/code&gt;, then we can pick out the &lt;code&gt;f a&lt;/code&gt; from a
&lt;code&gt;Rec f as&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb53"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb53-1"&gt;&lt;a href="#cb53-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L60-L63&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb53-2"&gt;&lt;a href="#cb53-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb53-3"&gt;&lt;a href="#cb53-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;indexRec ::&lt;/span&gt; &lt;span class="dt"&gt;Index&lt;/span&gt; xs x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; f xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f x&lt;/span&gt;
&lt;span id="cb53-4"&gt;&lt;a href="#cb53-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;indexRec &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb53-5"&gt;&lt;a href="#cb53-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;IZ&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \(x &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; _) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; x&lt;/span&gt;
&lt;span id="cb53-6"&gt;&lt;a href="#cb53-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;IS&lt;/span&gt; i &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \(_ &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; xs) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; indexRec i xs&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We also can recursively iterate a function over each item, assuming the
function &lt;code&gt;forall x. f x -&amp;gt; g x&lt;/code&gt;: that is, we can turn a
&lt;code&gt;Rec f as&lt;/code&gt; into a &lt;code&gt;Rec g as&lt;/code&gt; assuming our function is
polymorphic over each &lt;code&gt;x&lt;/code&gt;, and only depends on the shape of
&lt;code&gt;f&lt;/code&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb54"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb54-1"&gt;&lt;a href="#cb54-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L65-L67&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb54-2"&gt;&lt;a href="#cb54-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb54-3"&gt;&lt;a href="#cb54-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;traverseRec ::&lt;/span&gt; &lt;span class="dt"&gt;Applicative&lt;/span&gt; m &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; (&lt;span class="kw"&gt;forall&lt;/span&gt; x&lt;span class="op"&gt;.&lt;/span&gt; f x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; m (g x)) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; f xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; m (&lt;span class="dt"&gt;Rec&lt;/span&gt; g xs)&lt;/span&gt;
&lt;span id="cb54-4"&gt;&lt;a href="#cb54-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;traverseRec _ &lt;span class="dt"&gt;RNil&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;pure&lt;/span&gt; &lt;span class="dt"&gt;RNil&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb54-5"&gt;&lt;a href="#cb54-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;traverseRec f (x &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; xs) &lt;span class="ot"&gt;=&lt;/span&gt; (&lt;span class="op"&gt;:&amp;amp;&lt;/span&gt;) &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; f x &lt;span class="op"&gt;&amp;lt;*&amp;gt;&lt;/span&gt; traverseRec f xs&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With that, we can write our full &lt;code&gt;eval&lt;/code&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb55"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb55-1"&gt;&lt;a href="#cb55-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L326-L369&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-2"&gt;&lt;a href="#cb55-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb55-3"&gt;&lt;a href="#cb55-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;eval ::&lt;/span&gt; &lt;span class="dt"&gt;Map&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="dt"&gt;SomeValue&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; t &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; (&lt;span class="dt"&gt;EValue&lt;/span&gt; t)&lt;/span&gt;
&lt;span id="cb55-4"&gt;&lt;a href="#cb55-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;eval env &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-5"&gt;&lt;a href="#cb55-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; n) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;pure&lt;/span&gt; (&lt;span class="dt"&gt;EVInt&lt;/span&gt; n)&lt;/span&gt;
&lt;span id="cb55-6"&gt;&lt;a href="#cb55-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PBool&lt;/span&gt; b) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;pure&lt;/span&gt; (&lt;span class="dt"&gt;EVBool&lt;/span&gt; b)&lt;/span&gt;
&lt;span id="cb55-7"&gt;&lt;a href="#cb55-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PString&lt;/span&gt; s) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;pure&lt;/span&gt; (&lt;span class="dt"&gt;EVString&lt;/span&gt; s)&lt;/span&gt;
&lt;span id="cb55-8"&gt;&lt;a href="#cb55-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVar&lt;/span&gt; t v &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-9"&gt;&lt;a href="#cb55-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;SomeValue&lt;/span&gt; t&amp;#39; v&amp;#39; &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; M.lookup v env&lt;/span&gt;
&lt;span id="cb55-10"&gt;&lt;a href="#cb55-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;Refl&lt;/span&gt; &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; sameTy t t&amp;#39;&lt;/span&gt;
&lt;span id="cb55-11"&gt;&lt;a href="#cb55-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="fu"&gt;pure&lt;/span&gt; v&amp;#39;&lt;/span&gt;
&lt;span id="cb55-12"&gt;&lt;a href="#cb55-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ELambda&lt;/span&gt; ta n body &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-13"&gt;&lt;a href="#cb55-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="fu"&gt;pure&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="dt"&gt;EVFun&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; \x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; eval (M.insert n (&lt;span class="dt"&gt;SomeValue&lt;/span&gt; ta x) env) body&lt;/span&gt;
&lt;span id="cb55-14"&gt;&lt;a href="#cb55-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EApply&lt;/span&gt; f x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-15"&gt;&lt;a href="#cb55-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;EVFun&lt;/span&gt; g &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env f&lt;/span&gt;
&lt;span id="cb55-16"&gt;&lt;a href="#cb55-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    x&amp;#39; &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env x&lt;/span&gt;
&lt;span id="cb55-17"&gt;&lt;a href="#cb55-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    g x&amp;#39;&lt;/span&gt;
&lt;span id="cb55-18"&gt;&lt;a href="#cb55-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EOp&lt;/span&gt; o x y &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;case&lt;/span&gt; o &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-19"&gt;&lt;a href="#cb55-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;OPlus&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-20"&gt;&lt;a href="#cb55-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EVInt&lt;/span&gt; a &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env x&lt;/span&gt;
&lt;span id="cb55-21"&gt;&lt;a href="#cb55-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EVInt&lt;/span&gt; b &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env y&lt;/span&gt;
&lt;span id="cb55-22"&gt;&lt;a href="#cb55-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="fu"&gt;pure&lt;/span&gt; (&lt;span class="dt"&gt;EVInt&lt;/span&gt; (a &lt;span class="op"&gt;+&lt;/span&gt; b))&lt;/span&gt;
&lt;span id="cb55-23"&gt;&lt;a href="#cb55-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;OTimes&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-24"&gt;&lt;a href="#cb55-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EVInt&lt;/span&gt; a &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env x&lt;/span&gt;
&lt;span id="cb55-25"&gt;&lt;a href="#cb55-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EVInt&lt;/span&gt; b &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env y&lt;/span&gt;
&lt;span id="cb55-26"&gt;&lt;a href="#cb55-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="fu"&gt;pure&lt;/span&gt; (&lt;span class="dt"&gt;EVInt&lt;/span&gt; (a &lt;span class="op"&gt;*&lt;/span&gt; b))&lt;/span&gt;
&lt;span id="cb55-27"&gt;&lt;a href="#cb55-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;OLte&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-28"&gt;&lt;a href="#cb55-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EVInt&lt;/span&gt; a &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env x&lt;/span&gt;
&lt;span id="cb55-29"&gt;&lt;a href="#cb55-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EVInt&lt;/span&gt; b &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env y&lt;/span&gt;
&lt;span id="cb55-30"&gt;&lt;a href="#cb55-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="fu"&gt;pure&lt;/span&gt; (&lt;span class="dt"&gt;EVBool&lt;/span&gt; (a &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; b))&lt;/span&gt;
&lt;span id="cb55-31"&gt;&lt;a href="#cb55-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;OAnd&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-32"&gt;&lt;a href="#cb55-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EVBool&lt;/span&gt; a &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env x&lt;/span&gt;
&lt;span id="cb55-33"&gt;&lt;a href="#cb55-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EVBool&lt;/span&gt; b &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env y&lt;/span&gt;
&lt;span id="cb55-34"&gt;&lt;a href="#cb55-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="fu"&gt;pure&lt;/span&gt; (&lt;span class="dt"&gt;EVBool&lt;/span&gt; (a &lt;span class="op"&gt;&amp;amp;&amp;amp;&lt;/span&gt; b))&lt;/span&gt;
&lt;span id="cb55-35"&gt;&lt;a href="#cb55-35" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ERecord&lt;/span&gt; xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-36"&gt;&lt;a href="#cb55-36" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;EVRecord&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; traverseRec (evalField env) xs&lt;/span&gt;
&lt;span id="cb55-37"&gt;&lt;a href="#cb55-37" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EAccess&lt;/span&gt; e i &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-38"&gt;&lt;a href="#cb55-38" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;EVRecord&lt;/span&gt; xs &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env e&lt;/span&gt;
&lt;span id="cb55-39"&gt;&lt;a href="#cb55-39" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;case&lt;/span&gt; indexRec i xs &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-40"&gt;&lt;a href="#cb55-40" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EVField&lt;/span&gt; v &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;pure&lt;/span&gt; v&lt;/span&gt;
&lt;span id="cb55-41"&gt;&lt;a href="#cb55-41" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EChoice&lt;/span&gt; i x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-42"&gt;&lt;a href="#cb55-42" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;EVSum&lt;/span&gt; i &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; eval env x&lt;/span&gt;
&lt;span id="cb55-43"&gt;&lt;a href="#cb55-43" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ECase&lt;/span&gt; x hs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-44"&gt;&lt;a href="#cb55-44" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;EVSum&lt;/span&gt; i v &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; eval env x&lt;/span&gt;
&lt;span id="cb55-45"&gt;&lt;a href="#cb55-45" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;case&lt;/span&gt; indexRec i hs &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-46"&gt;&lt;a href="#cb55-46" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EHandler&lt;/span&gt; t n body &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; eval (M.insert n (&lt;span class="dt"&gt;SomeValue&lt;/span&gt; t v) env) body&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="ergonomics-of-records-and-sums"&gt;Ergonomics of Records and Sums&lt;/h3&gt;
&lt;p&gt;Note that we could also choose to implement records and sums using row types
indexed by the name of the field itself, instead of an ordered list of tuples.
This would have the advantage of making, for example,
&lt;code&gt;{ value :: Int, label :: String }&lt;/code&gt; the same type as
&lt;code&gt;{ label :: String, value :: Int }&lt;/code&gt;. However, I personally prefer the
style of building things inductively (&lt;code&gt;:&amp;amp;&lt;/code&gt;/&lt;code&gt;RNil&lt;/code&gt; and
&lt;code&gt;IS&lt;/code&gt;/&lt;code&gt;IZ&lt;/code&gt;), it makes the type errors and constructions a
lot easier to work with and reason with.&lt;/p&gt;
&lt;p&gt;However, we can get a little bit of the best of both worlds by using
typeclasses to auto-insert the &lt;code&gt;Index&lt;/code&gt; witnesses into a list.&lt;/p&gt;
&lt;p&gt;First, we can write a typeclass that searches a type-level list of fields and
produces the right &lt;code&gt;Index&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb56"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb56-1"&gt;&lt;a href="#cb56-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L51-L58&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb56-2"&gt;&lt;a href="#cb56-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb56-3"&gt;&lt;a href="#cb56-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;class&lt;/span&gt; &lt;span class="dt"&gt;ListIx&lt;/span&gt; (&lt;span class="ot"&gt;l ::&lt;/span&gt; &lt;span class="dt"&gt;Symbol&lt;/span&gt;) (&lt;span class="ot"&gt;xs ::&lt;/span&gt; [(&lt;span class="dt"&gt;Symbol&lt;/span&gt;, &lt;span class="dt"&gt;Ty&lt;/span&gt;)]) (&lt;span class="ot"&gt;a ::&lt;/span&gt; &lt;span class="dt"&gt;Ty&lt;/span&gt;) &lt;span class="op"&gt;|&lt;/span&gt; l xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb56-4"&gt;&lt;a href="#cb56-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;  listIx ::&lt;/span&gt; &lt;span class="dt"&gt;Index&lt;/span&gt; xs (l &lt;span class="op"&gt;:::&lt;/span&gt; a)&lt;/span&gt;
&lt;span id="cb56-5"&gt;&lt;a href="#cb56-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb56-6"&gt;&lt;a href="#cb56-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;ListIx&lt;/span&gt; l (l &lt;span class="op"&gt;:::&lt;/span&gt; a &lt;span class="op"&gt;:&lt;/span&gt; xs) a &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb56-7"&gt;&lt;a href="#cb56-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  listIx &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;IZ&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb56-8"&gt;&lt;a href="#cb56-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb56-9"&gt;&lt;a href="#cb56-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="ot"&gt;{-# OVERLAPPABLE #-}&lt;/span&gt; &lt;span class="dt"&gt;ListIx&lt;/span&gt; l xs a &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;ListIx&lt;/span&gt; l (m &lt;span class="op"&gt;:::&lt;/span&gt; b &lt;span class="op"&gt;:&lt;/span&gt; xs) a &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb56-10"&gt;&lt;a href="#cb56-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  listIx &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;IS&lt;/span&gt; (listIx &lt;span class="op"&gt;@&lt;/span&gt;l)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The FunDep &lt;code&gt;l xs -&amp;gt; a&lt;/code&gt; lets us use this like a function: for a
label &lt;code&gt;l&lt;/code&gt; and a list &lt;code&gt;xs&lt;/code&gt;, we should be able to uniquely
determine the &lt;code&gt;a&lt;/code&gt; type it singles out, if it exists. So we have an
instance of
&lt;code&gt;ListIx "value" ["value" ::: TInt, "label" ::: TString] TInt&lt;/code&gt;, where
the label &lt;code&gt;"value"&lt;/code&gt; and the list uniquely determines the result type
&lt;code&gt;TInt&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can now have a helper function that we can call like
&lt;code&gt;eAccess "value"&lt;/code&gt; using GHC 9.10’s
&lt;code&gt;RequiredTypeArguments&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb57"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb57-1"&gt;&lt;a href="#cb57-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L118-L123&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb57-2"&gt;&lt;a href="#cb57-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb57-3"&gt;&lt;a href="#cb57-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;eAccess ::&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb57-4"&gt;&lt;a href="#cb57-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="kw"&gt;forall&lt;/span&gt; (&lt;span class="ot"&gt;l ::&lt;/span&gt; &lt;span class="dt"&gt;Symbol&lt;/span&gt;) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb57-5"&gt;&lt;a href="#cb57-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  (&lt;span class="dt"&gt;KnownSymbol&lt;/span&gt; l, &lt;span class="dt"&gt;ListIx&lt;/span&gt; l as a) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb57-6"&gt;&lt;a href="#cb57-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Expr&lt;/span&gt; (&lt;span class="dt"&gt;TRecord&lt;/span&gt; as) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb57-7"&gt;&lt;a href="#cb57-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Expr&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb57-8"&gt;&lt;a href="#cb57-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;eAccess l e &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;EAccess&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l e (listIx &lt;span class="op"&gt;@&lt;/span&gt;l)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That lets us write the field name directly, and the compiler will generate
the &lt;code&gt;Index&lt;/code&gt; automatically for us:&lt;/p&gt;
&lt;div class="sourceCode" id="cb58"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb58-1"&gt;&lt;a href="#cb58-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L167-L176&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb58-2"&gt;&lt;a href="#cb58-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb58-3"&gt;&lt;a href="#cb58-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;namedAccessExample ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb58-4"&gt;&lt;a href="#cb58-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;namedAccessExample &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb58-5"&gt;&lt;a href="#cb58-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  eAccess&lt;/span&gt;
&lt;span id="cb58-6"&gt;&lt;a href="#cb58-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;&amp;quot;label&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb58-7"&gt;&lt;a href="#cb58-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ( &lt;span class="dt"&gt;ERecord&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb58-8"&gt;&lt;a href="#cb58-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ( eField &lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;7&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb58-9"&gt;&lt;a href="#cb58-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; eField &lt;span class="st"&gt;&amp;quot;label&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PString&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;found&amp;quot;&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb58-10"&gt;&lt;a href="#cb58-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; &lt;span class="dt"&gt;RNil&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb58-11"&gt;&lt;a href="#cb58-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        )&lt;/span&gt;
&lt;span id="cb58-12"&gt;&lt;a href="#cb58-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here,
&lt;code&gt;eAccess "value" :: Expr (TRecord ["value" ::: TInt, "label" ::: TString]) -&amp;gt; Expr TInt&lt;/code&gt;,
its result type uniquely determined by the types in the record fields.&lt;/p&gt;
&lt;p&gt;The same trick works for sum injections, so we can write the constructor name
directly:&lt;/p&gt;
&lt;div class="sourceCode" id="cb59"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb59-1"&gt;&lt;a href="#cb59-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L125-L179&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb59-2"&gt;&lt;a href="#cb59-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb59-3"&gt;&lt;a href="#cb59-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;eChoice ::&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb59-4"&gt;&lt;a href="#cb59-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="kw"&gt;forall&lt;/span&gt; (&lt;span class="ot"&gt;l ::&lt;/span&gt; &lt;span class="dt"&gt;Symbol&lt;/span&gt;) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb59-5"&gt;&lt;a href="#cb59-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  (&lt;span class="dt"&gt;KnownSymbol&lt;/span&gt; l, &lt;span class="dt"&gt;ListIx&lt;/span&gt; l as a) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb59-6"&gt;&lt;a href="#cb59-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Expr&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb59-7"&gt;&lt;a href="#cb59-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Expr&lt;/span&gt; (&lt;span class="dt"&gt;TSum&lt;/span&gt; as)&lt;/span&gt;
&lt;span id="cb59-8"&gt;&lt;a href="#cb59-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;eChoice l e &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;EChoice&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l (listIx &lt;span class="op"&gt;@&lt;/span&gt;l) e&lt;/span&gt;
&lt;span id="cb59-9"&gt;&lt;a href="#cb59-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb59-10"&gt;&lt;a href="#cb59-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;namedChoiceExample ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; (&lt;span class="dt"&gt;TSum&lt;/span&gt; [&lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;, &lt;span class="st"&gt;&amp;quot;Missing&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb59-11"&gt;&lt;a href="#cb59-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;namedChoiceExample &lt;span class="ot"&gt;=&lt;/span&gt; eChoice &lt;span class="st"&gt;&amp;quot;Missing&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PString&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;not here&amp;quot;&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here,
&lt;code&gt;eChoice "Missing" :: Expr TString -&amp;gt; Expr (TSum ["Found" ::: TInt, "Missing" ::: TString])&lt;/code&gt;,
because the constructor name &lt;code&gt;"Missing"&lt;/code&gt; uniquely determines the
payload type inside that sum.&lt;/p&gt;
&lt;h3 id="pretty-printing-records-and-sums"&gt;Pretty-Printing Records and Sums&lt;/h3&gt;
&lt;p&gt;To pretty-print, we finally use that &lt;code&gt;KnownSymbol&lt;/code&gt; constraint
we’ve been tracking this entire time. We can use
&lt;code&gt;symbolVal :: KnownSymbol s =&amp;gt; p s -&amp;gt; String&lt;/code&gt; to get the string
&lt;em&gt;value&lt;/em&gt; from the type-level string.&lt;/p&gt;
&lt;div class="sourceCode" id="cb60"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb60-1"&gt;&lt;a href="#cb60-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage3.hs#L237-L282&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-2"&gt;&lt;a href="#cb60-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb60-3"&gt;&lt;a href="#cb60-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;ppPrim ::&lt;/span&gt; &lt;span class="dt"&gt;Prim&lt;/span&gt; t &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;PP.Doc&lt;/span&gt; ann&lt;/span&gt;
&lt;span id="cb60-4"&gt;&lt;a href="#cb60-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ppPrim &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-5"&gt;&lt;a href="#cb60-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;PInt&lt;/span&gt; n &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; PP.pretty n&lt;/span&gt;
&lt;span id="cb60-6"&gt;&lt;a href="#cb60-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;PBool&lt;/span&gt; b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;if&lt;/span&gt; b &lt;span class="kw"&gt;then&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span class="kw"&gt;else&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;false&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-7"&gt;&lt;a href="#cb60-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;PString&lt;/span&gt; s &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; PP.pretty (&lt;span class="fu"&gt;show&lt;/span&gt; s)&lt;/span&gt;
&lt;span id="cb60-8"&gt;&lt;a href="#cb60-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb60-9"&gt;&lt;a href="#cb60-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;ppOp ::&lt;/span&gt; &lt;span class="dt"&gt;Op&lt;/span&gt; a b c &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;PP.Doc&lt;/span&gt; ann&lt;/span&gt;
&lt;span id="cb60-10"&gt;&lt;a href="#cb60-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ppOp &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-11"&gt;&lt;a href="#cb60-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;OPlus&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;+&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-12"&gt;&lt;a href="#cb60-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;OTimes&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;*&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-13"&gt;&lt;a href="#cb60-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;OLte&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;&amp;lt;=&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-14"&gt;&lt;a href="#cb60-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;OAnd&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;&amp;amp;&amp;amp;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-15"&gt;&lt;a href="#cb60-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb60-16"&gt;&lt;a href="#cb60-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;ppFields ::&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; &lt;span class="dt"&gt;ExprField&lt;/span&gt; xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; [&lt;span class="dt"&gt;PP.Doc&lt;/span&gt; ann]&lt;/span&gt;
&lt;span id="cb60-17"&gt;&lt;a href="#cb60-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ppFields &lt;span class="dt"&gt;RNil&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; []&lt;/span&gt;
&lt;span id="cb60-18"&gt;&lt;a href="#cb60-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ppFields (&lt;span class="dt"&gt;EField&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l x &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; xs) &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-19"&gt;&lt;a href="#cb60-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  (PP.pretty (symbolVal (&lt;span class="dt"&gt;Proxy&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l)) &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;=&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr &lt;span class="dt"&gt;False&lt;/span&gt; x) &lt;span class="op"&gt;:&lt;/span&gt; ppFields xs&lt;/span&gt;
&lt;span id="cb60-20"&gt;&lt;a href="#cb60-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb60-21"&gt;&lt;a href="#cb60-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;ppHandlers ::&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; (&lt;span class="dt"&gt;ExprHandler&lt;/span&gt; b) xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; [&lt;span class="dt"&gt;PP.Doc&lt;/span&gt; ann]&lt;/span&gt;
&lt;span id="cb60-22"&gt;&lt;a href="#cb60-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ppHandlers &lt;span class="dt"&gt;RNil&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; []&lt;/span&gt;
&lt;span id="cb60-23"&gt;&lt;a href="#cb60-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ppHandlers (&lt;span class="dt"&gt;EHandler&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l _ n body &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; xs) &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-24"&gt;&lt;a href="#cb60-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  (PP.pretty (symbolVal (&lt;span class="dt"&gt;Proxy&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l)) &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; PP.pretty n &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;-&amp;gt;&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr &lt;span class="dt"&gt;False&lt;/span&gt; body) &lt;span class="op"&gt;:&lt;/span&gt; ppHandlers xs&lt;/span&gt;
&lt;span id="cb60-25"&gt;&lt;a href="#cb60-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb60-26"&gt;&lt;a href="#cb60-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;ppExpr ::&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; t &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;PP.Doc&lt;/span&gt; ann&lt;/span&gt;
&lt;span id="cb60-27"&gt;&lt;a href="#cb60-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ppExpr paren &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-28"&gt;&lt;a href="#cb60-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EPrim&lt;/span&gt; p &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; ppPrim p&lt;/span&gt;
&lt;span id="cb60-29"&gt;&lt;a href="#cb60-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVar&lt;/span&gt; _ v &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; PP.pretty v&lt;/span&gt;
&lt;span id="cb60-30"&gt;&lt;a href="#cb60-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ELambda&lt;/span&gt; _ n body &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; wrap &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;\\&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; PP.pretty n &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;-&amp;gt;&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr &lt;span class="dt"&gt;False&lt;/span&gt; body&lt;/span&gt;
&lt;span id="cb60-31"&gt;&lt;a href="#cb60-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EApply&lt;/span&gt; f x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; wrap &lt;span class="op"&gt;$&lt;/span&gt; ppExpr &lt;span class="dt"&gt;True&lt;/span&gt; f &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr &lt;span class="dt"&gt;True&lt;/span&gt; x&lt;/span&gt;
&lt;span id="cb60-32"&gt;&lt;a href="#cb60-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EOp&lt;/span&gt; o x y &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; wrap &lt;span class="op"&gt;$&lt;/span&gt; ppExpr &lt;span class="dt"&gt;True&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppOp o &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr &lt;span class="dt"&gt;True&lt;/span&gt; y&lt;/span&gt;
&lt;span id="cb60-33"&gt;&lt;a href="#cb60-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ERecord&lt;/span&gt; xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; PP.encloseSep &lt;span class="st"&gt;&amp;quot;{ &amp;quot;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot; }&amp;quot;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;, &amp;quot;&lt;/span&gt; (ppFields xs)&lt;/span&gt;
&lt;span id="cb60-34"&gt;&lt;a href="#cb60-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EAccess&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l e _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; ppExpr &lt;span class="dt"&gt;True&lt;/span&gt; e &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;.&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; PP.pretty (symbolVal (&lt;span class="dt"&gt;Proxy&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l))&lt;/span&gt;
&lt;span id="cb60-35"&gt;&lt;a href="#cb60-35" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EChoice&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l _ x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; wrap &lt;span class="op"&gt;$&lt;/span&gt; PP.pretty (symbolVal (&lt;span class="dt"&gt;Proxy&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l)) &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr &lt;span class="dt"&gt;True&lt;/span&gt; x&lt;/span&gt;
&lt;span id="cb60-36"&gt;&lt;a href="#cb60-36" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ECase&lt;/span&gt; x hs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-37"&gt;&lt;a href="#cb60-37" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    wrap &lt;span class="op"&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-38"&gt;&lt;a href="#cb60-38" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      PP.sep&lt;/span&gt;
&lt;span id="cb60-39"&gt;&lt;a href="#cb60-39" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        [ &lt;span class="st"&gt;&amp;quot;case&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr &lt;span class="dt"&gt;False&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;of&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-40"&gt;&lt;a href="#cb60-40" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        , PP.encloseSep &lt;span class="st"&gt;&amp;quot;{ &amp;quot;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot; }&amp;quot;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;; &amp;quot;&lt;/span&gt; (ppHandlers hs)&lt;/span&gt;
&lt;span id="cb60-41"&gt;&lt;a href="#cb60-41" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ]&lt;/span&gt;
&lt;span id="cb60-42"&gt;&lt;a href="#cb60-42" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-43"&gt;&lt;a href="#cb60-43" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    wrap&lt;/span&gt;
&lt;span id="cb60-44"&gt;&lt;a href="#cb60-44" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="op"&gt;|&lt;/span&gt; paren &lt;span class="ot"&gt;=&lt;/span&gt; PP.parens&lt;/span&gt;
&lt;span id="cb60-45"&gt;&lt;a href="#cb60-45" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="fu"&gt;otherwise&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-46"&gt;&lt;a href="#cb60-46" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb60-47"&gt;&lt;a href="#cb60-47" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;prettyExpr ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; t &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;PP.Doc&lt;/span&gt; ann&lt;/span&gt;
&lt;span id="cb60-48"&gt;&lt;a href="#cb60-48" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;prettyExpr &lt;span class="ot"&gt;=&lt;/span&gt; ppExpr &lt;span class="dt"&gt;False&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="capturing-variables"&gt;Capturing Variables&lt;/h2&gt;
&lt;p&gt;In order to have &lt;code&gt;EVar&lt;/code&gt; be type-safe, the environment itself needs
to be a part of the &lt;code&gt;Expr&lt;/code&gt; type, and you should only be able to use
&lt;code&gt;EVar&lt;/code&gt; if the &lt;code&gt;Expr&lt;/code&gt; enforces it. &lt;code&gt;ELambda&lt;/code&gt;
would, therefore, introduce the new variable to the environment.&lt;/p&gt;
&lt;p&gt;We’ll have:&lt;/p&gt;
&lt;div class="sourceCode" id="cb61"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb61-1"&gt;&lt;a href="#cb61-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage4.hs#L80-L80&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb61-2"&gt;&lt;a href="#cb61-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb61-3"&gt;&lt;a href="#cb61-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; [(&lt;span class="dt"&gt;Symbol&lt;/span&gt;, &lt;span class="dt"&gt;Ty&lt;/span&gt;)] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Ty&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So a value of type &lt;code&gt;Expr ["x" ::: TInt, "y" ::: TBool] t&lt;/code&gt; is an
expression with free variables &lt;code&gt;x&lt;/code&gt; of type &lt;code&gt;Int&lt;/code&gt; and
&lt;code&gt;y&lt;/code&gt; of type &lt;code&gt;Bool&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Surprise! That small detour to add records and sums to our language actually
ended up being a smooth precursor to all of the techniques we will be using to
solve for variable binders.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ELambda&lt;/code&gt; would therefore take an &lt;code&gt;Expr&lt;/code&gt; with a free
variable and turn it into an &lt;code&gt;Expr&lt;/code&gt; of a function type. We also keep
a &lt;code&gt;KnownSymbol&lt;/code&gt; constraint for the name so that we can recover the
name when we render the expression.&lt;/p&gt;
&lt;div class="sourceCode" id="cb62"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb62-1"&gt;&lt;a href="#cb62-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage4.hs#L83-L83&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb62-2"&gt;&lt;a href="#cb62-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb62-3"&gt;&lt;a href="#cb62-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ELambda&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;KnownSymbol&lt;/span&gt; n &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; (n &lt;span class="op"&gt;:::&lt;/span&gt; a &amp;#39;&lt;span class="op"&gt;:&lt;/span&gt; vs) b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs (a &lt;span class="op"&gt;:-&amp;gt;&lt;/span&gt; b)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;EVar&lt;/code&gt; then becomes exactly like &lt;code&gt;EAccess&lt;/code&gt;! We “index”
into the environment of the &lt;code&gt;Expr vs a&lt;/code&gt; using &lt;code&gt;Index&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb63"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb63-1"&gt;&lt;a href="#cb63-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage4.hs#L82-L82&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb63-2"&gt;&lt;a href="#cb63-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb63-3"&gt;&lt;a href="#cb63-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVar&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Index&lt;/span&gt; vs (n &lt;span class="op"&gt;:::&lt;/span&gt; t) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs t&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So it is legal to have
&lt;code&gt;EVar IZ :: Expr ["x" ::: TInt, "y" ::: TBool] TInt&lt;/code&gt;, and also it is
automatically inferred to be a &lt;code&gt;TInt&lt;/code&gt;. But we could &lt;em&gt;not&lt;/em&gt;
write &lt;code&gt;EVar IZ :: Expr [] TInt&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;And finally, our whole &lt;code&gt;Expr&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb64"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb64-1"&gt;&lt;a href="#cb64-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage4.hs#L80-L89&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb64-2"&gt;&lt;a href="#cb64-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb64-3"&gt;&lt;a href="#cb64-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; [(&lt;span class="dt"&gt;Symbol&lt;/span&gt;, &lt;span class="dt"&gt;Ty&lt;/span&gt;)] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Ty&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb64-4"&gt;&lt;a href="#cb64-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EPrim&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Prim&lt;/span&gt; t &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs t&lt;/span&gt;
&lt;span id="cb64-5"&gt;&lt;a href="#cb64-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVar&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Index&lt;/span&gt; vs (n &lt;span class="op"&gt;:::&lt;/span&gt; t) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs t&lt;/span&gt;
&lt;span id="cb64-6"&gt;&lt;a href="#cb64-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ELambda&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;KnownSymbol&lt;/span&gt; n &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; (n &lt;span class="op"&gt;:::&lt;/span&gt; a &amp;#39;&lt;span class="op"&gt;:&lt;/span&gt; vs) b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs (a &lt;span class="op"&gt;:-&amp;gt;&lt;/span&gt; b)&lt;/span&gt;
&lt;span id="cb64-7"&gt;&lt;a href="#cb64-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EApply&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs (a &lt;span class="op"&gt;:-&amp;gt;&lt;/span&gt; b) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs b&lt;/span&gt;
&lt;span id="cb64-8"&gt;&lt;a href="#cb64-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EOp&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Op&lt;/span&gt; a b c &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs c&lt;/span&gt;
&lt;span id="cb64-9"&gt;&lt;a href="#cb64-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ERecord&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; (&lt;span class="dt"&gt;ExprField&lt;/span&gt; vs) as &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs (&lt;span class="dt"&gt;TRecord&lt;/span&gt; as)&lt;/span&gt;
&lt;span id="cb64-10"&gt;&lt;a href="#cb64-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EAccess&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;KnownSymbol&lt;/span&gt; l &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs (&lt;span class="dt"&gt;TRecord&lt;/span&gt; as) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Index&lt;/span&gt; as (l &lt;span class="op"&gt;:::&lt;/span&gt; a) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs a&lt;/span&gt;
&lt;span id="cb64-11"&gt;&lt;a href="#cb64-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EChoice&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;KnownSymbol&lt;/span&gt; l &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Index&lt;/span&gt; as (l &lt;span class="op"&gt;:::&lt;/span&gt; a) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs (&lt;span class="dt"&gt;TSum&lt;/span&gt; as)&lt;/span&gt;
&lt;span id="cb64-12"&gt;&lt;a href="#cb64-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ECase&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs (&lt;span class="dt"&gt;TSum&lt;/span&gt; as) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; (&lt;span class="dt"&gt;ExprHandler&lt;/span&gt; vs b) as &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs b&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Just like with record access, we can use the &lt;code&gt;ListIx&lt;/code&gt; class to
write a named helper:&lt;/p&gt;
&lt;div class="sourceCode" id="cb65"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb65-1"&gt;&lt;a href="#cb65-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage4.hs#L47-L120&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb65-2"&gt;&lt;a href="#cb65-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb65-3"&gt;&lt;a href="#cb65-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;class&lt;/span&gt; &lt;span class="dt"&gt;ListIx&lt;/span&gt; (&lt;span class="ot"&gt;l ::&lt;/span&gt; &lt;span class="dt"&gt;Symbol&lt;/span&gt;) (&lt;span class="ot"&gt;xs ::&lt;/span&gt; [(&lt;span class="dt"&gt;Symbol&lt;/span&gt;, &lt;span class="dt"&gt;Ty&lt;/span&gt;)]) (&lt;span class="ot"&gt;a ::&lt;/span&gt; &lt;span class="dt"&gt;Ty&lt;/span&gt;) &lt;span class="op"&gt;|&lt;/span&gt; l xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb65-4"&gt;&lt;a href="#cb65-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;  listIx ::&lt;/span&gt; &lt;span class="dt"&gt;Index&lt;/span&gt; xs (l &lt;span class="op"&gt;:::&lt;/span&gt; a)&lt;/span&gt;
&lt;span id="cb65-5"&gt;&lt;a href="#cb65-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb65-6"&gt;&lt;a href="#cb65-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;ListIx&lt;/span&gt; l (l &lt;span class="op"&gt;:::&lt;/span&gt; a &amp;#39;&lt;span class="op"&gt;:&lt;/span&gt; xs) a &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb65-7"&gt;&lt;a href="#cb65-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  listIx &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;IZ&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb65-8"&gt;&lt;a href="#cb65-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb65-9"&gt;&lt;a href="#cb65-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="ot"&gt;{-# OVERLAPPABLE #-}&lt;/span&gt; &lt;span class="dt"&gt;ListIx&lt;/span&gt; l xs a &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;ListIx&lt;/span&gt; l (m &lt;span class="op"&gt;:::&lt;/span&gt; b &amp;#39;&lt;span class="op"&gt;:&lt;/span&gt; xs) a &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb65-10"&gt;&lt;a href="#cb65-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  listIx &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;IS&lt;/span&gt; (listIx &lt;span class="op"&gt;@&lt;/span&gt;l)&lt;/span&gt;
&lt;span id="cb65-11"&gt;&lt;a href="#cb65-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb65-12"&gt;&lt;a href="#cb65-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;eVar ::&lt;/span&gt; &lt;span class="kw"&gt;forall&lt;/span&gt; n &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;ListIx&lt;/span&gt; n vs a &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs a&lt;/span&gt;
&lt;span id="cb65-13"&gt;&lt;a href="#cb65-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;eVar n &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;EVar&lt;/span&gt; (listIx &lt;span class="op"&gt;@&lt;/span&gt;n)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Adding in our other &lt;code&gt;-XRequiredTypeArguments&lt;/code&gt; helpers:&lt;/p&gt;
&lt;div class="sourceCode" id="cb66"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb66-1"&gt;&lt;a href="#cb66-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage4.hs#L91-L117&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb66-2"&gt;&lt;a href="#cb66-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb66-3"&gt;&lt;a href="#cb66-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;eLambda ::&lt;/span&gt; &lt;span class="kw"&gt;forall&lt;/span&gt; n &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;KnownSymbol&lt;/span&gt; n &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; (n &lt;span class="op"&gt;:::&lt;/span&gt; a &amp;#39;&lt;span class="op"&gt;:&lt;/span&gt; vs) b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs (a &lt;span class="op"&gt;:-&amp;gt;&lt;/span&gt; b)&lt;/span&gt;
&lt;span id="cb66-4"&gt;&lt;a href="#cb66-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;eLambda n &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;ELambda&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;n&lt;/span&gt;
&lt;span id="cb66-5"&gt;&lt;a href="#cb66-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb66-6"&gt;&lt;a href="#cb66-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;eField ::&lt;/span&gt; &lt;span class="kw"&gt;forall&lt;/span&gt; l &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;KnownSymbol&lt;/span&gt; l &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;ExprField&lt;/span&gt; vs (l &lt;span class="op"&gt;:::&lt;/span&gt; a)&lt;/span&gt;
&lt;span id="cb66-7"&gt;&lt;a href="#cb66-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;eField l &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;EField&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l&lt;/span&gt;
&lt;span id="cb66-8"&gt;&lt;a href="#cb66-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb66-9"&gt;&lt;a href="#cb66-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;eAccess ::&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb66-10"&gt;&lt;a href="#cb66-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="kw"&gt;forall&lt;/span&gt; l &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb66-11"&gt;&lt;a href="#cb66-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  (&lt;span class="dt"&gt;KnownSymbol&lt;/span&gt; l, &lt;span class="dt"&gt;ListIx&lt;/span&gt; l as a) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb66-12"&gt;&lt;a href="#cb66-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Expr&lt;/span&gt; vs (&lt;span class="dt"&gt;TRecord&lt;/span&gt; as) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb66-13"&gt;&lt;a href="#cb66-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Expr&lt;/span&gt; vs a&lt;/span&gt;
&lt;span id="cb66-14"&gt;&lt;a href="#cb66-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;eAccess l e &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;EAccess&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l e (listIx &lt;span class="op"&gt;@&lt;/span&gt;l)&lt;/span&gt;
&lt;span id="cb66-15"&gt;&lt;a href="#cb66-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb66-16"&gt;&lt;a href="#cb66-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;eChoice ::&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb66-17"&gt;&lt;a href="#cb66-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="kw"&gt;forall&lt;/span&gt; l &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb66-18"&gt;&lt;a href="#cb66-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  (&lt;span class="dt"&gt;KnownSymbol&lt;/span&gt; l, &lt;span class="dt"&gt;ListIx&lt;/span&gt; l as a) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb66-19"&gt;&lt;a href="#cb66-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Expr&lt;/span&gt; vs a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb66-20"&gt;&lt;a href="#cb66-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Expr&lt;/span&gt; vs (&lt;span class="dt"&gt;TSum&lt;/span&gt; as)&lt;/span&gt;
&lt;span id="cb66-21"&gt;&lt;a href="#cb66-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;eChoice l e &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;EChoice&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l (listIx &lt;span class="op"&gt;@&lt;/span&gt;l) e&lt;/span&gt;
&lt;span id="cb66-22"&gt;&lt;a href="#cb66-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb66-23"&gt;&lt;a href="#cb66-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;eHandler ::&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb66-24"&gt;&lt;a href="#cb66-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="kw"&gt;forall&lt;/span&gt; n &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb66-25"&gt;&lt;a href="#cb66-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="kw"&gt;forall&lt;/span&gt; l &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb66-26"&gt;&lt;a href="#cb66-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  (&lt;span class="dt"&gt;KnownSymbol&lt;/span&gt; n, &lt;span class="dt"&gt;KnownSymbol&lt;/span&gt; l) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb66-27"&gt;&lt;a href="#cb66-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Expr&lt;/span&gt; (n &lt;span class="op"&gt;:::&lt;/span&gt; a &amp;#39;&lt;span class="op"&gt;:&lt;/span&gt; vs) b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb66-28"&gt;&lt;a href="#cb66-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ExprHandler&lt;/span&gt; vs b (l &lt;span class="op"&gt;:::&lt;/span&gt; a)&lt;/span&gt;
&lt;span id="cb66-29"&gt;&lt;a href="#cb66-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;eHandler n l &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;EHandler&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;n &lt;span class="op"&gt;@&lt;/span&gt;l&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we get something that is &lt;em&gt;truly&lt;/em&gt; type-safe: all expressions are
well-typed, and all variables are ensured to be bound!&lt;/p&gt;
&lt;div class="sourceCode" id="cb67"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb67-1"&gt;&lt;a href="#cb67-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage4.hs#L139-L171&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-2"&gt;&lt;a href="#cb67-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb67-3"&gt;&lt;a href="#cb67-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;fifteen ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &amp;#39;[] &lt;span class="dt"&gt;TInt&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-4"&gt;&lt;a href="#cb67-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fifteen &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-5"&gt;&lt;a href="#cb67-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EApply&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-6"&gt;&lt;a href="#cb67-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    (eLambda &lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OTimes&lt;/span&gt; (eVar &lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt;) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;))))&lt;/span&gt;
&lt;span id="cb67-7"&gt;&lt;a href="#cb67-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;5&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb67-8"&gt;&lt;a href="#cb67-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb67-9"&gt;&lt;a href="#cb67-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;recordExample ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &amp;#39;[] &lt;span class="dt"&gt;TInt&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-10"&gt;&lt;a href="#cb67-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;recordExample &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-11"&gt;&lt;a href="#cb67-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EOp&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-12"&gt;&lt;a href="#cb67-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;OPlus&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-13"&gt;&lt;a href="#cb67-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ( eAccess&lt;/span&gt;
&lt;span id="cb67-14"&gt;&lt;a href="#cb67-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-15"&gt;&lt;a href="#cb67-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ( &lt;span class="dt"&gt;ERecord&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-16"&gt;&lt;a href="#cb67-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            ( eField &lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;7&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb67-17"&gt;&lt;a href="#cb67-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; eField &lt;span class="st"&gt;&amp;quot;label&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PString&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;found&amp;quot;&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb67-18"&gt;&lt;a href="#cb67-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; &lt;span class="dt"&gt;RNil&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-19"&gt;&lt;a href="#cb67-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            )&lt;/span&gt;
&lt;span id="cb67-20"&gt;&lt;a href="#cb67-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        )&lt;/span&gt;
&lt;span id="cb67-21"&gt;&lt;a href="#cb67-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb67-22"&gt;&lt;a href="#cb67-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb67-23"&gt;&lt;a href="#cb67-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb67-24"&gt;&lt;a href="#cb67-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;sumExample ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &amp;#39;[] &lt;span class="dt"&gt;TInt&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-25"&gt;&lt;a href="#cb67-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sumExample &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-26"&gt;&lt;a href="#cb67-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ECase&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-27"&gt;&lt;a href="#cb67-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    (eChoice &lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;7&lt;/span&gt;)))&lt;/span&gt;
&lt;span id="cb67-28"&gt;&lt;a href="#cb67-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ( eHandler &lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OPlus&lt;/span&gt; (eVar &lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;)))&lt;/span&gt;
&lt;span id="cb67-29"&gt;&lt;a href="#cb67-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; eHandler &lt;span class="st"&gt;&amp;quot;message&amp;quot;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Missing&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb67-30"&gt;&lt;a href="#cb67-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; &lt;span class="dt"&gt;RNil&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-31"&gt;&lt;a href="#cb67-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="what-we-gained"&gt;What we gained&lt;/h3&gt;
&lt;p&gt;Now all of the previous “bad” examples we gave are finally
compiler-verified:&lt;/p&gt;
&lt;div class="sourceCode" id="cb68"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb68-1"&gt;&lt;a href="#cb68-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;:&lt;/span&gt;t (&lt;span class="dt"&gt;EVar&lt;/span&gt; &lt;span class="dt"&gt;IZ&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &amp;#39;[] &lt;span class="dt"&gt;TInt&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb68-2"&gt;&lt;a href="#cb68-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;interactive&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;error&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb68-3"&gt;&lt;a href="#cb68-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    • &lt;span class="dt"&gt;Couldn&amp;#39;t&lt;/span&gt; match &lt;span class="kw"&gt;type&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; (n0 &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;) &lt;span class="op"&gt;:&lt;/span&gt; xs0&lt;/span&gt;
&lt;span id="cb68-4"&gt;&lt;a href="#cb68-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                     with&lt;span class="op"&gt;:&lt;/span&gt; &amp;#39;[]&lt;/span&gt;
&lt;span id="cb68-5"&gt;&lt;a href="#cb68-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;Expected&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;Index&lt;/span&gt; &amp;#39;[] (n0 &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb68-6"&gt;&lt;a href="#cb68-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="dt"&gt;Actual&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;Index&lt;/span&gt; ((n0 &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;) &lt;span class="op"&gt;:&lt;/span&gt; xs0) (n0 &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb68-7"&gt;&lt;a href="#cb68-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb68-8"&gt;&lt;a href="#cb68-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;:&lt;/span&gt;t (&lt;span class="dt"&gt;EVar&lt;/span&gt; &lt;span class="dt"&gt;IZ&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &amp;#39;[&lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;] &lt;span class="dt"&gt;TInt&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb68-9"&gt;&lt;a href="#cb68-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;interactive&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;error&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb68-10"&gt;&lt;a href="#cb68-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    • &lt;span class="dt"&gt;Couldn&amp;#39;t&lt;/span&gt; match &lt;span class="kw"&gt;type&lt;/span&gt; ‘&lt;span class="dt"&gt;TString&lt;/span&gt;’ with ‘&lt;span class="dt"&gt;TInt&lt;/span&gt;’&lt;/span&gt;
&lt;span id="cb68-11"&gt;&lt;a href="#cb68-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;Expected&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;Index&lt;/span&gt; &amp;#39;[&lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;] (&lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb68-12"&gt;&lt;a href="#cb68-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="dt"&gt;Actual&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;Index&lt;/span&gt; &amp;#39;[&lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;] (&lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb68-13"&gt;&lt;a href="#cb68-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb68-14"&gt;&lt;a href="#cb68-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;:&lt;/span&gt;t &lt;span class="dt"&gt;ECase&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb68-15"&gt;&lt;a href="#cb68-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      (&lt;span class="dt"&gt;EChoice&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;&lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; &lt;span class="dt"&gt;IZ&lt;/span&gt; (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;7&lt;/span&gt;))&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &amp;#39;[] (&lt;span class="dt"&gt;TSum&lt;/span&gt; &amp;#39;[&lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;, &lt;span class="st"&gt;&amp;quot;Missing&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;]))&lt;/span&gt;
&lt;span id="cb68-16"&gt;&lt;a href="#cb68-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      ( &lt;span class="dt"&gt;EHandler&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;&lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;&lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OPlus&lt;/span&gt; (&lt;span class="dt"&gt;EVar&lt;/span&gt; (&lt;span class="dt"&gt;IS&lt;/span&gt; &lt;span class="dt"&gt;IZ&lt;/span&gt;)) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;)))&lt;/span&gt;
&lt;span id="cb68-17"&gt;&lt;a href="#cb68-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; &lt;span class="dt"&gt;EHandler&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;&lt;span class="st"&gt;&amp;quot;message&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;&lt;span class="st"&gt;&amp;quot;Missing&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OPlus&lt;/span&gt; (&lt;span class="dt"&gt;EVar&lt;/span&gt; &lt;span class="dt"&gt;IZ&lt;/span&gt;) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;)))&lt;/span&gt;
&lt;span id="cb68-18"&gt;&lt;a href="#cb68-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; &lt;span class="dt"&gt;RNil&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb68-19"&gt;&lt;a href="#cb68-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      )&lt;/span&gt;
&lt;span id="cb68-20"&gt;&lt;a href="#cb68-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;interactive&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;error&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb68-21"&gt;&lt;a href="#cb68-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    • &lt;span class="dt"&gt;Couldn&amp;#39;t&lt;/span&gt; match &lt;span class="kw"&gt;type&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; (n0 &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;) &lt;span class="op"&gt;:&lt;/span&gt; xs0&lt;/span&gt;
&lt;span id="cb68-22"&gt;&lt;a href="#cb68-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                     with&lt;span class="op"&gt;:&lt;/span&gt; &amp;#39;[]&lt;/span&gt;
&lt;span id="cb68-23"&gt;&lt;a href="#cb68-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;interactive&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;error&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb68-24"&gt;&lt;a href="#cb68-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    • &lt;span class="dt"&gt;Couldn&amp;#39;t&lt;/span&gt; match &lt;span class="kw"&gt;type&lt;/span&gt; ‘&lt;span class="dt"&gt;TString&lt;/span&gt;’ with ‘&lt;span class="dt"&gt;TInt&lt;/span&gt;’&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And using the &lt;code&gt;ListIx&lt;/code&gt; helpers, those same failures show up as
failed index searches:&lt;/p&gt;
&lt;div class="sourceCode" id="cb69"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb69-1"&gt;&lt;a href="#cb69-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;:&lt;/span&gt;t (eVar &lt;span class="st"&gt;&amp;quot;missing&amp;quot;&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &amp;#39;[] &lt;span class="dt"&gt;TInt&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb69-2"&gt;&lt;a href="#cb69-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;interactive&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;error&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb69-3"&gt;&lt;a href="#cb69-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    • &lt;span class="dt"&gt;No&lt;/span&gt; &lt;span class="kw"&gt;instance&lt;/span&gt; for ‘&lt;span class="dt"&gt;ListIx&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;missing&amp;quot;&lt;/span&gt; &amp;#39;[] &lt;span class="dt"&gt;TInt&lt;/span&gt;’&lt;/span&gt;
&lt;span id="cb69-4"&gt;&lt;a href="#cb69-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb69-5"&gt;&lt;a href="#cb69-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;:&lt;/span&gt;t (eVar &lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &amp;#39;[&lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;] &lt;span class="dt"&gt;TInt&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb69-6"&gt;&lt;a href="#cb69-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;interactive&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;error&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb69-7"&gt;&lt;a href="#cb69-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    • &lt;span class="dt"&gt;No&lt;/span&gt; &lt;span class="kw"&gt;instance&lt;/span&gt; for ‘&lt;span class="dt"&gt;ListIx&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt; &amp;#39;[] &lt;span class="dt"&gt;TInt&lt;/span&gt;’&lt;/span&gt;
&lt;span id="cb69-8"&gt;&lt;a href="#cb69-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb69-9"&gt;&lt;a href="#cb69-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;:&lt;/span&gt;t &lt;span class="dt"&gt;ECase&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb69-10"&gt;&lt;a href="#cb69-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      (eChoice &lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;7&lt;/span&gt;))&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &amp;#39;[] (&lt;span class="dt"&gt;TSum&lt;/span&gt; &amp;#39;[&lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;, &lt;span class="st"&gt;&amp;quot;Missing&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;]))&lt;/span&gt;
&lt;span id="cb69-11"&gt;&lt;a href="#cb69-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      ( eHandler &lt;span class="st"&gt;&amp;quot;value&amp;quot;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Found&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OPlus&lt;/span&gt; (eVar &lt;span class="st"&gt;&amp;quot;missing&amp;quot;&lt;/span&gt;) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;)))&lt;/span&gt;
&lt;span id="cb69-12"&gt;&lt;a href="#cb69-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; eHandler &lt;span class="st"&gt;&amp;quot;message&amp;quot;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Missing&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OPlus&lt;/span&gt; (eVar &lt;span class="st"&gt;&amp;quot;message&amp;quot;&lt;/span&gt;) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;)))&lt;/span&gt;
&lt;span id="cb69-13"&gt;&lt;a href="#cb69-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; &lt;span class="dt"&gt;RNil&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb69-14"&gt;&lt;a href="#cb69-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      )&lt;/span&gt;
&lt;span id="cb69-15"&gt;&lt;a href="#cb69-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;interactive&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;error&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb69-16"&gt;&lt;a href="#cb69-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    • &lt;span class="dt"&gt;No&lt;/span&gt; &lt;span class="kw"&gt;instance&lt;/span&gt; for ‘&lt;span class="dt"&gt;ListIx&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;missing&amp;quot;&lt;/span&gt; &amp;#39;[] &lt;span class="dt"&gt;TInt&lt;/span&gt;’&lt;/span&gt;
&lt;span id="cb69-17"&gt;&lt;a href="#cb69-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;interactive&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;error&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb69-18"&gt;&lt;a href="#cb69-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    • &lt;span class="dt"&gt;No&lt;/span&gt; &lt;span class="kw"&gt;instance&lt;/span&gt; for ‘&lt;span class="dt"&gt;ListIx&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;message&amp;quot;&lt;/span&gt; &amp;#39;[] &lt;span class="dt"&gt;TInt&lt;/span&gt;’&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Expressions that are not well-typed in our domain language are now rejected
by GHC!&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;(As an exercise, can understand why those errors are what they are? Why they
all contain &lt;code&gt;ListIx _ '[]&lt;/code&gt;? For more ergonomics there is stuff we can
do with &lt;code&gt;TypeError&lt;/code&gt; machinery to make the messages a little prettier;
the &lt;em&gt;vinyl&lt;/em&gt; library does a lot to make error messages a bit better, like
in &lt;code&gt;HasField&lt;/code&gt; &lt;a
href="https://hackage.haskell.org/package/vinyl/docs/Data-Vinyl-Derived.html#t:FieldType"&gt;instance&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Note that this is sometimes done using straight &lt;a
href="https://en.wikipedia.org/wiki/De_Bruijn_index"&gt;De Bruijn indices&lt;/a&gt;:
&lt;code&gt;Expr :: [Ty] -&amp;gt; Type&lt;/code&gt;, so we don’t use any names but just the
direct index, but the point of this exercise is to be &lt;em&gt;borderline&lt;/em&gt;
unbearable to write, and &lt;em&gt;not&lt;/em&gt; to be &lt;em&gt;actually&lt;/em&gt; unbearable to
write.&lt;/p&gt;
&lt;h3 id="eval-with-a-typed-environment"&gt;Eval with a typed environment&lt;/h3&gt;
&lt;p&gt;To actually write &lt;em&gt;eval&lt;/em&gt; now, we need to have a type-safe environment
to store these variables. In order to &lt;code&gt;eval&lt;/code&gt; an &lt;code&gt;Expr vs&lt;/code&gt;,
we need &lt;code&gt;EValue&lt;/code&gt;s for each &lt;code&gt;v&lt;/code&gt; in &lt;code&gt;vs&lt;/code&gt;. So for
&lt;code&gt;Expr ["x" ::: TInt, "y" ::: TBool]&lt;/code&gt;, we need to store a
&lt;code&gt;TInt&lt;/code&gt; and a &lt;code&gt;TBool&lt;/code&gt;. We can once again re-purpose
&lt;code&gt;Rec&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb70"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb70-1"&gt;&lt;a href="#cb70-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage4.hs#L130-L131&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb70-2"&gt;&lt;a href="#cb70-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb70-3"&gt;&lt;a href="#cb70-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;EValueField&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; (&lt;span class="dt"&gt;Symbol&lt;/span&gt;, &lt;span class="dt"&gt;Ty&lt;/span&gt;) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb70-4"&gt;&lt;a href="#cb70-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVField&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EValueField&lt;/span&gt; &amp;#39;(l, a)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb71"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb71-1"&gt;&lt;a href="#cb71-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;:&lt;/span&gt;t (&lt;span class="dt"&gt;EVField&lt;/span&gt; (&lt;span class="dt"&gt;EVInt&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;) &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; &lt;span class="dt"&gt;EVField&lt;/span&gt; (&lt;span class="dt"&gt;EVBool&lt;/span&gt; &lt;span class="dt"&gt;True&lt;/span&gt;) &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; &lt;span class="dt"&gt;RNil&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; &lt;span class="dt"&gt;EValueField&lt;/span&gt; [&lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;, &lt;span class="st"&gt;&amp;quot;y&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TBool&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb71-2"&gt;&lt;a href="#cb71-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Rec&lt;/span&gt; &lt;span class="dt"&gt;EValueField&lt;/span&gt; [&lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;, &lt;span class="st"&gt;&amp;quot;y&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; &lt;span class="dt"&gt;TBool&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And so we can finally write:&lt;/p&gt;
&lt;div class="sourceCode" id="cb72"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb72-1"&gt;&lt;a href="#cb72-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage4.hs#L122-L271&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb72-2"&gt;&lt;a href="#cb72-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb72-3"&gt;&lt;a href="#cb72-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Ty&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb72-4"&gt;&lt;a href="#cb72-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVInt&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb72-5"&gt;&lt;a href="#cb72-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVBool&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt; &lt;span class="dt"&gt;TBool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb72-6"&gt;&lt;a href="#cb72-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVString&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt; &lt;span class="dt"&gt;TString&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb72-7"&gt;&lt;a href="#cb72-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVRecord&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; &lt;span class="dt"&gt;EValueField&lt;/span&gt; as &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt; (&lt;span class="dt"&gt;TRecord&lt;/span&gt; as)&lt;/span&gt;
&lt;span id="cb72-8"&gt;&lt;a href="#cb72-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVSum&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Index&lt;/span&gt; as (l &lt;span class="op"&gt;:::&lt;/span&gt; a) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt; (&lt;span class="dt"&gt;TSum&lt;/span&gt; as)&lt;/span&gt;
&lt;span id="cb72-9"&gt;&lt;a href="#cb72-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVFun&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; (&lt;span class="dt"&gt;EValue&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt; b) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt; (a &lt;span class="op"&gt;:-&amp;gt;&lt;/span&gt; b)&lt;/span&gt;
&lt;span id="cb72-10"&gt;&lt;a href="#cb72-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb72-11"&gt;&lt;a href="#cb72-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;eval ::&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; &lt;span class="dt"&gt;EValueField&lt;/span&gt; vs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs t &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EValue&lt;/span&gt; t&lt;/span&gt;
&lt;span id="cb72-12"&gt;&lt;a href="#cb72-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;eval env &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb72-13"&gt;&lt;a href="#cb72-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; n) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EVInt&lt;/span&gt; n&lt;/span&gt;
&lt;span id="cb72-14"&gt;&lt;a href="#cb72-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PBool&lt;/span&gt; b) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EVBool&lt;/span&gt; b&lt;/span&gt;
&lt;span id="cb72-15"&gt;&lt;a href="#cb72-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PString&lt;/span&gt; s) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EVString&lt;/span&gt; s&lt;/span&gt;
&lt;span id="cb72-16"&gt;&lt;a href="#cb72-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVar&lt;/span&gt; i &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;case&lt;/span&gt; indexRec i env &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb72-17"&gt;&lt;a href="#cb72-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;EVField&lt;/span&gt; v &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; v&lt;/span&gt;
&lt;span id="cb72-18"&gt;&lt;a href="#cb72-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ELambda&lt;/span&gt; body &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb72-19"&gt;&lt;a href="#cb72-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;EVFun&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; \x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; eval (&lt;span class="dt"&gt;EVField&lt;/span&gt; x &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; env) body&lt;/span&gt;
&lt;span id="cb72-20"&gt;&lt;a href="#cb72-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EApply&lt;/span&gt; f x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;case&lt;/span&gt; eval env f &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb72-21"&gt;&lt;a href="#cb72-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;EVFun&lt;/span&gt; g &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; g (eval env x)&lt;/span&gt;
&lt;span id="cb72-22"&gt;&lt;a href="#cb72-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EOp&lt;/span&gt; o x y &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;case&lt;/span&gt; (o, eval env x, eval env y) &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb72-23"&gt;&lt;a href="#cb72-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    (&lt;span class="dt"&gt;OPlus&lt;/span&gt;, &lt;span class="dt"&gt;EVInt&lt;/span&gt; a, &lt;span class="dt"&gt;EVInt&lt;/span&gt; b) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EVInt&lt;/span&gt; (a &lt;span class="op"&gt;+&lt;/span&gt; b)&lt;/span&gt;
&lt;span id="cb72-24"&gt;&lt;a href="#cb72-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    (&lt;span class="dt"&gt;OTimes&lt;/span&gt;, &lt;span class="dt"&gt;EVInt&lt;/span&gt; a, &lt;span class="dt"&gt;EVInt&lt;/span&gt; b) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EVInt&lt;/span&gt; (a &lt;span class="op"&gt;*&lt;/span&gt; b)&lt;/span&gt;
&lt;span id="cb72-25"&gt;&lt;a href="#cb72-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    (&lt;span class="dt"&gt;OLte&lt;/span&gt;, &lt;span class="dt"&gt;EVInt&lt;/span&gt; a, &lt;span class="dt"&gt;EVInt&lt;/span&gt; b) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EVBool&lt;/span&gt; (a &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; b)&lt;/span&gt;
&lt;span id="cb72-26"&gt;&lt;a href="#cb72-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    (&lt;span class="dt"&gt;OAnd&lt;/span&gt;, &lt;span class="dt"&gt;EVBool&lt;/span&gt; a, &lt;span class="dt"&gt;EVBool&lt;/span&gt; b) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EVBool&lt;/span&gt; (a &lt;span class="op"&gt;&amp;amp;&amp;amp;&lt;/span&gt; b)&lt;/span&gt;
&lt;span id="cb72-27"&gt;&lt;a href="#cb72-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ERecord&lt;/span&gt; xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb72-28"&gt;&lt;a href="#cb72-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;EVRecord&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; mapRec (\(&lt;span class="dt"&gt;EField&lt;/span&gt; x) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EVField&lt;/span&gt; (eval env x)) xs&lt;/span&gt;
&lt;span id="cb72-29"&gt;&lt;a href="#cb72-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EAccess&lt;/span&gt; e i &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;case&lt;/span&gt; eval env e &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb72-30"&gt;&lt;a href="#cb72-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;EVRecord&lt;/span&gt; xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;case&lt;/span&gt; indexRec i xs &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb72-31"&gt;&lt;a href="#cb72-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EVField&lt;/span&gt; v &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; v&lt;/span&gt;
&lt;span id="cb72-32"&gt;&lt;a href="#cb72-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EChoice&lt;/span&gt; i x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;EVSum&lt;/span&gt; i (eval env x)&lt;/span&gt;
&lt;span id="cb72-33"&gt;&lt;a href="#cb72-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ECase&lt;/span&gt; x hs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;case&lt;/span&gt; eval env x &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb72-34"&gt;&lt;a href="#cb72-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;EVSum&lt;/span&gt; i y &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;case&lt;/span&gt; indexRec i hs &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb72-35"&gt;&lt;a href="#cb72-35" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EHandler&lt;/span&gt; h &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; eval (&lt;span class="dt"&gt;EVField&lt;/span&gt; y &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; env) h&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;At least, we are here. A type-safe EDSL where only AST’s that can be validly
evaluated are legal to represent in Haskell. At least, we can embrace the
freedom of not having to carefully construct your terms. You can relax now. The
compiler and the types have your back.&lt;/p&gt;
&lt;p&gt;Even
&lt;code&gt;EVFun :: (EValue a -&amp;gt; EValue b) -&amp;gt; EValue (a :-&amp;gt; b)&lt;/code&gt; has a
total &lt;code&gt;EValue a -&amp;gt; EValue b&lt;/code&gt;, making the closure evaluation also
fully total.&lt;/p&gt;
&lt;div class="sourceCode" id="cb73"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb73-1"&gt;&lt;a href="#cb73-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage4.hs#L145-L147&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb73-2"&gt;&lt;a href="#cb73-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb73-3"&gt;&lt;a href="#cb73-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;plusThree ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &amp;#39;[] (&lt;span class="dt"&gt;TInt&lt;/span&gt; &lt;span class="op"&gt;:-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;TInt&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb73-4"&gt;&lt;a href="#cb73-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plusThree &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb73-5"&gt;&lt;a href="#cb73-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  eLambda &lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;EOp&lt;/span&gt; &lt;span class="dt"&gt;OPlus&lt;/span&gt; (eVar &lt;span class="st"&gt;&amp;quot;x&amp;quot;&lt;/span&gt;) (&lt;span class="dt"&gt;EPrim&lt;/span&gt; (&lt;span class="dt"&gt;PInt&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;)))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb74"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb74-1"&gt;&lt;a href="#cb74-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;case&lt;/span&gt; eval &lt;span class="dt"&gt;RNil&lt;/span&gt; plusThree &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb74-2"&gt;&lt;a href="#cb74-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;EVFun&lt;/span&gt; f &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;case&lt;/span&gt; f (&lt;span class="dt"&gt;EVInt&lt;/span&gt; &lt;span class="dv"&gt;4&lt;/span&gt;) &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb74-3"&gt;&lt;a href="#cb74-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;EVInt&lt;/span&gt; x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;print&lt;/span&gt; x&lt;/span&gt;
&lt;span id="cb74-4"&gt;&lt;a href="#cb74-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dv"&gt;7&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="pretty-printing-scoped-expressions"&gt;Pretty-Printing Scoped
Expressions&lt;/h3&gt;
&lt;p&gt;Now to get to the entire utility of this abstraction: inspecting and
consuming the structure. For our new structure, we took out the string name from
&lt;code&gt;EVar&lt;/code&gt; in lieu of an index. This is intentional, so that we keep the
“responsibility” of storing the string name at the &lt;code&gt;ELambda&lt;/code&gt;
constructor and not have &lt;code&gt;EVar&lt;/code&gt; redundantly store it.&lt;/p&gt;
&lt;p&gt;However, this means that for pretty-printing, we will need to track the
variable names in the environment as we descend into lambdas. This is done very
similar to how it was done in &lt;code&gt;eval&lt;/code&gt;, but instead of tracking and
indexing out the evaluated &lt;code&gt;EValue&lt;/code&gt;s, we track and index out the
string names of each variable instead.&lt;/p&gt;
&lt;div class="sourceCode" id="cb75"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb75-1"&gt;&lt;a href="#cb75-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage4.hs#L182-L183&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb75-2"&gt;&lt;a href="#cb75-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb75-3"&gt;&lt;a href="#cb75-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;NameField&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; (&lt;span class="dt"&gt;Symbol&lt;/span&gt;, &lt;span class="dt"&gt;Ty&lt;/span&gt;) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb75-4"&gt;&lt;a href="#cb75-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;NameField&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;KnownSymbol&lt;/span&gt; l &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;NameField&lt;/span&gt; (l &lt;span class="op"&gt;:::&lt;/span&gt; a)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb76"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb76-1"&gt;&lt;a href="#cb76-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;:&lt;/span&gt;t &lt;span class="dt"&gt;NameField&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;&lt;span class="st"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; &lt;span class="dt"&gt;NameField&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;&lt;span class="st"&gt;&amp;quot;world&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; &lt;span class="dt"&gt;RNil&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb76-2"&gt;&lt;a href="#cb76-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Rec&lt;/span&gt; &lt;span class="dt"&gt;NameField&lt;/span&gt; [&lt;span class="st"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; a, &lt;span class="st"&gt;&amp;quot;world&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;:::&lt;/span&gt; b]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb77"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb77-1"&gt;&lt;a href="#cb77-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- source: https://github.com/mstksg/inCode/tree/master/code-samples/typed-sm-lc/ExprStage4.hs#L185-L245&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-2"&gt;&lt;a href="#cb77-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb77-3"&gt;&lt;a href="#cb77-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;ppPrim ::&lt;/span&gt; &lt;span class="dt"&gt;Prim&lt;/span&gt; t &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;PP.Doc&lt;/span&gt; ann&lt;/span&gt;
&lt;span id="cb77-4"&gt;&lt;a href="#cb77-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ppPrim &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-5"&gt;&lt;a href="#cb77-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;PInt&lt;/span&gt; n &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; PP.pretty n&lt;/span&gt;
&lt;span id="cb77-6"&gt;&lt;a href="#cb77-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;PBool&lt;/span&gt; b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;if&lt;/span&gt; b &lt;span class="kw"&gt;then&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span class="kw"&gt;else&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;false&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-7"&gt;&lt;a href="#cb77-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;PString&lt;/span&gt; s &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; PP.pretty (&lt;span class="fu"&gt;show&lt;/span&gt; s)&lt;/span&gt;
&lt;span id="cb77-8"&gt;&lt;a href="#cb77-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb77-9"&gt;&lt;a href="#cb77-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;ppOp ::&lt;/span&gt; &lt;span class="dt"&gt;Op&lt;/span&gt; a b c &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;PP.Doc&lt;/span&gt; ann&lt;/span&gt;
&lt;span id="cb77-10"&gt;&lt;a href="#cb77-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ppOp &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-11"&gt;&lt;a href="#cb77-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;OPlus&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;+&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-12"&gt;&lt;a href="#cb77-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;OTimes&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;*&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-13"&gt;&lt;a href="#cb77-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;OLte&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;&amp;lt;=&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-14"&gt;&lt;a href="#cb77-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;OAnd&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;&amp;amp;&amp;amp;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-15"&gt;&lt;a href="#cb77-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb77-16"&gt;&lt;a href="#cb77-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;ppFields ::&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; &lt;span class="dt"&gt;NameField&lt;/span&gt; vs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; (&lt;span class="dt"&gt;ExprField&lt;/span&gt; vs) xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; [&lt;span class="dt"&gt;PP.Doc&lt;/span&gt; ann]&lt;/span&gt;
&lt;span id="cb77-17"&gt;&lt;a href="#cb77-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ppFields _ &lt;span class="dt"&gt;RNil&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; []&lt;/span&gt;
&lt;span id="cb77-18"&gt;&lt;a href="#cb77-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ppFields names (&lt;span class="dt"&gt;EField&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l x &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; xs) &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-19"&gt;&lt;a href="#cb77-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  (PP.pretty (symbolVal (&lt;span class="dt"&gt;Proxy&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l)) &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;=&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr names &lt;span class="dt"&gt;False&lt;/span&gt; x) &lt;span class="op"&gt;:&lt;/span&gt; ppFields names xs&lt;/span&gt;
&lt;span id="cb77-20"&gt;&lt;a href="#cb77-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb77-21"&gt;&lt;a href="#cb77-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;ppHandlers ::&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; &lt;span class="dt"&gt;NameField&lt;/span&gt; vs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; (&lt;span class="dt"&gt;ExprHandler&lt;/span&gt; vs b) xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; [&lt;span class="dt"&gt;PP.Doc&lt;/span&gt; ann]&lt;/span&gt;
&lt;span id="cb77-22"&gt;&lt;a href="#cb77-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ppHandlers _ &lt;span class="dt"&gt;RNil&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; []&lt;/span&gt;
&lt;span id="cb77-23"&gt;&lt;a href="#cb77-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ppHandlers names (&lt;span class="dt"&gt;EHandler&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;n &lt;span class="op"&gt;@&lt;/span&gt;l body &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; xs) &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-24"&gt;&lt;a href="#cb77-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  ( PP.pretty (symbolVal (&lt;span class="dt"&gt;Proxy&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l))&lt;/span&gt;
&lt;span id="cb77-25"&gt;&lt;a href="#cb77-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; PP.pretty (symbolVal (&lt;span class="dt"&gt;Proxy&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;n))&lt;/span&gt;
&lt;span id="cb77-26"&gt;&lt;a href="#cb77-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;-&amp;gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-27"&gt;&lt;a href="#cb77-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr (&lt;span class="dt"&gt;NameField&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;n &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; names) &lt;span class="dt"&gt;False&lt;/span&gt; body&lt;/span&gt;
&lt;span id="cb77-28"&gt;&lt;a href="#cb77-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  )&lt;/span&gt;
&lt;span id="cb77-29"&gt;&lt;a href="#cb77-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;:&lt;/span&gt; ppHandlers names xs&lt;/span&gt;
&lt;span id="cb77-30"&gt;&lt;a href="#cb77-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb77-31"&gt;&lt;a href="#cb77-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;ppExpr ::&lt;/span&gt; &lt;span class="dt"&gt;Rec&lt;/span&gt; &lt;span class="dt"&gt;NameField&lt;/span&gt; vs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; vs t &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;PP.Doc&lt;/span&gt; ann&lt;/span&gt;
&lt;span id="cb77-32"&gt;&lt;a href="#cb77-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ppExpr names paren &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-33"&gt;&lt;a href="#cb77-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EPrim&lt;/span&gt; p &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; ppPrim p&lt;/span&gt;
&lt;span id="cb77-34"&gt;&lt;a href="#cb77-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EVar&lt;/span&gt; i &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;case&lt;/span&gt; indexRec i names &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-35"&gt;&lt;a href="#cb77-35" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;NameField&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;n &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; PP.pretty (symbolVal (&lt;span class="dt"&gt;Proxy&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;n))&lt;/span&gt;
&lt;span id="cb77-36"&gt;&lt;a href="#cb77-36" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ELambda&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;n body &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-37"&gt;&lt;a href="#cb77-37" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    wrap &lt;span class="op"&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-38"&gt;&lt;a href="#cb77-38" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="st"&gt;&amp;quot;\\&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; PP.pretty (symbolVal (&lt;span class="dt"&gt;Proxy&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;n))&lt;/span&gt;
&lt;span id="cb77-39"&gt;&lt;a href="#cb77-39" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;-&amp;gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-40"&gt;&lt;a href="#cb77-40" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr (&lt;span class="dt"&gt;NameField&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;n &lt;span class="op"&gt;:&amp;amp;&lt;/span&gt; names) &lt;span class="dt"&gt;False&lt;/span&gt; body&lt;/span&gt;
&lt;span id="cb77-41"&gt;&lt;a href="#cb77-41" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EApply&lt;/span&gt; f x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-42"&gt;&lt;a href="#cb77-42" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    wrap &lt;span class="op"&gt;$&lt;/span&gt; ppExpr names &lt;span class="dt"&gt;True&lt;/span&gt; f &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr names &lt;span class="dt"&gt;True&lt;/span&gt; x&lt;/span&gt;
&lt;span id="cb77-43"&gt;&lt;a href="#cb77-43" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EOp&lt;/span&gt; o x y &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-44"&gt;&lt;a href="#cb77-44" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    wrap &lt;span class="op"&gt;$&lt;/span&gt; ppExpr names &lt;span class="dt"&gt;True&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppOp o &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr names &lt;span class="dt"&gt;True&lt;/span&gt; y&lt;/span&gt;
&lt;span id="cb77-45"&gt;&lt;a href="#cb77-45" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ERecord&lt;/span&gt; xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-46"&gt;&lt;a href="#cb77-46" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    PP.encloseSep &lt;span class="st"&gt;&amp;quot;{ &amp;quot;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot; }&amp;quot;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;, &amp;quot;&lt;/span&gt; (ppFields names xs)&lt;/span&gt;
&lt;span id="cb77-47"&gt;&lt;a href="#cb77-47" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EAccess&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l e _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-48"&gt;&lt;a href="#cb77-48" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ppExpr names &lt;span class="dt"&gt;True&lt;/span&gt; e &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;.&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; PP.pretty (symbolVal (&lt;span class="dt"&gt;Proxy&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l))&lt;/span&gt;
&lt;span id="cb77-49"&gt;&lt;a href="#cb77-49" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;EChoice&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l _ x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-50"&gt;&lt;a href="#cb77-50" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    wrap &lt;span class="op"&gt;$&lt;/span&gt; PP.pretty (symbolVal (&lt;span class="dt"&gt;Proxy&lt;/span&gt; &lt;span class="op"&gt;@&lt;/span&gt;l)) &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr names &lt;span class="dt"&gt;True&lt;/span&gt; x&lt;/span&gt;
&lt;span id="cb77-51"&gt;&lt;a href="#cb77-51" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;ECase&lt;/span&gt; x hs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-52"&gt;&lt;a href="#cb77-52" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    wrap &lt;span class="op"&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-53"&gt;&lt;a href="#cb77-53" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      PP.sep&lt;/span&gt;
&lt;span id="cb77-54"&gt;&lt;a href="#cb77-54" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        [ &lt;span class="st"&gt;&amp;quot;case&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; ppExpr names &lt;span class="dt"&gt;False&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;of&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-55"&gt;&lt;a href="#cb77-55" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        , PP.encloseSep &lt;span class="st"&gt;&amp;quot;{ &amp;quot;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot; }&amp;quot;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;; &amp;quot;&lt;/span&gt; (ppHandlers names hs)&lt;/span&gt;
&lt;span id="cb77-56"&gt;&lt;a href="#cb77-56" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ]&lt;/span&gt;
&lt;span id="cb77-57"&gt;&lt;a href="#cb77-57" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-58"&gt;&lt;a href="#cb77-58" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    wrap&lt;/span&gt;
&lt;span id="cb77-59"&gt;&lt;a href="#cb77-59" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="op"&gt;|&lt;/span&gt; paren &lt;span class="ot"&gt;=&lt;/span&gt; PP.parens&lt;/span&gt;
&lt;span id="cb77-60"&gt;&lt;a href="#cb77-60" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="fu"&gt;otherwise&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb77-61"&gt;&lt;a href="#cb77-61" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb77-62"&gt;&lt;a href="#cb77-62" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;prettyExpr ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &amp;#39;[] t &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;PP.Doc&lt;/span&gt; ann&lt;/span&gt;
&lt;span id="cb77-63"&gt;&lt;a href="#cb77-63" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;prettyExpr &lt;span class="ot"&gt;=&lt;/span&gt; ppExpr &lt;span class="dt"&gt;RNil&lt;/span&gt; &lt;span class="dt"&gt;False&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb78"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb78-1"&gt;&lt;a href="#cb78-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; prettyExpr fifteen&lt;/span&gt;
&lt;span id="cb78-2"&gt;&lt;a href="#cb78-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(\x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; x &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;) &lt;span class="dv"&gt;5&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="the-next-step"&gt;The Next Step&lt;/h2&gt;
&lt;p&gt;Well, we set out with a simple goal: an expression language that lives within
Haskell that we can inspect and interrogate within the language, but where it
was impossible to construct (in Haskell) a term that did not type-check (in the
domain language).&lt;/p&gt;
&lt;p&gt;But, honestly, why does it matter that our expression language has to reject
invalid domain-level terms at the Haskell level? Why couldn’t we go the way of
other expression DSLs in Haskell, where we settle with “untyped” terms being
expressible in Haskell, and validated using a separate &lt;code&gt;typeCheck&lt;/code&gt;
function to validate terms at runtime?&lt;/p&gt;
&lt;p&gt;I don’t know. But really, maybe this is another way of taking the old &lt;a
href="https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/"&gt;Parse,
Don’t Validate&lt;/a&gt; adage to the extreme. Why allow yourself to construct invalid
terms of your domain inside Haskell? Why use a “validate” function
(&lt;code&gt;isValid&lt;/code&gt;) when you can just make invalid terms impossible to
construct?&lt;/p&gt;
&lt;p&gt;But…no. There is no other choice. We CANNOT allow invalid domain terms to be
constructible. If we have the ability to do better, we MUST. With great power
comes great responsibility. And if we compromise here, how can we trust
ourselves not to compromise when it really matters?&lt;/p&gt;
&lt;p&gt;One must imagine the stubborn typer happy.&lt;/p&gt;
&lt;p&gt;In Part 2, we’ll use our new EDSL to specify visualizable state machines and
programs within Haskell that are type-checked to be correct, and what it looks
like to actually &lt;em&gt;use&lt;/em&gt; these within Haskell. And in Part 3, we’ll start
“compiling” them to different language targets and different backends, with the
assurance that our generated programs are all synchronized and
self-consistent.&lt;/p&gt;
&lt;h3 id="a-note-on-ai-coding"&gt;A Note on AI Coding&lt;/h3&gt;
&lt;p&gt;I guess I’m going to have to start mentioning this in every post.
&lt;em&gt;But&lt;/em&gt;, I really do feel like this “extreme type safety” approach is more
critical than ever, in the age of agentic coding and LLM. I’ve been using LLMs
in my daily coding for many months now at this point, and one common pattern
I’ve noticed: when I start with a design with very clear, very strict types,
LLMs excel. They make much fewer errors, and the type system provides more
immediate feedback on their progress, without needing hundreds of defensive
&lt;code&gt;x != null&lt;/code&gt;-style guard pollution.&lt;/p&gt;
&lt;p&gt;Once I can express what I want in the language of extreme “invalid states
unrepresentable” types, LLM agents no longer feel like agents of chaotic
spaghetti extruding unmaintainable code. Instead, it feels like…seeding a
crystal and watching it grow into a beautiful, shimmering lattice. It feels like
the language they yearn to speak. And the more expressive your types, the more
beautiful the crystalline structure in the end.&lt;/p&gt;
&lt;p&gt;Honestly, humans might have problems writing and using this code, but LLMs
definitely don’t, if properly scaffolded! Since early 2026, at least, for me.
We’ll explore a bit more about this once we have more to work with in Part
2.&lt;/p&gt;
&lt;h2 id="special-thanks"&gt;Special Thanks&lt;/h2&gt;
&lt;p&gt;I am very humbled to be supported by an amazing community, who make it
possible for me to devote time to researching and writing these posts. Very
special thanks to my supporter at the “Amazing” level on &lt;a
href="https://www.patreon.com/justinle/overview"&gt;patreon&lt;/a&gt;, Josh Vera! :)&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;Excluding &lt;code&gt;_|_&lt;/code&gt; in Haskell-land (recursion or
&lt;code&gt;undefined&lt;/code&gt;), unfortunately.&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>Justin Le</author><category>Haskell</category><guid isPermaLink="true">https://blog.jle.im/entry/extreme-haskell-typed-expression-edsls-1.html</guid><pubDate>Tue,  7 Jul 2026 17:11:34 UTC</pubDate><creator>Justin Le</creator><subject>Haskell</subject><date>2026-07-07</date></item><item><title>"Five-Point Haskell": Total Depravity (and Defensive Typing)</title><link>https://blog.jle.im/entry/five-point-haskell-part-1-total-depravity.html</link><description>&lt;p&gt;I have thought about distilling the principles by which I program Haskell,
and how I’ve been able to steer long-lived projects over years of growth,
refactorings, and changes in demands. I find myself coming back to a few
distinct and helpful “points” (“doctrines”, if you may allow me to say) that
have yet to lead me astray.&lt;/p&gt;
&lt;p&gt;With a new age of software development coming, what does it even mean to
write good, robust, correct code? It is long overdue to clarify the mindset we
use to define “good” coding principles.&lt;/p&gt;
&lt;p&gt;In this series, &lt;em&gt;&lt;a
href="https://blog.jle.im/entries/series/+five-point-haskell.html"&gt;Five-Point
Haskell&lt;/a&gt;&lt;/em&gt;, I’ll set out to establish a five-point framework for typed
functional programming (and Haskell-derived) design that aims to produce code
that is maintainable, correct, long-lasting, extensible, and beautiful to write
and work with. We’ll reference real-world case studies with actual examples when
we can, and also attempt to dispel thought-leader sound bites that have become
all too popular on Twitter (“heresies”, so to speak).&lt;/p&gt;
&lt;p&gt;Let’s jump right into point 1: the doctrine of &lt;strong&gt;Total
Depravity&lt;/strong&gt;, and why Haskell is perfectly primed to make living with it
as frictionless as possible.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Total Depravity: If your code’s correctness depends on keeping complicated
interconnected structure in your head, a devastating incident is not a matter of
&lt;em&gt;if&lt;/em&gt; but &lt;em&gt;when&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Therefore, delegate these concerns to tooling and a sufficiently powerful
compiler, use types to guard against errors, and free yourself to only mentally
track the actual important things.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="mix-ups-are-inevitable"&gt;Mix-ups Are Inevitable&lt;/h2&gt;
&lt;p&gt;Think about the stereotype of a “brilliant programmer” that an inexperienced
programmer has in their mind — someone who can hold every detail of a complex
system in their head, every intricate connection and relationship between each
component. There’s the classic &lt;a
href="https://www.monkeyuser.com/2018/focus/"&gt;Monkey User Comic&lt;/a&gt; that
valorizes this ideal.&lt;/p&gt;
&lt;figure&gt;
&lt;img src="/img/entries/five-point-haskell/79-focus.png"
title="Monkey User --- Focus" style="width:50%;height:auto;"
alt="Monkey User — Focus" /&gt;
&lt;figcaption aria-hidden="true"&gt;Monkey User — Focus&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The 10x developer is one who can carry the state and interconnectedness of an
entire system in their brain, and the bigger the state they can carry, the more
10x they are.&lt;/p&gt;
&lt;p&gt;This is the myth of the hero programmer. Did you have a bug? Well, you just
need to upgrade your mental awareness and your context window. You just need to
be better and better at keeping more in your mind.&lt;/p&gt;
&lt;p&gt;Actually &lt;em&gt;addressing&lt;/em&gt; these issues in most languages requires a lot of
overhead and clunkiness. But luckily we’re in Haskell.&lt;/p&gt;
&lt;h3 id="explicit-tags"&gt;Explicit Tags&lt;/h3&gt;
&lt;p&gt;The &lt;a
href="https://www.atlassian.com/blog/atlassian-engineering/post-incident-review-april-2022-outage"&gt;2022
Atlassian Outage&lt;/a&gt;, in part, was the result of passing the wrong type of ID.
The operators were intended to pass &lt;em&gt;App&lt;/em&gt; IDs, but instead passed
&lt;em&gt;Site&lt;/em&gt; IDs, and the errors cascaded from there. It goes without saying
that if you have a bunch of “naked” IDs, then mixing them up is eventually going
to backfire on you.&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;newtype&lt;/span&gt; &lt;span class="dt"&gt;Id&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Id&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-2"&gt;&lt;a href="#cb1-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb1-3"&gt;&lt;a href="#cb1-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;SiteId&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Id&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-4"&gt;&lt;a href="#cb1-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;AppId&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Id&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-5"&gt;&lt;a href="#cb1-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb1-6"&gt;&lt;a href="#cb1-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;getApps ::&lt;/span&gt; &lt;span class="dt"&gt;SiteId&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; [&lt;span class="dt"&gt;AppId&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb1-7"&gt;&lt;a href="#cb1-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;deleteSite ::&lt;/span&gt; &lt;span class="dt"&gt;SiteId&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb1-8"&gt;&lt;a href="#cb1-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;deleteApp ::&lt;/span&gt; &lt;span class="dt"&gt;AppId&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is convenient because you get functions for all IDs without any extra
work. Let’s say you want to serialize/print or deserialize/read these IDs — it
can be helpful to give them all the same type so that you can write this logic
in one place.&lt;/p&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb2-1"&gt;&lt;a href="#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;ToJSON&lt;/span&gt; &lt;span class="dt"&gt;Id&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  toJSON (&lt;span class="dt"&gt;Id&lt;/span&gt; x) &lt;span class="ot"&gt;=&lt;/span&gt; object [ &lt;span class="st"&gt;&amp;quot;id&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;.=&lt;/span&gt; x ]&lt;/span&gt;
&lt;span id="cb2-3"&gt;&lt;a href="#cb2-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb2-4"&gt;&lt;a href="#cb2-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;FromJSON&lt;/span&gt; &lt;span class="dt"&gt;Id&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-5"&gt;&lt;a href="#cb2-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  parseJSON &lt;span class="ot"&gt;=&lt;/span&gt; withObject &lt;span class="st"&gt;&amp;quot;Id&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; \v &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-6"&gt;&lt;a href="#cb2-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;Id&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; (v &lt;span class="op"&gt;.:&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Convenient and effective, as long as you never accidentally use a
&lt;code&gt;SiteId&lt;/code&gt; as an &lt;code&gt;AppId&lt;/code&gt; or vice versa. And this is a very
easy delusion to fall into, if you don’t believe in total depravity. However,
sooner or later (maybe in a week, maybe in a year, maybe after you onboard that
new team member)…someone is going to accidentally pass a site ID where an app ID
is expected.&lt;/p&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb3-1"&gt;&lt;a href="#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;main ::&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;main &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a href="#cb3-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;let&lt;/span&gt; targetSites &lt;span class="ot"&gt;=&lt;/span&gt; [&lt;span class="dt"&gt;Id&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;abc&amp;quot;&lt;/span&gt;, &lt;span class="dt"&gt;Id&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;def&amp;quot;&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb3-4"&gt;&lt;a href="#cb3-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="fu"&gt;mapM_&lt;/span&gt; deleteApp targetSites&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And at that point it’s all over.&lt;/p&gt;
&lt;p&gt;Knowing this can happen, we can add a simple newtype wrapper so that
accidentally using the wrong ID is a compile error:&lt;/p&gt;
&lt;div class="sourceCode" id="cb4"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb4-1"&gt;&lt;a href="#cb4-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;newtype&lt;/span&gt; &lt;span class="dt"&gt;SiteId&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;SiteId&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-2"&gt;&lt;a href="#cb4-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;newtype&lt;/span&gt; &lt;span class="dt"&gt;AppId&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;AppId&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now such a mis-call will never compile! Congratulations!&lt;/p&gt;
&lt;p&gt;We do have a downside now: we can no longer write code polymorphic over IDs
when we want to. In the untagged situation, we could &lt;em&gt;only&lt;/em&gt; write
polymorphic code, and in the new situation we can &lt;em&gt;only&lt;/em&gt; write code for
one ID type.&lt;/p&gt;
&lt;div class="sourceCode" id="cb5"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb5-1"&gt;&lt;a href="#cb5-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;FromJSON&lt;/span&gt; &lt;span class="dt"&gt;SiteId&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-2"&gt;&lt;a href="#cb5-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  parseJSON &lt;span class="ot"&gt;=&lt;/span&gt; withObject &lt;span class="st"&gt;&amp;quot;Id&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; \v &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-3"&gt;&lt;a href="#cb5-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    tag &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; v &lt;span class="op"&gt;.:&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-4"&gt;&lt;a href="#cb5-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    unless (tag &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Site&amp;quot;&lt;/span&gt;) &lt;span class="op"&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-5"&gt;&lt;a href="#cb5-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="fu"&gt;fail&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Parsed wrong type of ID!&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-6"&gt;&lt;a href="#cb5-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;SiteId&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; (v &lt;span class="op"&gt;.:&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb5-7"&gt;&lt;a href="#cb5-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb5-8"&gt;&lt;a href="#cb5-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;ToJSON&lt;/span&gt; &lt;span class="dt"&gt;SiteId&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-9"&gt;&lt;a href="#cb5-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  toJSON (&lt;span class="dt"&gt;SiteId&lt;/span&gt; x) &lt;span class="ot"&gt;=&lt;/span&gt; object [ &lt;span class="st"&gt;&amp;quot;type&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;.=&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Site&amp;quot;&lt;/span&gt;, &lt;span class="st"&gt;&amp;quot;id&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;.=&lt;/span&gt; x ]&lt;/span&gt;
&lt;span id="cb5-10"&gt;&lt;a href="#cb5-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb5-11"&gt;&lt;a href="#cb5-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;FromJSON&lt;/span&gt; &lt;span class="dt"&gt;AppId&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-12"&gt;&lt;a href="#cb5-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  parseJSON &lt;span class="ot"&gt;=&lt;/span&gt; withObject &lt;span class="st"&gt;&amp;quot;Id&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; \v &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-13"&gt;&lt;a href="#cb5-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    tag &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; v &lt;span class="op"&gt;.:&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-14"&gt;&lt;a href="#cb5-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    unless (tag &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;App&amp;quot;&lt;/span&gt;) &lt;span class="op"&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-15"&gt;&lt;a href="#cb5-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="fu"&gt;fail&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Parsed wrong type of ID!&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-16"&gt;&lt;a href="#cb5-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;AppId&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; (v &lt;span class="op"&gt;.:&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb5-17"&gt;&lt;a href="#cb5-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb5-18"&gt;&lt;a href="#cb5-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;ToJSON&lt;/span&gt; &lt;span class="dt"&gt;AppId&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-19"&gt;&lt;a href="#cb5-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  toJSON (&lt;span class="dt"&gt;AppId&lt;/span&gt; x) &lt;span class="ot"&gt;=&lt;/span&gt; object [ &lt;span class="st"&gt;&amp;quot;type&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;.=&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;App&amp;quot;&lt;/span&gt;, &lt;span class="st"&gt;&amp;quot;id&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;.=&lt;/span&gt; x ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;However, luckily, because we’re in Haskell, it’s easy to get the best of both
worlds with &lt;em&gt;phantom types&lt;/em&gt; (that don’t refer to anything inside the
actual data representation):&lt;/p&gt;
&lt;div class="sourceCode" id="cb6"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb6-1"&gt;&lt;a href="#cb6-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Id&lt;/span&gt; a &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Id&lt;/span&gt; {&lt;span class="ot"&gt; getId ::&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; }&lt;/span&gt;
&lt;span id="cb6-2"&gt;&lt;a href="#cb6-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb6-3"&gt;&lt;a href="#cb6-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Site&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-4"&gt;&lt;a href="#cb6-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;App&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-5"&gt;&lt;a href="#cb6-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb6-6"&gt;&lt;a href="#cb6-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;SiteId&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Id&lt;/span&gt; &lt;span class="dt"&gt;Site&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-7"&gt;&lt;a href="#cb6-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;AppId&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Id&lt;/span&gt; &lt;span class="dt"&gt;App&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-8"&gt;&lt;a href="#cb6-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb6-9"&gt;&lt;a href="#cb6-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- using Typeable for demonstration purposes&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-10"&gt;&lt;a href="#cb6-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;Typeable&lt;/span&gt; a &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;ToJSON&lt;/span&gt; (&lt;span class="dt"&gt;Id&lt;/span&gt; a) &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-11"&gt;&lt;a href="#cb6-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  toJSON (&lt;span class="dt"&gt;Id&lt;/span&gt; x) &lt;span class="ot"&gt;=&lt;/span&gt; object&lt;/span&gt;
&lt;span id="cb6-12"&gt;&lt;a href="#cb6-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    [ &lt;span class="st"&gt;&amp;quot;type&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;.=&lt;/span&gt; &lt;span class="fu"&gt;show&lt;/span&gt; (typeRep &lt;span class="op"&gt;@&lt;/span&gt;a)&lt;/span&gt;
&lt;span id="cb6-13"&gt;&lt;a href="#cb6-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    , &lt;span class="st"&gt;&amp;quot;id&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;.=&lt;/span&gt; x&lt;/span&gt;
&lt;span id="cb6-14"&gt;&lt;a href="#cb6-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ]&lt;/span&gt;
&lt;span id="cb6-15"&gt;&lt;a href="#cb6-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb6-16"&gt;&lt;a href="#cb6-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;Typeable&lt;/span&gt; a &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;FromJSON&lt;/span&gt; (&lt;span class="dt"&gt;Id&lt;/span&gt; a) &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-17"&gt;&lt;a href="#cb6-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  parseJSON &lt;span class="ot"&gt;=&lt;/span&gt; withObject &lt;span class="st"&gt;&amp;quot;Id&amp;quot;&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; \v &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-18"&gt;&lt;a href="#cb6-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    tag &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; v &lt;span class="op"&gt;.:&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-19"&gt;&lt;a href="#cb6-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    unless (tag &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="fu"&gt;show&lt;/span&gt; (typeRep &lt;span class="op"&gt;@&lt;/span&gt;a)) &lt;span class="op"&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-20"&gt;&lt;a href="#cb6-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="fu"&gt;fail&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Parsed wrong type of ID!&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-21"&gt;&lt;a href="#cb6-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;Id&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; (v &lt;span class="op"&gt;.:&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Type safety doesn’t necessarily mean inflexibility!&lt;/p&gt;
&lt;h3 id="phantom-powers"&gt;Phantom Powers&lt;/h3&gt;
&lt;p&gt;Phantom types give us a &lt;em&gt;lot&lt;/em&gt; of low-hanging fruit for preventing
inadvertent misuse.&lt;/p&gt;
&lt;p&gt;The &lt;a
href="https://www.theregister.com/2017/04/11/database_deletion_downed_digital_ocean_last_week/"&gt;2017
DigitalOcean outage&lt;/a&gt;, for example, was partially about the wrong environment
credentials being used.&lt;/p&gt;
&lt;p&gt;We could imagine a test harness that clears a test database using &lt;em&gt;&lt;a
href="https://hackage.haskell.org/package/postgresql-simple"&gt;postgresql-simple&lt;/a&gt;&lt;/em&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb7"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb7-1"&gt;&lt;a href="#cb7-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- | Warning: do NOT call this outside of test environment!&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-2"&gt;&lt;a href="#cb7-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;clearTestEnv ::&lt;/span&gt; &lt;span class="dt"&gt;Connection&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb7-3"&gt;&lt;a href="#cb7-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;clearTestEnv conn &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-4"&gt;&lt;a href="#cb7-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="fu"&gt;putStrLn&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Are you sure you read the warning on this function? Well, too late now!&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-5"&gt;&lt;a href="#cb7-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  _ &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; execute_ conn &lt;span class="st"&gt;&amp;quot;DROP TABLE IF EXISTS users CASCADE&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-6"&gt;&lt;a href="#cb7-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="fu"&gt;putStrLn&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Test data wiped.&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;However, somewhere down the line, someone is going to call
&lt;code&gt;clearTestEnv&lt;/code&gt; &lt;em&gt;deep&lt;/em&gt; inside a function inside a function
inside a function, which itself is called against the prod database. I guarantee
it.&lt;/p&gt;
&lt;p&gt;To ensure this never happens, we can use closed phantom types using
&lt;code&gt;DataKinds&lt;/code&gt; (made nicer with &lt;code&gt;TypeData&lt;/code&gt; post-GHC 9.6):&lt;/p&gt;
&lt;div class="sourceCode" id="cb8"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb8-1"&gt;&lt;a href="#cb8-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- type data = declare a closed kind and two type constructors at the type level using -XTypeData&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-2"&gt;&lt;a href="#cb8-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Env&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Prod&lt;/span&gt; &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;Test&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-3"&gt;&lt;a href="#cb8-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb8-4"&gt;&lt;a href="#cb8-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;newtype&lt;/span&gt; &lt;span class="dt"&gt;DbConnection&lt;/span&gt; (&lt;span class="ot"&gt;a ::&lt;/span&gt; &lt;span class="dt"&gt;Env&lt;/span&gt;) &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;DbConnection&lt;/span&gt; &lt;span class="dt"&gt;Connection&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-5"&gt;&lt;a href="#cb8-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb8-6"&gt;&lt;a href="#cb8-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;runQuery ::&lt;/span&gt; &lt;span class="dt"&gt;DbConnection&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Query&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; &lt;span class="dt"&gt;Int64&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-7"&gt;&lt;a href="#cb8-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;runQuery (&lt;span class="dt"&gt;DbConnection&lt;/span&gt; c) q &lt;span class="ot"&gt;=&lt;/span&gt; execute_ c q&lt;/span&gt;
&lt;span id="cb8-8"&gt;&lt;a href="#cb8-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb8-9"&gt;&lt;a href="#cb8-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- | Warning: Did you remember to charge your chromebook? Oh and this function&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-10"&gt;&lt;a href="#cb8-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- is safe by the way.&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-11"&gt;&lt;a href="#cb8-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;clearTestEnv ::&lt;/span&gt; &lt;span class="dt"&gt;DbConnection&lt;/span&gt; &lt;span class="dt"&gt;Test&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb8-12"&gt;&lt;a href="#cb8-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;clearTestEnv conn &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-13"&gt;&lt;a href="#cb8-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  _ &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; runQuery conn &lt;span class="st"&gt;&amp;quot;DROP TABLE IF EXISTS users CASCADE&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-14"&gt;&lt;a href="#cb8-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="fu"&gt;putStrLn&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Test data wiped.&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-15"&gt;&lt;a href="#cb8-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb8-16"&gt;&lt;a href="#cb8-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;connectProd ::&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; (&lt;span class="dt"&gt;DbConnection&lt;/span&gt; &lt;span class="dt"&gt;Prod&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb8-17"&gt;&lt;a href="#cb8-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;connectProd &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;DbConnection&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; connectPostgreSQL &lt;span class="st"&gt;&amp;quot;host=prod...&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, if you create a connection using &lt;code&gt;connectProd&lt;/code&gt;, you can use
&lt;code&gt;runQuery&lt;/code&gt; on it (because it can run any
&lt;code&gt;DbConnection a&lt;/code&gt;)…but if any sub-function of a sub-function calls
&lt;code&gt;clearTestEnv&lt;/code&gt;, it will have to unify with
&lt;code&gt;DbConnection Test&lt;/code&gt;, which is impossible for a prod connection.&lt;/p&gt;
&lt;p&gt;This is somewhat similar to using “mocking-only” subclasses for dependency
injection, but with a closed universe. I discuss patterns like this in my &lt;a
href="https://blog.jle.im/entries/series/+introduction-to-singletons.html"&gt;Introduction
to Singletons&lt;/a&gt; series.&lt;/p&gt;
&lt;h2 id="correct-representations"&gt;Correct Representations&lt;/h2&gt;
&lt;h3 id="semantic-phantoms"&gt;Semantic Phantoms&lt;/h3&gt;
&lt;p&gt;And sometimes, phantom types can do the work for you, not only preventing
mix-ups but also encoding business logic in their manipulation.&lt;/p&gt;
&lt;p&gt;Take, for instance, the &lt;a
href="https://en.wikipedia.org/wiki/Mars_Climate_Orbiter"&gt;Mars Climate Orbiter
failure&lt;/a&gt;, where the software module provided by Lockheed Martin expected US
Customary Units, and another one developed by NASA expected SI units.&lt;/p&gt;
&lt;p&gt;If I had a function like:&lt;/p&gt;
&lt;div class="sourceCode" id="cb9"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb9-1"&gt;&lt;a href="#cb9-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- | In Newton-seconds&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-2"&gt;&lt;a href="#cb9-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;myMomentum ::&lt;/span&gt; &lt;span class="dt"&gt;Double&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-3"&gt;&lt;a href="#cb9-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;myMomentum &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;20&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-4"&gt;&lt;a href="#cb9-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb9-5"&gt;&lt;a href="#cb9-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- | In Pounds-second&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-6"&gt;&lt;a href="#cb9-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;myImpulse ::&lt;/span&gt; &lt;span class="dt"&gt;Double&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-7"&gt;&lt;a href="#cb9-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;myImpulse &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;4&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-8"&gt;&lt;a href="#cb9-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb9-9"&gt;&lt;a href="#cb9-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- | Make sure these are both the same units!&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-10"&gt;&lt;a href="#cb9-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;applyImpulse ::&lt;/span&gt; &lt;span class="dt"&gt;Double&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Double&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Double&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-11"&gt;&lt;a href="#cb9-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;applyImpulse currentMomentum impulse &lt;span class="ot"&gt;=&lt;/span&gt; currentMomentum &lt;span class="op"&gt;+&lt;/span&gt; impulse&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is just &lt;em&gt;asking&lt;/em&gt; for someone to come along and provide newtons
alongside pounds. It isn’t even clear from the types what is expected!&lt;/p&gt;
&lt;p&gt;We can instead use the &lt;em&gt;&lt;a
href="https://hackage.haskell.org/package/dimensional"&gt;dimensional&lt;/a&gt;&lt;/em&gt;
library:&lt;/p&gt;
&lt;div class="sourceCode" id="cb10"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb10-1"&gt;&lt;a href="#cb10-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="kw"&gt;qualified&lt;/span&gt; &lt;span class="dt"&gt;Numeric.Units.Dimensional.Prelude&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-2"&gt;&lt;a href="#cb10-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Numeric.Units.Dimensional&lt;/span&gt; ((*~))&lt;/span&gt;
&lt;span id="cb10-3"&gt;&lt;a href="#cb10-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Numeric.Units.Dimensional.SIUnits&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-4"&gt;&lt;a href="#cb10-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Numeric.Units.Dimensional.NonSI&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-5"&gt;&lt;a href="#cb10-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-6"&gt;&lt;a href="#cb10-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;myMomentum ::&lt;/span&gt; &lt;span class="dt"&gt;Momentum&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-7"&gt;&lt;a href="#cb10-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;myMomentum &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;20&lt;/span&gt; &lt;span class="op"&gt;*~&lt;/span&gt; (newton &lt;span class="op"&gt;U.*&lt;/span&gt; seconds)&lt;/span&gt;
&lt;span id="cb10-8"&gt;&lt;a href="#cb10-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-9"&gt;&lt;a href="#cb10-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;myImpulse ::&lt;/span&gt; &lt;span class="dt"&gt;Impulse&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-10"&gt;&lt;a href="#cb10-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;myImpulse &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;4&lt;/span&gt; &lt;span class="op"&gt;*~&lt;/span&gt; (poundForce &lt;span class="op"&gt;U.*&lt;/span&gt; seconds)&lt;/span&gt;
&lt;span id="cb10-11"&gt;&lt;a href="#cb10-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-12"&gt;&lt;a href="#cb10-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- Verify at compile-time that we can use &amp;#39;+&amp;#39; with Momentum and Impulse&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-13"&gt;&lt;a href="#cb10-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;applyImpulse ::&lt;/span&gt; &lt;span class="dt"&gt;Momentum&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Impulse&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Momentum&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-14"&gt;&lt;a href="#cb10-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;applyImpulse currentMomentum impulse &lt;span class="ot"&gt;=&lt;/span&gt; currentMomentum &lt;span class="op"&gt;+&lt;/span&gt; impulse&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now as long as momentum and impulse are provided in the correct types at API
boundaries, no mix-up will happen. No need to send 300 million dollars down the
drain! Libraries will just need to provide a unified &lt;code&gt;Momentum&lt;/code&gt; or
&lt;code&gt;Impulse&lt;/code&gt; type, and everything will work out.&lt;/p&gt;
&lt;h3 id="the-billion-dollar-mistake"&gt;The Billion-Dollar Mistake&lt;/h3&gt;
&lt;p&gt;Speaking of costly errors, there is one extremely egregious pattern that is
so pervasive, so alluring, and yet so inevitably devastating, it has been dubbed
the “Billion Dollar Mistake”. It’s the idea of a &lt;em&gt;sentinel value&lt;/em&gt;, or
in-band signaling.&lt;/p&gt;
&lt;p&gt;There are examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;String.indexOf()&lt;/code&gt;, &lt;code&gt;str.find()&lt;/code&gt;, etc. in many
languages return -1 if the substring is not found&lt;/li&gt;
&lt;li&gt;C’s &lt;code&gt;fgetc()&lt;/code&gt;, &lt;code&gt;getchar()&lt;/code&gt;, return -1 for
&lt;code&gt;EOF&lt;/code&gt;. And if you cast to &lt;code&gt;char&lt;/code&gt;, you basically can’t
distinguish EOF from &lt;code&gt;0xff&lt;/code&gt; (&lt;code&gt;ÿ&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;malloc()&lt;/code&gt; returning the pointer 0 means not enough memory&lt;/li&gt;
&lt;li&gt;Some languages have a special &lt;code&gt;NULL&lt;/code&gt; pointer value as well — or
even a value &lt;code&gt;null&lt;/code&gt; that can be passed in for any expected type or
object or value.&lt;/li&gt;
&lt;li&gt;JavaScript’s &lt;code&gt;parseInt&lt;/code&gt; returns not &lt;code&gt;null&lt;/code&gt;, but rather
&lt;code&gt;NaN&lt;/code&gt; for a bad parse — giving two distinct sentinel values&lt;/li&gt;
&lt;li&gt;A lot of Unix scripting uses the empty string &lt;code&gt;""&lt;/code&gt; for
non-presence&lt;/li&gt;
&lt;li&gt;Sensor firmware often reports values like &lt;code&gt;-999&lt;/code&gt; for a bad
reading…but sometimes &lt;code&gt;-999&lt;/code&gt; might actually be a valid value!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It should be evident that these are just accidents and ticking time bombs
waiting to happen. Some caller just needs to forget to handle the sentinel
value, or to falsely assume that the sentinel value is impossible to occur in
any situation.&lt;/p&gt;
&lt;p&gt;It’s called the billion dollar mistake, but it’s definitely arguable that the
cumulative damage has been much higher. High-profile incidents include &lt;a
href="https://www.rapid7.com/db/modules/exploit/linux/local/sock_sendpage/"&gt;sock_sendpage&lt;/a&gt;
and the &lt;a
href="https://www.thousandeyes.com/blog/google-cloud-outage-analysis-june-12-2025"&gt;2025
GCP outage&lt;/a&gt;, but if you’re reading this and you are honest with yourself,
it’s probably happened to you multiple times and has been the source of many
frustrating bug hunts.&lt;/p&gt;
&lt;p&gt;There’s also &lt;a
href="https://www.invicti.com/web-application-vulnerabilities/openssl-improper-input-validation-vulnerability-cve-2008-5077"&gt;CVE-2008-5077&lt;/a&gt;,
because &lt;a
href="https://docs.openssl.org/1.1.1/man3/EVP_VerifyInit/"&gt;EVP_VerifyInit&lt;/a&gt;
returns &lt;code&gt;0&lt;/code&gt; for false, &lt;code&gt;1&lt;/code&gt; for true, and &lt;code&gt;-1&lt;/code&gt;
for error! So some OpenSSL code did a simple if-then-else check
(&lt;code&gt;result != 0&lt;/code&gt;) and treated error and true the same way. Whoops.&lt;/p&gt;
&lt;p&gt;Why do we do this to ourselves? Because it is convenient. In the case of
&lt;code&gt;EVP_VerifyInit&lt;/code&gt;, we can define an enum instead…&lt;/p&gt;
&lt;div class="sourceCode" id="cb11"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb11-1"&gt;&lt;a href="#cb11-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;VerifyResult&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Success&lt;/span&gt; &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;Failure&lt;/span&gt; &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;Error&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;However, it’s not easy to make an “integer or not found” type in C or
JavaScript without some sort of side-channel. Imagine if JavaScript’s
&lt;code&gt;String.indexOf()&lt;/code&gt; instead expected continuations on success and
failure and became much less usable as a result:&lt;/p&gt;
&lt;div class="sourceCode" id="cb12"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb12-1"&gt;&lt;a href="#cb12-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;unsafeIndexOf ::&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-2"&gt;&lt;a href="#cb12-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb12-3"&gt;&lt;a href="#cb12-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- vs.&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-4"&gt;&lt;a href="#cb12-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb12-5"&gt;&lt;a href="#cb12-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- takes a success continuation and a failure continuation&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-6"&gt;&lt;a href="#cb12-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;indexOf ::&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; (&lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; r) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; (() &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; r) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; r&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All of this just to &lt;a
href="https://blog.jle.im/entry/faking-adts-and-gadts.html"&gt;fake having actual
sum types&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We don’t really have an excuse in Haskell, since we can just return
&lt;code&gt;Maybe&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb13"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb13-1"&gt;&lt;a href="#cb13-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- from Data.Vector&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-2"&gt;&lt;a href="#cb13-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;elemIndex ::&lt;/span&gt; &lt;span class="dt"&gt;Eq&lt;/span&gt; a &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Vector&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Returning &lt;code&gt;Maybe&lt;/code&gt; or &lt;code&gt;Option&lt;/code&gt; forces the caller to
handle:&lt;/p&gt;
&lt;div class="sourceCode" id="cb14"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb14-1"&gt;&lt;a href="#cb14-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;case&lt;/span&gt; elemIndex &lt;span class="dv"&gt;3&lt;/span&gt; myVec &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb14-2"&gt;&lt;a href="#cb14-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Just&lt;/span&gt; i &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="co"&gt;-- ..&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb14-3"&gt;&lt;a href="#cb14-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Nothing&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="co"&gt;-- ..&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and this handling is compiler-enforced. Provided, of course, you don’t &lt;a
href="https://blog.cloudflare.com/18-november-2025-outage/"&gt;intentionally throw
away your type-safety and compiler checks for no reason&lt;/a&gt;. You can even return
&lt;code&gt;Either&lt;/code&gt; with an enum for richer responses, and very easily &lt;a
href="https://blog.jle.im/entry/inside-my-world-ode-to-functor-and-monad.html"&gt;chain
erroring operations using Functor and Monad&lt;/a&gt;. In fact, with cheap ADTs, you
can define your own rich result type, like in &lt;em&gt;&lt;a
href="https://hackage-content.haskell.org/package/unix"&gt;unix&lt;/a&gt;&lt;/em&gt;’s
&lt;code&gt;ProcessStatus&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb15"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb15-1"&gt;&lt;a href="#cb15-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;ProcessStatus&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb15-2"&gt;&lt;a href="#cb15-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;   &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Exited&lt;/span&gt; &lt;span class="dt"&gt;ExitCode&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb15-3"&gt;&lt;a href="#cb15-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;   &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;Terminated&lt;/span&gt; &lt;span class="dt"&gt;Signal&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb15-4"&gt;&lt;a href="#cb15-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;   &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;Stopped&lt;/span&gt; &lt;span class="dt"&gt;Signal&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Imagine trying to cram all of that information into an &lt;code&gt;int&lt;/code&gt;!&lt;/p&gt;
&lt;h2 id="unmarked-assumptions"&gt;Unmarked Assumptions&lt;/h2&gt;
&lt;p&gt;Assumptions kill, and a lot of times we arrive at implicit assumptions in our
code. Unfortunately, even if we add these assumptions in our documentation, it
only takes a minor refactor or lapse in memory for these to cause catastrophic
incidents.&lt;/p&gt;
&lt;p&gt;There are the simple cases — consider a &lt;code&gt;mean&lt;/code&gt; function:&lt;/p&gt;
&lt;div class="sourceCode" id="cb16"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb16-1"&gt;&lt;a href="#cb16-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- | Warning: do not give an empty list!&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-2"&gt;&lt;a href="#cb16-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;mean ::&lt;/span&gt; [&lt;span class="dt"&gt;Double&lt;/span&gt;] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Double&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-3"&gt;&lt;a href="#cb16-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;mean xs &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;sum&lt;/span&gt; xs &lt;span class="op"&gt;/&lt;/span&gt; &lt;span class="fu"&gt;fromIntegral&lt;/span&gt; (&lt;span class="fu"&gt;length&lt;/span&gt; xs)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But are you &lt;em&gt;really&lt;/em&gt; going to remember to check if your list is empty
&lt;em&gt;every&lt;/em&gt; time you give it to &lt;code&gt;mean&lt;/code&gt;? No, of course not.
Instead, make it a compiler-enforced constraint.&lt;/p&gt;
&lt;div class="sourceCode" id="cb17"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb17-1"&gt;&lt;a href="#cb17-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;mean ::&lt;/span&gt; &lt;span class="dt"&gt;NonEmpty&lt;/span&gt; &lt;span class="dt"&gt;Double&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Double&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb17-2"&gt;&lt;a href="#cb17-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;mean xs &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;sum&lt;/span&gt; xs &lt;span class="op"&gt;/&lt;/span&gt; &lt;span class="fu"&gt;fromIntegral&lt;/span&gt; (&lt;span class="fu"&gt;length&lt;/span&gt; xs)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now &lt;code&gt;mean&lt;/code&gt; takes a &lt;code&gt;NonEmpty&lt;/code&gt; list, which can only be
created safely using &lt;code&gt;nonEmpty :: [a] -&amp;gt; Maybe (NonEmpty a)&lt;/code&gt;
(where the caller has to explicitly handle the empty list case, so they’ll never
forget) or from functions that already return &lt;code&gt;NonEmpty&lt;/code&gt; by default
(like &lt;code&gt;some :: f a -&amp;gt; f (NonEmpty a)&lt;/code&gt; or
&lt;code&gt;group :: Eq a =&amp;gt; [a] -&amp;gt; [NonEmpty a]&lt;/code&gt;), allowing you to
beautifully chain post-conditions directly into pre-conditions.&lt;/p&gt;
&lt;p&gt;Accessing containers is, in general, very fraught…even things like indexing
lists can send us into a graveyard spiral. Sometimes the issue is more subtle.
This is our reminder to never let these implicit assumptions go unnoticed.&lt;/p&gt;
&lt;h3 id="separate-processed-data"&gt;Separate Processed Data&lt;/h3&gt;
&lt;p&gt;“Shotgun parsing” involves mixing validated and unvalidated data at different
levels in your program. Oftentimes it is considered “fine” because you just need
to remember which inputs are validated and which aren’t…right? In truth, all it
takes is a simple temporary lapse of mental model, a time delay between working
on code, or uncoordinated contributions before things fall apart.&lt;/p&gt;
&lt;p&gt;Consider a situation where we validate usernames only on write to the
database.&lt;/p&gt;
&lt;div class="sourceCode" id="cb18"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb18-1"&gt;&lt;a href="#cb18-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;validUsername ::&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-2"&gt;&lt;a href="#cb18-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;validUsername s &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;all&lt;/span&gt; &lt;span class="fu"&gt;isAlphaNum&lt;/span&gt; s &lt;span class="op"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="fu"&gt;all&lt;/span&gt; &lt;span class="fu"&gt;isLower&lt;/span&gt; s&lt;/span&gt;
&lt;span id="cb18-3"&gt;&lt;a href="#cb18-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb18-4"&gt;&lt;a href="#cb18-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- | Returns &amp;#39;Nothing&amp;#39; if username is invalid or insertion failed&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-5"&gt;&lt;a href="#cb18-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;saveUser ::&lt;/span&gt; &lt;span class="dt"&gt;Connection&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; (&lt;span class="dt"&gt;Maybe&lt;/span&gt; &lt;span class="dt"&gt;UUID&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb18-6"&gt;&lt;a href="#cb18-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;saveUser conn s&lt;/span&gt;
&lt;span id="cb18-7"&gt;&lt;a href="#cb18-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; validUsername s &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-8"&gt;&lt;a href="#cb18-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      newId &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; query conn &lt;span class="st"&gt;&amp;quot;INSERT INTO users (username) VALUES (?) returning user_id&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;Only&lt;/span&gt; s)&lt;/span&gt;
&lt;span id="cb18-9"&gt;&lt;a href="#cb18-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="fu"&gt;pure&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="kw"&gt;case&lt;/span&gt; newId &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-10"&gt;&lt;a href="#cb18-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        [] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-11"&gt;&lt;a href="#cb18-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="dt"&gt;Only&lt;/span&gt; i &lt;span class="op"&gt;:&lt;/span&gt; _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Just&lt;/span&gt; i&lt;/span&gt;
&lt;span id="cb18-12"&gt;&lt;a href="#cb18-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="fu"&gt;otherwise&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;pure&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-13"&gt;&lt;a href="#cb18-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb18-14"&gt;&lt;a href="#cb18-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;getUser ::&lt;/span&gt; &lt;span class="dt"&gt;Connection&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;UUID&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; (&lt;span class="dt"&gt;Maybe&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb18-15"&gt;&lt;a href="#cb18-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;getUser conn uid &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-16"&gt;&lt;a href="#cb18-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  unames &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; query conn &lt;span class="st"&gt;&amp;quot;SELECT username FROM users where user_id = ?&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;Only&lt;/span&gt; uid)&lt;/span&gt;
&lt;span id="cb18-17"&gt;&lt;a href="#cb18-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="fu"&gt;pure&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="kw"&gt;case&lt;/span&gt; unames &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-18"&gt;&lt;a href="#cb18-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    [] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-19"&gt;&lt;a href="#cb18-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;Only&lt;/span&gt; s &lt;span class="op"&gt;:&lt;/span&gt; _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Just&lt;/span&gt; s&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It &lt;em&gt;should&lt;/em&gt; be fine as long as you only ever use &lt;code&gt;saveUser&lt;/code&gt;
and &lt;code&gt;getUser&lt;/code&gt;…and nobody else has access to the database. But, if
someone hooks up a custom connector, or does some manual modifications, then the
&lt;code&gt;users&lt;/code&gt; table will now have an invalid username, bypassing Haskell.
And because of that, &lt;code&gt;getUser&lt;/code&gt; can return an invalid string!&lt;/p&gt;
&lt;p&gt;Don’t assume that these inconsequential slip-ups won’t happen; assume that
it’s only a matter of time.&lt;/p&gt;
&lt;p&gt;Instead, we can bake the state of a validated string into the type
itself:&lt;/p&gt;
&lt;div class="sourceCode" id="cb19"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb19-1"&gt;&lt;a href="#cb19-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;newtype&lt;/span&gt; &lt;span class="dt"&gt;Username&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;UnsafeUsername&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-2"&gt;&lt;a href="#cb19-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="kw"&gt;deriving&lt;/span&gt; (&lt;span class="dt"&gt;Show&lt;/span&gt;, &lt;span class="dt"&gt;Eq&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb19-3"&gt;&lt;a href="#cb19-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb19-4"&gt;&lt;a href="#cb19-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- | Our &amp;quot;Smart Constructor&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-5"&gt;&lt;a href="#cb19-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;mkUsername ::&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; &lt;span class="dt"&gt;Username&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-6"&gt;&lt;a href="#cb19-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;mkUsername s&lt;/span&gt;
&lt;span id="cb19-7"&gt;&lt;a href="#cb19-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; validUsername s &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Just&lt;/span&gt; (&lt;span class="dt"&gt;UnsafeUsername&lt;/span&gt; s)&lt;/span&gt;
&lt;span id="cb19-8"&gt;&lt;a href="#cb19-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="fu"&gt;otherwise&lt;/span&gt;       &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-9"&gt;&lt;a href="#cb19-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb19-10"&gt;&lt;a href="#cb19-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- | Access the raw string if needed&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-11"&gt;&lt;a href="#cb19-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;unUsername ::&lt;/span&gt; &lt;span class="dt"&gt;Username&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-12"&gt;&lt;a href="#cb19-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;unUsername (&lt;span class="dt"&gt;UnsafeUsername&lt;/span&gt; s) &lt;span class="ot"&gt;=&lt;/span&gt; s&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Username&lt;/code&gt; and &lt;code&gt;String&lt;/code&gt; themselves are not structurally
different — instead, &lt;code&gt;Username&lt;/code&gt; is a compiler-enforced tag specifying
it went through a specific required validation function &lt;em&gt;within Haskell&lt;/em&gt;,
not just externally verified.&lt;/p&gt;
&lt;p&gt;Now &lt;code&gt;saveUser&lt;/code&gt; and &lt;code&gt;getUser&lt;/code&gt; are safe at the
boundaries:&lt;/p&gt;
&lt;div class="sourceCode" id="cb20"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb20-1"&gt;&lt;a href="#cb20-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;saveUser ::&lt;/span&gt; &lt;span class="dt"&gt;Connection&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Username&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; (&lt;span class="dt"&gt;Maybe&lt;/span&gt; &lt;span class="dt"&gt;UUID&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb20-2"&gt;&lt;a href="#cb20-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;saveUser conn s &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-3"&gt;&lt;a href="#cb20-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  newId &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; query conn &lt;span class="st"&gt;&amp;quot;INSERT INTO users (username) VALUES (?) returning user_id&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;Only&lt;/span&gt; (unUsername s))&lt;/span&gt;
&lt;span id="cb20-4"&gt;&lt;a href="#cb20-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="fu"&gt;pure&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="kw"&gt;case&lt;/span&gt; newId &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-5"&gt;&lt;a href="#cb20-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    [] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-6"&gt;&lt;a href="#cb20-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;Only&lt;/span&gt; i &lt;span class="op"&gt;:&lt;/span&gt; _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Just&lt;/span&gt; i&lt;/span&gt;
&lt;span id="cb20-7"&gt;&lt;a href="#cb20-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb20-8"&gt;&lt;a href="#cb20-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;getUser ::&lt;/span&gt; &lt;span class="dt"&gt;Connection&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;UUID&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; (&lt;span class="dt"&gt;Maybe&lt;/span&gt; &lt;span class="dt"&gt;Username&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb20-9"&gt;&lt;a href="#cb20-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;getUser conn uid &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-10"&gt;&lt;a href="#cb20-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  unames &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; query conn &lt;span class="st"&gt;&amp;quot;SELECT username FROM users where user_id = ?&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;Only&lt;/span&gt; uid)&lt;/span&gt;
&lt;span id="cb20-11"&gt;&lt;a href="#cb20-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="fu"&gt;pure&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="kw"&gt;case&lt;/span&gt; unames &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-12"&gt;&lt;a href="#cb20-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    [] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-13"&gt;&lt;a href="#cb20-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;Only&lt;/span&gt; s &lt;span class="op"&gt;:&lt;/span&gt; _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; mkUsername s&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(In real code, of course, we would use a more usable indication of failure
than &lt;code&gt;Maybe&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;We can even hook this into Haskell’s typeclass system to make this even more
rigorous: &lt;code&gt;Username&lt;/code&gt; could have its own &lt;code&gt;FromField&lt;/code&gt; and
&lt;code&gt;ToField&lt;/code&gt; instances that push the validation to the driver level.&lt;/p&gt;
&lt;div class="sourceCode" id="cb21"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb21-1"&gt;&lt;a href="#cb21-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;FromField&lt;/span&gt; &lt;span class="dt"&gt;Username&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-2"&gt;&lt;a href="#cb21-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  fromField f mdata &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-3"&gt;&lt;a href="#cb21-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;    s ::&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; fromField f mdata&lt;/span&gt;
&lt;span id="cb21-4"&gt;&lt;a href="#cb21-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;case&lt;/span&gt; mkUsername s &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-5"&gt;&lt;a href="#cb21-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;Just&lt;/span&gt; u  &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;pure&lt;/span&gt; u&lt;/span&gt;
&lt;span id="cb21-6"&gt;&lt;a href="#cb21-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="dt"&gt;Nothing&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; returnError &lt;span class="dt"&gt;ConversionFailed&lt;/span&gt; f (&lt;span class="st"&gt;&amp;quot;Invalid username format: &amp;quot;&lt;/span&gt; &lt;span class="op"&gt;++&lt;/span&gt; s)&lt;/span&gt;
&lt;span id="cb21-7"&gt;&lt;a href="#cb21-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb21-8"&gt;&lt;a href="#cb21-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;ToField&lt;/span&gt; &lt;span class="dt"&gt;Username&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-9"&gt;&lt;a href="#cb21-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  toField &lt;span class="ot"&gt;=&lt;/span&gt; toField &lt;span class="op"&gt;.&lt;/span&gt; unUsername&lt;/span&gt;
&lt;span id="cb21-10"&gt;&lt;a href="#cb21-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb21-11"&gt;&lt;a href="#cb21-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;saveUser ::&lt;/span&gt; &lt;span class="dt"&gt;Connection&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Username&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; (&lt;span class="dt"&gt;Maybe&lt;/span&gt; &lt;span class="dt"&gt;UUID&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb21-12"&gt;&lt;a href="#cb21-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;saveUser conn s &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-13"&gt;&lt;a href="#cb21-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  newId &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; query conn &lt;span class="st"&gt;&amp;quot;INSERT INTO users (username) VALUES (?) returning user_id&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;Only&lt;/span&gt; s)&lt;/span&gt;
&lt;span id="cb21-14"&gt;&lt;a href="#cb21-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="fu"&gt;pure&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="kw"&gt;case&lt;/span&gt; newId &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-15"&gt;&lt;a href="#cb21-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    [] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-16"&gt;&lt;a href="#cb21-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;Only&lt;/span&gt; i &lt;span class="op"&gt;:&lt;/span&gt; _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Just&lt;/span&gt; i&lt;/span&gt;
&lt;span id="cb21-17"&gt;&lt;a href="#cb21-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb21-18"&gt;&lt;a href="#cb21-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;getUser ::&lt;/span&gt; &lt;span class="dt"&gt;Connection&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;UUID&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; (&lt;span class="dt"&gt;Maybe&lt;/span&gt; &lt;span class="dt"&gt;Username&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb21-19"&gt;&lt;a href="#cb21-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;getUser conn uid &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-20"&gt;&lt;a href="#cb21-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  unames &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; query conn &lt;span class="st"&gt;&amp;quot;SELECT username FROM users where user_id = ?&amp;quot;&lt;/span&gt; (&lt;span class="dt"&gt;Only&lt;/span&gt; uid)&lt;/span&gt;
&lt;span id="cb21-21"&gt;&lt;a href="#cb21-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="fu"&gt;pure&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="kw"&gt;case&lt;/span&gt; unames &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-22"&gt;&lt;a href="#cb21-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    [] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-23"&gt;&lt;a href="#cb21-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;Only&lt;/span&gt; s &lt;span class="op"&gt;:&lt;/span&gt; _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Just&lt;/span&gt; s&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pushing it to the driver level will also unify everything with the driver’s
error-handling system.&lt;/p&gt;
&lt;p&gt;These ideas are elaborated further in one of the best Haskell posts of all
time, &lt;a
href="https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/"&gt;Parse,
Don’t Validate&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="boolean-blindness"&gt;Boolean Blindness&lt;/h3&gt;
&lt;p&gt;At the heart of it, the previous examples’ cardinal sin was “boolean
blindness”. If we have a predicate like
&lt;code&gt;validUsername :: String -&amp;gt; Bool&lt;/code&gt;, we will branch on that
&lt;code&gt;Bool&lt;/code&gt; once and throw it away. Instead, by having a function like
&lt;code&gt;mkUsername :: String -&amp;gt; Maybe Username&lt;/code&gt;, we &lt;em&gt;keep&lt;/em&gt; the
proof alongside the value for the entire lifetime of the value. We basically
pair the string with its proof forever, making them inseparable.&lt;/p&gt;
&lt;p&gt;There was another example of such a thing earlier: instead of using
&lt;code&gt;null :: [a] -&amp;gt; Bool&lt;/code&gt; and gating a call to &lt;code&gt;mean&lt;/code&gt; with
&lt;code&gt;null&lt;/code&gt;, we instead use
&lt;code&gt;nonEmpty :: [a] -&amp;gt; Maybe (NonEmpty a)&lt;/code&gt;, and pass along the proof
of non-emptiness alongside the value itself. And, for the rest of that list’s
life, it will always be paired with its non-emptiness proof.&lt;/p&gt;
&lt;p&gt;Embracing total depravity means always keeping these proofs together, with
the witnesses bundled with the value itself, because if you don’t, someone is
going to assume it exists when it doesn’t, or drop it unnecessarily.&lt;/p&gt;
&lt;p&gt;Boolean blindness also has another facet, which is where &lt;code&gt;Bool&lt;/code&gt;
itself is not a semantically meaningful type. This is “semantic boolean
blindness”.&lt;/p&gt;
&lt;p&gt;The classic example is
&lt;code&gt;filter :: (a -&amp;gt; Bool) -&amp;gt; [a] -&amp;gt; [a]&lt;/code&gt;. It might sound silly
until it happens to you, but it is pretty easy to mix up if &lt;code&gt;True&lt;/code&gt;
means “keep” or “discard”. After all, a “water filter” only lets water through,
but a “profanity filter” only rejects profanity. Instead, how about
&lt;code&gt;mapMaybe :: (a -&amp;gt; Maybe b) -&amp;gt; [a] -&amp;gt; [b]&lt;/code&gt;? In that case, it
is clear that &lt;code&gt;Just&lt;/code&gt; results are kept, and the &lt;code&gt;Nothing&lt;/code&gt;
results are discarded.&lt;/p&gt;
&lt;p&gt;Sometimes, the boolean is ambiguous as to what it means. You can sort of
interpret the &lt;a href="https://en.wikipedia.org/wiki/Mars_Polar_Lander"&gt;1999
Mars Polar Lander&lt;/a&gt; crash this way. Its functions took a boolean based on the
state of the legs:&lt;/p&gt;
&lt;div class="sourceCode" id="cb22"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb22-1"&gt;&lt;a href="#cb22-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;deployThrusters ::&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and &lt;code&gt;True&lt;/code&gt; and &lt;code&gt;False&lt;/code&gt; were misinterpreted. Instead,
they could have considered semantically meaningful types: (simplified)&lt;/p&gt;
&lt;div class="sourceCode" id="cb23"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb23-1"&gt;&lt;a href="#cb23-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;LegState&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Extended&lt;/span&gt; &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;Retracted&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-2"&gt;&lt;a href="#cb23-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb23-3"&gt;&lt;a href="#cb23-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;deployThrusters ::&lt;/span&gt; &lt;span class="dt"&gt;LegState&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that &lt;code&gt;Maybe&lt;/code&gt; itself is not immune from “semantic blindness” —
if you find yourself using a lot of anonymous combinators like
&lt;code&gt;Maybe&lt;/code&gt; and &lt;code&gt;Either&lt;/code&gt; to get around boolean blindness, be
aware of falling into &lt;a
href="https://github.com/quchen/articles/blob/master/algebraic-blindness.md"&gt;algebraic
blindness&lt;/a&gt;!&lt;/p&gt;
&lt;h3 id="resource-cleanup"&gt;Resource Cleanup&lt;/h3&gt;
&lt;p&gt;Clean-up of finite system resources is another area that is very easy to
assume you have a handle on before it gets out of hand and sneaks up on you.&lt;/p&gt;
&lt;div class="sourceCode" id="cb24"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb24-1"&gt;&lt;a href="#cb24-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;process ::&lt;/span&gt; &lt;span class="dt"&gt;Handle&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb24-2"&gt;&lt;a href="#cb24-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb24-3"&gt;&lt;a href="#cb24-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;doTheThing ::&lt;/span&gt; &lt;span class="dt"&gt;FilePath&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb24-4"&gt;&lt;a href="#cb24-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;doTheThing path &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-5"&gt;&lt;a href="#cb24-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  h &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; openFile path &lt;span class="dt"&gt;ReadMode&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-6"&gt;&lt;a href="#cb24-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  process h&lt;/span&gt;
&lt;span id="cb24-7"&gt;&lt;a href="#cb24-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  hClose h&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A bunch of things could go wrong —&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You might forget to always &lt;code&gt;hClose&lt;/code&gt; a file handle, and if your
files come at you dynamically, you’re going to run out of file descriptors, or
hold on to locks longer than you should&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;process&lt;/code&gt; throws an exception, we never get to
&lt;code&gt;hClose&lt;/code&gt;, and the same issues happen&lt;/li&gt;
&lt;li&gt;If another thread throws an asynchronous exception (like a thread
cancellation), you have to make sure the close still happens!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The typical solution that other languages (like Python, modern Java) take is
to put everything inside a “block” where quitting the block guarantees the
closure. In Haskell we have the &lt;code&gt;bracket&lt;/code&gt; pattern:&lt;/p&gt;
&lt;div class="sourceCode" id="cb25"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb25-1"&gt;&lt;a href="#cb25-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- strongly discourage using `openFile` and `hClose` directly&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb25-2"&gt;&lt;a href="#cb25-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;withFile ::&lt;/span&gt; &lt;span class="dt"&gt;FilePath&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; (&lt;span class="dt"&gt;Handle&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; r) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; r&lt;/span&gt;
&lt;span id="cb25-3"&gt;&lt;a href="#cb25-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;withFile path &lt;span class="ot"&gt;=&lt;/span&gt; bracket (openFile path &lt;span class="dt"&gt;ReadMode&lt;/span&gt;) hClose&lt;/span&gt;
&lt;span id="cb25-4"&gt;&lt;a href="#cb25-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb25-5"&gt;&lt;a href="#cb25-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;doTheThing ::&lt;/span&gt; &lt;span class="dt"&gt;FilePath&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb25-6"&gt;&lt;a href="#cb25-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;doTheThing path &lt;span class="ot"&gt;=&lt;/span&gt; withFile path &lt;span class="op"&gt;$&lt;/span&gt; \h &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb25-7"&gt;&lt;a href="#cb25-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  process h&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you never use &lt;code&gt;openFile&lt;/code&gt; directly, and always use
&lt;code&gt;withFile&lt;/code&gt;, all file usage is safe!&lt;/p&gt;
&lt;p&gt;But, admittedly, continuations can be annoying to work with. For example,
what if you wanted to safely open a list of files?&lt;/p&gt;
&lt;div class="sourceCode" id="cb26"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb26-1"&gt;&lt;a href="#cb26-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;processAll ::&lt;/span&gt; [&lt;span class="dt"&gt;Handle&lt;/span&gt;] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb26-2"&gt;&lt;a href="#cb26-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb26-3"&gt;&lt;a href="#cb26-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;doTheThings ::&lt;/span&gt; [&lt;span class="dt"&gt;FilePath&lt;/span&gt;] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb26-4"&gt;&lt;a href="#cb26-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;doTheThings paths &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="co"&gt;-- uh...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All of a sudden, not so fun. And what if you had, for example, a Map of
files, like &lt;code&gt;Map Username FilePath&lt;/code&gt;?&lt;/p&gt;
&lt;div class="sourceCode" id="cb27"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb27-1"&gt;&lt;a href="#cb27-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;processAll ::&lt;/span&gt; &lt;span class="dt"&gt;Map&lt;/span&gt; &lt;span class="dt"&gt;Username&lt;/span&gt; &lt;span class="dt"&gt;Handle&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb27-2"&gt;&lt;a href="#cb27-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb27-3"&gt;&lt;a href="#cb27-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;doTheThings ::&lt;/span&gt; &lt;span class="dt"&gt;Map&lt;/span&gt; &lt;span class="dt"&gt;Username&lt;/span&gt; &lt;span class="dt"&gt;FilePath&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb27-4"&gt;&lt;a href="#cb27-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;doTheThings paths &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="co"&gt;-- uh...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In another language, at this point, we might just give up and resort to
manual opening and closing of files.&lt;/p&gt;
&lt;p&gt;But this is Haskell. We have a better solution: cleanup-tracking monads!&lt;/p&gt;
&lt;p&gt;This is a classic usage of &lt;code&gt;ContT&lt;/code&gt; to let you chain bracket-like
continuations:&lt;/p&gt;
&lt;div class="sourceCode" id="cb28"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb28-1"&gt;&lt;a href="#cb28-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;processTwo ::&lt;/span&gt; &lt;span class="dt"&gt;Handle&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Handle&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb28-2"&gt;&lt;a href="#cb28-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb28-3"&gt;&lt;a href="#cb28-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;doTwoThings ::&lt;/span&gt; &lt;span class="dt"&gt;FilePath&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;FilePath&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb28-4"&gt;&lt;a href="#cb28-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;doTwoThings path1 path2 &lt;span class="ot"&gt;=&lt;/span&gt; evalContT &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-5"&gt;&lt;a href="#cb28-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    h1 &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="dt"&gt;ContT&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; withFile path1&lt;/span&gt;
&lt;span id="cb28-6"&gt;&lt;a href="#cb28-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    h2 &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="dt"&gt;ContT&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; withFile path2&lt;/span&gt;
&lt;span id="cb28-7"&gt;&lt;a href="#cb28-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    liftIO &lt;span class="op"&gt;$&lt;/span&gt; processTwo h1 h2&lt;/span&gt;
&lt;span id="cb28-8"&gt;&lt;a href="#cb28-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb28-9"&gt;&lt;a href="#cb28-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;processAll ::&lt;/span&gt; &lt;span class="dt"&gt;Map&lt;/span&gt; &lt;span class="dt"&gt;Username&lt;/span&gt; &lt;span class="dt"&gt;Handle&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb28-10"&gt;&lt;a href="#cb28-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb28-11"&gt;&lt;a href="#cb28-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;doTheThings ::&lt;/span&gt; &lt;span class="dt"&gt;Map&lt;/span&gt; &lt;span class="dt"&gt;Username&lt;/span&gt; &lt;span class="dt"&gt;FilePath&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb28-12"&gt;&lt;a href="#cb28-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;doTheThings paths &lt;span class="ot"&gt;=&lt;/span&gt; evalContT &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-13"&gt;&lt;a href="#cb28-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    handles &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="fu"&gt;traverse&lt;/span&gt; (&lt;span class="dt"&gt;ContT&lt;/span&gt; &lt;span class="op"&gt;.&lt;/span&gt; withFile) paths&lt;/span&gt;
&lt;span id="cb28-14"&gt;&lt;a href="#cb28-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    liftIO &lt;span class="op"&gt;$&lt;/span&gt; processAll handles&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;However, using &lt;code&gt;ContT&lt;/code&gt; doesn’t allow you to do things like early
cleanups or canceling cleanup events. It forces us into a last-in, first-out
sort of cleanup pattern. If you want to deviate, this might cause you to, for
convenience, go for manual resource management. However, we have tools for more
fine-grained control, we have things like &lt;em&gt;&lt;a
href="https://hackage.haskell.org/package/resourcet"&gt;resourcet&lt;/a&gt;&lt;/em&gt;
&lt;code&gt;ResourceT&lt;/code&gt;, which lets you manually control the order of clean-up
events, with the guarantee that all of them &lt;em&gt;eventually&lt;/em&gt; happen.&lt;/p&gt;
&lt;div class="sourceCode" id="cb29"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb29-1"&gt;&lt;a href="#cb29-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="kw"&gt;qualified&lt;/span&gt; &lt;span class="dt"&gt;Data.Map&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; &lt;span class="dt"&gt;M&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-2"&gt;&lt;a href="#cb29-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-3"&gt;&lt;a href="#cb29-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- | Returns set of usernames to close&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-4"&gt;&lt;a href="#cb29-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;processAll ::&lt;/span&gt; &lt;span class="dt"&gt;Map&lt;/span&gt; &lt;span class="dt"&gt;Username&lt;/span&gt; &lt;span class="dt"&gt;Handle&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; (&lt;span class="dt"&gt;Set&lt;/span&gt; &lt;span class="dt"&gt;Username&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb29-5"&gt;&lt;a href="#cb29-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-6"&gt;&lt;a href="#cb29-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;allocateFile ::&lt;/span&gt; &lt;span class="dt"&gt;FilePath&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;ResourceT&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; (&lt;span class="dt"&gt;ReleaseKey&lt;/span&gt;, &lt;span class="dt"&gt;Handle&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb29-7"&gt;&lt;a href="#cb29-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;allocateFile fp &lt;span class="ot"&gt;=&lt;/span&gt; allocate (openFile fp &lt;span class="dt"&gt;ReadMode&lt;/span&gt;) hClose&lt;/span&gt;
&lt;span id="cb29-8"&gt;&lt;a href="#cb29-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-9"&gt;&lt;a href="#cb29-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- Guarantees that all handles will eventually close, even if `go` crashes&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-10"&gt;&lt;a href="#cb29-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;doTheThings ::&lt;/span&gt; &lt;span class="dt"&gt;Map&lt;/span&gt; &lt;span class="dt"&gt;Username&lt;/span&gt; &lt;span class="dt"&gt;FilePath&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb29-11"&gt;&lt;a href="#cb29-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;doTheThings paths &lt;span class="ot"&gt;=&lt;/span&gt; runResourceT &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-12"&gt;&lt;a href="#cb29-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    releasersAndHandlers &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="fu"&gt;traverse&lt;/span&gt; allocateFile paths&lt;/span&gt;
&lt;span id="cb29-13"&gt;&lt;a href="#cb29-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    go releasersAndHandlers&lt;/span&gt;
&lt;span id="cb29-14"&gt;&lt;a href="#cb29-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-15"&gt;&lt;a href="#cb29-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="co"&gt;-- normal operation: slowly releases handlers as we drop them&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-16"&gt;&lt;a href="#cb29-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;    go ::&lt;/span&gt; &lt;span class="dt"&gt;Map&lt;/span&gt; &lt;span class="dt"&gt;Username&lt;/span&gt; (&lt;span class="dt"&gt;ReleaseKey&lt;/span&gt;, &lt;span class="dt"&gt;Handle&lt;/span&gt;) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;ResourceT&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb29-17"&gt;&lt;a href="#cb29-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    go currOpen &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-18"&gt;&lt;a href="#cb29-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      toClose &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; liftIO &lt;span class="op"&gt;$&lt;/span&gt; processAll (&lt;span class="fu"&gt;snd&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; currOpen)&lt;/span&gt;
&lt;span id="cb29-19"&gt;&lt;a href="#cb29-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      traverse_ (release &lt;span class="op"&gt;.&lt;/span&gt; &lt;span class="fu"&gt;fst&lt;/span&gt;) (currOpen &lt;span class="ot"&gt;`M.restrictKeys`&lt;/span&gt; toClose)&lt;/span&gt;
&lt;span id="cb29-20"&gt;&lt;a href="#cb29-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="kw"&gt;let&lt;/span&gt; newOpen &lt;span class="ot"&gt;=&lt;/span&gt; currOpen &lt;span class="ot"&gt;`M.withoutKeys`&lt;/span&gt; toClose&lt;/span&gt;
&lt;span id="cb29-21"&gt;&lt;a href="#cb29-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      unless (M.null newOpen) &lt;span class="op"&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-22"&gt;&lt;a href="#cb29-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        go newOpen&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here we get the best of both worlds: the ability to manually close handlers
when they are no longer needed, but also the guarantee that they will eventually
be closed.&lt;/p&gt;
&lt;h2 id="embracing-total-depravity"&gt;Embracing Total Depravity&lt;/h2&gt;
&lt;p&gt;Hopefully these examples, and similar situations, should feel relatable.
We’ve all experienced the biting pain of too much self-trust. Or, too much trust
in our ability to communicate with team members. Or, too much trust in ourselves
6 months from now. The traumas described here &lt;em&gt;should&lt;/em&gt; resonate with you
if you have programmed in any capacity for more than a couple of scripts.&lt;/p&gt;
&lt;p&gt;The doctrine of total depravity does not mean that we don’t recognize the
ability to write sloppy code that works, or that flow states can enable some
great feats. After all, we all program with a certain sense of &lt;em&gt;imago
machinae&lt;/em&gt;. Instead, it means that all such states are &lt;em&gt;fundamentally
unstable&lt;/em&gt; in their nature and will always fail at some point. The “total”
doesn’t mean we are totally cooked, it means this eventual reckoning applies to
&lt;em&gt;all&lt;/em&gt; such shortcuts.&lt;/p&gt;
&lt;p&gt;The problem won’t be solved by “get good”. The problem is solved by utilizing
the tooling we are given, especially since Haskell makes them so accessible and
easy to pull in.&lt;/p&gt;
&lt;p&gt;There’s another layer here that comes as a result of embracing this mindset:
you’ll find that you have more mental space to dedicate to things that actually
matter! Instead of worrying about inconsequential minutiae and details of your
flawed abstractions, you can actually think about your business logic, the flow
of your program, and architecting that castle of beauty I know you are capable
of.&lt;/p&gt;
&lt;h3 id="in-the-age-of-agentic-coding"&gt;In the Age of Agentic Coding&lt;/h3&gt;
&lt;p&gt;Before we end, let’s address the elephant in the room. We’re writing this in
2026, in the middle of one of the biggest revolutions in software engineering in
the history of the field. A lot of people have claimed that types and safety are
now no longer important in the age of LLMs and agentic coding.&lt;/p&gt;
&lt;p&gt;However, these claims seem to miss the fact that the fundamental issue being
addressed here exists both in LLMs and humans: the limited “context window” and
attention. Humans might be barely able to keep a dozen things in our heads, LLMs
might be able to keep a dozen dozen things, but it will still be ultimately
finite. So, the more we can move concerns out of our context window (be it
biological or mechanical), the less crowded our context windows will be, and the
more productive we will be.&lt;/p&gt;
&lt;p&gt;Agentic coding is progressing quickly, and over the past few months I have
been exploring this a lot, using models hands-on. One conclusion I have found
(and, this agrees with everyone else I’ve asked who has been trying the same
thing) is that Haskell’s types, in many ways, are the killer productivity secret
of agentic coding.&lt;/p&gt;
&lt;p&gt;Many of my Haskell coding tasks for an LLM agent often involve:&lt;/p&gt;
&lt;ol type="1"&gt;
&lt;li&gt;How will the types change, or what should the types be?&lt;/li&gt;
&lt;li&gt;Ralph Wiggum loop to death until the program typechecks, using
&lt;code&gt;ghci&lt;/code&gt; and &lt;code&gt;cabal&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And, this isn’t 100% effective, but from personal experience it is much more
effective than the similar situation without typed guardrails for fast feedback,
and without instant compiler feedback. The feedback loop is tighter, the
objectives clearer, the constraints more resilient, the tooling more
utilized.&lt;/p&gt;
&lt;p&gt;I have noticed, also, that my LLM agents often check the types of the APIs
using &lt;code&gt;ghci :type&lt;/code&gt;, and rarely the documentation of the functions
using &lt;code&gt;ghci :docs&lt;/code&gt;. So, any “documentation-based contracts” are
definitely much more likely to explode in your face in this new world than
type-based contracts.&lt;/p&gt;
&lt;p&gt;I’m not sure how quickly LLM-based agentic coding will progress, but I am
sure that the accidental “dropping” of concerns will continue to be a
bottleneck. All of the traits described in this post for humans will continue to
be traits of limited context windows for LLMs.&lt;/p&gt;
&lt;p&gt;If anything, limited “brain space” might be &lt;em&gt;the&lt;/em&gt; bottleneck, for both
humans and LLMs. If provide LLMs with properly “depravity-aware” typed code (and
encourage them to write it by giving them the right iterative tooling), I truly
believe that we have the key to unlocking the full potential of agentic
coding.&lt;/p&gt;
&lt;p&gt;And…not whatever &lt;a
href="https://x.com/rywalker/status/2003525268821188746"&gt;this tweet is&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="the-next-step"&gt;The Next Step&lt;/h3&gt;
&lt;p&gt;Total depravity is all about using types to &lt;em&gt;prevent errors&lt;/em&gt;. However,
you can only go so far with defensive programming and carefully picking the
structure of your types. Sometimes, it feels like you are expending a lot of
energy and human effort just picking the perfectly designed data type, only for
things out of your hand to ruin your typed castle.&lt;/p&gt;
&lt;p&gt;In the next chapter, we’ll see how a little-discussed aspect of Haskell’s
type system gives you a powerful tool for opening your mind to new avenues of
design that were impossible before. At the same time, we’ll see how we can
leverage universal properties of mathematics itself to help us analyze our code
in unexpected ways.&lt;/p&gt;
&lt;p&gt;Let’s explore this further in the next principle of &lt;a
href="https://blog.jle.im/entries/series/+five-point-haskell.html"&gt;Five-Point
Haskell&lt;/a&gt;, &lt;strong&gt;Unconditional Election&lt;/strong&gt;!&lt;/p&gt;
&lt;h2 id="special-thanks"&gt;Special Thanks&lt;/h2&gt;
&lt;p&gt;I am very humbled to be supported by an amazing community, who make it
possible for me to devote time to researching and writing these posts. Very
special thanks to my supporter at the “Amazing” level on &lt;a
href="https://www.patreon.com/justinle/overview"&gt;patreon&lt;/a&gt;, Josh Vera! :)&lt;/p&gt;
&lt;p&gt;Also thanks to &lt;a
href="https://www.reddit.com/r/haskell/comments/1qtxnsm/comment/o3889uy"&gt;&lt;em&gt;jackdk&lt;/em&gt;’s
comment&lt;/a&gt; for highlighting extra resources and context that I believe are very
useful and relevant!&lt;/p&gt;</description><author>Justin Le</author><category>Haskell</category><guid isPermaLink="true">https://blog.jle.im/entry/five-point-haskell-part-1-total-depravity.html</guid><pubDate>Mon,  2 Feb 2026 15:06:46 UTC</pubDate><creator>Justin Le</creator><subject>Haskell</subject><date>2026-02-02</date></item><item><title>Advent of Code 2025: Haskell Solution Reflections for all 12 Days</title><link>https://blog.jle.im/entry/advent-of-code-2025.html</link><description>&lt;p&gt;Merry Christmas all! This is my annual &lt;a
href="http://adventofcode.com/"&gt;Advent of Code&lt;/a&gt; post! Advent of Code is a
series of (this year) 12 daily Christmas-themed programming puzzles that are
meant to be fun diversions from your daily life, help you find a bit of whimsy
in your world, give you a chance to explore new ideas and program together with
your friends. I always enjoy discussing creative ways to solve these puzzles
every day, and it’s become a bit of an annual highlight for me and a lot of
others. My favorite part about these puzzles is that they are open ended enough
that there are usually many different interesting ways to solve them — it’s not
like a stressful interview question where you have to recite the obscure
incantation to pass the test. In the past I’ve leveraged &lt;a
href="https://blog.jle.im/entry/alchemical-groups.html"&gt;group theory&lt;/a&gt;, &lt;a
href="https://blog.jle.im/entry/shifting-the-stars.html"&gt;galilean
transformations and linear algebra&lt;/a&gt;, and &lt;a
href="https://blog.jle.im/entry/shuffling-things-up.html"&gt;more group
theory&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Haskell is especially fun for these because if you set up your abstractions
in just the right way, the puzzles seem to solve themselves. It’s a good
opportunity every year to get exposed to different parts of the Haskell
ecosystem! Last year, I moved almost all of my Haskell code to &lt;a
href="https://github.com/mstksg/advent-of-code"&gt;an Advent of Code Megarepo&lt;/a&gt;,
and I also write up my favorite ways to solve each one in the &lt;a
href="https://github.com/mstksg/advent-of-code/wiki"&gt;megarepo wiki&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;All of this year’s 12 puzzles &lt;a
href="https://github.com/mstksg/advent-of-code/wiki/Reflections-2025"&gt;are
here&lt;/a&gt;, but I’ve also included links to each individual one in this post. I’m
also considering expanding some of these into full on blog posts, so be on the
look out, or let me know if there are any that you might want fully expanded!
And if you haven’t, why not try these out yourself? Be sure to drop by the
libera-chat &lt;code&gt;##advent-of-code&lt;/code&gt; channel to discuss any fun ways you
solve them, or any questions! Thanks again to Eric for a great new fresh take on
the event this year!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a
href="https://github.com/mstksg/advent-of-code/blob/main/reflections/2025/day01.md"&gt;Day
1 - Secret Entrance&lt;/a&gt; — The classic Day 1 &lt;code&gt;scanl&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a
href="https://github.com/mstksg/advent-of-code/blob/main/reflections/2025/day02.md"&gt;Day
2 - Gift Shop&lt;/a&gt; — The super efficient &lt;code&gt;IntSet&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a
href="https://github.com/mstksg/advent-of-code/blob/main/reflections/2025/day03.md"&gt;Day
3 - Lobby&lt;/a&gt; — &lt;code&gt;StateT&lt;/code&gt; + &lt;code&gt;[]&lt;/code&gt; = backtracking search
monad&lt;/li&gt;
&lt;li&gt;&lt;a
href="https://github.com/mstksg/advent-of-code/blob/main/reflections/2025/day04.md"&gt;Day
4 - Printing Department&lt;/a&gt; — 2D cellular automata&lt;/li&gt;
&lt;li&gt;&lt;a
href="https://github.com/mstksg/advent-of-code/blob/main/reflections/2025/day05.md"&gt;Day
5 - Cafeteria&lt;/a&gt; — The power of the &lt;code&gt;data-interval&lt;/code&gt; library&lt;/li&gt;
&lt;li&gt;&lt;a
href="https://github.com/mstksg/advent-of-code/blob/main/reflections/2025/day06.md"&gt;Day
6 - Trash Compactor&lt;/a&gt; — &lt;code&gt;Data.List&lt;/code&gt; manipulations&lt;/li&gt;
&lt;li&gt;&lt;a
href="https://github.com/mstksg/advent-of-code/blob/main/reflections/2025/day07.md"&gt;Day
7 - Laboratories&lt;/a&gt; — Tying the knot&lt;/li&gt;
&lt;li&gt;&lt;a
href="https://github.com/mstksg/advent-of-code/blob/main/reflections/2025/day08.md"&gt;Day
8 - Playground&lt;/a&gt; — Iterative Clustering&lt;/li&gt;
&lt;li&gt;&lt;a
href="https://github.com/mstksg/advent-of-code/blob/main/reflections/2025/day09.md"&gt;Day
9 - Movie Theater&lt;/a&gt; — &lt;code&gt;IntervalSet&lt;/code&gt; and
&lt;code&gt;IntervalMap&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a
href="https://github.com/mstksg/advent-of-code/blob/main/reflections/2025/day10.md"&gt;Day
10 - Factory&lt;/a&gt; — Guassian Elimation, Type-safe Mutable Vectors&lt;/li&gt;
&lt;li&gt;&lt;a
href="https://github.com/mstksg/advent-of-code/blob/main/reflections/2025/day11.md"&gt;Day
11 - Reactor&lt;/a&gt; — More Knot Tying and DP!&lt;/li&gt;
&lt;li&gt;&lt;a
href="https://github.com/mstksg/advent-of-code/blob/main/reflections/2025/day12.md"&gt;Day
12 - Christmas Tree Farm&lt;/a&gt; — Counting&lt;/li&gt;
&lt;/ul&gt;</description><author>Justin Le</author><category>Haskell</category><guid isPermaLink="true">https://blog.jle.im/entry/advent-of-code-2025.html</guid><pubDate>Wed, 24 Dec 2025 20:44:05 UTC</pubDate><creator>Justin Le</creator><subject>Haskell</subject><date>2025-12-24</date></item><item><title>The Baby Paradox in Haskell</title><link>https://blog.jle.im/entry/the-baby-paradox-in-haskell.html</link><description>&lt;p&gt;&lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Everybody_Loves_My_Baby"&gt;Everybody
Loves My Baby&lt;/a&gt;&lt;/em&gt; is a Jazz Standard from 1924 with the famous lyric:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Everybody loves my baby, but my baby don’t love nobody but me.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Which is often formalized as:&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align}
\text{Axiom}_1 . &amp;amp; \forall x. \text{Loves}(x, \text{Baby})  \\
\text{Axiom}_2 . \forall x. &amp;amp; \text{Loves}(\text{Baby}, x) \implies x = me
\end{align}
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Let’s prove in Haskell (in one line) that these two statements, taken
together, imply that I am my own baby.&lt;/p&gt;
&lt;h2 id="the-normal-proof"&gt;The normal proof&lt;/h2&gt;
&lt;p&gt;The normal proof using propositional logic goes as follows:&lt;/p&gt;
&lt;ol type="1"&gt;
&lt;li&gt;If everyone loves Baby, Baby must love baby. (instantiate axiom 1 with &lt;span
class="math inline"&gt;\(x =
\text{Baby}\)&lt;/span&gt;).&lt;/li&gt;
&lt;li&gt;If baby loves someone, that someone must be me. (axiom 2)&lt;/li&gt;
&lt;li&gt;Therefore, because baby loves baby, baby must be me. (instantiate axiom 2
with axiom 1 with &lt;span class="math inline"&gt;\(x = \text{Baby}\)&lt;/span&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="haskell-as-a-theorem-prover"&gt;Haskell as a Theorem Prover&lt;/h2&gt;
&lt;p&gt;First, some background: when using Haskell as a theorem prover, you represent
the theorem as a type, and &lt;em&gt;proving&lt;/em&gt; it involves &lt;em&gt;constructing&lt;/em&gt; a
value of that type — you create an inhabitant of that type.&lt;/p&gt;
&lt;p&gt;Using the Curry-Howard correspondence (often also called the Curry-Howard
isomorphism), we can pair some simple logical connectives with types:&lt;/p&gt;
&lt;ol type="1"&gt;
&lt;li&gt;Logical “and” corresponds to tupling (or records of values). If
&lt;code&gt;(a, b)&lt;/code&gt; is inhabited, it means that both &lt;code&gt;a&lt;/code&gt; and
&lt;code&gt;b&lt;/code&gt; are inhabited.&lt;/li&gt;
&lt;li&gt;Logical “or” corresponds to sums, &lt;code&gt;Either a b&lt;/code&gt; being inhabited
implies that either &lt;code&gt;a&lt;/code&gt; or &lt;code&gt;b&lt;/code&gt; are inhabited. They might
both the inhabited, but &lt;code&gt;Either     a b&lt;/code&gt; requires the “proof” of only
one.&lt;/li&gt;
&lt;li&gt;Constructivist logical implication is a function: If &lt;code&gt;a -&amp;gt; b&lt;/code&gt;
is inhabited, it means that an inhabitant of &lt;code&gt;a&lt;/code&gt; can be used to
create an inhabitant of &lt;code&gt;b&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Any type with a constructor is “true”: &lt;code&gt;()&lt;/code&gt;, &lt;code&gt;Bool&lt;/code&gt;,
&lt;code&gt;String&lt;/code&gt;, etc.; any type with no constructor (&lt;code&gt;data Void&lt;/code&gt;)
is “false” because it has no inhabitants.&lt;/li&gt;
&lt;li&gt;Introducing type variables (&lt;code&gt;forall a.&lt;/code&gt;) corresponds to…well, for
all. If &lt;code&gt;forall a. Either a ()&lt;/code&gt; means that &lt;code&gt;Either a ()&lt;/code&gt;
is “true” (inhabited) for all possible &lt;code&gt;a&lt;/code&gt;. This one represented
logically as &lt;span class="math inline"&gt;\(\forall x. x \lor
\text{True}\)&lt;/span&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can see that, by chaining together those primitives, you can translate a
lot of simple proofs. For example, the proof of “If &lt;code&gt;x&lt;/code&gt; and
&lt;code&gt;y&lt;/code&gt; together imply &lt;code&gt;z&lt;/code&gt;, then &lt;code&gt;x&lt;/code&gt; implies that
&lt;code&gt;y&lt;/code&gt; implies &lt;code&gt;z&lt;/code&gt;”:&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\forall x y z. ((x \wedge y) \implies z) \implies (x \implies (y \implies z))
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;can be expressed as:&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;curry&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="kw"&gt;forall&lt;/span&gt; a b c&lt;span class="op"&gt;.&lt;/span&gt; ((a, b) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; c) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; c&lt;/span&gt;
&lt;span id="cb1-2"&gt;&lt;a href="#cb1-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;curry&lt;/span&gt; f x y &lt;span class="ot"&gt;=&lt;/span&gt; f (x, y)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or maybe, “If either x or y imply z, then x implies z and y implies z,
independently:”&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\forall x y z. ((x \lor y) \implies z) \implies ((x \implies z) \land (y
\implies z)))
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In haskell:&lt;/p&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb2-1"&gt;&lt;a href="#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;unEither ::&lt;/span&gt; (&lt;span class="dt"&gt;Either&lt;/span&gt; a b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; c) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; (a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; c, b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; c)&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;unEither f &lt;span class="ot"&gt;=&lt;/span&gt; (f &lt;span class="op"&gt;.&lt;/span&gt; &lt;span class="dt"&gt;Left&lt;/span&gt;, f &lt;span class="op"&gt;.&lt;/span&gt; &lt;span class="dt"&gt;Right&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And, we have a version of negation: if &lt;code&gt;a -&amp;gt; Void&lt;/code&gt; is
inhabited, then &lt;code&gt;a&lt;/code&gt; must be uninhabited (the &lt;a
href="https://en.wikipedia.org/wiki/Principle_of_explosion"&gt;principle of
explosion&lt;/a&gt;). Let’s prove that “‘x or y’ being false implies both x and y are
false”: &lt;span class="math inline"&gt;\(\forall x y. \neg(x \lor y)
\implies (\neg x \wedge \neg y)\)&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb3-1"&gt;&lt;a href="#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;deMorgan ::&lt;/span&gt; (&lt;span class="dt"&gt;Either&lt;/span&gt; a b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Void&lt;/span&gt;) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; (a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Void&lt;/span&gt;, b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Void&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;deMorgan f &lt;span class="ot"&gt;=&lt;/span&gt; (f &lt;span class="op"&gt;.&lt;/span&gt; &lt;span class="dt"&gt;Left&lt;/span&gt;, f &lt;span class="op"&gt;.&lt;/span&gt; &lt;span class="dt"&gt;Right&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(Maybe surprisingly, that’s the same proof as &lt;code&gt;unEither&lt;/code&gt;!)&lt;/p&gt;
&lt;p&gt;We can also think of “type functions” (type constructors that take arguments)
as “parameterized propositions”:&lt;/p&gt;
&lt;div class="sourceCode" id="cb4"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb4-1"&gt;&lt;a href="#cb4-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; a &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt; &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;Maybe a&lt;/code&gt; (like &lt;span
class="math inline"&gt;\(\text{Maybe}(x)\)&lt;/span&gt;) is the proposition that &lt;span
class="math inline"&gt;\(\text{True} \lor x\)&lt;/span&gt;: &lt;code&gt;Maybe a&lt;/code&gt; is
always inhabited, because “True or X” is always True. Even
&lt;code&gt;Maybe Void&lt;/code&gt; is inhabited, as &lt;code&gt;Nothing :: Maybe Void&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The sky is the limit if we use GADTs. We can create arbitrary propositions by
restricting what types constructors can be called with. For example, we can
create a proposition that &lt;code&gt;x&lt;/code&gt; is an element of a list:&lt;/p&gt;
&lt;div class="sourceCode" id="cb5"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb5-1"&gt;&lt;a href="#cb5-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Elem&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; k &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; [k] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-2"&gt;&lt;a href="#cb5-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;Here&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Elem&lt;/span&gt; x (x &lt;span class="op"&gt;:&lt;/span&gt; xs)&lt;/span&gt;
&lt;span id="cb5-3"&gt;&lt;a href="#cb5-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;There&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="op"&gt;!&lt;/span&gt;(&lt;span class="dt"&gt;Elem&lt;/span&gt; x ys) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Elem&lt;/span&gt; x (y &lt;span class="op"&gt;:&lt;/span&gt; ys)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Read this as “&lt;code&gt;Elem x xs&lt;/code&gt; is true (inhabited) if either
&lt;code&gt;x&lt;/code&gt; is the first item, or if &lt;code&gt;x&lt;/code&gt; is an elem of the tail of
the list”. So for example, &lt;code&gt;Elem 5 [1,5,6]&lt;/code&gt; is inhabited but
&lt;code&gt;Elem 7 [1,5,6]&lt;/code&gt; is not:&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;div class="sourceCode" id="cb6"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb6-1"&gt;&lt;a href="#cb6-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;itsTrue ::&lt;/span&gt; &lt;span class="dt"&gt;Elem&lt;/span&gt; &lt;span class="dv"&gt;5&lt;/span&gt; [&lt;span class="dv"&gt;1&lt;/span&gt;,&lt;span class="dv"&gt;5&lt;/span&gt;,&lt;span class="dv"&gt;6&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb6-2"&gt;&lt;a href="#cb6-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;itsTrue &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;There&lt;/span&gt; &lt;span class="dt"&gt;Here&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-3"&gt;&lt;a href="#cb6-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb6-4"&gt;&lt;a href="#cb6-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;itsNotTrue ::&lt;/span&gt; &lt;span class="dt"&gt;Elem&lt;/span&gt; &lt;span class="dv"&gt;7&lt;/span&gt; [&lt;span class="dv"&gt;1&lt;/span&gt;,&lt;span class="dv"&gt;5&lt;/span&gt;,&lt;span class="dv"&gt;6&lt;/span&gt;] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Void&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-5"&gt;&lt;a href="#cb6-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;itsNotTrue &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt; {}     &lt;span class="co"&gt;-- GHC is smart enough to know both cases are invalid&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can create a two-argument proposition that two types are equal,
&lt;code&gt;a :~: b&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb7"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb7-1"&gt;&lt;a href="#cb7-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt;&lt;span class="ot"&gt; (:~:) ::&lt;/span&gt; k &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; k &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-2"&gt;&lt;a href="#cb7-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;Refl&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; a &lt;span class="op"&gt;:~:&lt;/span&gt; a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The proposition &lt;code&gt;a :~: b&lt;/code&gt; is only inhabited if &lt;code&gt;a&lt;/code&gt; is
equal to &lt;code&gt;b&lt;/code&gt;, since &lt;code&gt;Refl&lt;/code&gt; is its only constructor.&lt;/p&gt;
&lt;p&gt;Of course, this whole correspondence assumes we aren’t ever touching bottom
(things like &lt;code&gt;undefined&lt;/code&gt; for &lt;code&gt;let x = x in x&lt;/code&gt;). For this
exercise, we are working in a total subset of Haskell.&lt;/p&gt;
&lt;h2 id="the-baby-paradox"&gt;The Baby Paradox&lt;/h2&gt;
&lt;p&gt;Now we have enough. Let’s parameterize it over a proposition
&lt;code&gt;loves&lt;/code&gt;, where &lt;code&gt;loves a b&lt;/code&gt; being inhabited means that
&lt;code&gt;a&lt;/code&gt; loves &lt;code&gt;b&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can express our axiom as a record of propositions in terms of the atoms
&lt;code&gt;loves&lt;/code&gt;, &lt;code&gt;me&lt;/code&gt;, and &lt;code&gt;baby&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb8"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb8-1"&gt;&lt;a href="#cb8-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;BabyAxioms&lt;/span&gt; loves me baby &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;BabyAxioms&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-2"&gt;&lt;a href="#cb8-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    {&lt;span class="ot"&gt; everybodyLovesMyBaby ::&lt;/span&gt; &lt;span class="kw"&gt;forall&lt;/span&gt; x&lt;span class="op"&gt;.&lt;/span&gt; loves x baby&lt;/span&gt;
&lt;span id="cb8-3"&gt;&lt;a href="#cb8-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ,&lt;span class="ot"&gt; myBabyOnlyLovesMe ::&lt;/span&gt; &lt;span class="kw"&gt;forall&lt;/span&gt; x&lt;span class="op"&gt;.&lt;/span&gt; loves baby x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; x &lt;span class="op"&gt;:~:&lt;/span&gt; me&lt;/span&gt;
&lt;span id="cb8-4"&gt;&lt;a href="#cb8-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The first axiom &lt;code&gt;everybodyLovesMyBaby&lt;/code&gt; means that for &lt;em&gt;any&lt;/em&gt;
&lt;code&gt;x&lt;/code&gt;, &lt;code&gt;loves x baby&lt;/code&gt; must be “true” (inhabited). The second
axiom &lt;code&gt;myBabyOnlyLovesMe&lt;/code&gt; means that &lt;em&gt;if&lt;/em&gt; we have a
&lt;code&gt;loves baby x&lt;/code&gt; (if my baby loves someone), then it must be that
&lt;code&gt;x ~ me&lt;/code&gt;: we must be able to derive that person the baby loves is
indeed &lt;code&gt;me&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The expression of the baby paradox then relies on writing the function&lt;/p&gt;
&lt;div class="sourceCode" id="cb9"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb9-1"&gt;&lt;a href="#cb9-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;babyParadox ::&lt;/span&gt; &lt;span class="dt"&gt;BabyAxioms&lt;/span&gt; loves me baby &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; me &lt;span class="op"&gt;:~:&lt;/span&gt; baby&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And indeed if we play around with GHC enough, we’ll get this typechecking
implementation:&lt;/p&gt;
&lt;div class="sourceCode" id="cb10"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb10-1"&gt;&lt;a href="#cb10-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;babyParadox ::&lt;/span&gt; &lt;span class="dt"&gt;BabyAxioms&lt;/span&gt; loves me baby &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; me &lt;span class="op"&gt;:~:&lt;/span&gt; baby&lt;/span&gt;
&lt;span id="cb10-2"&gt;&lt;a href="#cb10-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;babyParadox &lt;span class="dt"&gt;BabyAxioms&lt;/span&gt;{everybodyLovesMyBaby, myBabyOnlyLovesMe} &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-3"&gt;&lt;a href="#cb10-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    myBabyOnlyLovesMe everybodyLovesMyBaby&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Using &lt;code&gt;x &amp;amp; f = f x&lt;/code&gt; from &lt;em&gt;Data.Function&lt;/em&gt;, this becomes
a bit smoother to read:&lt;/p&gt;
&lt;div class="sourceCode" id="cb11"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb11-1"&gt;&lt;a href="#cb11-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;babyParadox ::&lt;/span&gt; &lt;span class="dt"&gt;BabyAxioms&lt;/span&gt; loves me baby &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; me &lt;span class="op"&gt;:~:&lt;/span&gt; baby&lt;/span&gt;
&lt;span id="cb11-2"&gt;&lt;a href="#cb11-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;babyParadox &lt;span class="dt"&gt;BabyAxioms&lt;/span&gt;{everybodyLovesMyBaby, myBabyOnlyLovesMe} &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-3"&gt;&lt;a href="#cb11-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    everybodyLovesMyBaby &lt;span class="op"&gt;&amp;amp;&lt;/span&gt; myBabyOnlyLovesMe&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we have just proved it! It ended up being a one-liner. So, given the
&lt;code&gt;BabyAxioms loves me baby&lt;/code&gt;, it is possible to prove that
&lt;code&gt;me&lt;/code&gt; &lt;em&gt;must&lt;/em&gt; be equal to &lt;code&gt;baby&lt;/code&gt;. That is, it is
impossible to create any &lt;code&gt;BabyAxioms&lt;/code&gt; without &lt;code&gt;me&lt;/code&gt; and
&lt;code&gt;baby&lt;/code&gt; being the same type.&lt;/p&gt;
&lt;p&gt;The actual structure of the proof goes like this:&lt;/p&gt;
&lt;ol type="1"&gt;
&lt;li&gt;First, we instantiated &lt;code&gt;everybodyLovesBaby&lt;/code&gt; with
&lt;code&gt;x ~ baby&lt;/code&gt;, to get &lt;code&gt;loves     baby baby&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Then, we used &lt;code&gt;myBabyOnlyLovesMe&lt;/code&gt;, which normally takes
&lt;code&gt;loves baby x&lt;/code&gt; and returns &lt;code&gt;x :~: me&lt;/code&gt;. Because we give it
&lt;code&gt;loves baby baby&lt;/code&gt;, we get a &lt;code&gt;baby     :~: me&lt;/code&gt;!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And that’s exactly the same structure of the original symbolic proof.&lt;/p&gt;
&lt;h3 id="what-is-love"&gt;What is Love?&lt;/h3&gt;
&lt;p&gt;We made &lt;code&gt;BabyAxioms&lt;/code&gt; parametric over &lt;code&gt;loves&lt;/code&gt;,
&lt;code&gt;me&lt;/code&gt;, and &lt;code&gt;baby&lt;/code&gt;, which means that these apply in
&lt;em&gt;any&lt;/em&gt; universe where love, me, and baby follow the rules of the song
lyrics.&lt;/p&gt;
&lt;p&gt;Essentially this means that for &lt;em&gt;any&lt;/em&gt; binary relationship
&lt;code&gt;Loves x y&lt;/code&gt;, &lt;em&gt;if&lt;/em&gt; that relationship follows these axioms, it
&lt;em&gt;must&lt;/em&gt; be true that me is baby. No matter what that relationship actually
&lt;em&gt;is&lt;/em&gt;, concretely.&lt;/p&gt;
&lt;p&gt;That being said, it might be fun to play around with what this might look
like in concrete realizations of love, me, and my baby.&lt;/p&gt;
&lt;p&gt;First, we could imagine that Love is completely mundane, and can be created
between any two operands without any extra required data or constraints —
essentially, a &lt;a
href="https://hackage.haskell.org/package/base-4.21.0.0/docs/Data-Proxy.html#t:Proxy"&gt;proxy&lt;/a&gt;
between two phantoms:&lt;/p&gt;
&lt;div class="sourceCode" id="cb12"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb12-1"&gt;&lt;a href="#cb12-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Love&lt;/span&gt; a b &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Love&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this case, it’s impossible to create a &lt;code&gt;BabyAxioms&lt;/code&gt; where
&lt;code&gt;me&lt;/code&gt; and &lt;code&gt;baby&lt;/code&gt; are different:&lt;/p&gt;
&lt;div class="sourceCode" id="cb13"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb13-1"&gt;&lt;a href="#cb13-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Love&lt;/span&gt; a b &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Love&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-2"&gt;&lt;a href="#cb13-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb13-3"&gt;&lt;a href="#cb13-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- | me ~ baby is a cosntraint required by GHC&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-4"&gt;&lt;a href="#cb13-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;proxyLove ::&lt;/span&gt; (me &lt;span class="op"&gt;~&lt;/span&gt; baby) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;BabyAxioms&lt;/span&gt; &lt;span class="dt"&gt;Love&lt;/span&gt; me baby&lt;/span&gt;
&lt;span id="cb13-5"&gt;&lt;a href="#cb13-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;proxyLove &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;BabyAxioms&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-6"&gt;&lt;a href="#cb13-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    { everybodyLovesMyBaby &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Love&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-7"&gt;&lt;a href="#cb13-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    , myBabyOnlyLovesMe &lt;span class="ot"&gt;=&lt;/span&gt; \_ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Refl&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-8"&gt;&lt;a href="#cb13-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;me ~ baby&lt;/code&gt; constraint being required by GHC is actually an
interesting manifestation of the paradox itself, without an explicit proof
required on our part. Alternatively, and more traditionally, we can write
&lt;code&gt;proxyLove :: BabyAxioms Love baby baby&lt;/code&gt; or
&lt;code&gt;proxyLove :: BabyAxioms Love me me&lt;/code&gt; to mean the same thing.&lt;/p&gt;
&lt;p&gt;We can imagine another concrete universe where it is only possible to love my
baby, and my baby is the singular recipient of love in this entire universe:&lt;/p&gt;
&lt;div class="sourceCode" id="cb14"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb14-1"&gt;&lt;a href="#cb14-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;LoveOnly&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; k &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; k &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; k &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb14-2"&gt;&lt;a href="#cb14-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;LoveMyBaby&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;LoveOnly&lt;/span&gt; baby x baby&lt;/span&gt;
&lt;span id="cb14-3"&gt;&lt;a href="#cb14-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb14-4"&gt;&lt;a href="#cb14-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;onlyBaby ::&lt;/span&gt; &lt;span class="dt"&gt;BabyAxioms&lt;/span&gt; (&lt;span class="dt"&gt;LoveOnly&lt;/span&gt; baby) me baby&lt;/span&gt;
&lt;span id="cb14-5"&gt;&lt;a href="#cb14-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;onlyBaby &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;BabyAxioms&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb14-6"&gt;&lt;a href="#cb14-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    { everybodyLovesMyBaby &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;LoveMyBaby&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb14-7"&gt;&lt;a href="#cb14-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    , myBabyOnlyLovesMe &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt; &lt;span class="dt"&gt;LoveMyBaby&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Refl&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb14-8"&gt;&lt;a href="#cb14-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we get both axioms fulfilled for free! Basically if we ever have a
&lt;code&gt;LoveOnly baby x me&lt;/code&gt;, the only possible constructor is is
&lt;code&gt;LoveMyBaby :: LoveOnly baby x baby&lt;/code&gt;, so me &lt;em&gt;must&lt;/em&gt; be
baby!&lt;/p&gt;
&lt;p&gt;Finally, we could imagine that love has no possible construction, with no way
to construct or realize. In this case, love is the uninhabited
&lt;code&gt;Void&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb15"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb15-1"&gt;&lt;a href="#cb15-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Love&lt;/span&gt; a b&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this universe, we can finally fulfil &lt;code&gt;myBabyOnlyLovesMe&lt;/code&gt;
without &lt;code&gt;me&lt;/code&gt; being &lt;code&gt;baby&lt;/code&gt;, because “my baby don’t love
nobody but me” is vacuously true if there is no possible love. However, we
cannot fulfil &lt;code&gt;everybodyLovesMyBaby&lt;/code&gt; because no love is possible,
except in the case that the universe of people (&lt;code&gt;k&lt;/code&gt;) is also empty.
But GHC doesn’t have any way to encode empty kinds, I believe (I would love to
hear of any techniques if you knew of any), so we cannot realize these axioms
even if &lt;code&gt;forall (x :: k)&lt;/code&gt; is truly empty.&lt;/p&gt;
&lt;p&gt;Note that we cannot fully encode the axioms purely as a GADT in Haskell — our
&lt;code&gt;LoveOnly&lt;/code&gt; was close, but it is too restrictive: in a fully general
interpretation of the song, we want to be able to allow other recipients of love
besides baby. Basically, Haskell GADTs cannot express the eliminators necessary
to encode &lt;code&gt;myBabyOnlyLovesMe&lt;/code&gt; purely structurally, as far as I am
aware. But I could be wrong.&lt;/p&gt;
&lt;h2 id="why"&gt;Why&lt;/h2&gt;
&lt;p&gt;Nobody who listens to this song seriously believes that the speaker is
intending to convey that they are their own baby, or attempting to tantalize the
listener with an unintuitive tautology. However, this is indeed a common
homework assignment in predicate logic classes, and I wasn’t able to find anyone
covering this yet in Haskell, so I thought might as well be the first.&lt;/p&gt;
&lt;p&gt;Sorry, teachers of courses that teach logic through Haskell.&lt;/p&gt;
&lt;p&gt;I’ve also been using paradox as one of my go-to LLM stumpers, and it’s
actually only recently (with GPT 5) that it’s been able to get this right. Yay
the future? Before this, it would get stuck on trying to define a
&lt;code&gt;Loves&lt;/code&gt; GADT, which is a dead end as previously discussed.&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;I’m pretty sure nobody has ever used it for anything useful, but
I wrote the entire &lt;em&gt;&lt;a
href="https://hackage.haskell.org/package/decidable"&gt;decidable&lt;/a&gt;&lt;/em&gt; library
around manipulating propositions like this.&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>Justin Le</author><category>Haskell</category><guid isPermaLink="true">https://blog.jle.im/entry/the-baby-paradox-in-haskell.html</guid><pubDate>Thu, 21 Aug 2025 15:36:28 UTC</pubDate><creator>Justin Le</creator><subject>Haskell</subject><date>2025-08-21</date></item><item><title>Faking ADTs and GADTs in Languages That Shouldn't Have Them</title><link>https://blog.jle.im/entry/faking-adts-and-gadts.html</link><description>&lt;p&gt;Haskell is the world’s best programming language&lt;a href="#fn1"
class="footnote-ref" id="fnref1" role="doc-noteref"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;, but let’s
face the harsh reality that a lot of times in life you’ll have to write in other
programming languages. But alas you have been fully &lt;a
href="https://x.com/kmett/status/1844812186608099463"&gt;Haskell-brained&lt;/a&gt; and
lost all ability to program unless it is type-directed, you don’t even know how
to start writing a program without imagining its shape as a type first.&lt;/p&gt;
&lt;p&gt;Well, fear not. The foundational theory behind Algebraic Data Types and
Generalized Algebraic Data Types (ADTs and GADTs) are so fundamental that
they’ll fit (somewhat) seamlessly into whatever language you’re forced to write.
After all, if they can fit &lt;a
href="https://www.reddit.com/r/haskell/comments/9m2o5r/digging_reveals_profunctor_optics_in_mineacraft/"&gt;profunctor
optics in Microsoft’s Java code&lt;/a&gt;, the sky’s the limit!&lt;/p&gt;
&lt;p&gt;This is an “April Fools” joke in the tradition of &lt;a
href="https://blog.jle.im/entry/verified-instances-in-haskell.html"&gt;my previous
one&lt;/a&gt; in some of these ways that we are going to twist these other languages
might seem unconventional or possibly ill-advised… but also the title is
definitely a lie: these languages definitely &lt;em&gt;should&lt;/em&gt; have them! :D&lt;/p&gt;
&lt;h2 id="normal-adts"&gt;Normal ADTs&lt;/h2&gt;
&lt;p&gt;As a reminder, algebraic Data Types (ADTs) are products and sums; that’s why
they’re algebraic, after all!&lt;/p&gt;
&lt;h3 id="product-types"&gt;Product Types&lt;/h3&gt;
&lt;p&gt;Products are just immutable structs, which pretty much every language
supports — as long as you’re able to make sure they are never mutated.&lt;/p&gt;
&lt;p&gt;Structs in &lt;code&gt;c&lt;/code&gt;, for example, look like:&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode c"&gt;&lt;code class="sourceCode c"&gt;&lt;span id="cb1-1"&gt;&lt;a href="#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="pp"&gt;#include &lt;/span&gt;&lt;span class="im"&gt;&amp;lt;stdint.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-2"&gt;&lt;a href="#cb1-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb1-3"&gt;&lt;a href="#cb1-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;typedef&lt;/span&gt; &lt;span class="kw"&gt;struct&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-4"&gt;&lt;a href="#cb1-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;uint32_t&lt;/span&gt; timestamp&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-5"&gt;&lt;a href="#cb1-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;double&lt;/span&gt; amount&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb1-6"&gt;&lt;a href="#cb1-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt; Transaction&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But you’ll need proper immutable API for it:&lt;/p&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode c"&gt;&lt;code class="sourceCode c"&gt;&lt;span id="cb2-1"&gt;&lt;a href="#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Transaction createTransaction&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dt"&gt;uint32_t&lt;/span&gt; timestamp&lt;span class="op"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;double&lt;/span&gt; amount&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;Transaction&lt;span class="op"&gt;){&lt;/span&gt; timestamp&lt;span class="op"&gt;,&lt;/span&gt; amount&lt;span class="op"&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-3"&gt;&lt;a href="#cb2-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-4"&gt;&lt;a href="#cb2-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb2-5"&gt;&lt;a href="#cb2-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;uint32_t&lt;/span&gt; getTimestamp&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dt"&gt;const&lt;/span&gt; Transaction&lt;span class="op"&gt;*&lt;/span&gt; t&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-6"&gt;&lt;a href="#cb2-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; t&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;timestamp&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-7"&gt;&lt;a href="#cb2-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-8"&gt;&lt;a href="#cb2-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb2-9"&gt;&lt;a href="#cb2-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;double&lt;/span&gt; getAmount&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dt"&gt;const&lt;/span&gt; Transaction&lt;span class="op"&gt;*&lt;/span&gt; t&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-10"&gt;&lt;a href="#cb2-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; t&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;amount&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-11"&gt;&lt;a href="#cb2-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-12"&gt;&lt;a href="#cb2-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb2-13"&gt;&lt;a href="#cb2-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Transaction setTimestamp&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dt"&gt;const&lt;/span&gt; Transaction&lt;span class="op"&gt;*&lt;/span&gt; t&lt;span class="op"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;uint32_t&lt;/span&gt; timestamp&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-14"&gt;&lt;a href="#cb2-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;Transaction&lt;span class="op"&gt;){&lt;/span&gt;timestamp&lt;span class="op"&gt;,&lt;/span&gt; t&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;amount&lt;span class="op"&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-15"&gt;&lt;a href="#cb2-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-16"&gt;&lt;a href="#cb2-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb2-17"&gt;&lt;a href="#cb2-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Transaction setAmount&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dt"&gt;const&lt;/span&gt; Transaction&lt;span class="op"&gt;*&lt;/span&gt; t&lt;span class="op"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;double&lt;/span&gt; amount&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-18"&gt;&lt;a href="#cb2-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;Transaction&lt;span class="op"&gt;){&lt;/span&gt;t&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;timestamp&lt;span class="op"&gt;,&lt;/span&gt; amount&lt;span class="op"&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-19"&gt;&lt;a href="#cb2-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is much simpler in languages where you can associate functions with
data, like OOP and classes. For example, this is the common “value object”
pattern in java (roughly related to the java bean&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;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode java"&gt;&lt;code class="sourceCode java"&gt;&lt;span id="cb3-1"&gt;&lt;a href="#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="kw"&gt;class&lt;/span&gt; Transaction &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;private&lt;/span&gt; &lt;span class="dt"&gt;final&lt;/span&gt; &lt;span class="dt"&gt;long&lt;/span&gt; timestamp&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a href="#cb3-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;private&lt;/span&gt; &lt;span class="dt"&gt;final&lt;/span&gt; &lt;span class="dt"&gt;double&lt;/span&gt; amount&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-4"&gt;&lt;a href="#cb3-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb3-5"&gt;&lt;a href="#cb3-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="fu"&gt;Transaction&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dt"&gt;long&lt;/span&gt; timestamp&lt;span class="op"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;double&lt;/span&gt; amount&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-6"&gt;&lt;a href="#cb3-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="kw"&gt;this&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;timestamp&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; timestamp&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-7"&gt;&lt;a href="#cb3-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="kw"&gt;this&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;amount&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; amount&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-8"&gt;&lt;a href="#cb3-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-9"&gt;&lt;a href="#cb3-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb3-10"&gt;&lt;a href="#cb3-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="dt"&gt;long&lt;/span&gt; &lt;span class="fu"&gt;getTimestamp&lt;/span&gt;&lt;span class="op"&gt;()&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt; &lt;span class="cf"&gt;return&lt;/span&gt; timestamp&lt;span class="op"&gt;;&lt;/span&gt; &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-11"&gt;&lt;a href="#cb3-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="dt"&gt;double&lt;/span&gt; &lt;span class="fu"&gt;getAmount&lt;/span&gt;&lt;span class="op"&gt;()&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt; &lt;span class="cf"&gt;return&lt;/span&gt; amount&lt;span class="op"&gt;;&lt;/span&gt; &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-12"&gt;&lt;a href="#cb3-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb3-13"&gt;&lt;a href="#cb3-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; Transaction &lt;span class="fu"&gt;setTimestamp&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dt"&gt;long&lt;/span&gt; newTimestamp&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-14"&gt;&lt;a href="#cb3-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="kw"&gt;new&lt;/span&gt; &lt;span class="fu"&gt;Transaction&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;newTimestamp&lt;span class="op"&gt;,&lt;/span&gt; &lt;span class="kw"&gt;this&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;amount&lt;/span&gt;&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-15"&gt;&lt;a href="#cb3-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-16"&gt;&lt;a href="#cb3-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb3-17"&gt;&lt;a href="#cb3-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; Transaction &lt;span class="fu"&gt;setAmount&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dt"&gt;double&lt;/span&gt; newAmount&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-18"&gt;&lt;a href="#cb3-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="kw"&gt;new&lt;/span&gt; &lt;span class="fu"&gt;Transaction&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="kw"&gt;this&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;timestamp&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt; newAmount&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-19"&gt;&lt;a href="#cb3-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-20"&gt;&lt;a href="#cb3-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And there you go. Nothing too surprising there!&lt;/p&gt;
&lt;p&gt;In this case, not only are these ADTs (algebraic data types), they’re also
ADTs (&lt;strong&gt;abstract&lt;/strong&gt; data types): you are meant to work with them
based on a pre-defined abstract interface based on type algebra, instead of
their internal representations.&lt;/p&gt;
&lt;h3 id="sum-types"&gt;Sum Types&lt;/h3&gt;
&lt;p&gt;If your language doesn’t support sum types, usually the way to go is with the
&lt;em&gt;visitor pattern&lt;/em&gt;: the underlying implementation is hidden, and the only
way to process a sum type value is by providing handlers for every branch — a
pattern match as a function, essentially. Your sum values then basically
determine which handler is called.&lt;/p&gt;
&lt;p&gt;For example, we can implement it for a network address type that can either
be IPv4 or IPv6. Here we are using C++ just for generics and lambdas with
closures, for simplicity, but we’ll discuss how this might look in C later.&lt;/p&gt;
&lt;div class="sourceCode" id="cb4"&gt;&lt;pre class="sourceCode cpp"&gt;&lt;code class="sourceCode cpp"&gt;&lt;span id="cb4-1"&gt;&lt;a href="#cb4-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="pp"&gt;#include &lt;/span&gt;&lt;span class="im"&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-2"&gt;&lt;a href="#cb4-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="pp"&gt;#include &lt;/span&gt;&lt;span class="im"&gt;&amp;lt;format&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-3"&gt;&lt;a href="#cb4-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="pp"&gt;#include &lt;/span&gt;&lt;span class="im"&gt;&amp;lt;cstdint&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-4"&gt;&lt;a href="#cb4-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb4-5"&gt;&lt;a href="#cb4-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;struct&lt;/span&gt; IPAddress &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-6"&gt;&lt;a href="#cb4-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;bool&lt;/span&gt; isIPv4&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-7"&gt;&lt;a href="#cb4-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;union&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-8"&gt;&lt;a href="#cb4-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="dt"&gt;uint32_t&lt;/span&gt; ipv4&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-9"&gt;&lt;a href="#cb4-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="dt"&gt;uint8_t&lt;/span&gt; ipv6&lt;span class="op"&gt;[&lt;/span&gt;&lt;span class="dv"&gt;16&lt;/span&gt;&lt;span class="op"&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-10"&gt;&lt;a href="#cb4-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-11"&gt;&lt;a href="#cb4-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-12"&gt;&lt;a href="#cb4-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb4-13"&gt;&lt;a href="#cb4-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;template&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kw"&gt;typename&lt;/span&gt; R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-14"&gt;&lt;a href="#cb4-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;struct&lt;/span&gt; IPAddressVisitor &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-15"&gt;&lt;a href="#cb4-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    R &lt;span class="op"&gt;(*&lt;/span&gt;visitIPv4&lt;span class="op"&gt;)(&lt;/span&gt;&lt;span class="dt"&gt;uint32_t&lt;/span&gt;&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-16"&gt;&lt;a href="#cb4-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    R &lt;span class="op"&gt;(*&lt;/span&gt;visitIPv6&lt;span class="op"&gt;)(&lt;/span&gt;&lt;span class="at"&gt;const&lt;/span&gt; &lt;span class="dt"&gt;uint8_t&lt;/span&gt; &lt;span class="op"&gt;(&amp;amp;)[&lt;/span&gt;&lt;span class="dv"&gt;16&lt;/span&gt;&lt;span class="op"&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-17"&gt;&lt;a href="#cb4-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-18"&gt;&lt;a href="#cb4-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb4-19"&gt;&lt;a href="#cb4-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;template&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kw"&gt;typename&lt;/span&gt; R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-20"&gt;&lt;a href="#cb4-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;R acceptIPAddress&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="at"&gt;const&lt;/span&gt; IPAddress&lt;span class="op"&gt;&amp;amp;&lt;/span&gt; ip&lt;span class="op"&gt;,&lt;/span&gt; IPAddressVisitor&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; visitor&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-21"&gt;&lt;a href="#cb4-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; ip&lt;span class="op"&gt;.&lt;/span&gt;isIPv4 &lt;span class="op"&gt;?&lt;/span&gt; visitor&lt;span class="op"&gt;.&lt;/span&gt;visitIPv4&lt;span class="op"&gt;(&lt;/span&gt;ip&lt;span class="op"&gt;.&lt;/span&gt;ipv4&lt;span class="op"&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-22"&gt;&lt;a href="#cb4-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                     &lt;span class="op"&gt;:&lt;/span&gt; visitor&lt;span class="op"&gt;.&lt;/span&gt;visitIPv6&lt;span class="op"&gt;(&lt;/span&gt;ip&lt;span class="op"&gt;.&lt;/span&gt;ipv6&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-23"&gt;&lt;a href="#cb4-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can create the values using:&lt;/p&gt;
&lt;div class="sourceCode" id="cb5"&gt;&lt;pre class="sourceCode cpp"&gt;&lt;code class="sourceCode cpp"&gt;&lt;span id="cb5-1"&gt;&lt;a href="#cb5-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;IPAddress mkIPv4&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dt"&gt;uint32_t&lt;/span&gt; value&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-2"&gt;&lt;a href="#cb5-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt; &lt;span class="kw"&gt;true&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt; value &lt;span class="op"&gt;}&lt;/span&gt; &lt;span class="op"&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-3"&gt;&lt;a href="#cb5-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-4"&gt;&lt;a href="#cb5-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb5-5"&gt;&lt;a href="#cb5-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;IPAddress mkIPv6&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="at"&gt;const&lt;/span&gt; &lt;span class="dt"&gt;uint8_t&lt;/span&gt; &lt;span class="op"&gt;(&amp;amp;&lt;/span&gt;value&lt;span class="op"&gt;)[&lt;/span&gt;&lt;span class="dv"&gt;16&lt;/span&gt;&lt;span class="op"&gt;])&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-6"&gt;&lt;a href="#cb5-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    IPAddress out &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt; &lt;span class="kw"&gt;false&lt;/span&gt; &lt;span class="op"&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-7"&gt;&lt;a href="#cb5-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="bu"&gt;std::&lt;/span&gt;copy&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="bu"&gt;std::&lt;/span&gt;begin&lt;span class="op"&gt;(&lt;/span&gt;value&lt;span class="op"&gt;),&lt;/span&gt; &lt;span class="bu"&gt;std::&lt;/span&gt;end&lt;span class="op"&gt;(&lt;/span&gt;value&lt;span class="op"&gt;),&lt;/span&gt; out&lt;span class="op"&gt;.&lt;/span&gt;ipv6&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-8"&gt;&lt;a href="#cb5-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; out&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-9"&gt;&lt;a href="#cb5-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we can show an address:&lt;/p&gt;
&lt;div class="sourceCode" id="cb6"&gt;&lt;pre class="sourceCode cpp"&gt;&lt;code class="sourceCode cpp"&gt;&lt;span id="cb6-1"&gt;&lt;a href="#cb6-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="bu"&gt;std::&lt;/span&gt;string showIPAddress&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="at"&gt;const&lt;/span&gt; IPAddress&lt;span class="op"&gt;&amp;amp;&lt;/span&gt; ip&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-2"&gt;&lt;a href="#cb6-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    IPAddressVisitor&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bu"&gt;std::&lt;/span&gt;string&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; visitor &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-3"&gt;&lt;a href="#cb6-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;[](&lt;/span&gt;&lt;span class="dt"&gt;uint32_t&lt;/span&gt; v&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-4"&gt;&lt;a href="#cb6-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="bu"&gt;std::&lt;/span&gt;format&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;&amp;quot;&lt;/span&gt;&lt;span class="sc"&gt;{}&lt;/span&gt;&lt;span class="st"&gt;.&lt;/span&gt;&lt;span class="sc"&gt;{}&lt;/span&gt;&lt;span class="st"&gt;.&lt;/span&gt;&lt;span class="sc"&gt;{}&lt;/span&gt;&lt;span class="st"&gt;.&lt;/span&gt;&lt;span class="sc"&gt;{}&lt;/span&gt;&lt;span class="st"&gt;&amp;quot;&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-5"&gt;&lt;a href="#cb6-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                               &lt;span class="op"&gt;(&lt;/span&gt;v &lt;span class="op"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="dv"&gt;24&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;&amp;amp;&lt;/span&gt; &lt;span class="bn"&gt;0xFF&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt; &lt;span class="op"&gt;(&lt;/span&gt;v &lt;span class="op"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="dv"&gt;16&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;&amp;amp;&lt;/span&gt; &lt;span class="bn"&gt;0xFF&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-6"&gt;&lt;a href="#cb6-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                               &lt;span class="op"&gt;(&lt;/span&gt;v &lt;span class="op"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="dv"&gt;8&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;&amp;amp;&lt;/span&gt; &lt;span class="bn"&gt;0xFF&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt; v &lt;span class="op"&gt;&amp;amp;&lt;/span&gt; &lt;span class="bn"&gt;0xFF&lt;/span&gt;&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-7"&gt;&lt;a href="#cb6-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-8"&gt;&lt;a href="#cb6-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;[](&lt;/span&gt;&lt;span class="at"&gt;const&lt;/span&gt; &lt;span class="dt"&gt;uint8_t&lt;/span&gt; &lt;span class="op"&gt;(&amp;amp;&lt;/span&gt;v&lt;span class="op"&gt;)[&lt;/span&gt;&lt;span class="dv"&gt;16&lt;/span&gt;&lt;span class="op"&gt;])&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-9"&gt;&lt;a href="#cb6-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="bu"&gt;std::&lt;/span&gt;format&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;&amp;quot;&lt;/span&gt;&lt;span class="sc"&gt;{:02X}{:02X}&lt;/span&gt;&lt;span class="st"&gt;:&lt;/span&gt;&lt;span class="sc"&gt;{:02X}{:02X}&lt;/span&gt;&lt;span class="st"&gt;:&lt;/span&gt;&lt;span class="sc"&gt;{:02X}{:02X}&lt;/span&gt;&lt;span class="st"&gt;:&lt;/span&gt;&lt;span class="sc"&gt;{:02X}{:02X}&lt;/span&gt;&lt;span class="st"&gt;:&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-10"&gt;&lt;a href="#cb6-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                               &lt;span class="st"&gt;&amp;quot;&lt;/span&gt;&lt;span class="sc"&gt;{:02X}{:02X}&lt;/span&gt;&lt;span class="st"&gt;:&lt;/span&gt;&lt;span class="sc"&gt;{:02X}{:02X}&lt;/span&gt;&lt;span class="st"&gt;:&lt;/span&gt;&lt;span class="sc"&gt;{:02X}{:02X}&lt;/span&gt;&lt;span class="st"&gt;:&lt;/span&gt;&lt;span class="sc"&gt;{:02X}{:02X}&lt;/span&gt;&lt;span class="st"&gt;&amp;quot;&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-11"&gt;&lt;a href="#cb6-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                               v&lt;span class="op"&gt;[&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="op"&gt;],&lt;/span&gt; v&lt;span class="op"&gt;[&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;&lt;span class="op"&gt;],&lt;/span&gt; v&lt;span class="op"&gt;[&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;&lt;span class="op"&gt;],&lt;/span&gt; v&lt;span class="op"&gt;[&lt;/span&gt;&lt;span class="dv"&gt;3&lt;/span&gt;&lt;span class="op"&gt;],&lt;/span&gt; v&lt;span class="op"&gt;[&lt;/span&gt;&lt;span class="dv"&gt;4&lt;/span&gt;&lt;span class="op"&gt;],&lt;/span&gt; v&lt;span class="op"&gt;[&lt;/span&gt;&lt;span class="dv"&gt;5&lt;/span&gt;&lt;span class="op"&gt;],&lt;/span&gt; v&lt;span class="op"&gt;[&lt;/span&gt;&lt;span class="dv"&gt;6&lt;/span&gt;&lt;span class="op"&gt;],&lt;/span&gt; v&lt;span class="op"&gt;[&lt;/span&gt;&lt;span class="dv"&gt;7&lt;/span&gt;&lt;span class="op"&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-12"&gt;&lt;a href="#cb6-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                               v&lt;span class="op"&gt;[&lt;/span&gt;&lt;span class="dv"&gt;8&lt;/span&gt;&lt;span class="op"&gt;],&lt;/span&gt; v&lt;span class="op"&gt;[&lt;/span&gt;&lt;span class="dv"&gt;9&lt;/span&gt;&lt;span class="op"&gt;],&lt;/span&gt; v&lt;span class="op"&gt;[&lt;/span&gt;&lt;span class="dv"&gt;10&lt;/span&gt;&lt;span class="op"&gt;],&lt;/span&gt; v&lt;span class="op"&gt;[&lt;/span&gt;&lt;span class="dv"&gt;11&lt;/span&gt;&lt;span class="op"&gt;],&lt;/span&gt; v&lt;span class="op"&gt;[&lt;/span&gt;&lt;span class="dv"&gt;12&lt;/span&gt;&lt;span class="op"&gt;],&lt;/span&gt; v&lt;span class="op"&gt;[&lt;/span&gt;&lt;span class="dv"&gt;13&lt;/span&gt;&lt;span class="op"&gt;],&lt;/span&gt; v&lt;span class="op"&gt;[&lt;/span&gt;&lt;span class="dv"&gt;14&lt;/span&gt;&lt;span class="op"&gt;],&lt;/span&gt; v&lt;span class="op"&gt;[&lt;/span&gt;&lt;span class="dv"&gt;15&lt;/span&gt;&lt;span class="op"&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-13"&gt;&lt;a href="#cb6-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-14"&gt;&lt;a href="#cb6-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-15"&gt;&lt;a href="#cb6-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; acceptIPAddress&lt;span class="op"&gt;(&lt;/span&gt;ip&lt;span class="op"&gt;,&lt;/span&gt; visitor&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-16"&gt;&lt;a href="#cb6-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that in this way, the compiler enforces that we handle every branch.
And, if we ever add a new branch, everything that ever consumes
&lt;code&gt;IPAddress&lt;/code&gt; with an &lt;code&gt;IPAddressVisitor&lt;/code&gt; will have to add a
new handler.&lt;/p&gt;
&lt;p&gt;In a language &lt;em&gt;without&lt;/em&gt; generics or powerful enough polymorphism, it’s
difficult to enforce the “pure” visitor pattern because you can’t ensure that
all branches return the same type.&lt;/p&gt;
&lt;p&gt;One common pattern is to have an “effectful” visitor pattern, where the point
isn’t to &lt;em&gt;return&lt;/em&gt; something, but to execute something on the payload of
the present branch. This is pretty effective for languages like C, javascript,
python, etc. where types aren’t really a rigid thing.&lt;/p&gt;
&lt;p&gt;For example, this might be how you treat an “implicit nullable”:&lt;/p&gt;
&lt;div class="sourceCode" id="cb7"&gt;&lt;pre class="sourceCode javascript"&gt;&lt;code class="sourceCode javascript"&gt;&lt;span id="cb7-1"&gt;&lt;a href="#cb7-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;export&lt;/span&gt; &lt;span class="kw"&gt;const&lt;/span&gt; visitMaybe &lt;span class="op"&gt;=&lt;/span&gt; (visitNothing&lt;span class="op"&gt;,&lt;/span&gt; visitJust&lt;span class="op"&gt;,&lt;/span&gt; val) &lt;span class="kw"&gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-2"&gt;&lt;a href="#cb7-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  (val &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="kw"&gt;null&lt;/span&gt;) &lt;span class="op"&gt;?&lt;/span&gt; &lt;span class="fu"&gt;visitNothing&lt;/span&gt;() &lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;visitJust&lt;/span&gt;(val)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is basically &lt;code&gt;for_&lt;/code&gt; from Haskell: You can do something like
conditionally launch some action if the value is present.&lt;/p&gt;
&lt;div class="sourceCode" id="cb8"&gt;&lt;pre class="sourceCode javascript"&gt;&lt;code class="sourceCode javascript"&gt;&lt;span id="cb8-1"&gt;&lt;a href="#cb8-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;visitMaybe&lt;/span&gt;(&lt;/span&gt;
&lt;span id="cb8-2"&gt;&lt;a href="#cb8-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  () &lt;span class="kw"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="bu"&gt;console&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;log&lt;/span&gt;(&lt;span class="st"&gt;&amp;quot;Nothing to request&amp;quot;&lt;/span&gt;)&lt;span class="op"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-3"&gt;&lt;a href="#cb8-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  (reqPayload) &lt;span class="kw"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;makeRequest&lt;/span&gt;(&lt;span class="st"&gt;&amp;quot;google.com&amp;quot;&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt; reqPayload)&lt;span class="op"&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-4"&gt;&lt;a href="#cb8-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  maybeRequest&lt;/span&gt;
&lt;span id="cb8-5"&gt;&lt;a href="#cb8-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;On a simpler note, if your language as subtyping built in (maybe with classes
and subclasses) or some other form of dynamic dispatch, you can implement it in
terms of that, which is nice in python, java, C++, etc.&lt;/p&gt;
&lt;div class="sourceCode" id="cb9"&gt;&lt;pre class="sourceCode java"&gt;&lt;code class="sourceCode java"&gt;&lt;span id="cb9-1"&gt;&lt;a href="#cb9-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;interface&lt;/span&gt; ExprVisitor&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-2"&gt;&lt;a href="#cb9-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    R &lt;span class="fu"&gt;visitLit&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dt"&gt;int&lt;/span&gt; value&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-3"&gt;&lt;a href="#cb9-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    R &lt;span class="fu"&gt;visitNegate&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;Expr unary&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-4"&gt;&lt;a href="#cb9-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    R &lt;span class="fu"&gt;visitAdd&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;Expr left&lt;span class="op"&gt;,&lt;/span&gt; Expr right&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-5"&gt;&lt;a href="#cb9-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    R &lt;span class="fu"&gt;visitMul&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;Expr left&lt;span class="op"&gt;,&lt;/span&gt; Expr right&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-6"&gt;&lt;a href="#cb9-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-7"&gt;&lt;a href="#cb9-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb9-8"&gt;&lt;a href="#cb9-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;abstract&lt;/span&gt; &lt;span class="kw"&gt;class&lt;/span&gt; Expr &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-9"&gt;&lt;a href="#cb9-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="kw"&gt;abstract&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; R &lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;ExprVisitor&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; visitor&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-10"&gt;&lt;a href="#cb9-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Alternatively, you’re in a language where lambdas are easy, instead of
tupling up the visitor, you could just have &lt;code&gt;accept&lt;/code&gt; itself take a
number of arguments corresponding to each constructor:&lt;/p&gt;
&lt;div class="sourceCode" id="cb10"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb10-1"&gt;&lt;a href="#cb10-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;//&lt;/span&gt; &lt;span class="dt"&gt;Alternative&lt;/span&gt; definition without an explicit &lt;span class="dt"&gt;Visitor&lt;/span&gt; &lt;span class="kw"&gt;class&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-2"&gt;&lt;a href="#cb10-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;abstract &lt;span class="kw"&gt;class&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; {&lt;/span&gt;
&lt;span id="cb10-3"&gt;&lt;a href="#cb10-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    public abstract &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dt"&gt;R&lt;/span&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;R&lt;/span&gt; accept(&lt;/span&gt;
&lt;span id="cb10-4"&gt;&lt;a href="#cb10-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="dt"&gt;Function&lt;/span&gt;&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;int,&lt;span class="dt"&gt;R&lt;/span&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; visitLit,&lt;/span&gt;
&lt;span id="cb10-5"&gt;&lt;a href="#cb10-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="dt"&gt;Function&lt;/span&gt;&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dt"&gt;Expr&lt;/span&gt;,&lt;span class="dt"&gt;R&lt;/span&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; visitNegate,&lt;/span&gt;
&lt;span id="cb10-6"&gt;&lt;a href="#cb10-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="dt"&gt;BiFunction&lt;/span&gt;&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dt"&gt;Expr&lt;/span&gt;,&lt;span class="dt"&gt;Expr&lt;/span&gt;,&lt;span class="dt"&gt;R&lt;/span&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; visitAdd,&lt;/span&gt;
&lt;span id="cb10-7"&gt;&lt;a href="#cb10-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="dt"&gt;BiFunction&lt;/span&gt;&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dt"&gt;Expr&lt;/span&gt;,&lt;span class="dt"&gt;Expr&lt;/span&gt;,&lt;span class="dt"&gt;R&lt;/span&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; visitMul&lt;/span&gt;
&lt;span id="cb10-8"&gt;&lt;a href="#cb10-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    );&lt;/span&gt;
&lt;span id="cb10-9"&gt;&lt;a href="#cb10-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(Note that C++ doesn’t allow template virtual methods — not because it’s not
possible within the language semantics and syntax, but rather because the
maintainers are too lazy to add it — so doing this faithfully requires a bit
more creativity)&lt;/p&gt;
&lt;p&gt;Now, if your language has dynamic dispatch or subclass polymorphism, you can
actually do a different encoding, instead of the tagged union. This will work in
languages that don’t allow or fully support naked union types, too. In this
method, each constructor becomes a class, but it’s important to &lt;em&gt;only
allow&lt;/em&gt; access using &lt;code&gt;accept&lt;/code&gt; to properly enforce the sum type
pattern.&lt;/p&gt;
&lt;div class="sourceCode" id="cb11"&gt;&lt;pre class="sourceCode java"&gt;&lt;code class="sourceCode java"&gt;&lt;span id="cb11-1"&gt;&lt;a href="#cb11-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;class&lt;/span&gt; Lit &lt;span class="kw"&gt;extends&lt;/span&gt; Expr &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-2"&gt;&lt;a href="#cb11-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;private&lt;/span&gt; &lt;span class="dt"&gt;final&lt;/span&gt; &lt;span class="dt"&gt;int&lt;/span&gt; value&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-3"&gt;&lt;a href="#cb11-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb11-4"&gt;&lt;a href="#cb11-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="fu"&gt;Lit&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dt"&gt;int&lt;/span&gt; value&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-5"&gt;&lt;a href="#cb11-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="kw"&gt;this&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;value&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; value&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-6"&gt;&lt;a href="#cb11-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-7"&gt;&lt;a href="#cb11-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb11-8"&gt;&lt;a href="#cb11-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="at"&gt;@Override&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-9"&gt;&lt;a href="#cb11-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; R &lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;ExprVisitor&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; visitor&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-10"&gt;&lt;a href="#cb11-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; visitor&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;visitLit&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;value&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-11"&gt;&lt;a href="#cb11-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-12"&gt;&lt;a href="#cb11-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-13"&gt;&lt;a href="#cb11-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb11-14"&gt;&lt;a href="#cb11-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;class&lt;/span&gt; Negate &lt;span class="kw"&gt;extends&lt;/span&gt; Expr &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-15"&gt;&lt;a href="#cb11-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;private&lt;/span&gt; &lt;span class="dt"&gt;final&lt;/span&gt; Expr unary&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-16"&gt;&lt;a href="#cb11-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb11-17"&gt;&lt;a href="#cb11-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="fu"&gt;Negate&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;Expr unary&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt; &lt;span class="kw"&gt;this&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;unary&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; unary&lt;span class="op"&gt;;&lt;/span&gt; &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-18"&gt;&lt;a href="#cb11-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb11-19"&gt;&lt;a href="#cb11-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="at"&gt;@Override&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-20"&gt;&lt;a href="#cb11-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; R &lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;ExprVisitor&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; visitor&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-21"&gt;&lt;a href="#cb11-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; visitor&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;visitNegate&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;unary&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-22"&gt;&lt;a href="#cb11-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-23"&gt;&lt;a href="#cb11-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-24"&gt;&lt;a href="#cb11-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb11-25"&gt;&lt;a href="#cb11-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;class&lt;/span&gt; Add &lt;span class="kw"&gt;extends&lt;/span&gt; Expr &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-26"&gt;&lt;a href="#cb11-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;private&lt;/span&gt; &lt;span class="dt"&gt;final&lt;/span&gt; Expr left&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-27"&gt;&lt;a href="#cb11-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;private&lt;/span&gt; &lt;span class="dt"&gt;final&lt;/span&gt; Expr right&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-28"&gt;&lt;a href="#cb11-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb11-29"&gt;&lt;a href="#cb11-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="fu"&gt;Add&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;Expr left&lt;span class="op"&gt;,&lt;/span&gt; Expr right&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-30"&gt;&lt;a href="#cb11-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="kw"&gt;this&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;left&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; left&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-31"&gt;&lt;a href="#cb11-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="kw"&gt;this&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;right&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; right&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-32"&gt;&lt;a href="#cb11-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-33"&gt;&lt;a href="#cb11-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb11-34"&gt;&lt;a href="#cb11-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="at"&gt;@Override&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-35"&gt;&lt;a href="#cb11-35" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; R &lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;ExprVisitor&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; visitor&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-36"&gt;&lt;a href="#cb11-36" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; visitor&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;visitAdd&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;left&lt;span class="op"&gt;,&lt;/span&gt; right&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-37"&gt;&lt;a href="#cb11-37" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-38"&gt;&lt;a href="#cb11-38" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-39"&gt;&lt;a href="#cb11-39" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb11-40"&gt;&lt;a href="#cb11-40" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;class&lt;/span&gt; Mul &lt;span class="kw"&gt;extends&lt;/span&gt; Expr &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-41"&gt;&lt;a href="#cb11-41" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;private&lt;/span&gt; &lt;span class="dt"&gt;final&lt;/span&gt; Expr left&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-42"&gt;&lt;a href="#cb11-42" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;private&lt;/span&gt; &lt;span class="dt"&gt;final&lt;/span&gt; Expr right&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-43"&gt;&lt;a href="#cb11-43" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb11-44"&gt;&lt;a href="#cb11-44" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="fu"&gt;Mul&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;Expr left&lt;span class="op"&gt;,&lt;/span&gt; Expr right&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-45"&gt;&lt;a href="#cb11-45" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="kw"&gt;this&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;left&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; left&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-46"&gt;&lt;a href="#cb11-46" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="kw"&gt;this&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;right&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; right&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-47"&gt;&lt;a href="#cb11-47" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-48"&gt;&lt;a href="#cb11-48" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb11-49"&gt;&lt;a href="#cb11-49" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="at"&gt;@Override&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-50"&gt;&lt;a href="#cb11-50" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; R &lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;ExprVisitor&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; visitor&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-51"&gt;&lt;a href="#cb11-51" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; visitor&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;visitMul&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;left&lt;span class="op"&gt;,&lt;/span&gt; right&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-52"&gt;&lt;a href="#cb11-52" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-53"&gt;&lt;a href="#cb11-53" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(But, just wanted to note that if you actually &lt;em&gt;are&lt;/em&gt; working in java,
you can actually do something with sealed classes, which allows exhaustiveness
checking for its native switch/case statements.)&lt;/p&gt;
&lt;p&gt;Alternatively you could make all of the subclasses anonymous and expose them
as factory methods, if your language allows it:&lt;/p&gt;
&lt;div class="sourceCode" id="cb12"&gt;&lt;pre class="sourceCode java"&gt;&lt;code class="sourceCode java"&gt;&lt;span id="cb12-1"&gt;&lt;a href="#cb12-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;abstract&lt;/span&gt; &lt;span class="kw"&gt;class&lt;/span&gt; Expr &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-2"&gt;&lt;a href="#cb12-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="kw"&gt;abstract&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; R &lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;ExprVisitor&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; visitor&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-3"&gt;&lt;a href="#cb12-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb12-4"&gt;&lt;a href="#cb12-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="dt"&gt;static&lt;/span&gt; Expr &lt;span class="fu"&gt;lit&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dt"&gt;int&lt;/span&gt; value&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-5"&gt;&lt;a href="#cb12-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="kw"&gt;new&lt;/span&gt; &lt;span class="fu"&gt;Expr&lt;/span&gt;&lt;span class="op"&gt;()&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-6"&gt;&lt;a href="#cb12-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="at"&gt;@Override&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-7"&gt;&lt;a href="#cb12-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; R &lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;ExprVisitor&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; visitor&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-8"&gt;&lt;a href="#cb12-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="cf"&gt;return&lt;/span&gt; visitor&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;visitLit&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;value&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-9"&gt;&lt;a href="#cb12-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-10"&gt;&lt;a href="#cb12-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-11"&gt;&lt;a href="#cb12-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-12"&gt;&lt;a href="#cb12-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb12-13"&gt;&lt;a href="#cb12-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="dt"&gt;static&lt;/span&gt; Expr &lt;span class="fu"&gt;negate&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;Expr unary&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-14"&gt;&lt;a href="#cb12-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="kw"&gt;new&lt;/span&gt; &lt;span class="fu"&gt;Expr&lt;/span&gt;&lt;span class="op"&gt;()&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-15"&gt;&lt;a href="#cb12-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="at"&gt;@Override&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-16"&gt;&lt;a href="#cb12-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; R &lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;ExprVisitor&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; visitor&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-17"&gt;&lt;a href="#cb12-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="cf"&gt;return&lt;/span&gt; visitor&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;visitNegate&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;unary&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-18"&gt;&lt;a href="#cb12-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-19"&gt;&lt;a href="#cb12-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-20"&gt;&lt;a href="#cb12-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-21"&gt;&lt;a href="#cb12-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb12-22"&gt;&lt;a href="#cb12-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="dt"&gt;static&lt;/span&gt; Expr &lt;span class="fu"&gt;add&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;Expr left&lt;span class="op"&gt;,&lt;/span&gt; Expr right&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-23"&gt;&lt;a href="#cb12-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="kw"&gt;new&lt;/span&gt; &lt;span class="fu"&gt;Expr&lt;/span&gt;&lt;span class="op"&gt;()&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-24"&gt;&lt;a href="#cb12-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="at"&gt;@Override&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-25"&gt;&lt;a href="#cb12-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; R &lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;ExprVisitor&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; visitor&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-26"&gt;&lt;a href="#cb12-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="cf"&gt;return&lt;/span&gt; visitor&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;visitAdd&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;left&lt;span class="op"&gt;,&lt;/span&gt; right&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-27"&gt;&lt;a href="#cb12-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-28"&gt;&lt;a href="#cb12-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-29"&gt;&lt;a href="#cb12-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-30"&gt;&lt;a href="#cb12-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb12-31"&gt;&lt;a href="#cb12-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="co"&gt;// ... etc&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-32"&gt;&lt;a href="#cb12-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You’d then call using:&lt;/p&gt;
&lt;div class="sourceCode" id="cb13"&gt;&lt;pre class="sourceCode java"&gt;&lt;code class="sourceCode java"&gt;&lt;span id="cb13-1"&gt;&lt;a href="#cb13-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="kw"&gt;class&lt;/span&gt; Main &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-2"&gt;&lt;a href="#cb13-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="dt"&gt;static&lt;/span&gt; &lt;span class="dt"&gt;void&lt;/span&gt; &lt;span class="fu"&gt;main&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="bu"&gt;String&lt;/span&gt;&lt;span class="op"&gt;[]&lt;/span&gt; args&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-3"&gt;&lt;a href="#cb13-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        Expr expr &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;new&lt;/span&gt; &lt;span class="fu"&gt;Mul&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="kw"&gt;new&lt;/span&gt; &lt;span class="fu"&gt;Negate&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="kw"&gt;new&lt;/span&gt; &lt;span class="fu"&gt;Add&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="kw"&gt;new&lt;/span&gt; &lt;span class="fu"&gt;Lit&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dv"&gt;4&lt;/span&gt;&lt;span class="op"&gt;),&lt;/span&gt; &lt;span class="kw"&gt;new&lt;/span&gt; &lt;span class="fu"&gt;Lit&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dv"&gt;5&lt;/span&gt;&lt;span class="op"&gt;))),&lt;/span&gt; &lt;span class="kw"&gt;new&lt;/span&gt; &lt;span class="fu"&gt;Lit&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dv"&gt;8&lt;/span&gt;&lt;span class="op"&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-4"&gt;&lt;a href="#cb13-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="co"&gt;// or&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-5"&gt;&lt;a href="#cb13-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="co"&gt;// Expr expr = Eval.mul(Eval.negate(Eval.add(Eval.lit(4), Eval.lit(5))), Eval.lit(8));&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-6"&gt;&lt;a href="#cb13-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb13-7"&gt;&lt;a href="#cb13-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ExprVisitor&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;&lt;span class="bu"&gt;Integer&lt;/span&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; eval &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;new&lt;/span&gt; ExprVisitor&lt;span class="op"&gt;&amp;lt;&amp;gt;()&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-8"&gt;&lt;a href="#cb13-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="at"&gt;@Override&lt;/span&gt; &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="bu"&gt;Integer&lt;/span&gt; &lt;span class="fu"&gt;visitLit&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dt"&gt;int&lt;/span&gt; value&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-9"&gt;&lt;a href="#cb13-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="cf"&gt;return&lt;/span&gt; value&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-10"&gt;&lt;a href="#cb13-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-11"&gt;&lt;a href="#cb13-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="at"&gt;@Override&lt;/span&gt; &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="bu"&gt;Integer&lt;/span&gt; &lt;span class="fu"&gt;visitNegate&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;Expr unary&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-12"&gt;&lt;a href="#cb13-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="op"&gt;-&lt;/span&gt;unary&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="kw"&gt;this&lt;/span&gt;&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-13"&gt;&lt;a href="#cb13-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-14"&gt;&lt;a href="#cb13-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="at"&gt;@Override&lt;/span&gt; &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="bu"&gt;Integer&lt;/span&gt; &lt;span class="fu"&gt;visitAdd&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;Expr left&lt;span class="op"&gt;,&lt;/span&gt; Expr right&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-15"&gt;&lt;a href="#cb13-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="cf"&gt;return&lt;/span&gt; left&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="kw"&gt;this&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; right&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="kw"&gt;this&lt;/span&gt;&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-16"&gt;&lt;a href="#cb13-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-17"&gt;&lt;a href="#cb13-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="at"&gt;@Override&lt;/span&gt; &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="bu"&gt;Integer&lt;/span&gt; &lt;span class="fu"&gt;visitMul&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;Expr left&lt;span class="op"&gt;,&lt;/span&gt; Expr right&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-18"&gt;&lt;a href="#cb13-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="cf"&gt;return&lt;/span&gt; left&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="kw"&gt;this&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; right&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="kw"&gt;this&lt;/span&gt;&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-19"&gt;&lt;a href="#cb13-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-20"&gt;&lt;a href="#cb13-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-21"&gt;&lt;a href="#cb13-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb13-22"&gt;&lt;a href="#cb13-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="bu"&gt;System&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;out&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;println&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="st"&gt;&amp;quot;Result: &amp;quot;&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; expr&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;eval&lt;span class="op"&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-23"&gt;&lt;a href="#cb13-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-24"&gt;&lt;a href="#cb13-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Passing around function references like this is actually pretty close to the
scott encoding of our data type — and for non-recursive types, it’s essentially
the church encoding.&lt;/p&gt;
&lt;h3 id="recursive-types"&gt;Recursive Types&lt;/h3&gt;
&lt;p&gt;Speaking of recursive types…what if your language doesn’t allow recursive
data types? What if it doesn’t allow recursion at all, or what if recursively
generated values are just annoying to deal with? Just imagine writing that
&lt;code&gt;Expr&lt;/code&gt; type in a language with explicit memory management, for
example. Or, what if you wanted a way to express your recursive types in a more
elegant and runtime-safe manner?&lt;/p&gt;
&lt;p&gt;One thing you can instead do is have your visitor be in its “catamorphism”,
or church encoding. Instead of having the “visitor” take the recursive
sub-values, instead have it return the result of recursively applying
itself.&lt;/p&gt;
&lt;p&gt;Let’s do this in &lt;em&gt;dhall&lt;/em&gt;, one of the most famous non-recursive
languages. Dhall &lt;em&gt;does&lt;/em&gt; have native sum types, so we won’t worry about
manually writing a visitor pattern. But it does &lt;em&gt;not&lt;/em&gt; have recursive data
types.&lt;/p&gt;
&lt;p&gt;Let’s define a type like:&lt;/p&gt;
&lt;div class="sourceCode" id="cb14"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb14-1"&gt;&lt;a href="#cb14-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Lit&lt;/span&gt; &lt;span class="dt"&gt;Natural&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb14-2"&gt;&lt;a href="#cb14-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;Add&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb14-3"&gt;&lt;a href="#cb14-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;Mul&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But we can’t define data types in dhall that refer to themselves. So instead,
we can define them in their “church encoding”: give what you would do with an
&lt;code&gt;Expr&lt;/code&gt; to consume it, where the consumption function is given as if
it were recursively applied.&lt;/p&gt;
&lt;div class="sourceCode" id="cb15"&gt;&lt;pre class="sourceCode dhall"&gt;&lt;code class="sourceCode "&gt;&lt;span id="cb15-1"&gt;&lt;a href="#cb15-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;let&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;ExprF&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Type&lt;/span&gt;
&lt;span id="cb15-2"&gt;&lt;a href="#cb15-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;      &lt;/span&gt;=&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(r&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb15-3"&gt;&lt;a href="#cb15-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;{&lt;span class="co"&gt; &lt;/span&gt;lit&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Natural&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;r&lt;/span&gt;
&lt;span id="cb15-4"&gt;&lt;a href="#cb15-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;,&lt;span class="co"&gt; &lt;/span&gt;add&lt;span class="co"&gt;    &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;r&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;r&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;r&lt;/span&gt;
&lt;span id="cb15-5"&gt;&lt;a href="#cb15-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;,&lt;span class="co"&gt; &lt;/span&gt;mul&lt;span class="co"&gt;    &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;r&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;r&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;r&lt;/span&gt;
&lt;span id="cb15-6"&gt;&lt;a href="#cb15-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;}&lt;/span&gt;
&lt;span id="cb15-7"&gt;&lt;a href="#cb15-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb15-8"&gt;&lt;a href="#cb15-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;let&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type&lt;/span&gt;
&lt;span id="cb15-9"&gt;&lt;a href="#cb15-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;      &lt;/span&gt;=&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="kw"&gt;forall&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;(r&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;ExprF&lt;span class="co"&gt; &lt;/span&gt;r&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;r&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that &lt;code&gt;ExprF r&lt;/code&gt; is essentially
&lt;code&gt;ExprVisitor&amp;lt;R&amp;gt;&lt;/code&gt;, except instead of &lt;code&gt;add&lt;/code&gt; being
&lt;code&gt;Expr -&amp;gt; Expr -&amp;gt; r&lt;/code&gt;, it’s &lt;code&gt;r -&amp;gt; r -&amp;gt; r&lt;/code&gt;: the
input values aren’t the expression, but rather the results of recursively
folding on the expression. In fact, our original non-recursive
&lt;code&gt;ExprVisitor&amp;lt;R&amp;gt;&lt;/code&gt; (to be more precise, the
&lt;code&gt;R accept(ExprVisitor&amp;lt;R&amp;gt;)&lt;/code&gt;) is often called the “scott
encoding”, as opposed to the recursive “church encoding” fold.&lt;/p&gt;
&lt;p&gt;For value creation, you &lt;em&gt;take&lt;/em&gt; the visitor and recursively apply:&lt;/p&gt;
&lt;div class="sourceCode" id="cb16"&gt;&lt;pre class="sourceCode dhall"&gt;&lt;code class="sourceCode "&gt;&lt;span id="cb16-1"&gt;&lt;a href="#cb16-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;let&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;lit&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Natural&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;/span&gt;
&lt;span id="cb16-2"&gt;&lt;a href="#cb16-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;      &lt;/span&gt;=&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(x&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Natural)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-3"&gt;&lt;a href="#cb16-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(r&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-4"&gt;&lt;a href="#cb16-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(handlers&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;ExprF&lt;span class="co"&gt; &lt;/span&gt;r)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-5"&gt;&lt;a href="#cb16-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;            &lt;/span&gt;handlers.lit&lt;span class="co"&gt; &lt;/span&gt;x&lt;/span&gt;
&lt;span id="cb16-6"&gt;&lt;a href="#cb16-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb16-7"&gt;&lt;a href="#cb16-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;let&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;add&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;/span&gt;
&lt;span id="cb16-8"&gt;&lt;a href="#cb16-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;      &lt;/span&gt;=&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(left&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Expr)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-9"&gt;&lt;a href="#cb16-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(right&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Expr)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-10"&gt;&lt;a href="#cb16-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(r&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-11"&gt;&lt;a href="#cb16-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(handlers&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;ExprF&lt;span class="co"&gt; &lt;/span&gt;r)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-12"&gt;&lt;a href="#cb16-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;            &lt;/span&gt;handlers.add&lt;span class="co"&gt; &lt;/span&gt;(left&lt;span class="co"&gt; &lt;/span&gt;r&lt;span class="co"&gt; &lt;/span&gt;handlers)&lt;span class="co"&gt; &lt;/span&gt;(right&lt;span class="co"&gt; &lt;/span&gt;r&lt;span class="co"&gt; &lt;/span&gt;handlers)&lt;/span&gt;
&lt;span id="cb16-13"&gt;&lt;a href="#cb16-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb16-14"&gt;&lt;a href="#cb16-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;let&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;mul&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;/span&gt;
&lt;span id="cb16-15"&gt;&lt;a href="#cb16-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;      &lt;/span&gt;=&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(left&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Expr)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-16"&gt;&lt;a href="#cb16-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(right&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Expr)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-17"&gt;&lt;a href="#cb16-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(r&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-18"&gt;&lt;a href="#cb16-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(handlers&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;ExprF&lt;span class="co"&gt; &lt;/span&gt;r)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-19"&gt;&lt;a href="#cb16-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;            &lt;/span&gt;handlers.mul&lt;span class="co"&gt; &lt;/span&gt;(left&lt;span class="co"&gt; &lt;/span&gt;r&lt;span class="co"&gt; &lt;/span&gt;handlers)&lt;span class="co"&gt; &lt;/span&gt;(right&lt;span class="co"&gt; &lt;/span&gt;r&lt;span class="co"&gt; &lt;/span&gt;handlers)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And finally, &lt;em&gt;using&lt;/em&gt; the data type involves providing the
&lt;code&gt;handler&lt;/code&gt; to fold up from the bottom to top. Note that
&lt;code&gt;add : \(left : Natural) -&amp;gt; \(right : Natural) -&amp;gt; left + right&lt;/code&gt;
already assumes that the handler has been applied to the sub-expressions, so you
get &lt;code&gt;Natural&lt;/code&gt;s on both sides instead of &lt;code&gt;Expr&lt;/code&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb17"&gt;&lt;pre class="sourceCode dhall"&gt;&lt;code class="sourceCode "&gt;&lt;span id="cb17-1"&gt;&lt;a href="#cb17-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;let&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;eval&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Natural&lt;/span&gt;
&lt;span id="cb17-2"&gt;&lt;a href="#cb17-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;      &lt;/span&gt;=&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(e&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Expr)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb17-3"&gt;&lt;a href="#cb17-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;          &lt;/span&gt;e&lt;span class="co"&gt; &lt;/span&gt;Natural&lt;/span&gt;
&lt;span id="cb17-4"&gt;&lt;a href="#cb17-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;            &lt;/span&gt;{&lt;span class="co"&gt; &lt;/span&gt;lit&lt;span class="co"&gt; &lt;/span&gt;=&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(x&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Natural)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;x&lt;/span&gt;
&lt;span id="cb17-5"&gt;&lt;a href="#cb17-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;            &lt;/span&gt;,&lt;span class="co"&gt; &lt;/span&gt;add&lt;span class="co"&gt; &lt;/span&gt;=&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(left&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Natural)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(right&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Natural)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;left&lt;span class="co"&gt; &lt;/span&gt;+&lt;span class="co"&gt; &lt;/span&gt;right&lt;/span&gt;
&lt;span id="cb17-6"&gt;&lt;a href="#cb17-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;            &lt;/span&gt;,&lt;span class="co"&gt; &lt;/span&gt;mul&lt;span class="co"&gt; &lt;/span&gt;=&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(left&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Natural)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(right&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Natural)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;left&lt;span class="co"&gt; &lt;/span&gt;*&lt;span class="co"&gt; &lt;/span&gt;right&lt;/span&gt;
&lt;span id="cb17-7"&gt;&lt;a href="#cb17-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;            &lt;/span&gt;}&lt;/span&gt;
&lt;span id="cb17-8"&gt;&lt;a href="#cb17-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb17-9"&gt;&lt;a href="#cb17-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;let&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;testVal&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;/span&gt;
&lt;span id="cb17-10"&gt;&lt;a href="#cb17-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;      &lt;/span&gt;=&lt;span class="co"&gt; &lt;/span&gt;mul&lt;span class="co"&gt; &lt;/span&gt;(add&lt;span class="co"&gt; &lt;/span&gt;(lit&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="dv"&gt;4&lt;/span&gt;)&lt;span class="co"&gt; &lt;/span&gt;(lit&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="dv"&gt;5&lt;/span&gt;))&lt;span class="co"&gt; &lt;/span&gt;(lit&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="dv"&gt;8&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb17-11"&gt;&lt;a href="#cb17-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb17-12"&gt;&lt;a href="#cb17-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;in&lt;/span&gt;&lt;span class="co"&gt;  &lt;/span&gt;&lt;span class="kw"&gt;assert&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;eval&lt;span class="co"&gt; &lt;/span&gt;testVal&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;===&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="dv"&gt;72&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This pattern is useful even in languages with good datatype recursion, like
Haskell — it’s actually the &lt;a
href="https://hackage.haskell.org/package/recursion-schemes"&gt;recursion-schemes&lt;/a&gt;
refactoring of a recursive data type, and it can be useful to have it live
alongside your normal recursive types. I’ve written &lt;a
href="https://blog.jle.im/entry/tries-with-recursion-schemes.html"&gt;this blog
post&lt;/a&gt; talking about how useful this pattern is to have alongside your normal
recursive types.&lt;/p&gt;
&lt;p&gt;This pattern is pretty portable to other languages too, as long as you can
scrounge together something like Rank-N types:&lt;/p&gt;
&lt;div class="sourceCode" id="cb18"&gt;&lt;pre class="sourceCode java"&gt;&lt;code class="sourceCode java"&gt;&lt;span id="cb18-1"&gt;&lt;a href="#cb18-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;interface&lt;/span&gt; ExprFold&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-2"&gt;&lt;a href="#cb18-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    R &lt;span class="fu"&gt;foldLit&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dt"&gt;int&lt;/span&gt; value&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-3"&gt;&lt;a href="#cb18-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    R &lt;span class="fu"&gt;foldNegate&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;R unary&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-4"&gt;&lt;a href="#cb18-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    R &lt;span class="fu"&gt;foldAdd&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;R left&lt;span class="op"&gt;,&lt;/span&gt; R right&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-5"&gt;&lt;a href="#cb18-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    R &lt;span class="fu"&gt;foldMul&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;R left&lt;span class="op"&gt;,&lt;/span&gt; R right&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-6"&gt;&lt;a href="#cb18-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-7"&gt;&lt;a href="#cb18-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb18-8"&gt;&lt;a href="#cb18-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;interface&lt;/span&gt; Expr &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-9"&gt;&lt;a href="#cb18-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="kw"&gt;abstract&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; R &lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;ExprFold&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; fold&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-10"&gt;&lt;a href="#cb18-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb18-11"&gt;&lt;a href="#cb18-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="dt"&gt;static&lt;/span&gt; Expr &lt;span class="fu"&gt;lit&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="dt"&gt;int&lt;/span&gt; value&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-12"&gt;&lt;a href="#cb18-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="kw"&gt;new&lt;/span&gt; &lt;span class="fu"&gt;Expr&lt;/span&gt;&lt;span class="op"&gt;()&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-13"&gt;&lt;a href="#cb18-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="at"&gt;@Override&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-14"&gt;&lt;a href="#cb18-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; R &lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;ExprFold&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; fold&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-15"&gt;&lt;a href="#cb18-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="cf"&gt;return&lt;/span&gt; fold&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;foldLit&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;value&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-16"&gt;&lt;a href="#cb18-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-17"&gt;&lt;a href="#cb18-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-18"&gt;&lt;a href="#cb18-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-19"&gt;&lt;a href="#cb18-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb18-20"&gt;&lt;a href="#cb18-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="dt"&gt;static&lt;/span&gt; Expr &lt;span class="fu"&gt;negate&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;Expr unary&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-21"&gt;&lt;a href="#cb18-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="kw"&gt;new&lt;/span&gt; &lt;span class="fu"&gt;Expr&lt;/span&gt;&lt;span class="op"&gt;()&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-22"&gt;&lt;a href="#cb18-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="at"&gt;@Override&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-23"&gt;&lt;a href="#cb18-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; R &lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;ExprFold&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; fold&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-24"&gt;&lt;a href="#cb18-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="cf"&gt;return&lt;/span&gt; fold&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;foldNegate&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;unary&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;fold&lt;span class="op"&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-25"&gt;&lt;a href="#cb18-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-26"&gt;&lt;a href="#cb18-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-27"&gt;&lt;a href="#cb18-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-28"&gt;&lt;a href="#cb18-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb18-29"&gt;&lt;a href="#cb18-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="co"&gt;// etc.&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-30"&gt;&lt;a href="#cb18-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By “Rank-N types” here, I mean that your objects can generate polymorphic
functions: given an &lt;code&gt;Expr&lt;/code&gt;, you could &lt;em&gt;generate&lt;/em&gt; an
&lt;code&gt;&amp;lt;R&amp;gt; R accept(ExprFold &amp;lt;R&amp;gt; fold)&lt;/code&gt; for any &lt;code&gt;R&lt;/code&gt;,
and not something pre-determined or pre-chosen by your choice of representation
of &lt;code&gt;Expr&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="generalized-algebraic-data-types"&gt;Generalized Algebraic Data Types&lt;/h2&gt;
&lt;p&gt;You’ve implemented ADTs in your language of choice, or you are currently in a
language with native ADTs. Life is good, right? Until that sneaky voice starts
whispering in your hear: “we need more type safety.” You resist that urge, maybe
even get a lot done without it, but eventually you are compelled to give in and
embrace the warm yet harsh embrace of ultimate type safety. Now what?&lt;/p&gt;
&lt;h3 id="singletons-and-witnesses"&gt;Singletons and Witnesses&lt;/h3&gt;
&lt;p&gt;In Haskell, singletons are essentially enums used to associate a value with a
reifiable type. “Reifiable” here means that you can take the runtime value of a
singleton and use it to bring evidence to the type-level. I ran into a
real-world usage of this while writing &lt;a href="https://coronavirus.jle.im/"
class="uri"&gt;https://coronavirus.jle.im/&lt;/a&gt;, a web-based data visualizer of
COVID-19 data (&lt;a
href="https://github.com/mstksg/corona-charts/tree/master"&gt;source here&lt;/a&gt;) in
purescript. I needed a singleton to represent &lt;em&gt;scales&lt;/em&gt; for scatter plots
and linking them to the data that can be plotted. And, not only did it need to
be type-safe in purescript (which has ADTs but not GADTs), it had to be
type-safe in the javascript ffi as well.&lt;/p&gt;
&lt;p&gt;Here’s how it might look in Haskell:&lt;/p&gt;
&lt;div class="sourceCode" id="cb19"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb19-1"&gt;&lt;a href="#cb19-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- | Numeric types&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-2"&gt;&lt;a href="#cb19-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-3"&gt;&lt;a href="#cb19-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;NInt&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-4"&gt;&lt;a href="#cb19-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;NDouble&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; &lt;span class="dt"&gt;Double&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-5"&gt;&lt;a href="#cb19-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;NPercent&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; &lt;span class="dt"&gt;Percent&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-6"&gt;&lt;a href="#cb19-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb19-7"&gt;&lt;a href="#cb19-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- | Define a scale&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-8"&gt;&lt;a href="#cb19-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Scale&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-9"&gt;&lt;a href="#cb19-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;ScaleDate&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Scale&lt;/span&gt; &lt;span class="dt"&gt;Date&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-10"&gt;&lt;a href="#cb19-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;ScaleLinear&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Scale&lt;/span&gt; a   &lt;span class="co"&gt;-- ^ whether to include zero in the axis or not&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-11"&gt;&lt;a href="#cb19-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;ScaleLog&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Scale&lt;/span&gt; a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You’d then run it like this:&lt;/p&gt;
&lt;div class="sourceCode" id="cb20"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb20-1"&gt;&lt;a href="#cb20-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;plot ::&lt;/span&gt; &lt;span class="dt"&gt;Scale&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Scale&lt;/span&gt; b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; [(a, b)] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Canvas&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So, we have the &lt;em&gt;type&lt;/em&gt; of the input tuples being determined by the
&lt;em&gt;values&lt;/em&gt; you pass to &lt;code&gt;plot&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb21"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb21-1"&gt;&lt;a href="#cb21-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;:&lt;/span&gt;t plot &lt;span class="dt"&gt;ScaleDate&lt;/span&gt; (&lt;span class="dt"&gt;ScaleLinear&lt;/span&gt; &lt;span class="dt"&gt;True&lt;/span&gt; (&lt;span class="dt"&gt;LNumeric&lt;/span&gt; &lt;span class="dt"&gt;NInt&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb21-2"&gt;&lt;a href="#cb21-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;[(&lt;span class="dt"&gt;Date&lt;/span&gt;, &lt;span class="dt"&gt;Int&lt;/span&gt;)] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Canvas&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But let’s say we only had ADTs. And then we’re passing them down to a
javascript FFI which only has structs and functions. We could drop the
type-safety and instead error on runtime, but…no. Type unsafety is not
acceptable.&lt;/p&gt;
&lt;p&gt;The fundamental ability we want to gain is that if we pattern match on
&lt;code&gt;ScaleDate&lt;/code&gt;, then we &lt;em&gt;know&lt;/em&gt; &lt;code&gt;a&lt;/code&gt; has to be
&lt;code&gt;Date&lt;/code&gt;. If we match on &lt;code&gt;NInt&lt;/code&gt;, we know that &lt;code&gt;a&lt;/code&gt;
&lt;em&gt;has&lt;/em&gt; to be &lt;code&gt;Int&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For the sake of this example, we’re going to be implementing a simpler
function in purescript and in javascript: a function that takes a scale type and
a list of points prints the bounds. In Haskell, this looks like:&lt;/p&gt;
&lt;div class="sourceCode" id="cb22"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb22-1"&gt;&lt;a href="#cb22-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;AxisBounds&lt;/span&gt; a &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;AB&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-2"&gt;&lt;a href="#cb22-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    {&lt;span class="ot"&gt; minValue ::&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb22-3"&gt;&lt;a href="#cb22-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ,&lt;span class="ot"&gt; minLabel ::&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-4"&gt;&lt;a href="#cb22-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ,&lt;span class="ot"&gt; maxValue ::&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb22-5"&gt;&lt;a href="#cb22-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ,&lt;span class="ot"&gt; maxLabel ::&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-6"&gt;&lt;a href="#cb22-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    }&lt;/span&gt;
&lt;span id="cb22-7"&gt;&lt;a href="#cb22-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb22-8"&gt;&lt;a href="#cb22-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;displayAxis ::&lt;/span&gt; &lt;span class="dt"&gt;Scale&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; [a] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;AxisBounds&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb22-9"&gt;&lt;a href="#cb22-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;displayAxis &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-10"&gt;&lt;a href="#cb22-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;ScaleDate&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-11"&gt;&lt;a href="#cb22-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="kw"&gt;let&lt;/span&gt; xMin &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;minimum&lt;/span&gt; xs&lt;/span&gt;
&lt;span id="cb22-12"&gt;&lt;a href="#cb22-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          xMax &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;maximum&lt;/span&gt; xs&lt;/span&gt;
&lt;span id="cb22-13"&gt;&lt;a href="#cb22-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="dt"&gt;AB&lt;/span&gt; xMin (showDate xMin) xMax (showDate xMax)&lt;/span&gt;
&lt;span id="cb22-14"&gt;&lt;a href="#cb22-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;ScaleLinear&lt;/span&gt; hasZero nt &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-15"&gt;&lt;a href="#cb22-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      displayNumericAxis (&lt;span class="kw"&gt;if&lt;/span&gt; hasZero &lt;span class="kw"&gt;then&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt;xs &lt;span class="kw"&gt;else&lt;/span&gt; xs)&lt;/span&gt;
&lt;span id="cb22-16"&gt;&lt;a href="#cb22-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;ScaleLog&lt;/span&gt; nt &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-17"&gt;&lt;a href="#cb22-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      displayNumericAxis nt xs&lt;/span&gt;
&lt;span id="cb22-18"&gt;&lt;a href="#cb22-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb22-19"&gt;&lt;a href="#cb22-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;displayNumericAxis ::&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; [a] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;AxisBounds&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb22-20"&gt;&lt;a href="#cb22-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;displayNumericAxis &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-21"&gt;&lt;a href="#cb22-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;NInt&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-22"&gt;&lt;a href="#cb22-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="kw"&gt;let&lt;/span&gt; xMin &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;minimum&lt;/span&gt; xs&lt;/span&gt;
&lt;span id="cb22-23"&gt;&lt;a href="#cb22-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          xMax &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;maximum&lt;/span&gt; xs&lt;/span&gt;
&lt;span id="cb22-24"&gt;&lt;a href="#cb22-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="dt"&gt;AB&lt;/span&gt; xMin (printf &lt;span class="st"&gt;&amp;quot;%d&amp;quot;&lt;/span&gt; xMin) xMax (printf &lt;span class="st"&gt;&amp;quot;%d&amp;quot;&lt;/span&gt; xMax)&lt;/span&gt;
&lt;span id="cb22-25"&gt;&lt;a href="#cb22-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;NDouble&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-26"&gt;&lt;a href="#cb22-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="kw"&gt;let&lt;/span&gt; xMin &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;minimum&lt;/span&gt; xs&lt;/span&gt;
&lt;span id="cb22-27"&gt;&lt;a href="#cb22-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          xMax &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;maximum&lt;/span&gt; xs&lt;/span&gt;
&lt;span id="cb22-28"&gt;&lt;a href="#cb22-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="dt"&gt;AB&lt;/span&gt; xMin (printf &lt;span class="st"&gt;&amp;quot;%.4f&amp;quot;&lt;/span&gt; xMin) xMax (printf &lt;span class="st"&gt;&amp;quot;%.4f&amp;quot;&lt;/span&gt; xMax)&lt;/span&gt;
&lt;span id="cb22-29"&gt;&lt;a href="#cb22-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;NPercent&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-30"&gt;&lt;a href="#cb22-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="kw"&gt;let&lt;/span&gt; xMin &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;minimum&lt;/span&gt; xs&lt;/span&gt;
&lt;span id="cb22-31"&gt;&lt;a href="#cb22-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          xMax &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;maximum&lt;/span&gt; xs&lt;/span&gt;
&lt;span id="cb22-32"&gt;&lt;a href="#cb22-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="dt"&gt;AB&lt;/span&gt; xMin (printf &lt;span class="st"&gt;&amp;quot;%.1f%%&amp;quot;&lt;/span&gt; (xMin&lt;span class="op"&gt;*&lt;/span&gt;&lt;span class="dv"&gt;100&lt;/span&gt;)) xMax (printf &lt;span class="st"&gt;&amp;quot;%.1f%%&amp;quot;&lt;/span&gt; (xMax&lt;span class="op"&gt;*&lt;/span&gt;&lt;span class="dv"&gt;100&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(Pretend the &lt;code&gt;Percent&lt;/code&gt; type is just a newtype-wrapped
&lt;code&gt;Float&lt;/code&gt; or something)&lt;/p&gt;
&lt;p&gt;There are at least two main approaches to do this. We’ll be discussing
runtime equality witnesses and Higher-Kinded Eliminators.&lt;/p&gt;
&lt;h4 id="runtime-witnesses-and-coyoneda-embedding"&gt;Runtime Witnesses and Coyoneda
Embedding&lt;/h4&gt;
&lt;p&gt;The &lt;a href="https://ncatlab.org/nlab/show/Yoneda+embedding"&gt;Yoneda Lemma&lt;/a&gt;
is one of the most powerful tools that Category Theory has yielded as a branch
of math, but its sibling &lt;a
href="https://hackage.haskell.org/package/kan-extensions/docs/Data-Functor-Coyoneda.html"&gt;coyoneda&lt;/a&gt;
is one of the most useful Haskell abstractions.&lt;/p&gt;
&lt;p&gt;This doesn’t give you GADTs, but it’s a very lightweight way to “downgrade”
your GADTs into normal GADTs which is appropriate if you don’t need the full
power.&lt;/p&gt;
&lt;p&gt;The trick is this: if you have &lt;code&gt;MyGADT a&lt;/code&gt;, and you know you are
going to be using it to &lt;em&gt;produce&lt;/em&gt; &lt;code&gt;a&lt;/code&gt;s, you can do a covariant
coyoneda transform.&lt;/p&gt;
&lt;p&gt;For example, if you have this type representing potential data sources:&lt;/p&gt;
&lt;div class="sourceCode" id="cb23"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb23-1"&gt;&lt;a href="#cb23-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Source&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-2"&gt;&lt;a href="#cb23-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;ByteSource&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Handle&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Source&lt;/span&gt; &lt;span class="dt"&gt;Word&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-3"&gt;&lt;a href="#cb23-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;StringSource&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;FilePath&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Source&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-4"&gt;&lt;a href="#cb23-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb23-5"&gt;&lt;a href="#cb23-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;readByte ::&lt;/span&gt; &lt;span class="dt"&gt;Handle&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; &lt;span class="dt"&gt;Word&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-6"&gt;&lt;a href="#cb23-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;readString ::&lt;/span&gt; &lt;span class="dt"&gt;FilePath&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-7"&gt;&lt;a href="#cb23-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb23-8"&gt;&lt;a href="#cb23-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;readSource ::&lt;/span&gt; &lt;span class="dt"&gt;Source&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb23-9"&gt;&lt;a href="#cb23-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;readSource &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-10"&gt;&lt;a href="#cb23-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;ByteSource&lt;/span&gt; h &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; readByte h&lt;/span&gt;
&lt;span id="cb23-11"&gt;&lt;a href="#cb23-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;StringSource&lt;/span&gt; fp &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; readString fp&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You could instead turn &lt;code&gt;Source&lt;/code&gt; into a non-GADT by making it a
normal parameterized ADT and adding a &lt;code&gt;X -&amp;gt; a&lt;/code&gt; field, which is a
type of CPS transformation:&lt;/p&gt;
&lt;div class="sourceCode" id="cb24"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb24-1"&gt;&lt;a href="#cb24-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Source&lt;/span&gt; a &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-2"&gt;&lt;a href="#cb24-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;ByteSource&lt;/span&gt; &lt;span class="dt"&gt;Handle&lt;/span&gt; (&lt;span class="dt"&gt;Word&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a)&lt;/span&gt;
&lt;span id="cb24-3"&gt;&lt;a href="#cb24-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;StringSource&lt;/span&gt; &lt;span class="dt"&gt;FilePath&lt;/span&gt; (&lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a)&lt;/span&gt;
&lt;span id="cb24-4"&gt;&lt;a href="#cb24-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb24-5"&gt;&lt;a href="#cb24-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;byteSource ::&lt;/span&gt; &lt;span class="dt"&gt;Handle&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Source&lt;/span&gt; &lt;span class="dt"&gt;Word&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-6"&gt;&lt;a href="#cb24-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;byteSource h &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;ByteSource&lt;/span&gt; h &lt;span class="fu"&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-7"&gt;&lt;a href="#cb24-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb24-8"&gt;&lt;a href="#cb24-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;stringSource ::&lt;/span&gt; &lt;span class="dt"&gt;FilePath&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Source&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-9"&gt;&lt;a href="#cb24-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;stringSource fp &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;StringSource&lt;/span&gt; fp &lt;span class="fu"&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-10"&gt;&lt;a href="#cb24-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb24-11"&gt;&lt;a href="#cb24-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;readSource ::&lt;/span&gt; &lt;span class="dt"&gt;Source&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb24-12"&gt;&lt;a href="#cb24-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;readSource &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-13"&gt;&lt;a href="#cb24-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;ByteSource&lt;/span&gt; h out &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; out &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; readByte h&lt;/span&gt;
&lt;span id="cb24-14"&gt;&lt;a href="#cb24-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;StringSource&lt;/span&gt; fp out &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; out &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; readString fp&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A nice benefit of this method is that &lt;code&gt;Source&lt;/code&gt; can now have a
&lt;code&gt;Functor&lt;/code&gt; instance, which the original GADT could not.&lt;/p&gt;
&lt;p&gt;And, if &lt;code&gt;MyGADT a&lt;/code&gt; is going to be &lt;em&gt;consuming&lt;/em&gt;
&lt;code&gt;a&lt;/code&gt;s, you can do the &lt;a
href="https://hackage.haskell.org/package/kan-extensions/docs/Data-Functor-Contravariant-Coyoneda.html"&gt;contravariant
coyoneda&lt;/a&gt; transform:&lt;/p&gt;
&lt;div class="sourceCode" id="cb25"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb25-1"&gt;&lt;a href="#cb25-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Sink&lt;/span&gt; a &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb25-2"&gt;&lt;a href="#cb25-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;ByteSink&lt;/span&gt; &lt;span class="dt"&gt;Handle&lt;/span&gt; (a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Word&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb25-3"&gt;&lt;a href="#cb25-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;StringSink&lt;/span&gt; &lt;span class="dt"&gt;FilePath&lt;/span&gt; (a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This gives it a free &lt;a
href="https://hackage.haskell.org/package/base/docs/Data-Functor-Contravariant.html"&gt;Contravariant&lt;/a&gt;
instance too!&lt;/p&gt;
&lt;p&gt;And, if you are going to be both consuming and producing &lt;code&gt;a&lt;/code&gt;s, you
can do the &lt;em&gt;invariant coyoneda&lt;/em&gt; transform&lt;/p&gt;
&lt;div class="sourceCode" id="cb26"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb26-1"&gt;&lt;a href="#cb26-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Interface&lt;/span&gt; a &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb26-2"&gt;&lt;a href="#cb26-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;ByteInterface&lt;/span&gt; &lt;span class="dt"&gt;Handle&lt;/span&gt; (&lt;span class="dt"&gt;Word&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a) (a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Word&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb26-3"&gt;&lt;a href="#cb26-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;StringInterface&lt;/span&gt; &lt;span class="dt"&gt;FilePath&lt;/span&gt; (&lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a) (&lt;span class="dt"&gt;Word&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;However, in practice, &lt;em&gt;true equality&lt;/em&gt; involves being able to lift
under injective type constructors, and carrying &lt;em&gt;every single&lt;/em&gt;
continuation is unwieldy. We can package them up together with a &lt;strong&gt;runtime
equality witness&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This is something we can put “inside” &lt;code&gt;NInt&lt;/code&gt; such that, when we
pattern match on a &lt;code&gt;NType a&lt;/code&gt;, the type system can be assured that
&lt;code&gt;a&lt;/code&gt; is an &lt;code&gt;Int&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You need some sort of data of type &lt;code&gt;IsEq a b&lt;/code&gt; with functions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;refl :: IsEq a a&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;to :: IsEq a b -&amp;gt; a -&amp;gt; b&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sym :: IsEq a b -&amp;gt; IsEq b a&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;trans :: IsEq a b -&amp;gt; IsEq b c -&amp;gt; IsEq a c&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;inj :: IsEq (f a) (f b) -&amp;gt; IsEq a b&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you have &lt;code&gt;to&lt;/code&gt; and &lt;code&gt;sym&lt;/code&gt; you also get
&lt;code&gt;from :: IsEq a b -&amp;gt; b -&amp;gt; a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;From all of this, we can recover our original
&lt;code&gt;IsEq a Word -&amp;gt; Word -&amp;gt; a&lt;/code&gt; and
&lt;code&gt;IsEq a Word -&amp;gt; a -&amp;gt; Word&lt;/code&gt; functions, saving us from having to
put two functions.&lt;/p&gt;
&lt;p&gt;Your language of choice might already have this &lt;code&gt;IsEq&lt;/code&gt;. But one of
the more interesting ways to me is Leibniz equality (discussed a lot in &lt;a
href="https://ryanglscott.github.io/2021/08/22/leibniz-equality-in-haskell-part-1/"&gt;this
Ryan Scott post&lt;/a&gt;), which works in languages with higher-kinded polymorphism.
Leibniz quality in languages with higher-kinded polymorphism means that
&lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; are equal if
&lt;code&gt;forall p. p a -&amp;gt; p b&lt;/code&gt;: any property of &lt;code&gt;a&lt;/code&gt; is also
true of &lt;code&gt;b&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In Haskell, we write this like:&lt;/p&gt;
&lt;div class="sourceCode" id="cb27"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb27-1"&gt;&lt;a href="#cb27-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;newtype&lt;/span&gt; &lt;span class="dt"&gt;Leibniz&lt;/span&gt; a b &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Leibniz&lt;/span&gt; (&lt;span class="kw"&gt;forall&lt;/span&gt; p&lt;span class="op"&gt;.&lt;/span&gt; p a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; p b)&lt;/span&gt;
&lt;span id="cb27-2"&gt;&lt;a href="#cb27-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb27-3"&gt;&lt;a href="#cb27-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;refl ::&lt;/span&gt; &lt;span class="dt"&gt;Leibniz&lt;/span&gt; a a&lt;/span&gt;
&lt;span id="cb27-4"&gt;&lt;a href="#cb27-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;refl &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Leibniz&lt;/span&gt; &lt;span class="fu"&gt;id&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The only possible way to construct a ‘Leibniz’ is with both type parameters
being the same: You can only ever &lt;em&gt;create&lt;/em&gt; a value of type
&lt;code&gt;Leibniz a a&lt;/code&gt;, never a value of &lt;code&gt;Leibniz a b&lt;/code&gt; where
&lt;code&gt;b&lt;/code&gt; is not &lt;code&gt;a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can prove that this is actually equality by writing functions
&lt;code&gt;Leibniz a b -&amp;gt; Leibniz b a&lt;/code&gt; and
&lt;code&gt;Leibniz a b -&amp;gt; Leibniz b c -&amp;gt; Leibniz a c&lt;/code&gt; (&lt;a
href="https://ryanglscott.github.io/2021/08/22/leibniz-equality-in-haskell-part-1/"&gt;this
Ryan Scott post&lt;/a&gt; goes over it well), but in practice we realize this equality
by safely coercing &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; back and forth:&lt;/p&gt;
&lt;div class="sourceCode" id="cb28"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb28-1"&gt;&lt;a href="#cb28-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;newtype&lt;/span&gt; &lt;span class="dt"&gt;Identity&lt;/span&gt; a &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Identity&lt;/span&gt; {&lt;span class="ot"&gt; runIdentity ::&lt;/span&gt; a }&lt;/span&gt;
&lt;span id="cb28-2"&gt;&lt;a href="#cb28-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb28-3"&gt;&lt;a href="#cb28-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;to ::&lt;/span&gt; &lt;span class="dt"&gt;Leibniz&lt;/span&gt; a b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; b&lt;/span&gt;
&lt;span id="cb28-4"&gt;&lt;a href="#cb28-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;to (&lt;span class="dt"&gt;Leibniz&lt;/span&gt; f) &lt;span class="ot"&gt;=&lt;/span&gt; runIdentity &lt;span class="op"&gt;.&lt;/span&gt; f &lt;span class="op"&gt;.&lt;/span&gt; &lt;span class="dt"&gt;Identity&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-5"&gt;&lt;a href="#cb28-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb28-6"&gt;&lt;a href="#cb28-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;newtype&lt;/span&gt; &lt;span class="dt"&gt;Op&lt;/span&gt; a b &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Op&lt;/span&gt; {&lt;span class="ot"&gt; getOp ::&lt;/span&gt; b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a }&lt;/span&gt;
&lt;span id="cb28-7"&gt;&lt;a href="#cb28-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb28-8"&gt;&lt;a href="#cb28-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;from ::&lt;/span&gt; &lt;span class="dt"&gt;Leibniz&lt;/span&gt; a b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb28-9"&gt;&lt;a href="#cb28-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;from (&lt;span class="dt"&gt;Leibniz&lt;/span&gt; f) &lt;span class="ot"&gt;=&lt;/span&gt; getOp (f (&lt;span class="dt"&gt;Op&lt;/span&gt; &lt;span class="fu"&gt;id&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So, if your language supports higher-kinded Rank-2 types, you have a
solution!&lt;/p&gt;
&lt;p&gt;There are other solutions in other languages, but they will usually all be
language-dependent.&lt;/p&gt;
&lt;p&gt;Let’s write everything in purescript. The key difference is we use
&lt;code&gt;map (to isNumber) :: Array a -&amp;gt; Array Number&lt;/code&gt;, etc., to get our
&lt;code&gt;Array&lt;/code&gt; as something we know it has the type of.&lt;/p&gt;
&lt;div class="sourceCode" id="cb29"&gt;&lt;pre
class="sourceCode purescript"&gt;&lt;code class="sourceCode purescript"&gt;&lt;span id="cb29-1"&gt;&lt;a href="#cb29-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Text.Printf&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-2"&gt;&lt;a href="#cb29-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-3"&gt;&lt;a href="#cb29-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;newtype&lt;/span&gt; &lt;span class="dt"&gt;Leibniz&lt;/span&gt; a b &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Leibniz&lt;/span&gt; (&lt;span class="kw"&gt;forall&lt;/span&gt; p&lt;span class="op"&gt;.&lt;/span&gt; p a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; p b)&lt;/span&gt;
&lt;span id="cb29-4"&gt;&lt;a href="#cb29-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-5"&gt;&lt;a href="#cb29-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;to ::&lt;/span&gt; &lt;span class="dt"&gt;Leibniz&lt;/span&gt; a b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; b&lt;/span&gt;
&lt;span id="cb29-6"&gt;&lt;a href="#cb29-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;from ::&lt;/span&gt; &lt;span class="dt"&gt;Leibniz&lt;/span&gt; a b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb29-7"&gt;&lt;a href="#cb29-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-8"&gt;&lt;a href="#cb29-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; a &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-9"&gt;&lt;a href="#cb29-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;NInt&lt;/span&gt; (&lt;span class="dt"&gt;Leibniz&lt;/span&gt; a &lt;span class="dt"&gt;Int&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb29-10"&gt;&lt;a href="#cb29-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;NNumber&lt;/span&gt; (&lt;span class="dt"&gt;Leibniz&lt;/span&gt; a &lt;span class="dt"&gt;Number&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb29-11"&gt;&lt;a href="#cb29-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;NPercent&lt;/span&gt; (&lt;span class="dt"&gt;Leibniz&lt;/span&gt; a &lt;span class="dt"&gt;Percent&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb29-12"&gt;&lt;a href="#cb29-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-13"&gt;&lt;a href="#cb29-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;AxisBounds&lt;/span&gt; a &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-14"&gt;&lt;a href="#cb29-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    {&lt;span class="ot"&gt; minValue ::&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb29-15"&gt;&lt;a href="#cb29-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ,&lt;span class="ot"&gt; minLabel ::&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-16"&gt;&lt;a href="#cb29-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ,&lt;span class="ot"&gt; maxValue ::&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb29-17"&gt;&lt;a href="#cb29-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ,&lt;span class="ot"&gt; maxLabel ::&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-18"&gt;&lt;a href="#cb29-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    }&lt;/span&gt;
&lt;span id="cb29-19"&gt;&lt;a href="#cb29-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-20"&gt;&lt;a href="#cb29-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;displayNumericAxis ::&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Array&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;AxisBounds&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb29-21"&gt;&lt;a href="#cb29-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;displayNumericAxis &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-22"&gt;&lt;a href="#cb29-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;NInt&lt;/span&gt; isInt &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-23"&gt;&lt;a href="#cb29-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="kw"&gt;let&lt;/span&gt; xMin &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;minimum&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="fu"&gt;map&lt;/span&gt; (to isInt) xs&lt;/span&gt;
&lt;span id="cb29-24"&gt;&lt;a href="#cb29-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          xMax &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;maximum&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="fu"&gt;map&lt;/span&gt; (to isInt) xs&lt;/span&gt;
&lt;span id="cb29-25"&gt;&lt;a href="#cb29-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          &lt;span class="fu"&gt;showInt&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;show&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-26"&gt;&lt;a href="#cb29-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       &lt;span class="kw"&gt;in&lt;/span&gt; { minValue&lt;span class="op"&gt;:&lt;/span&gt; xMin&lt;/span&gt;
&lt;span id="cb29-27"&gt;&lt;a href="#cb29-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          , minLabel&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;showInt&lt;/span&gt; xMin&lt;/span&gt;
&lt;span id="cb29-28"&gt;&lt;a href="#cb29-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          , maxValue&lt;span class="op"&gt;:&lt;/span&gt; xMax&lt;/span&gt;
&lt;span id="cb29-29"&gt;&lt;a href="#cb29-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          , maxLabel&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="fu"&gt;showInt&lt;/span&gt; xMax&lt;/span&gt;
&lt;span id="cb29-30"&gt;&lt;a href="#cb29-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          }&lt;/span&gt;
&lt;span id="cb29-31"&gt;&lt;a href="#cb29-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;NNumber&lt;/span&gt; isNumber &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-32"&gt;&lt;a href="#cb29-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="kw"&gt;let&lt;/span&gt; xMin &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;minimum&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="fu"&gt;map&lt;/span&gt; (to isNumber) xs&lt;/span&gt;
&lt;span id="cb29-33"&gt;&lt;a href="#cb29-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          xMax &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;maximum&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="fu"&gt;map&lt;/span&gt; (to isNumber) xs&lt;/span&gt;
&lt;span id="cb29-34"&gt;&lt;a href="#cb29-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          showFloat &lt;span class="ot"&gt;=&lt;/span&gt; printf (&lt;span class="dt"&gt;Proxy&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Proxy&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;%.4f&amp;quot;&lt;/span&gt;)   &lt;span class="co"&gt;-- it works a little differently&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-35"&gt;&lt;a href="#cb29-35" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       &lt;span class="kw"&gt;in&lt;/span&gt; { minValue&lt;span class="op"&gt;:&lt;/span&gt; xMin&lt;/span&gt;
&lt;span id="cb29-36"&gt;&lt;a href="#cb29-36" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          , minLabel&lt;span class="op"&gt;:&lt;/span&gt; showFloat xMin&lt;/span&gt;
&lt;span id="cb29-37"&gt;&lt;a href="#cb29-37" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          , maxValue&lt;span class="op"&gt;:&lt;/span&gt; xMax&lt;/span&gt;
&lt;span id="cb29-38"&gt;&lt;a href="#cb29-38" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          , maxLabel&lt;span class="op"&gt;:&lt;/span&gt; showFloat xMax&lt;/span&gt;
&lt;span id="cb29-39"&gt;&lt;a href="#cb29-39" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          }&lt;/span&gt;
&lt;span id="cb29-40"&gt;&lt;a href="#cb29-40" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;NPercent&lt;/span&gt; isPercent &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \xs &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-41"&gt;&lt;a href="#cb29-41" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="kw"&gt;let&lt;/span&gt; xMin &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;minimum&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="fu"&gt;map&lt;/span&gt; (to isPercent) xs&lt;/span&gt;
&lt;span id="cb29-42"&gt;&lt;a href="#cb29-42" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          xMax &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;maximum&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="fu"&gt;map&lt;/span&gt; (to isPercent) xs&lt;/span&gt;
&lt;span id="cb29-43"&gt;&lt;a href="#cb29-43" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          showPercent &lt;span class="ot"&gt;=&lt;/span&gt; printf (&lt;span class="dt"&gt;Proxy&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Proxy&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;%.1f%%&amp;quot;&lt;/span&gt;) &lt;span class="op"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; (_ &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="fl"&gt;100.0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb29-44"&gt;&lt;a href="#cb29-44" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       &lt;span class="kw"&gt;in&lt;/span&gt; { minValue&lt;span class="op"&gt;:&lt;/span&gt; xMin&lt;/span&gt;
&lt;span id="cb29-45"&gt;&lt;a href="#cb29-45" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          , minLabel&lt;span class="op"&gt;:&lt;/span&gt; showPercent xMin&lt;/span&gt;
&lt;span id="cb29-46"&gt;&lt;a href="#cb29-46" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          , maxValue&lt;span class="op"&gt;:&lt;/span&gt; xMax&lt;/span&gt;
&lt;span id="cb29-47"&gt;&lt;a href="#cb29-47" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          , maxLabel&lt;span class="op"&gt;:&lt;/span&gt; showPercent xMax&lt;/span&gt;
&lt;span id="cb29-48"&gt;&lt;a href="#cb29-48" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To work with our &lt;code&gt;[a]&lt;/code&gt; as if it were &lt;code&gt;[Int]&lt;/code&gt;, we have
to map the coercion function over it that our &lt;code&gt;Leibniz a Int&lt;/code&gt; gave
us. Admittedly, this naive way adds a runtime cost of copying the array. But we
could be more creative with finding the minimum and maximum in this way in
constant space and no extra allocations.&lt;/p&gt;
&lt;p&gt;And, if we wanted to outsource this to the javascript FFI, remember that
javascript doesn’t quite have sum types, so we can create a quick visitor:&lt;/p&gt;
&lt;div class="sourceCode" id="cb30"&gt;&lt;pre
class="sourceCode purescript"&gt;&lt;code class="sourceCode purescript"&gt;&lt;span id="cb30-1"&gt;&lt;a href="#cb30-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;NVisitor&lt;/span&gt; a r &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb30-2"&gt;&lt;a href="#cb30-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    {&lt;span class="ot"&gt; nvInt ::&lt;/span&gt; &lt;span class="dt"&gt;Leibniz&lt;/span&gt; a &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; r&lt;/span&gt;
&lt;span id="cb30-3"&gt;&lt;a href="#cb30-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ,&lt;span class="ot"&gt; nvNumber ::&lt;/span&gt; &lt;span class="dt"&gt;Leibniz&lt;/span&gt; a &lt;span class="dt"&gt;Number&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; r&lt;/span&gt;
&lt;span id="cb30-4"&gt;&lt;a href="#cb30-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ,&lt;span class="ot"&gt; nvPercent ::&lt;/span&gt; &lt;span class="dt"&gt;Leibniz&lt;/span&gt; a &lt;span class="dt"&gt;Percent&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; r&lt;/span&gt;
&lt;span id="cb30-5"&gt;&lt;a href="#cb30-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    }&lt;/span&gt;
&lt;span id="cb30-6"&gt;&lt;a href="#cb30-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb30-7"&gt;&lt;a href="#cb30-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;NAccept&lt;/span&gt; a &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;forall&lt;/span&gt; r&lt;span class="op"&gt;.&lt;/span&gt; &lt;span class="dt"&gt;NVisitor&lt;/span&gt; a r &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; r&lt;/span&gt;
&lt;span id="cb30-8"&gt;&lt;a href="#cb30-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb30-9"&gt;&lt;a href="#cb30-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;toAccept ::&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;NAccept&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb30-10"&gt;&lt;a href="#cb30-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;toAccept &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;case&lt;/span&gt; _ &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb30-11"&gt;&lt;a href="#cb30-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;NInt&lt;/span&gt; isInt &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \nv &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; nv&lt;span class="op"&gt;.&lt;/span&gt;nvInt isInt&lt;/span&gt;
&lt;span id="cb30-12"&gt;&lt;a href="#cb30-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;NNumber&lt;/span&gt; isNumber &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \nv &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; nv&lt;span class="op"&gt;.&lt;/span&gt;nvNumber isNumber&lt;/span&gt;
&lt;span id="cb30-13"&gt;&lt;a href="#cb30-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;NPercent&lt;/span&gt; isPercent &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \nv &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; nv&lt;span class="op"&gt;.&lt;/span&gt;nvPercent isPercent&lt;/span&gt;
&lt;span id="cb30-14"&gt;&lt;a href="#cb30-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb30-15"&gt;&lt;a href="#cb30-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;foreign &lt;span class="kw"&gt;import&lt;/span&gt; _formatNumeric :: forall a. &lt;span class="dt"&gt;Fn2&lt;/span&gt; (&lt;span class="dt"&gt;NAccept&lt;/span&gt; a) a &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb30-16"&gt;&lt;a href="#cb30-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb30-17"&gt;&lt;a href="#cb30-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;formatNumeric ::&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb30-18"&gt;&lt;a href="#cb30-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;formatNumeric nt &lt;span class="ot"&gt;=&lt;/span&gt; runFn2 _formatNumeric (toAccept nt)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The FFI binding looks like: (taken from &lt;a
href="https://github.com/mstksg/corona-charts/blob/master/src/D3/Scatter/Type.js"&gt;my
actual source code&lt;/a&gt;)&lt;/p&gt;
&lt;div class="sourceCode" id="cb31"&gt;&lt;pre
class="sourceCode javascript"&gt;&lt;code class="sourceCode javascript"&gt;&lt;span id="cb31-1"&gt;&lt;a href="#cb31-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="im"&gt;as&lt;/span&gt; d3 &lt;span class="im"&gt;from&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;d3-format&amp;quot;&lt;/span&gt;&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-2"&gt;&lt;a href="#cb31-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb31-3"&gt;&lt;a href="#cb31-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;export&lt;/span&gt; &lt;span class="kw"&gt;const&lt;/span&gt; _formatNumeric &lt;span class="op"&gt;=&lt;/span&gt; (naccept&lt;span class="op"&gt;,&lt;/span&gt; xs) &lt;span class="kw"&gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-4"&gt;&lt;a href="#cb31-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="fu"&gt;naccept&lt;/span&gt;(&lt;/span&gt;
&lt;span id="cb31-5"&gt;&lt;a href="#cb31-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    { &lt;span class="dt"&gt;nvInt&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; (isInt) &lt;span class="kw"&gt;=&amp;gt;&lt;/span&gt; d3&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;format&lt;/span&gt;(&lt;span class="st"&gt;&amp;quot;~s&amp;quot;&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb31-6"&gt;&lt;a href="#cb31-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;nvNumber&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; (isNumber) &lt;span class="kw"&gt;=&amp;gt;&lt;/span&gt; d3&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;format&lt;/span&gt;(&lt;span class="st"&gt;&amp;quot;.3~s&amp;quot;&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb31-7"&gt;&lt;a href="#cb31-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;,&lt;/span&gt; &lt;span class="dt"&gt;nvPercent&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; (isPercent) &lt;span class="kw"&gt;=&amp;gt;&lt;/span&gt; d3&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;format&lt;/span&gt;(&lt;span class="st"&gt;&amp;quot;+.3~p&amp;quot;&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb31-8"&gt;&lt;a href="#cb31-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    }&lt;/span&gt;
&lt;span id="cb31-9"&gt;&lt;a href="#cb31-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  )&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Admittedly in the javascript we are throwing away the “GADT type safety”
because we throw away the equality. But we take what we can — we at least retain
the visitor pattern for sum-type type safety and exhaustiveness checking. I
haven’t done this in typescript yet so there might be a way to formalize Leibniz
equality to do this in typescript and keep the whole chain type-safe from top to
bottom.&lt;/p&gt;
&lt;h4 id="higher-kinded-eliminators"&gt;Higher-Kinded Eliminators&lt;/h4&gt;
&lt;p&gt;This is essentially the higher-kinded version of the visitor pattern, except
in dependent type theory these visitors are more often called “eliminators” or
destructors, which is definitely a cooler name.&lt;/p&gt;
&lt;p&gt;In the normal visitor you’d have:&lt;/p&gt;
&lt;div class="sourceCode" id="cb32"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb32-1"&gt;&lt;a href="#cb32-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;User&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;TheAdmin&lt;/span&gt; &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;Member&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb32-2"&gt;&lt;a href="#cb32-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb32-3"&gt;&lt;a href="#cb32-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;UserHandler&lt;/span&gt; r &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;UH&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb32-4"&gt;&lt;a href="#cb32-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    {&lt;span class="ot"&gt; uhTheAdmin ::&lt;/span&gt; r&lt;/span&gt;
&lt;span id="cb32-5"&gt;&lt;a href="#cb32-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ,&lt;span class="ot"&gt; uhMember ::&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; r&lt;/span&gt;
&lt;span id="cb32-6"&gt;&lt;a href="#cb32-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But note that if you have the right set of continuations, you have something
that is essentially equal to &lt;code&gt;User&lt;/code&gt; without having to actually use
&lt;code&gt;User&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb33"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb33-1"&gt;&lt;a href="#cb33-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;User&amp;#39;&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;forall&lt;/span&gt; r&lt;span class="op"&gt;.&lt;/span&gt; &lt;span class="dt"&gt;UserHandler&lt;/span&gt; r &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; r&lt;/span&gt;
&lt;span id="cb33-2"&gt;&lt;a href="#cb33-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb33-3"&gt;&lt;a href="#cb33-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;fromUser ::&lt;/span&gt; &lt;span class="dt"&gt;User&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;User&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb33-4"&gt;&lt;a href="#cb33-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fromUser &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb33-5"&gt;&lt;a href="#cb33-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;TheAdmin&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \&lt;span class="dt"&gt;UH&lt;/span&gt;{&lt;span class="op"&gt;..&lt;/span&gt;} &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; uhTheAdmin&lt;/span&gt;
&lt;span id="cb33-6"&gt;&lt;a href="#cb33-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;Member&lt;/span&gt; userId &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \&lt;span class="dt"&gt;UH&lt;/span&gt;{&lt;span class="op"&gt;..&lt;/span&gt;} &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; uhMember userId&lt;/span&gt;
&lt;span id="cb33-7"&gt;&lt;a href="#cb33-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb33-8"&gt;&lt;a href="#cb33-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;toUser ::&lt;/span&gt; &lt;span class="dt"&gt;User&amp;#39;&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Foo&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb33-9"&gt;&lt;a href="#cb33-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;toUser f &lt;span class="ot"&gt;=&lt;/span&gt; f &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="dt"&gt;UH&lt;/span&gt; { fhTheAdmin &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;TheAdmin&lt;/span&gt;, fhMember &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Member&lt;/span&gt; }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This means that &lt;code&gt;User&lt;/code&gt; is actually equivalent to
&lt;code&gt;forall r. UserHandler r -&amp;gt; r&lt;/code&gt;: they’re the same type, so if your
language doesn’t have sum types, you could encode it as
&lt;code&gt;forall r. UserHandler r -&amp;gt; r&lt;/code&gt; instead. Visitors, baby.&lt;/p&gt;
&lt;p&gt;But, then, what actually does the &lt;code&gt;r&lt;/code&gt; type variable represent
here, semantically? Well, in a &lt;code&gt;UserHandler r&lt;/code&gt;, &lt;code&gt;r&lt;/code&gt; is the
“target” that we interpret into. But there’s a deeper relationship between
&lt;code&gt;r&lt;/code&gt; and &lt;code&gt;User&lt;/code&gt;: A &lt;code&gt;UserHandler r&lt;/code&gt; essentially
“embeds” a &lt;code&gt;User&lt;/code&gt; into an &lt;code&gt;r&lt;/code&gt;. And, a
&lt;code&gt;UserHandler r -&amp;gt; r&lt;/code&gt; is the application of that embedding to an
actual &lt;code&gt;User&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If we pick &lt;code&gt;r ~ ()&lt;/code&gt;, then &lt;code&gt;UserHandler ()&lt;/code&gt; embeds
&lt;code&gt;User&lt;/code&gt; into &lt;code&gt;()&lt;/code&gt;. If we pick &lt;code&gt;r ~ String&lt;/code&gt;, then
&lt;code&gt;UserHandler ()&lt;/code&gt; embeds &lt;code&gt;User&lt;/code&gt; into &lt;code&gt;String&lt;/code&gt;
(like, “showing” it). And if we pick &lt;code&gt;r ~ User&lt;/code&gt;, a
&lt;code&gt;UserHandler User&lt;/code&gt; embeds a &lt;code&gt;User&lt;/code&gt; into…itself?&lt;/p&gt;
&lt;p&gt;So here, &lt;code&gt;r&lt;/code&gt; is essentially the projection that we view the user
through. And by making sure we are &lt;code&gt;forall r. UserHandler r -&amp;gt; r&lt;/code&gt;
for &lt;em&gt;all&lt;/em&gt; &lt;code&gt;r&lt;/code&gt;, we ensure that we do not lose any information:
the embedding is completely 1-to-1. It lets you “create” the &lt;code&gt;User&lt;/code&gt;
faithfully in a “polymorphic” way.&lt;/p&gt;
&lt;p&gt;In fact, to hammer this home, some people like to use the name of the type as
the type variable: &lt;code&gt;UserHandler user&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb34"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb34-1"&gt;&lt;a href="#cb34-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- | The same thing as before but with things renamed to prove a point&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb34-2"&gt;&lt;a href="#cb34-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;MakeUser&lt;/span&gt; user &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;MakeUser&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb34-3"&gt;&lt;a href="#cb34-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    {&lt;span class="ot"&gt; uhTheAdmin ::&lt;/span&gt; user&lt;/span&gt;
&lt;span id="cb34-4"&gt;&lt;a href="#cb34-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ,&lt;span class="ot"&gt; uhMember ::&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; user&lt;/span&gt;
&lt;span id="cb34-5"&gt;&lt;a href="#cb34-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    }&lt;/span&gt;
&lt;span id="cb34-6"&gt;&lt;a href="#cb34-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb34-7"&gt;&lt;a href="#cb34-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;User&amp;#39;&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;forall&lt;/span&gt; user&lt;span class="op"&gt;.&lt;/span&gt; &lt;span class="dt"&gt;MakeUser&lt;/span&gt; user &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; user&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;forall user.&lt;/code&gt; lets us faithfully “create” a &lt;code&gt;User&lt;/code&gt;
within the system we have, without actually having a &lt;code&gt;User&lt;/code&gt; data
type. Essentially we can imagine the &lt;code&gt;r&lt;/code&gt; in the &lt;code&gt;forall r&lt;/code&gt;
as “standing in” for &lt;code&gt;User&lt;/code&gt;, even if that type doesn’t actually
exist.&lt;/p&gt;
&lt;p&gt;Now, here’s the breakthrough: If we can use &lt;code&gt;forall (r :: Type)&lt;/code&gt;
to substitute for &lt;code&gt;User :: Type&lt;/code&gt;, how about we use a
&lt;code&gt;forall (p :: Type -&amp;gt; Type)&lt;/code&gt; to substitute for a
&lt;code&gt;Scale :: Type -&amp;gt; Type&lt;/code&gt;?&lt;/p&gt;
&lt;div class="sourceCode" id="cb35"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb35-1"&gt;&lt;a href="#cb35-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Scale&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb35-2"&gt;&lt;a href="#cb35-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;ScaleDate&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Scale&lt;/span&gt; &lt;span class="dt"&gt;Date&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb35-3"&gt;&lt;a href="#cb35-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;ScaleLinear&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;LType&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Scale&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb35-4"&gt;&lt;a href="#cb35-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;ScaleLog&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Scale&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb35-5"&gt;&lt;a href="#cb35-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb35-6"&gt;&lt;a href="#cb35-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;ScaleHandler&lt;/span&gt; p a &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;SH&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb35-7"&gt;&lt;a href="#cb35-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    {&lt;span class="ot"&gt; shDate ::&lt;/span&gt; p &lt;span class="dt"&gt;Date&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb35-8"&gt;&lt;a href="#cb35-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ,&lt;span class="ot"&gt; shLinear ::&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; p a&lt;/span&gt;
&lt;span id="cb35-9"&gt;&lt;a href="#cb35-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ,&lt;span class="ot"&gt; shLog ::&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; p a&lt;/span&gt;
&lt;span id="cb35-10"&gt;&lt;a href="#cb35-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    }&lt;/span&gt;
&lt;span id="cb35-11"&gt;&lt;a href="#cb35-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb35-12"&gt;&lt;a href="#cb35-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;Scale&amp;#39;&lt;/span&gt; a &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;forall&lt;/span&gt; p&lt;span class="op"&gt;.&lt;/span&gt; &lt;span class="dt"&gt;ScaleHandler&lt;/span&gt; p a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; p a&lt;/span&gt;
&lt;span id="cb35-13"&gt;&lt;a href="#cb35-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb35-14"&gt;&lt;a href="#cb35-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;fromScale ::&lt;/span&gt; &lt;span class="dt"&gt;Scale&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Scale&amp;#39;&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb35-15"&gt;&lt;a href="#cb35-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fromScale &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb35-16"&gt;&lt;a href="#cb35-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;ScaleDate&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \&lt;span class="dt"&gt;SH&lt;/span&gt;{&lt;span class="op"&gt;..&lt;/span&gt;} &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; shDate&lt;/span&gt;
&lt;span id="cb35-17"&gt;&lt;a href="#cb35-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;ScaleLinear&lt;/span&gt; hasZero lt &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \&lt;span class="dt"&gt;SH&lt;/span&gt;{&lt;span class="op"&gt;..&lt;/span&gt;} &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; shLinear hasZero lt&lt;/span&gt;
&lt;span id="cb35-18"&gt;&lt;a href="#cb35-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;ScaleLog&lt;/span&gt; nt &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \&lt;span class="dt"&gt;SH&lt;/span&gt;{&lt;span class="op"&gt;..&lt;/span&gt;} &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; shLog nt&lt;/span&gt;
&lt;span id="cb35-19"&gt;&lt;a href="#cb35-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb35-20"&gt;&lt;a href="#cb35-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;toScale ::&lt;/span&gt; &lt;span class="dt"&gt;Scale&amp;#39;&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Scale&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb35-21"&gt;&lt;a href="#cb35-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;toScale f &lt;span class="ot"&gt;=&lt;/span&gt; f &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="dt"&gt;SH&lt;/span&gt; { shDate &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;ScaleDate&lt;/span&gt;, shLinear &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;ScaleLinear&lt;/span&gt;, shLog &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;ScaleLog&lt;/span&gt; }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So in our new system, &lt;code&gt;forall p. ScaleHandler p a -&amp;gt; p a&lt;/code&gt; is
identical to &lt;code&gt;Scale&lt;/code&gt;: we can use &lt;code&gt;p a&lt;/code&gt; to substitute in
&lt;code&gt;Scale&lt;/code&gt; in our language even if our language itself cannot support
GADTs.&lt;/p&gt;
&lt;p&gt;So let’s write &lt;code&gt;formatNType&lt;/code&gt; in purescript. We no longer have an
actual &lt;code&gt;Scale&lt;/code&gt; sum type, but its higher-kinded church encoding:&lt;/p&gt;
&lt;div class="sourceCode" id="cb36"&gt;&lt;pre
class="sourceCode purescript"&gt;&lt;code class="sourceCode purescript"&gt;&lt;span id="cb36-1"&gt;&lt;a href="#cb36-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; a &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;forall&lt;/span&gt; p&lt;span class="op"&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-2"&gt;&lt;a href="#cb36-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    {&lt;span class="ot"&gt; int ::&lt;/span&gt; p &lt;span class="dt"&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-3"&gt;&lt;a href="#cb36-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ,&lt;span class="ot"&gt; number ::&lt;/span&gt; p &lt;span class="dt"&gt;Number&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-4"&gt;&lt;a href="#cb36-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ,&lt;span class="ot"&gt; percent ::&lt;/span&gt; p &lt;span class="dt"&gt;Percent&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-5"&gt;&lt;a href="#cb36-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    } &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; p a&lt;/span&gt;
&lt;span id="cb36-6"&gt;&lt;a href="#cb36-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb36-7"&gt;&lt;a href="#cb36-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;Scale&lt;/span&gt; a &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;forall&lt;/span&gt; p&lt;span class="op"&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-8"&gt;&lt;a href="#cb36-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    {&lt;span class="ot"&gt; date ::&lt;/span&gt; p &lt;span class="dt"&gt;Date&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-9"&gt;&lt;a href="#cb36-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ,&lt;span class="ot"&gt; linear ::&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; p a&lt;/span&gt;
&lt;span id="cb36-10"&gt;&lt;a href="#cb36-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ,&lt;span class="ot"&gt; log ::&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; p a&lt;/span&gt;
&lt;span id="cb36-11"&gt;&lt;a href="#cb36-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    } &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; p a&lt;/span&gt;
&lt;span id="cb36-12"&gt;&lt;a href="#cb36-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb36-13"&gt;&lt;a href="#cb36-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;ntInt ::&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-14"&gt;&lt;a href="#cb36-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ntInt nth &lt;span class="ot"&gt;=&lt;/span&gt; nth&lt;span class="op"&gt;.&lt;/span&gt;int&lt;/span&gt;
&lt;span id="cb36-15"&gt;&lt;a href="#cb36-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb36-16"&gt;&lt;a href="#cb36-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;ntNumber ::&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; &lt;span class="dt"&gt;Number&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-17"&gt;&lt;a href="#cb36-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ntNumber nth &lt;span class="ot"&gt;=&lt;/span&gt; nth&lt;span class="op"&gt;.&lt;/span&gt;number&lt;/span&gt;
&lt;span id="cb36-18"&gt;&lt;a href="#cb36-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb36-19"&gt;&lt;a href="#cb36-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;ntPercent ::&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; &lt;span class="dt"&gt;Percent&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-20"&gt;&lt;a href="#cb36-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ntPercent nth &lt;span class="ot"&gt;=&lt;/span&gt; nth&lt;span class="op"&gt;.&lt;/span&gt;percent&lt;/span&gt;
&lt;span id="cb36-21"&gt;&lt;a href="#cb36-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb36-22"&gt;&lt;a href="#cb36-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;formatNType ::&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-23"&gt;&lt;a href="#cb36-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;formatNType nt &lt;span class="ot"&gt;=&lt;/span&gt; f&lt;/span&gt;
&lt;span id="cb36-24"&gt;&lt;a href="#cb36-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-25"&gt;&lt;a href="#cb36-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;Op&lt;/span&gt; f &lt;span class="ot"&gt;=&lt;/span&gt; nt&lt;/span&gt;
&lt;span id="cb36-26"&gt;&lt;a href="#cb36-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      { int&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;Op&lt;/span&gt; &lt;span class="fu"&gt;show&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-27"&gt;&lt;a href="#cb36-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      , number&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;Op&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; printf (&lt;span class="dt"&gt;Proxy&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;%.4f&amp;quot;&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb36-28"&gt;&lt;a href="#cb36-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      , percent&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="dt"&gt;Op&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; printf (&lt;span class="dt"&gt;Proxy&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;%.1f%%&amp;quot;&lt;/span&gt;) &lt;span class="op"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; (_ &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="fl"&gt;100.0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb36-29"&gt;&lt;a href="#cb36-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here we are using&lt;/p&gt;
&lt;div class="sourceCode" id="cb37"&gt;&lt;pre
class="sourceCode purescript"&gt;&lt;code class="sourceCode purescript"&gt;&lt;span id="cb37-1"&gt;&lt;a href="#cb37-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;newtype&lt;/span&gt; &lt;span class="dt"&gt;Op&lt;/span&gt; b a &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Op&lt;/span&gt; (a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; b)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;as our “target”: turning an &lt;code&gt;NType a&lt;/code&gt; into an
&lt;code&gt;Op String a&lt;/code&gt;. And an &lt;code&gt;Op String a&lt;/code&gt; is an
&lt;code&gt;a -&amp;gt; String&lt;/code&gt;, which is what we wanted! The &lt;code&gt;int&lt;/code&gt; field
is &lt;code&gt;Op String Int&lt;/code&gt;, the &lt;code&gt;number&lt;/code&gt; field is
&lt;code&gt;Op String Number&lt;/code&gt;, etc.&lt;/p&gt;
&lt;p&gt;In many languages, using this technique effectively requires having a newtype
wrapper on-hand, so it might be unwieldy in non-trivial situations. For example,
if we wanted to write our previous axis function which is
&lt;code&gt;NType a -&amp;gt; [a] -&amp;gt; String&lt;/code&gt;, we’d have to have a newtype wrapper
for &lt;code&gt;[a] -&amp;gt; String&lt;/code&gt; that has &lt;code&gt;a&lt;/code&gt; as its argument:&lt;/p&gt;
&lt;div class="sourceCode" id="cb38"&gt;&lt;pre
class="sourceCode purescript"&gt;&lt;code class="sourceCode purescript"&gt;&lt;span id="cb38-1"&gt;&lt;a href="#cb38-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;newtype&lt;/span&gt; &lt;span class="dt"&gt;OpList&lt;/span&gt; b a &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Op&lt;/span&gt; ([a] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; b)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;or you could re-use &lt;code&gt;Compose&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb39"&gt;&lt;pre
class="sourceCode purescript"&gt;&lt;code class="sourceCode purescript"&gt;&lt;span id="cb39-1"&gt;&lt;a href="#cb39-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;newtype&lt;/span&gt; &lt;span class="dt"&gt;Compose&lt;/span&gt; f g a &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Compose&lt;/span&gt; (f (g a))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and your &lt;code&gt;p&lt;/code&gt; projection type would be &lt;code&gt;Compose Op []&lt;/code&gt;.
So, you don’t necessarily have to write a bespoke newtype wrapper, but you do
have to devote some brain cycles to think it through (unless you’re in a
language that doesn’t need newtype wrappers to have this work, like we’ll
discuss later).&lt;/p&gt;
&lt;p&gt;By the way, this method generalizes well to multiple arguments: if you have a
type like &lt;code&gt;MyGADT a b c&lt;/code&gt;, you just need to project into a
&lt;code&gt;forall (p :: k1 -&amp;gt; k2 -&amp;gt; k3 -&amp;gt; Type)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I believe I have read somewhere that the two methods discussed here (runtime
equality witness vs. higher-kinded eliminator) are not actually fully identical
in their power, and there are GADTs where one would work and not the other … but
I can’t remember where I read this and I’m also not big-brained enough to figure
out what those situations are. But if you, reader, have any idea, please let me
know!&lt;/p&gt;
&lt;h3 id="existential-types"&gt;Existential Types&lt;/h3&gt;
&lt;p&gt;Let’s take a quick break to talk about something that’s not
&lt;em&gt;technically&lt;/em&gt; related to GADTs but is often used alongside them.&lt;/p&gt;
&lt;p&gt;What if we wanted to store a value with its &lt;code&gt;NType&lt;/code&gt; and hide the
type variable? In Haskell we’d write this like:&lt;/p&gt;
&lt;div class="sourceCode" id="cb40"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb40-1"&gt;&lt;a href="#cb40-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb40-2"&gt;&lt;a href="#cb40-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;NInt&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb40-3"&gt;&lt;a href="#cb40-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;NDouble&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; &lt;span class="dt"&gt;Double&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb40-4"&gt;&lt;a href="#cb40-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;NPercent&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; &lt;span class="dt"&gt;Percent&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb40-5"&gt;&lt;a href="#cb40-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb40-6"&gt;&lt;a href="#cb40-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;SomeNType&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;forall&lt;/span&gt; a&lt;span class="op"&gt;.&lt;/span&gt; &lt;span class="dt"&gt;SomeNType&lt;/span&gt; (&lt;span class="dt"&gt;NType&lt;/span&gt; a) a&lt;/span&gt;
&lt;span id="cb40-7"&gt;&lt;a href="#cb40-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb40-8"&gt;&lt;a href="#cb40-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;formatNType ::&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb40-9"&gt;&lt;a href="#cb40-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;formatNType nt x &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="op"&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb40-10"&gt;&lt;a href="#cb40-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb40-11"&gt;&lt;a href="#cb40-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;formatSomeNType ::&lt;/span&gt; &lt;span class="dt"&gt;SomeNType&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb40-12"&gt;&lt;a href="#cb40-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;formatSomeNType (&lt;span class="dt"&gt;SomeNType&lt;/span&gt; nt x) &lt;span class="ot"&gt;=&lt;/span&gt; formatNType nt x&lt;/span&gt;
&lt;span id="cb40-13"&gt;&lt;a href="#cb40-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb40-14"&gt;&lt;a href="#cb40-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;myFavoriteNumbers ::&lt;/span&gt; [&lt;span class="dt"&gt;SomeNType&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb40-15"&gt;&lt;a href="#cb40-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;myFavoriteNumbers &lt;span class="ot"&gt;=&lt;/span&gt; [&lt;span class="dt"&gt;SomeNType&lt;/span&gt; &lt;span class="dt"&gt;NInt&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;, &lt;span class="dt"&gt;SomeNType&lt;/span&gt; &lt;span class="dt"&gt;NDouble&lt;/span&gt; &lt;span class="fu"&gt;pi&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But what if our language doesn’t have existentials? Remember, this is
basically a value &lt;code&gt;SomeNType&lt;/code&gt; that &lt;em&gt;isn’t&lt;/em&gt; a Generic, but
&lt;em&gt;contains&lt;/em&gt; both a &lt;code&gt;NType a&lt;/code&gt; and an &lt;code&gt;a&lt;/code&gt; of the
&lt;em&gt;same&lt;/em&gt; variable.&lt;/p&gt;
&lt;p&gt;One strategy we have available is to CPS-transform our existentials into
their CPS form (continuation-passing style form). Basically, we write exactly
what we want to do with our contents &lt;em&gt;if we pattern matched&lt;/em&gt; on them.
It’s essentially a Rank-N visitor pattern with only a single constructor:&lt;/p&gt;
&lt;div class="sourceCode" id="cb41"&gt;&lt;pre
class="sourceCode purescript"&gt;&lt;code class="sourceCode purescript"&gt;&lt;span id="cb41-1"&gt;&lt;a href="#cb41-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;SomeNType&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;forall&lt;/span&gt; r&lt;span class="op"&gt;.&lt;/span&gt; (&lt;span class="kw"&gt;forall&lt;/span&gt; a&lt;span class="op"&gt;.&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; r) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; r&lt;/span&gt;
&lt;span id="cb41-2"&gt;&lt;a href="#cb41-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb41-3"&gt;&lt;a href="#cb41-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;someNType ::&lt;/span&gt; &lt;span class="dt"&gt;NType&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;SomeNType&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb41-4"&gt;&lt;a href="#cb41-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;someNType nt x &lt;span class="ot"&gt;=&lt;/span&gt; \f &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f nt x&lt;/span&gt;
&lt;span id="cb41-5"&gt;&lt;a href="#cb41-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb41-6"&gt;&lt;a href="#cb41-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;formatSomeNumeric ::&lt;/span&gt; &lt;span class="dt"&gt;SomeNType&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb41-7"&gt;&lt;a href="#cb41-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;formatSomeNumeric snt &lt;span class="ot"&gt;=&lt;/span&gt; snt&lt;/span&gt;
&lt;span id="cb41-8"&gt;&lt;a href="#cb41-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    \nt x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; formatNumeric nt x&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can imagine, syntactically, that &lt;code&gt;snt&lt;/code&gt; acts as its “own”
pattern match, except instead of matching on
&lt;code&gt;SomeNType nt x -&amp;gt; ..&lt;/code&gt;, you “match” on
&lt;code&gt;\nt x -&amp;gt; ..&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This general pattern works for languages with traditional generics like Java
too:&lt;/p&gt;
&lt;div class="sourceCode" id="cb42"&gt;&lt;pre class="sourceCode java"&gt;&lt;code class="sourceCode java"&gt;&lt;span id="cb42-1"&gt;&lt;a href="#cb42-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;interface&lt;/span&gt; SomeNTypeVisitor&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-2"&gt;&lt;a href="#cb42-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;A&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; R &lt;span class="fu"&gt;visit&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;NType&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;A&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; nt&lt;span class="op"&gt;,&lt;/span&gt; A val&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-3"&gt;&lt;a href="#cb42-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-4"&gt;&lt;a href="#cb42-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-5"&gt;&lt;a href="#cb42-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;interface&lt;/span&gt; SomeNType &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-6"&gt;&lt;a href="#cb42-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="kw"&gt;abstract&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; R &lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;SomeNTypeVisitor&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; visitor&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-7"&gt;&lt;a href="#cb42-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-8"&gt;&lt;a href="#cb42-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="co"&gt;// One option: the factory method&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-9"&gt;&lt;a href="#cb42-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="dt"&gt;static&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;A&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; SomeNType &lt;span class="fu"&gt;someNType&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;NType&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;A&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; nt&lt;span class="op"&gt;,&lt;/span&gt; A val&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-10"&gt;&lt;a href="#cb42-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="kw"&gt;new&lt;/span&gt; &lt;span class="fu"&gt;SomeNType&lt;/span&gt;&lt;span class="op"&gt;()&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-11"&gt;&lt;a href="#cb42-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="at"&gt;@Override&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-12"&gt;&lt;a href="#cb42-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; R &lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;SomeNTypeVisitor&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; visitor&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-13"&gt;&lt;a href="#cb42-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="cf"&gt;return&lt;/span&gt; visitor&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;visit&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;nt&lt;span class="op"&gt;,&lt;/span&gt; val&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-14"&gt;&lt;a href="#cb42-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-15"&gt;&lt;a href="#cb42-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-16"&gt;&lt;a href="#cb42-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-17"&gt;&lt;a href="#cb42-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-18"&gt;&lt;a href="#cb42-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-19"&gt;&lt;a href="#cb42-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// Second option: the subtype hiding a type variable, which you have to always&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-20"&gt;&lt;a href="#cb42-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;// make sure to upcast into `SomeNType` after creating&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-21"&gt;&lt;a href="#cb42-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;class&lt;/span&gt; SomeNTypeImpl&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;A&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;extends&lt;/span&gt; SomeNType &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-22"&gt;&lt;a href="#cb42-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;private&lt;/span&gt; NType&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;A&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; nt&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-23"&gt;&lt;a href="#cb42-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;private&lt;/span&gt; A val&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-24"&gt;&lt;a href="#cb42-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-25"&gt;&lt;a href="#cb42-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="fu"&gt;SomeNTypeImpl&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;NType&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;A&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; nt&lt;span class="op"&gt;,&lt;/span&gt; A val&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-26"&gt;&lt;a href="#cb42-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="kw"&gt;this&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;nt&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; nt&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-27"&gt;&lt;a href="#cb42-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="kw"&gt;this&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;val&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; val&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-28"&gt;&lt;a href="#cb42-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-29"&gt;&lt;a href="#cb42-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-30"&gt;&lt;a href="#cb42-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="at"&gt;@Override&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-31"&gt;&lt;a href="#cb42-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;public&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; R &lt;span class="fu"&gt;accept&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;SomeNTypeVisitor&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;R&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; visitor&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-32"&gt;&lt;a href="#cb42-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; visitor&lt;span class="op"&gt;.&lt;/span&gt;&lt;span class="fu"&gt;visit&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;nt&lt;span class="op"&gt;,&lt;/span&gt; val&lt;span class="op"&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-33"&gt;&lt;a href="#cb42-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-34"&gt;&lt;a href="#cb42-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Does…anyone write java like this? I tried committing this once while at
Google and I got automatically flagged to be put on a PIP.&lt;/p&gt;
&lt;h3 id="recursive-gadts"&gt;Recursive GADTs&lt;/h3&gt;
&lt;p&gt;The climax of this discussion: what if your language does not support GADTs
&lt;em&gt;or&lt;/em&gt; recursive data types?&lt;/p&gt;
&lt;p&gt;We’re going to be using &lt;em&gt;dhall&lt;/em&gt; as an example again, but note that the
lessons applied here are potentially useful even when you &lt;em&gt;do&lt;/em&gt; have
recursive types: we’re going to be talking about a higher-kinded church
encoding, which can be a useful form of your data types that live alongside your
normal recursive ones.&lt;/p&gt;
&lt;p&gt;Let’s imagine &lt;code&gt;Expr&lt;/code&gt; as a GADT, where &lt;code&gt;Expr a&lt;/code&gt;
represents an &lt;code&gt;Expr&lt;/code&gt; that evaluates to an &lt;code&gt;a&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb43"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb43-1"&gt;&lt;a href="#cb43-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Type&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb43-2"&gt;&lt;a href="#cb43-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;NatLit&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Natural&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;Natural&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb43-3"&gt;&lt;a href="#cb43-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;BoolLit&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb43-4"&gt;&lt;a href="#cb43-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;Add&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;Natural&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;Natural&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;Natural&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb43-5"&gt;&lt;a href="#cb43-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;LTE&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;Natural&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;Natural&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb43-6"&gt;&lt;a href="#cb43-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;Ternary&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb43-7"&gt;&lt;a href="#cb43-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb43-8"&gt;&lt;a href="#cb43-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;eval ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb43-9"&gt;&lt;a href="#cb43-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;eval &lt;span class="ot"&gt;=&lt;/span&gt; \&lt;span class="kw"&gt;case&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb43-10"&gt;&lt;a href="#cb43-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;NatLit&lt;/span&gt; n &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; n&lt;/span&gt;
&lt;span id="cb43-11"&gt;&lt;a href="#cb43-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;BoolLit&lt;/span&gt; b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; b&lt;/span&gt;
&lt;span id="cb43-12"&gt;&lt;a href="#cb43-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;Add&lt;/span&gt; x y &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; eval x &lt;span class="op"&gt;+&lt;/span&gt; eval y&lt;/span&gt;
&lt;span id="cb43-13"&gt;&lt;a href="#cb43-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;LTE&lt;/span&gt; a b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; eval a &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; eval b&lt;/span&gt;
&lt;span id="cb43-14"&gt;&lt;a href="#cb43-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;Ternary&lt;/span&gt; b x y &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;if&lt;/span&gt; eval b &lt;span class="kw"&gt;then&lt;/span&gt; eval x &lt;span class="kw"&gt;else&lt;/span&gt; eval y&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Adding this type variable ensures that our &lt;code&gt;Expr&lt;/code&gt; is type-safe:
it’s impossible to &lt;code&gt;Add&lt;/code&gt; an &lt;code&gt;Expr Bool&lt;/code&gt;, and the two
branches of a &lt;code&gt;Ternary&lt;/code&gt; must have the same result type, etc. And, we
can write &lt;code&gt;eval :: Expr a -&amp;gt; a&lt;/code&gt; and know exactly what type will be
returned.&lt;/p&gt;
&lt;p&gt;Now, let’s combine the two concepts: First, the church encoding, where our
handlers take the “final result” of our fold &lt;code&gt;r&lt;/code&gt; instead of the
recursive value &lt;code&gt;Expr&lt;/code&gt;. Second, the higher-kinded eliminator pattern
where we embed &lt;code&gt;Expr :: Type -&amp;gt; Type&lt;/code&gt; into
&lt;code&gt;forall (p :: Type -&amp;gt; Type)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;And finally, we get:&lt;a href="#fn3" class="footnote-ref" id="fnref3"
role="doc-noteref"&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb44"&gt;&lt;pre class="sourceCode dhall"&gt;&lt;code class="sourceCode "&gt;&lt;span id="cb44-1"&gt;&lt;a href="#cb44-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;let&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;ExprF&lt;span class="co"&gt; &lt;/span&gt;=&lt;/span&gt;
&lt;span id="cb44-2"&gt;&lt;a href="#cb44-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;      &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(p&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Type)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb44-3"&gt;&lt;a href="#cb44-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;{&lt;span class="co"&gt; &lt;/span&gt;natLit&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Natural&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;p&lt;span class="co"&gt; &lt;/span&gt;Natural&lt;/span&gt;
&lt;span id="cb44-4"&gt;&lt;a href="#cb44-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;,&lt;span class="co"&gt; &lt;/span&gt;boolLit&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Bool&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;p&lt;span class="co"&gt; &lt;/span&gt;Bool&lt;/span&gt;
&lt;span id="cb44-5"&gt;&lt;a href="#cb44-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;,&lt;span class="co"&gt; &lt;/span&gt;add&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;p&lt;span class="co"&gt; &lt;/span&gt;Natural&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;p&lt;span class="co"&gt; &lt;/span&gt;Natural&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;p&lt;span class="co"&gt; &lt;/span&gt;Natural&lt;/span&gt;
&lt;span id="cb44-6"&gt;&lt;a href="#cb44-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;,&lt;span class="co"&gt; &lt;/span&gt;ternary&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="kw"&gt;forall&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;(a&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;p&lt;span class="co"&gt; &lt;/span&gt;Bool&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;p&lt;span class="co"&gt; &lt;/span&gt;a&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;p&lt;span class="co"&gt; &lt;/span&gt;a&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;p&lt;span class="co"&gt; &lt;/span&gt;a&lt;/span&gt;
&lt;span id="cb44-7"&gt;&lt;a href="#cb44-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;}&lt;/span&gt;
&lt;span id="cb44-8"&gt;&lt;a href="#cb44-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb44-9"&gt;&lt;a href="#cb44-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;let&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;/span&gt;
&lt;span id="cb44-10"&gt;&lt;a href="#cb44-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;    &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Type&lt;/span&gt;
&lt;span id="cb44-11"&gt;&lt;a href="#cb44-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;    &lt;/span&gt;=&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(a&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="kw"&gt;forall&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;(p&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Type)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;ExprF&lt;span class="co"&gt; &lt;/span&gt;p&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;p&lt;span class="co"&gt; &lt;/span&gt;a&lt;/span&gt;
&lt;span id="cb44-12"&gt;&lt;a href="#cb44-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb44-13"&gt;&lt;a href="#cb44-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;let&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;eval&lt;/span&gt;
&lt;span id="cb44-14"&gt;&lt;a href="#cb44-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;    &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="kw"&gt;forall&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;(a&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;a&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;a&lt;/span&gt;
&lt;span id="cb44-15"&gt;&lt;a href="#cb44-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;    &lt;/span&gt;=&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(a&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb44-16"&gt;&lt;a href="#cb44-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;      &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(e&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;a)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb44-17"&gt;&lt;a href="#cb44-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;e&lt;/span&gt;
&lt;span id="cb44-18"&gt;&lt;a href="#cb44-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;          &lt;/span&gt;(&lt;span class="op"&gt;\&lt;/span&gt;(q&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;q)&lt;/span&gt;
&lt;span id="cb44-19"&gt;&lt;a href="#cb44-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;          &lt;/span&gt;{&lt;span class="co"&gt; &lt;/span&gt;natLit&lt;span class="co"&gt; &lt;/span&gt;=&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(x&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Natural)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;x&lt;/span&gt;
&lt;span id="cb44-20"&gt;&lt;a href="#cb44-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;          &lt;/span&gt;,&lt;span class="co"&gt; &lt;/span&gt;boolLit&lt;span class="co"&gt; &lt;/span&gt;=&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(x&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Bool)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;x&lt;/span&gt;
&lt;span id="cb44-21"&gt;&lt;a href="#cb44-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;          &lt;/span&gt;,&lt;span class="co"&gt; &lt;/span&gt;add&lt;span class="co"&gt; &lt;/span&gt;=&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(x&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Natural)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(y&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Natural)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;x&lt;span class="co"&gt; &lt;/span&gt;+&lt;span class="co"&gt; &lt;/span&gt;y&lt;/span&gt;
&lt;span id="cb44-22"&gt;&lt;a href="#cb44-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;          &lt;/span&gt;,&lt;span class="co"&gt; &lt;/span&gt;ternary&lt;span class="co"&gt; &lt;/span&gt;=&lt;/span&gt;
&lt;span id="cb44-23"&gt;&lt;a href="#cb44-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;              &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(a&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb44-24"&gt;&lt;a href="#cb44-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;              &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(b&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Bool)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb44-25"&gt;&lt;a href="#cb44-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;              &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(x&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;a)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb44-26"&gt;&lt;a href="#cb44-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;              &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(y&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;a)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb44-27"&gt;&lt;a href="#cb44-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;                &lt;/span&gt;&lt;span class="kw"&gt;if&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;b&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="kw"&gt;then&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;x&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="kw"&gt;else&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;y&lt;/span&gt;
&lt;span id="cb44-28"&gt;&lt;a href="#cb44-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;          &lt;/span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Again, now instead of &lt;code&gt;add&lt;/code&gt; taking &lt;code&gt;Expr&lt;/code&gt;, it takes
&lt;code&gt;p Natural&lt;/code&gt;: the “&lt;code&gt;Natural&lt;/code&gt; result of the fold”.
&lt;code&gt;p&lt;/code&gt; not only stands in for what we embed &lt;code&gt;Expr&lt;/code&gt; into, it
stands in for the result of the recursive fold. That’s why in &lt;code&gt;eval&lt;/code&gt;,
the first arguments of &lt;code&gt;add&lt;/code&gt; are the &lt;code&gt;Natural&lt;/code&gt; results of
the sub-evaluation.&lt;/p&gt;
&lt;p&gt;These values can be created in the same way as before, merging the two
techniques, sending the handlers downstream:&lt;/p&gt;
&lt;div class="sourceCode" id="cb45"&gt;&lt;pre class="sourceCode dhall"&gt;&lt;code class="sourceCode "&gt;&lt;span id="cb45-1"&gt;&lt;a href="#cb45-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;let&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;natLit&lt;/span&gt;
&lt;span id="cb45-2"&gt;&lt;a href="#cb45-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;    &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Natural&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;Natural&lt;/span&gt;
&lt;span id="cb45-3"&gt;&lt;a href="#cb45-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;    &lt;/span&gt;=&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(n&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Natural)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-4"&gt;&lt;a href="#cb45-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;      &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(p&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Type)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-5"&gt;&lt;a href="#cb45-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;      &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(handlers&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;ExprF&lt;span class="co"&gt; &lt;/span&gt;p)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-6"&gt;&lt;a href="#cb45-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;handlers.natLit&lt;span class="co"&gt; &lt;/span&gt;n&lt;/span&gt;
&lt;span id="cb45-7"&gt;&lt;a href="#cb45-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb45-8"&gt;&lt;a href="#cb45-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;let&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;boolLit&lt;/span&gt;
&lt;span id="cb45-9"&gt;&lt;a href="#cb45-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;    &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Bool&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;Bool&lt;/span&gt;
&lt;span id="cb45-10"&gt;&lt;a href="#cb45-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;    &lt;/span&gt;=&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(n&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Bool)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-11"&gt;&lt;a href="#cb45-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;      &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(p&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Type)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-12"&gt;&lt;a href="#cb45-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;      &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(handlers&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;ExprF&lt;span class="co"&gt; &lt;/span&gt;p)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-13"&gt;&lt;a href="#cb45-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;handlers.boolLit&lt;span class="co"&gt; &lt;/span&gt;n&lt;/span&gt;
&lt;span id="cb45-14"&gt;&lt;a href="#cb45-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb45-15"&gt;&lt;a href="#cb45-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;let&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;add&lt;/span&gt;
&lt;span id="cb45-16"&gt;&lt;a href="#cb45-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;    &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;Natural&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;Natural&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;Natural&lt;/span&gt;
&lt;span id="cb45-17"&gt;&lt;a href="#cb45-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;    &lt;/span&gt;=&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(x&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;Natural)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-18"&gt;&lt;a href="#cb45-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;      &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(y&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;Natural)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-19"&gt;&lt;a href="#cb45-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;      &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(p&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Type)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-20"&gt;&lt;a href="#cb45-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;      &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(handlers&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;ExprF&lt;span class="co"&gt; &lt;/span&gt;p)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-21"&gt;&lt;a href="#cb45-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;handlers.add&lt;span class="co"&gt; &lt;/span&gt;(x&lt;span class="co"&gt; &lt;/span&gt;p&lt;span class="co"&gt; &lt;/span&gt;handlers)&lt;span class="co"&gt; &lt;/span&gt;(y&lt;span class="co"&gt; &lt;/span&gt;p&lt;span class="co"&gt; &lt;/span&gt;handlers)&lt;/span&gt;
&lt;span id="cb45-22"&gt;&lt;a href="#cb45-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb45-23"&gt;&lt;a href="#cb45-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;let&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;ternary&lt;/span&gt;
&lt;span id="cb45-24"&gt;&lt;a href="#cb45-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;    &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="kw"&gt;forall&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;(a&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;Bool&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;a&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;a&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;a&lt;/span&gt;
&lt;span id="cb45-25"&gt;&lt;a href="#cb45-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;    &lt;/span&gt;=&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(a&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-26"&gt;&lt;a href="#cb45-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;      &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(b&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;Bool)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-27"&gt;&lt;a href="#cb45-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;      &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(x&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;a)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-28"&gt;&lt;a href="#cb45-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;      &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(y&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;a)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-29"&gt;&lt;a href="#cb45-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;      &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(p&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Type&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;Type)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-30"&gt;&lt;a href="#cb45-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;      &lt;/span&gt;&lt;span class="op"&gt;\&lt;/span&gt;(handlers&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;ExprF&lt;span class="co"&gt; &lt;/span&gt;p)&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;-&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-31"&gt;&lt;a href="#cb45-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;        &lt;/span&gt;handlers.ternary&lt;span class="co"&gt; &lt;/span&gt;(b&lt;span class="co"&gt; &lt;/span&gt;p&lt;span class="co"&gt; &lt;/span&gt;handlers)&lt;span class="co"&gt; &lt;/span&gt;(x&lt;span class="co"&gt; &lt;/span&gt;p&lt;span class="co"&gt; &lt;/span&gt;handlers)&lt;span class="co"&gt; &lt;/span&gt;(y&lt;span class="co"&gt; &lt;/span&gt;p&lt;span class="co"&gt; &lt;/span&gt;handlers)&lt;/span&gt;
&lt;span id="cb45-32"&gt;&lt;a href="#cb45-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb45-33"&gt;&lt;a href="#cb45-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;let&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;testVal&lt;/span&gt;
&lt;span id="cb45-34"&gt;&lt;a href="#cb45-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;    &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;Expr&lt;span class="co"&gt; &lt;/span&gt;Natural&lt;/span&gt;
&lt;span id="cb45-35"&gt;&lt;a href="#cb45-35" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;    &lt;/span&gt;=&lt;span class="co"&gt; &lt;/span&gt;add&lt;span class="co"&gt; &lt;/span&gt;(natLit&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="dv"&gt;5&lt;/span&gt;)&lt;span class="co"&gt; &lt;/span&gt;(add&lt;span class="co"&gt; &lt;/span&gt;(natLit&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="dv"&gt;6&lt;/span&gt;)&lt;span class="co"&gt; &lt;/span&gt;(natLit&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="dv"&gt;7&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb45-36"&gt;&lt;a href="#cb45-36" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb45-37"&gt;&lt;a href="#cb45-37" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;in&lt;/span&gt;&lt;span class="co"&gt;  &lt;/span&gt;&lt;span class="kw"&gt;assert&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;:&lt;span class="co"&gt; &lt;/span&gt;eval&lt;span class="co"&gt; &lt;/span&gt;testVal&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="op"&gt;===&lt;/span&gt;&lt;span class="co"&gt; &lt;/span&gt;&lt;span class="dv"&gt;18&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If all of this is difficult to parse, try reviewing both the recursive ADT
section and the higher-kinded eliminator section and making sure you understand
both well before tackling this, which combines them together!&lt;/p&gt;
&lt;p&gt;Admittedly in Haskell (and purescript) this is a lot simpler because we don’t
have to explicitly pass in type variables:&lt;/p&gt;
&lt;div class="sourceCode" id="cb46"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb46-1"&gt;&lt;a href="#cb46-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;ExprF&lt;/span&gt; p &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;ExprF&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb46-2"&gt;&lt;a href="#cb46-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    {&lt;span class="ot"&gt; natLit ::&lt;/span&gt; &lt;span class="dt"&gt;Natural&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; p &lt;span class="dt"&gt;Natural&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb46-3"&gt;&lt;a href="#cb46-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ,&lt;span class="ot"&gt; boolLit ::&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; p &lt;span class="dt"&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb46-4"&gt;&lt;a href="#cb46-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ,&lt;span class="ot"&gt; add ::&lt;/span&gt; p &lt;span class="dt"&gt;Natural&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; p &lt;span class="dt"&gt;Natural&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; p &lt;span class="dt"&gt;Natural&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb46-5"&gt;&lt;a href="#cb46-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ,&lt;span class="ot"&gt; ternary ::&lt;/span&gt; &lt;span class="kw"&gt;forall&lt;/span&gt; a&lt;span class="op"&gt;.&lt;/span&gt;  p &lt;span class="dt"&gt;Bool&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; p a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; p a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; p a&lt;/span&gt;
&lt;span id="cb46-6"&gt;&lt;a href="#cb46-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    }&lt;/span&gt;
&lt;span id="cb46-7"&gt;&lt;a href="#cb46-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb46-8"&gt;&lt;a href="#cb46-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; a &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;forall&lt;/span&gt; p&lt;span class="op"&gt;.&lt;/span&gt; &lt;span class="dt"&gt;ExprF&lt;/span&gt; p a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; p a&lt;/span&gt;
&lt;span id="cb46-9"&gt;&lt;a href="#cb46-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb46-10"&gt;&lt;a href="#cb46-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;eval ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb46-11"&gt;&lt;a href="#cb46-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;eval e &lt;span class="ot"&gt;=&lt;/span&gt; runIdentity &lt;span class="op"&gt;$&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb46-12"&gt;&lt;a href="#cb46-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  e&lt;/span&gt;
&lt;span id="cb46-13"&gt;&lt;a href="#cb46-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    { natLit &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Identity&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb46-14"&gt;&lt;a href="#cb46-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    , boolLit &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Identity&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb46-15"&gt;&lt;a href="#cb46-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    , add &lt;span class="ot"&gt;=&lt;/span&gt; \(&lt;span class="dt"&gt;Identity&lt;/span&gt; x) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \(&lt;span class="dt"&gt;Identity&lt;/span&gt; y) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Identity&lt;/span&gt; (x &lt;span class="op"&gt;+&lt;/span&gt; y)&lt;/span&gt;
&lt;span id="cb46-16"&gt;&lt;a href="#cb46-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    , ternary &lt;span class="ot"&gt;=&lt;/span&gt; \(&lt;span class="dt"&gt;Identity&lt;/span&gt; b) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \(&lt;span class="dt"&gt;Identity&lt;/span&gt; x) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; \(&lt;span class="dt"&gt;Identity&lt;/span&gt; y) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;if&lt;/span&gt; b &lt;span class="kw"&gt;then&lt;/span&gt; x &lt;span class="kw"&gt;else&lt;/span&gt; y&lt;/span&gt;
&lt;span id="cb46-17"&gt;&lt;a href="#cb46-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    }&lt;/span&gt;
&lt;span id="cb46-18"&gt;&lt;a href="#cb46-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb46-19"&gt;&lt;a href="#cb46-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;ternary ::&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Expr&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb46-20"&gt;&lt;a href="#cb46-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ternary b x y handlers &lt;span class="ot"&gt;=&lt;/span&gt; handlers&lt;span class="op"&gt;.&lt;/span&gt;ternary (b handlers) (x handlers) (y handlers)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But one nice thing about the dhall version that’s incidental to dhall is that
it doesn’t require any extra newtype wrappers like the Haskell one does. That’s
because type inference tends to choke on things like this, but dhall doesn’t
really have any type inference: all of the types are passed explicitly. It’s one
of the facts about dhall that make it nice for things like this.&lt;/p&gt;
&lt;h2 id="congratulations"&gt;Congratulations&lt;/h2&gt;
&lt;p&gt;In any case, if you’ve made it this far, congratulations! You are a master of
ADTs and GADTs. Admittedly every language is different, and some of these
solutions have to be tweaked for the language in question. And, if your program
gets very complicated, there is a good chance that things will become
ergonomically unfeasible.&lt;/p&gt;
&lt;p&gt;But I hope, at least, that this inspires your imagination to try to bring
your haskell principles, techniques, standards, practices, and brainrot into the
language of your choice (or language you are forced to work with).&lt;/p&gt;
&lt;p&gt;And, if you ever find interesting ways to bring these things into a language
not discussed here (or a new interesting technique or pattern), I would
absolutely love to hear about it!&lt;/p&gt;
&lt;p&gt;Until next time, happy “Haskelling”!&lt;/p&gt;
&lt;h2 id="special-thanks"&gt;Special Thanks&lt;/h2&gt;
&lt;p&gt;I am very humbled to be supported by an amazing community, who make it
possible for me to devote time to researching and writing these posts. Very
special thanks to my supporter at the “Amazing” level on &lt;a
href="https://www.patreon.com/justinle/overview"&gt;patreon&lt;/a&gt;, Josh Vera! :)&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;I bet you thought there was going be some sort of caveat in this
footnote, didn’t you?&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 didn’t think I’d ever write “java bean” non-ironically on my
blog, but there’s a first time for everything.&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;Be aware that this implementation is not necessarily
appropriately lazy or short-circuiting in &lt;code&gt;Ternary&lt;/code&gt;: it might
evaluate both sides returning the chosen branch.&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>Justin Le</author><category>Haskell</category><guid isPermaLink="true">https://blog.jle.im/entry/faking-adts-and-gadts.html</guid><pubDate>Tue,  1 Apr 2025 17:29:41 UTC</pubDate><creator>Justin Le</creator><subject>Haskell</subject><date>2025-04-01</date></item><language>en</language><copyright>Copyright 2020 Justin Le</copyright><managingEditor>justin@jle.im (Justin Le)</managingEditor><webMaster>justin@jle.im (Justin Le)</webMaster><lastBuildDate>Tue,  7 Jul 2026 17:11:34 UTC</lastBuildDate><generator>feed-1.0.0.0 (Sigbjorn Finne)</generator><image><url>https://blog.jle.im/img/site_logo.jpg</url><title>in Code</title><link>https://blog.jle.im/</link></image><creator>Justin Le</creator><language>en</language><rights>Copyright 2020 Justin Le</rights><date>2026-07-07</date><description>Weblog of Justin Le, covering various adventures in programming and explorations in the worlds of computation physics, and knowledge.
</description></channel></rss>