<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title></title>
      <link>https://fallible.net</link>
      <description></description>
      <generator>Zola</generator>
      <language>en</language>
      <atom:link href="https://fallible.net/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Mon, 16 Dec 2024 00:00:00 +0000</lastBuildDate>
      <item>
          <title>Everyone&#x27;s a Syndicate</title>
          <pubDate>Mon, 16 Dec 2024 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://fallible.net/projects/syndicate/</link>
          <guid>https://fallible.net/projects/syndicate/</guid>
          <description xml:base="https://fallible.net/projects/syndicate/">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;syndicate.fallible.net&quot;&gt;&quot;Everyone&#x27;s a Syndicate&quot;&lt;&#x2F;a&gt; is an RSS&#x2F;Atom CORS proxy &amp;amp; HTML renderer. It provides the bridge for in-browser RSS&#x2F;Atom feed readers, and has an HTML rendering endpoint if you want to do as little work as possible building an RSS reader.&lt;&#x2F;p&gt;
&lt;p&gt;This is not a new way of doing things, people have done things like this before. Right now, I can&#x27;t find ones that encourage &quot;community&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s a reader for a bunch of cohost users:&lt;&#x2F;p&gt;
&lt;div&gt;
&lt;sub&gt;&lt;a href=&quot;https:&#x2F;&#x2F;syndicate.fallible.net&quot;&gt;Everyone&#x27;s a Syndicate&lt;&#x2F;a&gt;&lt;&#x2F;sub&gt;
&lt;script type=&quot;text&#x2F;javascript&quot;&gt;
    function everyones_a_syndicate_update_cohost() {
        &#x2F;&#x2F; Set the style 
        let style = &quot;\&lt;style\&gt;&quot; + [...document.styleSheets].map((styleSheet) =&gt; { try { return [...styleSheet.cssRules].map((rule) =&gt; rule.cssText).join(&quot;&quot;); } catch (e) {} }).filter(Boolean).join(&quot;\n&quot;) + &quot;\&lt;&#x2F;style\&gt;&quot;;
        document.getElementById(&#x27;place-here-cohost&#x27;).setAttribute(&quot;srcdoc&quot;, style);
        &#x2F;&#x2F; Fetch the rendered HTML.
        return fetch(&quot;https:&#x2F;&#x2F;syndicate.fallible.net&#x2F;poll_feeds_rendered&quot;, {
                method: &quot;POST&quot;, headers: new Headers({&#x27;content-type&#x27;: &#x27;application&#x2F;json&#x27;}),
                body: JSON.stringify({feeds: [&quot;https:&#x2F;&#x2F;fallible.net&#x2F;rss.xml&quot;, &quot;https:&#x2F;&#x2F;nickyflowers.com&#x2F;feed.xml&quot;, &quot;https:&#x2F;&#x2F;shelraphen.com&#x2F;rss&#x2F;&quot;, &quot;https:&#x2F;&#x2F;blog.dante.cool&#x2F;feed&#x2F;?type=rss&quot;, &quot;https:&#x2F;&#x2F;blog.someplace-else.xyz&#x2F;feed&#x2F;?type=rss&quot;, &quot;https:&#x2F;&#x2F;buttondown.com&#x2F;HTHR&#x2F;rss&quot;, &quot;https:&#x2F;&#x2F;www.alexanderbjoy.com&#x2F;feed?type=rss&quot;], 
                show_mode: &#x27;EqualChronoShuffle&#x27;}), 
            })
            .then(result =&gt; result.text())
            .then(body =&gt; {
                &#x2F;&#x2F; pre-append the style to the value of the 
                document.getElementById(&#x27;place-here-cohost&#x27;).setAttribute(&quot;srcdoc&quot;, style + body)
            });
    }
document.addEventListener(&quot;DOMContentLoaded&quot;, function(event){
    everyones_a_syndicate_update_cohost();
});
&lt;&#x2F;script&gt;
&lt;iframe id=&quot;place-here-cohost&quot; style=&quot;height: 20em&quot;&gt;&lt;&#x2F;iframe&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;And here&#x27;s another for people involved in the Scottish gamedev scene:&lt;&#x2F;p&gt;
&lt;div&gt;
&lt;sub&gt;&lt;a href=&quot;https:&#x2F;&#x2F;syndicate.fallible.net&quot;&gt;Everyone&#x27;s a Syndicate&lt;&#x2F;a&gt;&lt;&#x2F;sub&gt;
&lt;script type=&quot;text&#x2F;javascript&quot;&gt;
    function everyones_a_syndicate_update_scotland_gamedev() {
        &#x2F;&#x2F; Set the style 
        let style = &quot;\&lt;style\&gt;&quot; + [...document.styleSheets].map((styleSheet) =&gt; { try { return [...styleSheet.cssRules].map((rule) =&gt; rule.cssText).join(&quot;&quot;); } catch (e) {} }).filter(Boolean).join(&quot;\n&quot;) + &quot;\&lt;&#x2F;style\&gt;&quot;;
        document.getElementById(&#x27;place-here-scotdev&#x27;).setAttribute(&quot;srcdoc&quot;, style);
        &#x2F;&#x2F; Fetch the rendered HTML.
        return fetch(&quot;https:&#x2F;&#x2F;syndicate.fallible.net&#x2F;poll_feeds_rendered&quot;, {
                method: &quot;POST&quot;, headers: new Headers({&#x27;content-type&#x27;: &#x27;application&#x2F;json&#x27;}),
                body: JSON.stringify({feeds: [&quot;https:&#x2F;&#x2F;www.collegefun.games&#x2F;blog&#x2F;rss&quot;, &quot;https:&#x2F;&#x2F;raodaozao.net&#x2F;feed&#x2F;&quot;, &quot;https:&#x2F;&#x2F;blog.someplace-else.xyz&#x2F;feed&#x2F;?type=rss&quot;, &quot;https:&#x2F;&#x2F;sunny.garden&#x2F;@clasticartistic.rss&quot;, &quot;https:&#x2F;&#x2F;blog.fallible.net&#x2F;feed?type=rss&quot;], 
                show_mode: &#x27;EqualChronoShuffle&#x27;}), 
            })
            .then(result =&gt; result.text())
            .then(body =&gt; {
                &#x2F;&#x2F; pre-append the style to the value of the 
                document.getElementById(&#x27;place-here-scotdev&#x27;).setAttribute(&quot;srcdoc&quot;, style + body)
            });
    }
document.addEventListener(&quot;DOMContentLoaded&quot;, function(event){
    everyones_a_syndicate_update_scotland_gamedev();
});
&lt;&#x2F;script&gt;
&lt;iframe id=&quot;place-here-scotdev&quot; style=&quot;height: 20em&quot;&gt;&lt;&#x2F;iframe&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;You&#x27;ll notice some of these are not in &lt;em&gt;normal&lt;&#x2F;em&gt; reverse chronological order. One of the options for ordering posts is &quot;Equal shuffle&quot; which is &quot;show everyone&#x27;s most recent post first, shuffled together. Then everyone&#x27;s second most recent post, shuffled. Then everyone&#x27;s third most recent post, shuffled.&quot; and so on. This exists so that not posting frequently isn&#x27;t a penalty.&lt;&#x2F;p&gt;
&lt;p&gt;That is, if you post 50 times a day, your pal Ahmed posts 5 times a week, and your pal Belle posts 5 times a year, you won&#x27;t drown out Belle and Ahmed with your posting.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s still an option for &quot;Newest first&quot;&#x2F;Reverse chronological, so if you want to just have a Hosepipe.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s also a few options for CSS injection (or lack thereof) on the client-side. The default is &quot;Copy all stylesheets from the main page and apply them to the iframe&quot;. This makes it look like it&#x27;s in the right place in a lot of the places where you put it, like &lt;a href=&quot;https:&#x2F;&#x2F;blog.fallible.net&#x2F;everyones-a-syndicate&#x2F;&quot;&gt;Bear Blog&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In a time of AI scraping there might not be as many valid RSS feeds when picked up through a data centre hosted proxy, but this is a relatively simple way to enable more social websites, to make it feel like we&#x27;re less alone on our little website islands.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Spaces are Moments, Not Abstract or Far Away</title>
          <pubDate>Mon, 30 Sep 2024 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://fallible.net/projects/spaces-are-moments/</link>
          <guid>https://fallible.net/projects/spaces-are-moments/</guid>
          <description xml:base="https://fallible.net/projects/spaces-are-moments/">&lt;iframe frameborder=&quot;0&quot; src=&quot;https:&#x2F;&#x2F;itch.io&#x2F;embed&#x2F;3008648&quot; width=&quot;552&quot; height=&quot;167&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fallible.itch.io&#x2F;spaces-are-moments&quot;&gt;Spaces are moments, not abstract or far away. by Fallible Things&lt;&#x2F;a&gt;&lt;&#x2F;iframe&gt;
&lt;p&gt;&quot;Spaces are moments&quot; was my submission to my own game jam, &lt;a href=&quot;https:&#x2F;&#x2F;itch.io&#x2F;jam&#x2F;pretentious&quot;&gt;Pretentious jam&lt;&#x2F;a&gt;. I used godot, an aira S1, and the Lineal font. I massively regret participating in my own jam, and this game diverged quite a bit from my initial sketches, but I&#x27;m largely happy with where it ended up.&lt;&#x2F;p&gt;
&lt;p&gt;This game is a poemware. Intentionally, you need to participate to be able to view the whole poem. At the end, there is a collection of some of the fragments that survive.&lt;&#x2F;p&gt;
&lt;p&gt;Please play &lt;a href=&quot;https:&#x2F;&#x2F;itch.io&#x2F;jam&#x2F;pretentious&#x2F;entries&quot;&gt;other peoples submissions to the jam.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Shortly Departing From</title>
          <pubDate>Thu, 29 Feb 2024 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://fallible.net/projects/shortly-departing-from/</link>
          <guid>https://fallible.net/projects/shortly-departing-from/</guid>
          <description xml:base="https://fallible.net/projects/shortly-departing-from/">&lt;div class=&quot;iframe-center&quot;&gt;&lt;iframe frameborder=&quot;0&quot; src=&quot;https:&#x2F;&#x2F;itch.io&#x2F;embed&#x2F;2551424&quot; width=&quot;552&quot; height=&quot;167&quot;&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fallible.itch.io&#x2F;shortly-departing-from&quot;&gt;The Train Shortly Departing From Platform 33E3EE Is The 20:59 Service To Bristol-56 Temple 57-Meads-54 by Fallible Things&lt;&#x2F;a&gt;&lt;&#x2F;iframe&gt;&lt;&#x2F;div&gt;
&lt;p&gt;&quot;The Train Shortly Departing From Platform 33E3EE Is The 20:59 Service To Bristol-56 Temple 57-Meads-54&quot; Was an entry to the &lt;a href=&quot;https:&#x2F;&#x2F;itch.io&#x2F;jam&#x2F;lsdjam-2023&quot;&gt;LSD Dream Emulator Anniversary Jam 2023&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Outlining Typechecking for your Toy Language &#x2F; Feeding the lambda calculus its own tail</title>
          <pubDate>Fri, 01 Sep 2023 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://fallible.net/projects/types/</link>
          <guid>https://fallible.net/projects/types/</guid>
          <description xml:base="https://fallible.net/projects/types/">&lt;script id=&quot;MathJax-script&quot; async src=&quot;https:&#x2F;&#x2F;cdn.jsdelivr.net&#x2F;npm&#x2F;mathjax@3&#x2F;es5&#x2F;tex-mml-chtml.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;script&gt;
MathJax = {
  tex: {
    inlineMath: [[&#x27;$&#x27;, &#x27;$&#x27;], [&#x27;\\(&#x27;, &#x27;\\)&#x27;]]
  }
};
&lt;&#x2F;script&gt;
&lt;script type=&quot;module&quot; src=&quot;&#x2F;cohost-wc.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;&#x2F;cohost-wc.css&quot; &#x2F;&gt; 
&lt;link rel=&quot;stylesheet&quot;, href=&quot;&#x2F;atkinson.css&quot; &#x2F;&gt;
&lt;p&gt;This was originally a 2-part post on cohost.org, c&#x27;est la vie. I came to these methods from a lot of silent from-first-principles fiddling, but I expect others to have done them before too.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fallible.net&#x2F;projects&#x2F;types&#x2F;#pt2&quot;&gt;Feeding the Lambda Calculus its own Tail&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is further down the page too.&lt;&#x2F;p&gt;
&lt;div id=&quot;pt1&quot;&gt;
&lt;cohost-post avatarsrc=&quot;data:image&#x2F;jpeg;base64,&#x2F;9j&#x2F;4AAQSkZJRgABAQAAAQABAAD&#x2F;4gIcSUNDX1BST0ZJTEUAAQEAAAIMbGNtcwIQAABtbnRyUkdCIFhZWiAH3AABABkAAwApADlhY3NwQVBQTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWxjbXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApkZXNjAAAA&#x2F;AAAAF5jcHJ0AAABXAAAAAt3dHB0AAABaAAAABRia3B0AAABfAAAABRyWFlaAAABkAAAABRnWFlaAAABpAAAABRiWFlaAAABuAAAABRyVFJDAAABzAAAAEBnVFJDAAABzAAAAEBiVFJDAAABzAAAAEBkZXNjAAAAAAAAAANjMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0ZXh0AAAAAEZCAABYWVogAAAAAAAA9tYAAQAAAADTLVhZWiAAAAAAAAADFgAAAzMAAAKkWFlaIAAAAAAAAG+iAAA49QAAA5BYWVogAAAAAAAAYpkAALeFAAAY2lhZWiAAAAAAAAAkoAAAD4QAALbPY3VydgAAAAAAAAAaAAAAywHJA2MFkghrC&#x2F;YQPxVRGzQh8SmQMhg7kkYFUXdd7WtwegWJsZp8rGm&#x2F;fdPD6TD&#x2F;&#x2F;&#x2F;&#x2F;bAEMA&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;bAEMB&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;AABEIAEAAQAMBIgACEQEDEQH&#x2F;xAAWAAEBAQAAAAAAAAAAAAAAAAABAAL&#x2F;xAAcEAEBAQEBAQADAAAAAAAAAAAAARESIWECMVH&#x2F;xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf&#x2F;EABcRAQEBAQAAAAAAAAAAAAAAAAARASH&#x2F;2gAMAwEAAhEDEQA&#x2F;ADqrqsmBD18PXwYUpFvxagLMPU+rqBYqRmNifooqWIrE3WbMDd9jGBmpqBqIus6WWgXqQ06Q6NQUmEiQoM6dGX+LmqUhc1c0KjIp+NPolLOn1nKGP&#x2F;&#x2F;Z&quot; avatarshape=&quot;squircle&quot; comments=&quot;2&quot; displayname=&quot;Fallible Algebra&quot; handle=&quot;fallible-algebra&quot; originalurl=&quot;https:&#x2F;&#x2F;cohost.org&#x2F;fallible-algebra&#x2F;post&#x2F;2660945-outlining-type-check&quot; publishedat=&quot;2023-08-31T19:22:27.097Z&quot; standaloneheadline=&quot;Outlining type checking for your toy language (and many others)&quot; tags=&quot;programming language theory,type theory,programming languages,haskell,programming language development,rust,rust-lang,mathematics,I apologise for the recipe blog post style intro,computer science,maths,math,effortpost,The Cohost Global Feed,functional programming,lambda calculus,tutorial,compilers,PLT&quot;&gt;&lt;noscript&gt;Post by Fallible Algebra (@fallible-algebra): Outlining type checking for your toy language (and many others)&lt;&#x2F;noscript&gt;&lt;div&gt;&lt;div class=&quot;flex w-full flex-nowrap content-start justify-between&quot;&gt;&lt;button class=&quot;group relative w-full flex-initial&quot; tabindex=&quot;0&quot;&gt;&lt;img src=&quot;&#x2F;TypesHeader.jpg&quot; class=&quot;h-full w-full object-cover&quot; data-attachment-id=&quot;f75da206-7e5f-466d-a1b4-dce9ef055748&quot; alt=&quot;A handwritten design document for a non-existent programming language called &amp;quot;MyLang&amp;quot;. A dismissal of a type system for the language is in red pen.&quot; title=&quot;A handwritten design document for a non-existent programming language called &amp;quot;MyLang&amp;quot;. A dismissal of a type system for the language is in red pen.&quot;&gt;&lt;&#x2F;button&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;&lt;div class=&quot;co-prose prose my-4 overflow-hidden break-words px-3&quot;&gt;&lt;p&gt;Like many who fall into building programming languages as personal projects or research rabbit holes, there was a period where I became obsessed with type systems, formal languages, the specifics of what the lambda calculus is and what other computational calculi are.&lt;&#x2F;p&gt;
&lt;p&gt;One of my favourite things to do in programming languages with a strong type system is to find or otherwise design a type signature that leaves little room for &quot;misuse&quot;. I am not unique in enjoying this, it&#x27;s the premise of type-driven development and it&#x27;s arguably one of the most interesting itches to scratch when you have a complex type system to play with.&lt;&#x2F;p&gt;
&lt;p&gt;It is not unexpected to want to, once you understand a set of tools, turn those tools in on themselves. It feels smart, it feels satisfying, it feels like you&#x27;re coming up against the limits of a concept. Sometimes this is a quagmire, where you just get lost trying to define things from their surroundings in a way which becomes circular or muddied or distressing, but with formal systems there&#x27;s the clarity of playing in a sandbox.&lt;&#x2F;p&gt;
&lt;p&gt;This post serves as an illustration of my favourite way of leveraging powerful type systems to make the path for adding type theories &amp;mdash; specifically type checking and type inference &amp;mdash; to toy formal language projects as clear as possible. To be clear: I am talking about &lt;strong&gt;outlining&lt;&#x2F;strong&gt; type checking, not &lt;strong&gt;implementing&lt;&#x2F;strong&gt; type checking. That&#x27;s what you go on wikipedia and then google scholar and then JSTOR and other rabbit holes of research for. Or you follow your heart and decide to mess with these things from first-principles, as long as it&#x27;s not in your heart purely to feel The Smartest Of All.&lt;&#x2F;p&gt;&lt;&#x2F;div&gt;&lt;div class=&quot;co-prose prose my-4 overflow-hidden break-words px-3&quot;&gt;&lt;hr&gt;
&lt;p&gt;First things first, as we&#x27;re talking about a typed language developed in a typed language,  I&#x27;ll be referring to them this way:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Host language: The language we&#x27;re writing things in, not the language we&#x27;re designing.
&lt;ul&gt;
&lt;li&gt;Host type system: the type system of the host language, not the type system we&#x27;re designing.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Toy&lt;sup&gt;1&lt;&#x2F;sup&gt; language: The language we&#x27;re designing, not the language we&#x27;re writing things in.
&lt;ul&gt;
&lt;li&gt;Toy type system: The type system we&#x27;re designing, not the type system we&#x27;re using while designing the type system.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The host language I&#x27;m using is haskell, which definitely isn&#x27;t the most practical but I can leverage the host type system really well. I will also show how to do this in Rust, but that&#x27;s more as an afterthought. What your host language will need is 1. &lt;strong&gt;Algebraic Data Types&lt;&#x2F;strong&gt; aka &lt;strong&gt;Enums but Fancy &amp;#10024;&lt;&#x2F;strong&gt; and 2. &lt;strong&gt;Type Parameters&lt;&#x2F;strong&gt; aka &lt;strong&gt;Generics&lt;&#x2F;strong&gt; aka &lt;strong&gt;Parametric Polymorphism&lt;&#x2F;strong&gt;. These are the two features that tend to make a programming language theorist&#x27;s heart swell three times its size anyway. Appropriate host languages might then be:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Java 20 &lt;a href=&quot;https:&#x2F;&#x2F;openjdk.org&#x2F;jeps&#x2F;409&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot; tabindex=&quot;0&quot;&gt;(yes, really)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Rust
&lt;ul&gt;
&lt;li&gt;Many ancestors of Rust, like OCaml&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Haskell
&lt;ul&gt;
&lt;li&gt;Any number of haskell derivatives, i.e. Idris, Purescript&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Again, I will be using Haskell but please don&#x27;t let that scare you off. It&#x27;s just the language that this can be done the easiest and taken to the furthest length in.&lt;&#x2F;p&gt;
&lt;h2&gt;Your toy language&lt;&#x2F;h2&gt;
&lt;p&gt;Where does your toy type system &quot;live&quot; in your toy language? This is a question you&#x27;ll need to answer. I&#x27;ll be illustrating with a lambda calculus, but this is not necessarily the foundation you&#x27;ll go with. Here are some questions to ask yourself, if you haven&#x27;t already:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Do you have a point in the toy language where variables are explicitly introduced? Not all formal languages do.&lt;&#x2F;li&gt;
&lt;li&gt;Are there constants in your toy language whose type can be manually defined by you?&lt;&#x2F;li&gt;
&lt;li&gt;Are there constants in your toy type system that can be defined by you?&lt;&#x2F;li&gt;
&lt;li&gt;Are there rules you want types to follow in your toy type system?&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This isn&#x27;t an exhaustive list, I am not a type theorist and this is a blog post. Point is for this exercise, a language has a type system when its terms have types and those types have rules you follow. It&#x27;s up to you to figure out how to do that, and it&#x27;s up to you to see how the rules can be constructed and bent &lt;sup&gt;2&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To illustrate asking these questions, I&#x27;ll be using a lambda calculus (something we definitely know how to add a type system to), and asking these questions as I go through.&lt;&#x2F;p&gt;
&lt;h3&gt;An example: a typed lambda calculus&lt;&#x2F;h3&gt;
&lt;p&gt;
$$\Lambda := var(v) | apply(\Lambda, \Lambda) | \lambda v:t. \Lambda $$
&lt;&#x2F;p&gt;
&lt;p&gt;Fig: a half-remembered definition of a typed lambda calculus. Please don&#x27;t get lost here, I promise it&#x27;s not too spooky.&lt;&#x2F;p&gt;
&lt;p&gt;The lambda calculus is... fine, fun, alright, good enough. And mathematical notation can be hard to decipher, so instead of the above alone here&#x27;s a definition of it in the host language I&#x27;ll be using:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color: rgb(254, 254, 254); color: rgb(84, 84, 84); position: relative; padding: 0px; line-height: 1.2rem; margin-bottom: 0px;&quot;&gt;&lt;code style=&quot;padding: 0px 16px; display: block; margin-bottom: 9px; margin-top: 9px;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;data&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;ToyType&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span style=&quot;color: dimgray;&quot;&gt;-- When I refer to toy type expressions in the form `A -&amp;gt; B` I mean&lt;&#x2F;span&gt;
    &lt;span style=&quot;color: dimgray;&quot;&gt;-- effectively `Function &quot;A&quot; &quot;B&quot;`.`&lt;&#x2F;span&gt;
    = &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Function&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;ToyType&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;ToyType&lt;&#x2F;span&gt;
    | ... &lt;span style=&quot;color: dimgray;&quot;&gt;-- Not defining all other parts of the type, there can be many.&lt;&#x2F;span&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;data&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;LambdaCalc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
= &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Var&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;String&lt;&#x2F;span&gt;
| &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Apply&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;LambdaCalc&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;LambdaCalc&lt;&#x2F;span&gt;
| &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Abstract&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;String&lt;&#x2F;span&gt;, &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;ToyType&lt;&#x2F;span&gt;) &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;LambdaCalc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;div style=&quot;text-align: right; font-size: min(1.87vw, 70%); opacity: 0.7; margin-bottom: 1.71429em;&quot;&gt;made with &lt;a data-testid=&quot;mention&quot; href=&quot;https:&#x2F;&#x2F;cohost.org&#x2F;nex3&quot; class=&quot;!font-bold !no-underline hover:!underline&quot; tabindex=&quot;0&quot;&gt;@nex3&lt;&#x2F;a&gt;&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;nex3.github.io&#x2F;cohost-highlight&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot; tabindex=&quot;0&quot;&gt;syntax highlighter&lt;&#x2F;a&gt;&lt;&#x2F;div&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This is pretty kosher, though using strings for variables is a bit too specific and perhaps gaudy. But before getting distracted by the taunt of perfection, let&#x27;s ask those questions from before:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Do you have a point in the toy language where variables are explicitly introduced?
&lt;ul&gt;
&lt;li&gt;Yes! &lt;code&gt;Abstract&lt;&#x2F;code&gt; plays the part of the lambda operator, introducing a new variable to an expression body.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Are there constants in your toy language whose type can be manually defined by you?
&lt;ul&gt;
&lt;li&gt;Hmm, no. This lambda calculus doesn&#x27;t have constants. But, we could add them. We&#x27;d want a stronger way of differentiating between variables and constants if we did, mind.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Are there constants in your toy type system that can be defined by you?
&lt;ul&gt;
&lt;li&gt;Yes! At the very least, we&#x27;ve defined &lt;code&gt;Function&lt;&#x2F;code&gt; as a type that describes function types. The rest of the type system is left up to the imagination, but it could include explicit primitives like integers, etc.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Are there rules you want types to follow in your toy type system?
&lt;ul&gt;
&lt;li&gt;Yes! We want the following, in plain terms:
&lt;ul&gt;
&lt;li&gt;Variables have types, and those types are introduced at the same point as those variables: in the &lt;code&gt;Abstract&lt;&#x2F;code&gt; part of the syntax tree.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Apply&lt;&#x2F;code&gt; reduces the type of its left expression if it&#x27;s a function type, and its right expression should match the argument type of its left. In other words:
&lt;ul&gt;
&lt;li&gt;In our toy language we have two expressions &lt;code&gt;a&lt;&#x2F;code&gt; and &lt;code&gt;b&lt;&#x2F;code&gt;. &lt;code&gt;a&lt;&#x2F;code&gt; has type &lt;code&gt;X&lt;&#x2F;code&gt; and &lt;code&gt;b&lt;&#x2F;code&gt; has type &lt;code&gt;X -&amp;gt; Y&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Apply b a&lt;&#x2F;code&gt; should type check as having type &lt;code&gt;Y&lt;&#x2F;code&gt;, because we applied an expression of type &lt;code&gt;X&lt;&#x2F;code&gt; to a function of type &lt;code&gt;X -&amp;gt; Y&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Apply a b&lt;&#x2F;code&gt; should fail to type check, as we&#x27;re trying to apply the expression &lt;code&gt;b&lt;&#x2F;code&gt; to the non-function expression &lt;code&gt;a&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Apply b b&lt;&#x2F;code&gt; should fail to type check, as we&#x27;re trying to apply an expression of type &lt;code&gt;X -&amp;gt; Y&lt;&#x2F;code&gt; to a function of type &lt;code&gt;X -&amp;gt; Y&lt;&#x2F;code&gt;, which only takes arguments of type &lt;code&gt;X&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Abstract&lt;&#x2F;code&gt; Introduces a variable as a parameter to an expression, making it a function. So if it introduces a variable &lt;code&gt;v&lt;&#x2F;code&gt; of type &lt;code&gt;X&lt;&#x2F;code&gt; into an expression whose type is &lt;code&gt;Z&lt;&#x2F;code&gt;, then the expression it forms has the type &lt;code&gt;X -&amp;gt; Z&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2&gt;Abstracting the toy type system&lt;&#x2F;h2&gt;
&lt;p&gt;Another thing is that we don&#x27;t want all types to always have to be annotated in every circumstance, as we can probably design a nice type inference algorithm.&lt;&#x2F;p&gt;
&lt;p&gt;So what, do we then extend the &lt;code&gt;ToyType&lt;&#x2F;code&gt; type so there&#x27;s a lack of a type as one of its possibilities? That sounds horrible, an introduction of &lt;code&gt;null&lt;&#x2F;code&gt; to our toy type system also removes the certainty that when a variable has a type it has a &lt;em&gt;type&lt;&#x2F;em&gt; and not just a hole for a type to be derived into.&lt;&#x2F;p&gt;
&lt;p&gt;So do we then duplicate &lt;code&gt;LambdaCalc&lt;&#x2F;code&gt; into &lt;code&gt;PartiallyTypedLambdaCalc&lt;&#x2F;code&gt;? Where we replace &lt;code&gt;ToyType&lt;&#x2F;code&gt; with &lt;code&gt;Maybe ToyType&lt;&#x2F;code&gt;? That&#x27;s also bizarre as a data structure design choice. In haskell, in typed functional programming languages, in well-typed languages overall we get trained into viewing things like this as things we can solve with the host type system. And yeah, there&#x27;s a fairly obvious choice:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color: rgb(254, 254, 254); color: rgb(84, 84, 84); position: relative; padding: 0px; line-height: 1.2rem;&quot;&gt;&lt;code style=&quot;padding: 0px 16px; display: block; margin-bottom: 9px; margin-top: 9px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: dimgray;&quot;&gt;-- The toy type system is now a type parameter over our lambda calculus&lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;-- in our host language implementation.&lt;&#x2F;span&gt;
&lt;span&gt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;data&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;LambdaCalc&lt;&#x2F;span&gt; t =&lt;&#x2F;span&gt;
    &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Var&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;String&lt;&#x2F;span&gt;
    &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Apply&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;LambdaCalc&lt;&#x2F;span&gt; t) (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;LambdaCalc&lt;&#x2F;span&gt; t)
    &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Abstract&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;String&lt;&#x2F;span&gt;, t) (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;LambdaCalc&lt;&#x2F;span&gt; t)
    &lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;deriving&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Functor&lt;&#x2F;span&gt;, ...) &lt;span style=&quot;color: dimgray;&quot;&gt;-- oh we could derive so many things!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We even get to do things such as define an untyped lambda calculus as &lt;code&gt;LambdaCalc ()&lt;&#x2F;code&gt; using the Unit type. We get to define type erasure as just mapping &lt;code&gt;\a -&amp;gt; ()&lt;&#x2F;code&gt; over &lt;code&gt;LambdaCalc&lt;&#x2F;code&gt; because we can derive &lt;code&gt;Functor&lt;&#x2F;code&gt; (or implement it manually, pick your poison) for it in the host language.&lt;&#x2F;p&gt;
&lt;p&gt;This is the point of typing things this way, we get more operations for free. We have to do less work overall and there are more rules that the compiler of the host language takes care of, instead of us making unchecked assumptions.&lt;&#x2F;p&gt;
&lt;p&gt;This is also an small example of an instance where &lt;code&gt;Functor&lt;&#x2F;code&gt; does not mean &quot;Container&quot;. It&#x27;s an easy misstep, but this works as a dweeby illustration of &lt;code&gt;Functor&lt;&#x2F;code&gt;&#x27;s more nuanced semantics. Just because a data structure has a parameter does not mean it is supposed to be an alternative to an array, a set, a tree.&lt;&#x2F;p&gt;
&lt;h3&gt;Aside: Context, $\Gamma$, Monads&lt;&#x2F;h3&gt;
&lt;p&gt;If you go through papers and web pages on type theories, you&#x27;ll come across $\Gamma$ in the definitions. This is the representation for &quot;Context&quot; aka &lt;em&gt;known and ongoing information&lt;&#x2F;em&gt; or perhaps the most loathed term of all: &lt;em&gt;state&lt;&#x2F;em&gt;. Thinking through how we might do type checking operations we can imagine that when doing type checking on some toy languages we want an ongoing collection of named known expressions and their known types.&lt;&#x2F;p&gt;
&lt;p&gt;If we say that $(add\_one : Int \rightarrow Int) \in \Gamma$ we mean that in our context $\Gamma$ we know of a symbol &lt;code&gt;add_one&lt;&#x2F;code&gt; with the type &lt;code&gt;Int -&amp;gt; Int&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If we have a messy prototype complete with a helper function to parse basic type expressions then we could say that &lt;code&gt;typecheck_context.get(&quot;add_one&quot;) == parse_type(&quot;Int -&amp;gt; Int&quot;)&lt;&#x2F;code&gt; is true.&lt;&#x2F;p&gt;
&lt;p&gt;In practice, $\Gamma$ is implemented in any number of ways. It could be that you&#x27;re passing around a key-value map that you&#x27;re passing to every function, or there&#x27;s a global variable everything is referring to, or a database, or a server, or a web crawler that finds anything that looks like typed symbol, or anything your heart desires.&lt;&#x2F;p&gt;
&lt;p&gt;Or, you could do what I&#x27;m doing in Haskell. In Haskell we have a very obvious tool for representing context aka ongoing information aka &lt;em&gt;state&lt;&#x2F;em&gt; that lets us dismiss all the explicit notation away: The monad. If you&#x27;re not familiar with monads, just read this as &quot;the way I&#x27;m accessing and modifying context&quot;. Or, watch &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=LekhueQ4zVU&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot; tabindex=&quot;0&quot;&gt;this video&lt;&#x2F;a&gt;. Or, read &lt;a href=&quot;https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20210927150910&#x2F;http:&#x2F;&#x2F;dev.stephendiehl.com&#x2F;hask&#x2F;index.html#monads&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot; tabindex=&quot;0&quot;&gt;this blog post&lt;&#x2F;a&gt;. Or, try using promises and callbacks in javascript with the &lt;code&gt;then&lt;&#x2F;code&gt; method.&lt;&#x2F;p&gt;
&lt;p&gt;The assumption from here on is that you know that when I talk about using monads in the host language of my choice, I&#x27;m talking about the structure that manages information that we know.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color: rgb(254, 254, 254); color: rgb(84, 84, 84); position: relative; padding: 0px; line-height: 1.2rem;&quot;&gt;&lt;code style=&quot;padding: 0px 16px; display: block; margin-bottom: 9px; margin-top: 9px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: dimgray;&quot;&gt;-- from the haskell package &quot;mtl&quot;&lt;&#x2F;span&gt;
&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;import&lt;&#x2F;span&gt; Control.Monad.State.Lazy (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;State&lt;&#x2F;span&gt;)
&lt;p&gt;&lt;span style=&quot;color: dimgray;&quot;&gt;-- Typechecking could plausibly involve reading&#x2F;writing from disk, network. &lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;-- But that&#x27;s getting into the weeds. &lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;-- As an example here, I&#x27;m using a state monad whose state is a key-value &lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;-- map between symbol names and their types. This is not a prescription of &lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;-- what your type checking context should be, only an example.&lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;-- And really, this example is flawed as it also needs to support&lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;-- erroring and returning without having found a type for the &lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;-- expression as well.&lt;&#x2F;span&gt;
&lt;span&gt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;type&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;ToyContextM&lt;&#x2F;span&gt; = &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;State&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Map&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;String&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;ToyType&lt;&#x2F;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;h2&gt;Typing Type Checking&lt;&#x2F;h2&gt;
&lt;p&gt;For me, the most important operation is &lt;em&gt;finding the type of a fully-typed expression&lt;&#x2F;em&gt;. If the type can be found, I know the following:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The type of the expression overall (clearly).&lt;&#x2F;li&gt;
&lt;li&gt;The type checking operation was successful.&lt;&#x2F;li&gt;
&lt;li&gt;The types of any subexpressions, which may be added to the ongoing context.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This gives us more information than some &lt;code&gt;isCorrectlyTyped :: Context -&amp;gt; LambdaCalc ToyType -&amp;gt; Bool&lt;&#x2F;code&gt; function might give us.&lt;&#x2F;p&gt;
&lt;p&gt;So, we want an host language function that takes a toy language expression in its fully typed form and returns its type, plus any modifications to the context.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color: rgb(254, 254, 254); color: rgb(84, 84, 84); position: relative; padding: 0px; line-height: 1.2rem;&quot;&gt;&lt;code style=&quot;padding: 0px 16px; display: block; margin-bottom: 9px; margin-top: 9px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: rgb(0, 127, 170);&quot;&gt;typecheck&lt;&#x2F;span&gt; :: &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;LambdaCalc&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;ToyType&lt;&#x2F;span&gt; -&amp;gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;ToyContextM&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;ToyType&lt;&#x2F;span&gt;
&lt;span style=&quot;color: rgb(0, 127, 170);&quot;&gt;typecheck&lt;&#x2F;span&gt; expr = &lt;span style=&quot;color: dimgray;&quot;&gt;-- It&#x27;d take a lot of space here to write this all out. &lt;&#x2F;span&gt;
                 &lt;span style=&quot;color: dimgray;&quot;&gt;-- But, I believe in you. You can do it!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2&gt;Typing Type Inference&lt;&#x2F;h2&gt;
&lt;p&gt;We also can do something similar for type inference, which is an operation that takes a partially-typed expression and derives the types of the rest of the expression:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color: rgb(254, 254, 254); color: rgb(84, 84, 84); position: relative; padding: 0px; line-height: 1.2rem;&quot;&gt;&lt;code style=&quot;padding: 0px 16px; display: block; margin-bottom: 9px; margin-top: 9px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: rgb(0, 127, 170);&quot;&gt;infer&lt;&#x2F;span&gt; :: &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;LambdaCalc&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Maybe&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;ToyType&lt;&#x2F;span&gt;) -&amp;gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;ToyContextM&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;LambdaCalc&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;ToyType&lt;&#x2F;span&gt;)
&lt;span style=&quot;color: rgb(0, 127, 170);&quot;&gt;infer&lt;&#x2F;span&gt; expr = &lt;span style=&quot;color: dimgray;&quot;&gt;-- It&#x27;s true! Google hindley-milner type inference to find out more. &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which we can express really nicely in the type system because we made the type system a parameter to &lt;code&gt;LambdaCalc&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;h2&gt;Making a Typeclass&#x2F;Trait&#x2F;Interface&lt;&#x2F;h2&gt;
&lt;p&gt;We have a structure, so let&#x27;s be brash and make an assumption. Let&#x27;s assume that all typed languages will work kind of the same way, or can be modified a little to work the same way. Let&#x27;s assume we can make typeclasses that can encompass both inference and type checking analogously to how I&#x27;ve already presented them.&lt;&#x2F;p&gt;
&lt;p&gt;This will depend on host language features, but in Haskell&lt;sup&gt;3&lt;&#x2F;sup&gt; it will look a bit like this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color: rgb(254, 254, 254); color: rgb(84, 84, 84); position: relative; padding: 0px; line-height: 1.2rem;&quot;&gt;&lt;code style=&quot;padding: 0px 16px; display: block; margin-bottom: 9px; margin-top: 9px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;{-# LANGUAGE FunctionalDependencies #-}&lt;&#x2F;span&gt;
&lt;span&gt;
&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;class&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Monad&lt;&#x2F;span&gt; m =&amp;gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Typecheck&lt;&#x2F;span&gt; m l t | l t -&amp;gt; m &lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span style=&quot;color: dimgray;&quot;&gt;-- Here we define a typechecking operation by asking for a &lt;&#x2F;span&gt;
    &lt;span style=&quot;color: dimgray;&quot;&gt;-- function which, when given a typed expression, returns &lt;&#x2F;span&gt;
    &lt;span style=&quot;color: dimgray;&quot;&gt;-- its type within some monadic context `m`. &lt;&#x2F;span&gt;
    typecheck :: l t -&amp;gt; m t
&lt;span&gt;
&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;class&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Typecheck&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(0, 127, 170);&quot;&gt;m&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(0, 127, 170);&quot;&gt;l&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(0, 127, 170);&quot;&gt;t&lt;&#x2F;span&gt;) =&amp;gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Infer&lt;&#x2F;span&gt; m l t | l t -&amp;gt; m &lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    &lt;span style=&quot;color: dimgray;&quot;&gt;-- Something that is inferrable must also be typecheckable,&lt;&#x2F;span&gt;
    &lt;span style=&quot;color: dimgray;&quot;&gt;-- as we have defined the type checking operation as being&lt;&#x2F;span&gt;
    &lt;span style=&quot;color: dimgray;&quot;&gt;-- able to determine a fully-typed expression&#x27;s type and&lt;&#x2F;span&gt;
    &lt;span style=&quot;color: dimgray;&quot;&gt;-- we can imagine that inference would need that anyway.&lt;&#x2F;span&gt;
    infer :: l (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Maybe&lt;&#x2F;span&gt; t) -&amp;gt; m (l t)&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that &lt;code&gt;Infer&lt;&#x2F;code&gt; requires a &lt;code&gt;Typecheck&lt;&#x2F;code&gt; implementation to be implemented. This is because I&#x27;m making an assumption that while doing type inference we&#x27;ll want to type check subexpressions to know their types so that we can infer the correct type of the overall expression.&lt;&#x2F;p&gt;
&lt;p&gt;What does this give us, though? It puts two operations in a neat little box, it gives us &lt;em&gt;direction&lt;&#x2F;em&gt;. It is not the be-all end-all of what types or static analysis in general has to be. It&#x27;s efficient communication to someone who wants to make their data structures behave a certain way. It formalises a data transformation in a way that asks the user to think about how they&#x27;d implement these functions for the data structures that matter to them.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s also &lt;em&gt;satisfying&lt;&#x2F;em&gt; if you&#x27;ve been through bending your brain around type theories, typed languages. It&#x27;s a way of presenting a general form in a way that makes you feel like something more true has been uncovered, even though all that&#x27;s been done is the removal of specificities. We can now look at other abstract syntax trees for other languages and see how we might apply this way of doing things.&lt;&#x2F;p&gt;
&lt;h2&gt;The most joyful&#x2F;painful thing of all: Actually making your type system&lt;&#x2F;h2&gt;
&lt;p&gt;This is where the scope of this blog post abruptly ends, as I am not instructing in type theory construction here. What I can do is once again offer a short list of what might be generously called insights:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;It&#x27;s perfectly okay to do something that&#x27;s already been done before.&lt;&#x2F;li&gt;
&lt;li&gt;A language can have a type system and also be interpreted instead of compiled.&lt;&#x2F;li&gt;
&lt;li&gt;Values don&#x27;t have to only exist at &quot;runtime&quot;.&lt;&#x2F;li&gt;
&lt;li&gt;If you want to find some basic inspiration for toy type system features, look up the &quot;lambda cube&quot;.&lt;&#x2F;li&gt;
&lt;li&gt;Resolving free type variables honestly sucks and I&#x27;m really sorry. Terms you&#x27;ll be looking for include: alpha equivalence, term unification, occurs check. Don&#x27;t decide that you need to figure it out all by your self like I did when I was deep into this, reach out to others for help or to explain how to do things.&lt;&#x2F;li&gt;
&lt;li&gt;Chase ambition sure, but we are a social lot. If you isolate yourself to solve all the problems you come up against, you&#x27;ll find yourself lonely and perhaps without community to confidently share your work with or have appreciate your work. And don&#x27;t work yourself into sickness.&lt;&#x2F;li&gt;
&lt;li&gt;You don&#x27;t need to have a runtime to have fun working on a language.&lt;&#x2F;li&gt;
&lt;li&gt;What I laid out here won&#x27;t necessarily work for everything.&lt;&#x2F;li&gt;
&lt;li&gt;A language doesn&#x27;t necessarily have only one type system.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Designing a type system for your language is largely about decision making and lining up what you want with what you can do. We are privileged as people who write software in this world to have access to a very tight feedback loop in the form of compilers and automated tests which can give us confidence in what we&#x27;re doing very rapidly. Leverage your tools and keep an open mind.&lt;&#x2F;p&gt;
&lt;h2&gt;Conclusion and postscripts&lt;&#x2F;h2&gt;
&lt;p&gt;I hope this exercise in type-driven development as applied to building toy languages (domain-specific, programming, general, or otherwise) has been helpful and not too esoteric. This way of doing things lets us separate different stages of type checking from each other without having to repeat definitions of data structures, and without being able to plug wrong stages into each other, all while being able to tell some basics of what is known about the types during which processes.&lt;&#x2F;p&gt;
&lt;p&gt;Adding types to your languages can seem like an unnecessary and academic wander too far into the weeds. It doesn&#x27;t have to be. The first step can be just looking at your toy language&#x27;s AST and seeing if you can add a type parameter for extra data for your variables where they&#x27;re introduced, and if that extra data can be types or thought of as types.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Next time:&lt;&#x2F;strong&gt; &lt;a href=&quot;https:&#x2F;&#x2F;cohost.org&#x2F;fallible-algebra&#x2F;post&#x2F;2696543-dependent-types-fee&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot; tabindex=&quot;0&quot;&gt;This, but for dependent types.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;details&gt;
&lt;summary tabindex=&quot;0&quot;&gt;Postscript: Doing most of this in Rust&lt;&#x2F;summary&gt;
&lt;span&gt;
I do like Rust, and you can still do most of the cool stuff here in Rust. Rust doesn&#x27;t have Higher-Kinded Types (or it does, but... I don&#x27;t want to scare you off) so we can&#x27;t get functors for free, or use monads, or easily state a trait that defines type checking and type inference.
&lt;p&gt;But we can do the important things, so Rust is perfectly better-than-okay for this way of doing things:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color: rgb(254, 254, 254); color: rgb(84, 84, 84); position: relative; padding: 0px; line-height: 1.2rem;&quot;&gt;&lt;code style=&quot;padding: 0px 16px; display: block; margin-bottom: 9px; margin-top: 9px;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;struct&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(0, 127, 170);&quot;&gt;ToyContext&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; {
    &lt;span style=&quot;color: dimgray;&quot;&gt;&#x2F;&#x2F; ...&lt;&#x2F;span&gt;
}
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;enum&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(0, 127, 170);&quot;&gt;ToyType&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; {
&lt;span style=&quot;color: dimgray;&quot;&gt;&#x2F;&#x2F; ...&lt;&#x2F;span&gt;
}&lt;&#x2F;p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;enum&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(0, 127, 170);&quot;&gt;LambdaCalc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&amp;lt;T&amp;gt; {
Var(&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;String&lt;&#x2F;span&gt;),
Apply(&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Box&lt;&#x2F;span&gt;&amp;lt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;Self&lt;&#x2F;span&gt;&amp;gt;, &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Box&lt;&#x2F;span&gt;&amp;lt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;Self&lt;&#x2F;span&gt;&amp;gt;),
Abstract(&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;String&lt;&#x2F;span&gt;, T, &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Box&lt;&#x2F;span&gt;&amp;lt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;Self&lt;&#x2F;span&gt;&amp;gt;)
}&lt;&#x2F;p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;type&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(0, 127, 170);&quot;&gt;UntypedLC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; = LambdaCalc&amp;lt;()&amp;gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;span style=&quot;color: dimgray;&quot;&gt;&#x2F;&#x2F; Altneratively, ctx could be &lt;code&gt;&amp;amp;amp;mut ToyContext&lt;&#x2F;code&gt; and &lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;&#x2F;&#x2F; you wouldn&#x27;t need to return the &lt;code&gt;ToyContext&lt;&#x2F;code&gt;, but&lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;&#x2F;&#x2F; that&#x27;s not the only way you could do things and would&lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;&#x2F;&#x2F; get in the way of parallelisation efforts. I&#x27;m just&lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;&#x2F;&#x2F; doing it this way here to line up with the haskell examples.&lt;&#x2F;span&gt;
&lt;span&gt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;fn&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(0, 127, 170);&quot;&gt;typecheck&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;(
ctx: ToyContext,
expr: LambdaCalc&amp;lt;Type&amp;gt;,
) -&amp;gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Result&lt;&#x2F;span&gt;&amp;lt;(Ctx, Type), &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Err&lt;&#x2F;span&gt;&amp;gt; {
&lt;span style=&quot;color: dimgray;&quot;&gt;&#x2F;&#x2F; ...&lt;&#x2F;span&gt;
}&lt;&#x2F;p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;fn&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(0, 127, 170);&quot;&gt;infer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;(
ctx: ToyContext,
expr: LambdaCalc&amp;lt;&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Option&lt;&#x2F;span&gt;&amp;lt;Type&amp;gt;&amp;gt;,
) -&amp;gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Result&lt;&#x2F;span&gt;&amp;lt;(ToyContext, LambdaCalc&amp;lt;Type&amp;gt;), &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Err&lt;&#x2F;span&gt;&amp;gt; {
&lt;span style=&quot;color: dimgray;&quot;&gt;&#x2F;&#x2F; ...&lt;&#x2F;span&gt;
}&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Note that we need to specify context as a variable, but that&#x27;s fine. It&#x27;s easier to understand from the point of view of someone not entrenched in Haskell. Crates such as &lt;code&gt;nom&lt;&#x2F;code&gt; do this same thing, and it works out fine for them.&lt;&#x2F;p&gt;
&lt;p&gt;If Haskell is too esoteric these days I might do a Rust Version of this post. Should get with the times, after all.&lt;br&gt;
&lt;&#x2F;p&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;details&gt;
&lt;details&gt;
&lt;summary tabindex=&quot;0&quot;&gt;Postscript: Meta&lt;&#x2F;summary&gt;
I really wanted to call this &quot;typing the type checker&quot; but 1. not everyone has read &lt;a href=&quot;https:&#x2F;&#x2F;aphyr.com&#x2F;posts&#x2F;342-typing-the-technical-interview&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot; tabindex=&quot;-1&quot;&gt;Typing The Technical Interview&lt;&#x2F;a&gt; and 2. what I&#x27;m doing here isn&#x27;t nearly as complicated, I do not think it could live up to the reference. 
&lt;&#x2F;details&gt;
&lt;hr aria-label=&quot;Footnotes&quot; style=&quot;margin-bottom: -0.5rem;&quot;&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-user-content-fn-1&quot;&gt;
&lt;p&gt;Toy here not meant to demean the language being developed, but instead because this is more about having fun with language design than getting serious about the guts and bureaucracy of things. &lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;user-content-user-content-fn-2&quot;&gt;
&lt;p&gt;I mean this in an informal sense, not as a sweeping ontological statement of linguistics, type theory, mathematics. &lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;user-content-user-content-fn-3&quot;&gt;
&lt;p&gt;While I&#x27;m enabling the &lt;code&gt;FunctionalDependencies&lt;&#x2F;code&gt; feature here, isn&#x27;t a necessary addition. It does let us specify that the language and type system are what determine the type of the monadic context. &lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;div&gt;&lt;button class=&quot;co-link-button co-opaque inline-block pb-3 pl-3 text-left text-sm font-bold hover:underline&quot; tabindex=&quot;0&quot;&gt;read less&lt;&#x2F;button&gt;&lt;&#x2F;cohost-post&gt;
&lt;&#x2F;div&gt;
&lt;h1 id=&quot;follow-up-post&quot;&gt;Follow-up post&lt;&#x2F;h1&gt;
&lt;div id=&quot;pt2&quot;&gt;
&lt;cohost-post avatarsrc=&quot;data:image&#x2F;jpeg;base64,&#x2F;9j&#x2F;4AAQSkZJRgABAQAAAQABAAD&#x2F;4gIcSUNDX1BST0ZJTEUAAQEAAAIMbGNtcwIQAABtbnRyUkdCIFhZWiAH3AABABkAAwApADlhY3NwQVBQTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWxjbXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApkZXNjAAAA&#x2F;AAAAF5jcHJ0AAABXAAAAAt3dHB0AAABaAAAABRia3B0AAABfAAAABRyWFlaAAABkAAAABRnWFlaAAABpAAAABRiWFlaAAABuAAAABRyVFJDAAABzAAAAEBnVFJDAAABzAAAAEBiVFJDAAABzAAAAEBkZXNjAAAAAAAAAANjMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0ZXh0AAAAAEZCAABYWVogAAAAAAAA9tYAAQAAAADTLVhZWiAAAAAAAAADFgAAAzMAAAKkWFlaIAAAAAAAAG+iAAA49QAAA5BYWVogAAAAAAAAYpkAALeFAAAY2lhZWiAAAAAAAAAkoAAAD4QAALbPY3VydgAAAAAAAAAaAAAAywHJA2MFkghrC&#x2F;YQPxVRGzQh8SmQMhg7kkYFUXdd7WtwegWJsZp8rGm&#x2F;fdPD6TD&#x2F;&#x2F;&#x2F;&#x2F;bAEMA&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;bAEMB&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;AABEIAEAAQAMBIgACEQEDEQH&#x2F;xAAWAAEBAQAAAAAAAAAAAAAAAAABAAL&#x2F;xAAcEAEBAQEBAQADAAAAAAAAAAAAARESIWECMVH&#x2F;xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf&#x2F;EABcRAQEBAQAAAAAAAAAAAAAAAAARASH&#x2F;2gAMAwEAAhEDEQA&#x2F;ADqrqsmBD18PXwYUpFvxagLMPU+rqBYqRmNifooqWIrE3WbMDd9jGBmpqBqIus6WWgXqQ06Q6NQUmEiQoM6dGX+LmqUhc1c0KjIp+NPolLOn1nKGP&#x2F;&#x2F;Z&quot; avatarshape=&quot;squircle&quot; comments=&quot;0&quot; displayname=&quot;Fallible Algebra&quot; handle=&quot;fallible-algebra&quot; originalurl=&quot;https:&#x2F;&#x2F;cohost.org&#x2F;fallible-algebra&#x2F;post&#x2F;2696543-dependent-types-fee&quot; publishedat=&quot;2023-09-01T10:49:32.698Z&quot; standaloneheadline=&quot;Dependent Types: Feeding the lambda calculus its own tail&quot; tags=&quot;programming language theory,dependent types,mathematics,math,maths,type theory,haskell,lambda calculus,programming languages,tutorial,functional programming,PLT&quot;&gt;&lt;noscript&gt;Post by Fallible Algebra (@fallible-algebra): Dependent Types: Feeding the lambda calculus its own tail&lt;&#x2F;noscript&gt;&lt;div class=&quot;co-prose prose my-4 overflow-hidden break-words px-3&quot;&gt;&lt;p&gt;This is a short continuation of &lt;a href=&quot;https:&#x2F;&#x2F;cohost.org&#x2F;fallible-algebra&#x2F;post&#x2F;2660945-outlining-type-check&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot; tabindex=&quot;0&quot;&gt;Outlining type checking for your toy language (and many others)&lt;&#x2F;a&gt;. In my previous post, I introduced a way of classifying type checking and type inference as a transformation on an abstract syntax tree whose type system was a type parameter:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color: rgb(254, 254, 254); color: rgb(84, 84, 84); position: relative; padding: 0px; line-height: 1.2rem; margin-bottom: 0px;&quot;&gt;&lt;code style=&quot;padding: 0px 16px; display: block; margin-bottom: 9px; margin-top: 9px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;{-# LANGUAGE FunctionalDependencies #-}&lt;&#x2F;span&gt;
&lt;span&gt;
&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;class&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Monad&lt;&#x2F;span&gt; m =&amp;gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Typecheck&lt;&#x2F;span&gt; m l t | l t -&amp;gt; m &lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    typecheck :: l t -&amp;gt; m t
&lt;span&gt;
&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;class&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Typecheck&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(0, 127, 170);&quot;&gt;m&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(0, 127, 170);&quot;&gt;l&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(0, 127, 170);&quot;&gt;t&lt;&#x2F;span&gt;) =&amp;gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Infer&lt;&#x2F;span&gt; m l t | l t -&amp;gt; m &lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
    infer :: l (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Maybe&lt;&#x2F;span&gt; t) -&amp;gt; m (l t)&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;div style=&quot;text-align: right; font-size: min(1.87vw, 70%); opacity: 0.7; margin-bottom: 1.71429em;&quot;&gt;made with &lt;a data-testid=&quot;mention&quot; href=&quot;https:&#x2F;&#x2F;cohost.org&#x2F;nex3&quot; class=&quot;!font-bold !no-underline hover:!underline&quot; tabindex=&quot;0&quot;&gt;@nex3&lt;&#x2F;a&gt;&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;nex3.github.io&#x2F;cohost-highlight&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot; tabindex=&quot;0&quot;&gt;syntax highlighter&lt;&#x2F;a&gt;&lt;&#x2F;div&gt;
&lt;p&gt;I was using a lambda calculus whose type system I had made into a type parameter:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color: rgb(254, 254, 254); color: rgb(84, 84, 84); position: relative; padding: 0px; line-height: 1.2rem;&quot;&gt;&lt;code style=&quot;padding: 0px 16px; display: block; margin-bottom: 9px; margin-top: 9px;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;data&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;LambdaCalc&lt;&#x2F;span&gt; t&lt;&#x2F;span&gt;
	= &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Var&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;String&lt;&#x2F;span&gt;
	| &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Apply&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;LambdaCalc&lt;&#x2F;span&gt; t) (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;LambdaCalc&lt;&#x2F;span&gt; t)
	| &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Abstract&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;String&lt;&#x2F;span&gt;, t) (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;LambdaCalc&lt;&#x2F;span&gt; t)
	&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;deriving&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Functor&lt;&#x2F;span&gt;, ...)&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What I was walking through was the reasoning for doing things this way, especially how it means we can separate the stages of analysis really cleanly.&lt;&#x2F;p&gt;
&lt;p&gt;But hang on, what if we start treating the toy language&#x27;s type system as the toy language?&lt;&#x2F;p&gt;&lt;&#x2F;div&gt;&lt;div class=&quot;co-prose prose my-4 overflow-hidden break-words px-3&quot;&gt;&lt;hr&gt;
&lt;p&gt;If we bring the complexity of the type system up to something like System F Omega, we can ask the questions previously asked for the lambda calculus itself but about our type system:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;forall&lt;&#x2F;code&gt; introduces type variables to type expressions.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Function&lt;&#x2F;code&gt; is a constant with kind &lt;code&gt;Type -&amp;gt; Type&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;We have a notion of kindedness, as in (2), where &lt;code&gt;Function&lt;&#x2F;code&gt; has a kind instead of a type.&lt;&#x2F;li&gt;
&lt;li&gt;There are various reduction rules we can pull from for how to evaluate types during type checking.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;We can follow through on this with something along these lines:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color: rgb(254, 254, 254); color: rgb(84, 84, 84); position: relative; padding: 0px; line-height: 1.2rem;&quot;&gt;&lt;code style=&quot;padding: 0px 16px; display: block; margin-bottom: 9px; margin-top: 9px;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;type&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;KindcheckM&lt;&#x2F;span&gt; = ...&lt;&#x2F;span&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;data&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Kind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;-- AKA &lt;code&gt;*&lt;&#x2F;code&gt;, or &lt;code&gt;Type&lt;&#x2F;code&gt;. The type of types.&lt;&#x2F;span&gt;
= &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;MyType&lt;&#x2F;span&gt;
| &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Arrow&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Kind&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Kind&lt;&#x2F;span&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;data&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;MyTypeSystem&lt;&#x2F;span&gt; k &lt;&#x2F;span&gt;
= &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Forall&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;String&lt;&#x2F;span&gt;, k) &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;MyTypeSystem&lt;&#x2F;span&gt;
| &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Function&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;MyTypeSystem&lt;&#x2F;span&gt; k) (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;MyTypeSystem&lt;&#x2F;span&gt; k)
| &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;TypeVar&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;String&lt;&#x2F;span&gt;
| &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;TypeCon&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;String&lt;&#x2F;span&gt;
&lt;span&gt;
&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;instance&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Typecheck&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;KindcheckM&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;MyTypeSystem&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Kind&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
typecheck :: &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;MyTypeSystem&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Kind&lt;&#x2F;span&gt; -&amp;gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;KindcheckM&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Kind&lt;&#x2F;span&gt;
typecheck expr = ...
&lt;span&gt;
&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;instance&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Infer&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;KindcheckM&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;MyTypeSystem&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Kind&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
infer :: &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;MyTypeSystem&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Maybe&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Kind&lt;&#x2F;span&gt;) -&amp;gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;KindcheckM&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;MyTypeSystem&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Kind&lt;&#x2F;span&gt;)
infer = ...&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Can we take it a step further? Well, not like this. Kindedness does not at this point have the complexity we would want to be able to apply those same questions to it and get satisfying answers.&lt;&#x2F;p&gt;
&lt;p&gt;But if we were to step up the type system to a Dependent one, one where general expressions can live in type land we can tie this up in a way that fits the style I&#x27;ve been going for here. We will need one &lt;a href=&quot;https:&#x2F;&#x2F;hackage.haskell.org&#x2F;package&#x2F;data-fix-0.3.2&#x2F;docs&#x2F;Data-Fix.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot; tabindex=&quot;0&quot;&gt;fancy tool&lt;&#x2F;a&gt; so that we can feed host types to themselves:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color: rgb(254, 254, 254); color: rgb(84, 84, 84); position: relative; padding: 0px; line-height: 1.2rem;&quot;&gt;&lt;code style=&quot;padding: 0px 16px; display: block; margin-bottom: 9px; margin-top: 9px;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;newtype&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Fix&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(0, 127, 170);&quot;&gt;f&lt;&#x2F;span&gt; :: * -&amp;gt; *) = &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Fix&lt;&#x2F;span&gt; {&lt;span style=&quot;color: rgb(0, 127, 170);&quot;&gt;unfix&lt;&#x2F;span&gt; :: &lt;span style=&quot;color: rgb(0, 127, 170);&quot;&gt;f&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Fix&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(0, 127, 170);&quot;&gt;f&lt;&#x2F;span&gt;)}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;Fix&lt;&#x2F;code&gt; feels a bit like a form of dark magic, but it can be thought of doing the same thing we do when we build a recursive function. Once again this is a simplification, but one to smooth past complexity and maintain focus.&lt;&#x2F;p&gt;
&lt;p&gt;When we have &lt;code&gt;Fix&lt;&#x2F;code&gt;, it might tempt to just declare &lt;code&gt;LambdaCalc (Fix LambdaCalc)&lt;&#x2F;code&gt; as a dependently typed calculus. However there&#x27;s a few modifications to the original I would like to do to:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color: rgb(254, 254, 254); color: rgb(84, 84, 84); position: relative; padding: 0px; line-height: 1.2rem;&quot;&gt;&lt;code style=&quot;padding: 0px 16px; display: block; margin-bottom: 9px; margin-top: 9px;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: dimgray;&quot;&gt;-- A bit of housekeeping: I&#x27;ve made variables and constants distinct&lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;-- types and added constants to the lambda calculus because now, they&lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;-- not only represent &quot;runtime&quot; values but can also represent compile&lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;-- time ones. `Function` now occupies a similar space in the language&lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;-- as any user-defined constants. And some variable `a` could mean a&lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;-- type variable or a variable that .&lt;&#x2F;span&gt;
&lt;span&gt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;data&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Variable&lt;&#x2F;span&gt; = ...&lt;&#x2F;span&gt;
&lt;span&gt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;data&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Constant&lt;&#x2F;span&gt; = ...&lt;&#x2F;span&gt;
&lt;p&gt;&lt;span style=&quot;color: dimgray;&quot;&gt;-- A lambda calculus with variables, constants, and the type system &lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;-- made into parameters so we can focus on the important things in &lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;-- life like good tea and time with friends and loved ones.&lt;&#x2F;span&gt;
&lt;span&gt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;data&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;DepLambdaCalc&lt;&#x2F;span&gt; t&lt;&#x2F;span&gt;
= &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Var&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Variable&lt;&#x2F;span&gt;
| &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Const&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Constant&lt;&#x2F;span&gt;
| &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Apply&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;DepLambdaCalc&lt;&#x2F;span&gt; t) (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;DepLambdaCalc&lt;&#x2F;span&gt; t)
| &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Abstract&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Variable&lt;&#x2F;span&gt;, t) (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;DepLambdaCalc&lt;&#x2F;span&gt; t)
&lt;span style=&quot;color: dimgray;&quot;&gt;-- Okay, everything is looking fine so far. &lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;-- But with dependent typing we can lift up a variable into the&lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;-- type system. So we need to add one more thing:&lt;&#x2F;span&gt;
| &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Lift&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Variable&lt;&#x2F;span&gt;, t) t&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve introduced &lt;code&gt;Lift&lt;&#x2F;code&gt; which can be thought of as: abstract but it lifts the variable up into the type system. This is not necessarily the correct way of doing things, or the best explanation, but it&#x27;s how I&#x27;m doing it here. As with how I renamed $\lambda$ abstraction to simply &lt;code&gt;Abstract&lt;&#x2F;code&gt;, in type theory this is represented with $\Pi$ (capital letter pi).&lt;&#x2F;p&gt;
&lt;p&gt;With this, we can now make it fit the forms of the typeclasses and have enough space to do at least some dependent type system shenanigans smoothly:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color: rgb(254, 254, 254); color: rgb(84, 84, 84); position: relative; padding: 0px; line-height: 1.2rem;&quot;&gt;&lt;code style=&quot;padding: 0px 16px; display: block; margin-bottom: 9px; margin-top: 9px;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;type&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;DepTypecheckM&lt;&#x2F;span&gt; = ...&lt;&#x2F;span&gt;
&lt;span&gt;
&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;instance&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Typecheck&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;DepTypecheckM&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;DepLambdaCalc&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Fix&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;DepLambdaCalc&lt;&#x2F;span&gt;) &lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
	typecheck :: &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;DepLambdaCalc&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Fix&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;DepLambdaCalc&lt;&#x2F;span&gt;) 
			  -&amp;gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;DepTypecheckM&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Fix&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;DepLambdaCalc&lt;&#x2F;span&gt;)
    typecheck expr = ...
&lt;p&gt;&lt;span style=&quot;color: dimgray;&quot;&gt;-- Not all dependent terms can have their types inferred,&lt;&#x2F;span&gt;
&lt;span style=&quot;color: dimgray;&quot;&gt;-- that&#x27;s just the showbiz of complex type theories.&lt;&#x2F;span&gt;
&lt;span&gt;&lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;instance&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Infer&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;DepTypecheckM&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;DepLambdaCalc&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Fix&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;DepLambdaCalc&lt;&#x2F;span&gt;) &lt;span style=&quot;color: rgb(121, 40, 161);&quot;&gt;where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
infer :: &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;DepLambdaCalc&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Maybe&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Fix&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;DepLambdaCalc&lt;&#x2F;span&gt;))
-&amp;gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;DepTypecheckM&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;DepLambdaCalc&lt;&#x2F;span&gt; (&lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;Fix&lt;&#x2F;span&gt; &lt;span style=&quot;color: rgb(170, 93, 0);&quot;&gt;DepLambdaCalc&lt;&#x2F;span&gt;))
infer expr = ... &lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We have now fed the lambda calculus to itself as its own type system. At least, I&#x27;ve shown a way we could do that. I have not written type checker code in a long time, it takes a lot of effort. But, the framework has been successfully turned onto itself.&lt;&#x2F;p&gt;&lt;&#x2F;div&gt;&lt;button class=&quot;co-link-button co-opaque inline-block pb-3 pl-3 text-left text-sm font-bold hover:underline&quot; tabindex=&quot;0&quot;&gt;read less&lt;&#x2F;button&gt;&lt;&#x2F;cohost-post&gt;
&lt;&#x2F;div&gt;</description>
      </item>
    </channel>
</rss>
