<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Unformed Delta - inkhaven</title>
    <description>A place to collect the things I learn, figure out, or find interesting.
</description>
    <link>https://unformeddelta.wiki/</link>
    <atom:link href="https://unformeddelta.wiki/feed/inkhaven.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sat, 09 May 2026 14:44:19 +0000</pubDate>
    <lastBuildDate>Sat, 09 May 2026 14:44:19 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
    <item>
      <title>Inkhaven is two events stabled into one</title>
      <description>&lt;p&gt;&lt;em&gt;More to add here later + some editing, but the Closing Ceremony is about to start, so I’m going ahead and publishing this in its unfinished state for now!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Inkhaven is at least two different events stapled into one.&lt;/p&gt;

&lt;h2 id=&quot;commitment-mechanism&quot;&gt;Commitment Mechanism&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Publish a post every day or perish.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is what attracted me to Inkhaven. I did &lt;a href=&quot;/GrMhcXX3CY7s/review-the-6-club&quot;&gt;The 6% Club&lt;/a&gt; to try to kick start a blogging habit, breaking through my fear of publishing. It kind of worked, but I still wasn’t able to publish the “harder pieces” I wanted to, and only published irregularly.&lt;/p&gt;

&lt;p&gt;It worked, but not in the way that I expected. When I managed to publish before, I usually would sit down for a few hours, and end up with a finished post. For the posts I never ended up getting to, I assumed that my problem was just lack of motivation. With a hard deadline, I was certain I’d find the motivation to just grind out the harder posts.&lt;/p&gt;

&lt;p&gt;Early on in Inkhaven I tried this, but either ended up &lt;a href=&quot;/88GZeEhC4NLK/not-cutting-corners&quot;&gt;failing and needing to pivot&lt;/a&gt;, or publishing &lt;a href=&quot;/GEbCU1EGqkQU/an-expressive-programming-language&quot;&gt;an imperfect version of the idea inside of my head&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;At first this made me feel like a failure. But over the course of the month, I found time to continue to revisit the same ideas.&lt;/p&gt;

&lt;p&gt;Some of the ideas ended up eluding me the entire month&lt;sup id=&quot;fnref:code-is-communication&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:code-is-communication&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. Other ideas just took longer than I expected&lt;sup id=&quot;fnref:wanikani-vs-jpdbio&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:wanikani-vs-jpdbio&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. And sometimes I managed to publish a follow up that more clearly expressed the idea&lt;sup id=&quot;fnref:expressivity&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:expressivity&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. Publishing even something mediocre about the ideas I care about it easier to come back to them.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/v8mH7WGj5fNz/what-makes-a-good-spaced-repetition-system-wanikani&quot;&gt;What makes a good spaced repetition system? (WaniKani)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/0THf60NuwInF/what-makes-a-good-spaced-repetition-system-jpdbio&quot;&gt;What makes a good spaced repetition system? (jpdb.io)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/YLwRkdcbZJyA/against-foolproof-software&quot;&gt;Against foolproof software&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most valuable lesson for me from the commitment mechanism was the value of setting aside time to write. Though I still get writers block for specific ideas, I find it a lot easier to sit down with the intention to write. And doing that helps me think about and research my more difficult ideas.&lt;/p&gt;

&lt;h2 id=&quot;writing-residency&quot;&gt;Writing Residency&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Mentorship opportunities from celebrated writers, craft-honing workshops, and professional feedback.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Inkhaven provides an all you can eat buffet of feedback and workshops. This was strongly in tension with the daily publishing requirement for me. While the daily commitment mechanism was helping me overcome my perfectionism, the focus on better writing&lt;/p&gt;

&lt;p&gt;Much more so than the previous cohort, it was very common for residents to publish at the last minute. I only managed to publish 5 posts before 6pm, and 9 before 10pm&lt;sup id=&quot;fnref:after-11&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:after-11&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Because I was consistently cutting it close, I was rarely in a position to get feedback on my posts before publishing them. When I did manage to, it helped me improve the quality of my posts or at least made me feel better about publishing.&lt;/p&gt;

&lt;p&gt;I was also able to get feedback after publishing, but doing so usually felt less meaningful than getting it ahead of time. Because of the daily publishing requirement, it felt hard to justify going back and improving pieces that I had already published. I still found it useful to think about for my future writing. Plus, maybe I’ll go back and improve the pieces using the feedback after Inkhaven.&lt;/p&gt;

&lt;p&gt;The workshops were lower friction, and I found them a useful distraction when I was having trouble focusing on writing.&lt;/p&gt;

&lt;p&gt;I want to shout out Justis Mills for reading most of the blog posts for over half of the residents and giving higher level feedback on “Blog Gestalt”. I found this really useful for thinking about what direction I want to take my writing in the future.&lt;/p&gt;

&lt;p&gt;I aspire to make UnformedDelta a public archive of my notes similar &lt;a href=&quot;https://gwern.net&quot;&gt;https://gwern.net&lt;/a&gt;. With Gwern’s encouragement, I managed to publish ~50 of my existing unrefined notes in addition to my daily posts in the latter half of this month, while overcoming my perfectionism that was holding me back from publishing them.&lt;/p&gt;

&lt;h2 id=&quot;community&quot;&gt;Community&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;I don’t have anything fancy sounding to put here.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There’s also kind of a 3rd event. Inkhaven is meetup of particularly writing oriented rationalist-adjacent writers.&lt;/p&gt;

&lt;p&gt;I’m proud to have organized an evening playing board games, an outing to see Project Hail Mary, and a trip into the city to try Wildtype Salmon.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:code-is-communication&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;After failing to write “Code is communication”, I refined my thesis to “Code that is grown” but even after writing and trying to express my thoughts for hours I still wasn’t able to publish by the end of the month. (Stay tuned, I still want to write this post Inkhaven.) &lt;a href=&quot;#fnref:code-is-communication&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:wanikani-vs-jpdbio&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;My article comparing WaniKani and jpdb.io which broke my The 6% Club publishing streak in September turned into a 3 article series: &lt;a href=&quot;#fnref:wanikani-vs-jpdbio&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:expressivity&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;In some the introduction I wrote for &lt;a href=&quot;/dCtl1IFIC8VF/programming-language-features-and-optimizations&quot;&gt;programming language features (and optimizations)&lt;/a&gt; is follow up to &lt;a href=&quot;/GEbCU1EGqkQU/an-expressive-programming-language&quot;&gt;an expressive programming language&lt;/a&gt;, more clearly expressing why I care about expressivity of programming languages. This still isn’t perfect but designing my ideal programming language is a big project. &lt;a href=&quot;#fnref:expressivity&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:after-11&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;11 posts after 11:30pm, and 5 posts after 11:45pm, ouch! &lt;a href=&quot;#fnref:after-11&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
      <pubDate>Thu, 30 Apr 2026 23:25:00 +0000</pubDate>
      <link>https://unformeddelta.wiki/PK2boIoMk82X/inkhaven-is-two-events-stabled-into-one</link>
      <guid isPermaLink="true">https://unformeddelta.wiki/PK2boIoMk82X/inkhaven-is-two-events-stabled-into-one</guid>
      
      <category>inkhaven</category>
      
      <category>meta</category>
      
      <category>personal</category>
      
    </item>
    
    <item>
      <title>Why I&apos;m building my own knowledge management system</title>
      <description>&lt;p&gt;File systems are the default categorization system for personal information on a computer. They make it easy to store files, notes, repositories, or whatever in hierarchies.&lt;/p&gt;

&lt;p&gt;But hierarchies are limiting. A file can only exist at a single path&lt;sup id=&quot;fnref:hardlinks-symlinks&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:hardlinks-symlinks&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Information in our minds doesn’t work like this. When speaking we reference the same entity in lots of different ways. Whether I have a layover in “San Francisco”, am going to “the airport” to fly home, or am entering “SFO” on Google Flights to book a ticket, I’m referencing the same entity.&lt;/p&gt;

&lt;p&gt;Symlinks try to achieve this, but are fragile. If the original copy moves the symlink breaks and it is often isn’t easy to find the original copy.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/hbbzJ0lZT8Tc/hardlinks&quot;&gt;Hardlinks&lt;/a&gt; are closer you map multiple paths to the same underlying data. However, hardlinks suffer from &lt;a href=&quot;/FzO9RP3zvyBM/problems-with-hardlinks&quot;&gt;challenging edge cases&lt;/a&gt;, and generally don’t support directories.&lt;/p&gt;

&lt;p&gt;The internet promised to solve this problem. Hyperlinks let people reference and categorize things however they want, right?&lt;/p&gt;

&lt;p&gt;Take YouTube for example. It’s trivial to create a playlist of videos. If you want to categorize your playlists into a hierarchy, YouTube won’t let you do that, you just need to save them into a folder of bookmarks, or as links in a note.&lt;/p&gt;

&lt;p&gt;Personal knowledge management tools like Notion, Obsidian, Logseq, or Roam Research attempt to make keeping bookmarks, links, notes, and research easier. These are great, I use my Zettelkasten of markdown notes with Obsidian sometimes&lt;sup id=&quot;fnref:mostly&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:mostly&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;These systems make me sad that I can’t associate metadata with arbitrary data — YouTube videos, Wikipedia articles, songs, and so on. Often they support fancier features like canvases, PDF clippings, and even database like rows, once you leave the domain of markdown, metadata starts being stored in private formats.&lt;/p&gt;

&lt;p&gt;But I find it too risky to invest heavily into these systems, because building or maintaining a replacement that supports whatever custom features I use would be non-trivial.&lt;/p&gt;

&lt;p&gt;What I really want is a personal ontology that operates like &lt;a href=&quot;https://www.wikidata.org/wiki/Wikidata:Introduction&quot;&gt;Wikidata&lt;/a&gt;. I hope that Web3 (not the crypto kind) projects like &lt;a href=&quot;https://solidproject.org/&quot;&gt;Solid&lt;/a&gt; are steps in this direction, but they’re still very immature, and I don’t want to couple myself to shifting standards.&lt;/p&gt;

&lt;p&gt;Pretty much the only satisfying option seems to be building it from scratch myself.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;When I was ~10 I remember my uncle asking me how I thought my brain worked. I described it as a point of light bouncing around a network of memories.&lt;/p&gt;

&lt;p&gt;I’m hoping that someday I can bring that network of connections into the real world and interact with my computer the same way I interact with my mind.&lt;/p&gt;

&lt;p&gt;I want to build a system in which my mind can wander safely to the information it wants, while knowing that it contains only information that I put or chose to be there. Perhaps someday I will achieve this dream.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:hardlinks-symlinks&quot; role=&quot;doc-endnote&quot;&gt;

      &lt;p&gt;&lt;a href=&quot;#fnref:hardlinks-symlinks&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:mostly&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;In practice, I mostly edit my notes using Neovim with &lt;a href=&quot;https://github.com/lehmacdj/wiki-language-server&quot;&gt;custom language server&lt;/a&gt; for completion, transclusion, and jumping to links. &lt;a href=&quot;#fnref:mostly&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
      <pubDate>Thu, 30 Apr 2026 06:50:00 +0000</pubDate>
      <link>https://unformeddelta.wiki/1nWDiPLwMooh/why-im-building-my-own-knowledge-management-system</link>
      <guid isPermaLink="true">https://unformeddelta.wiki/1nWDiPLwMooh/why-im-building-my-own-knowledge-management-system</guid>
      
      <category>inkhaven</category>
      
      <category>knowledge-management</category>
      
    </item>
    
    <item>
      <title>For even a bad pause</title>
      <description>&lt;p&gt;Even a global treaty pausing all new training of frontier AI models, would leave a lot of room for existing models to continue to disrupt.&lt;/p&gt;

&lt;p&gt;Our existing workflows weren’t designed with AI agents in mind and there’s abundant low hanging fruit for optimization. Every time I use Codex or Claude Code, I learn something new, and there’s plenty of things I just don’t have time to try.&lt;/p&gt;

&lt;p&gt;Beyond code there’s plenty of other domains. Claude Cowork, the 10 folders of markdown files that caused the SaaSpocalypse, Claude Design, and more aren’t new models, they’re just harnesses for making it easier to work with existing ones.&lt;/p&gt;

&lt;p&gt;What will be the impact on the economy once even our existing systems are widely adopted?&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;There’s a bunch of good things that we get for free by pausing AI progress.&lt;/p&gt;

&lt;p&gt;The technology as it exists today would diffuse. The public lags behind what those of us interested in AI see.&lt;/p&gt;

&lt;p&gt;More election cycles gives more opportunity for more informed and reasonable lawmakers to be elected. It also gives us room to negotiate and dream up better AI policies.&lt;/p&gt;

&lt;p&gt;Nothing about pausing means AI safety research needs to stop. Who knows what novel problems or breakthroughs we might find in the next years?&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Bernie Sanders and Alexandria Ocasio-Cortez’ &lt;a href=&quot;https://www.congress.gov/bill/119th-congress/senate-bill/4214/text&quot;&gt;AI Data Center Moratorium Act&lt;/a&gt; is just 1853 words — well worth reading all of.&lt;/p&gt;

&lt;p&gt;Half of the bill is a sizzle reel of quotes from experts and industry leaders. The functional section of the bill is tiny:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;154 words&lt;/strong&gt; define “Artificial Intelligence Data Center”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;287 words&lt;/strong&gt; set the terms of the moratorium: no new AI data centers until AI is safe and built to be mutually beneficial for all Americans&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;275 words&lt;/strong&gt; requisition various reports, and give the Secretary of Energy the power to verify that the moratorium is being followed&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;161 words&lt;/strong&gt; ban the export of chips to countries not implementing similar measures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s a far cry from a global treaty. But it takes action now buying time and leverage to get a more comprehensive treaty implemented.&lt;/p&gt;

&lt;p&gt;The bill cedes our largest advantage to China. Chinese models are only 3-9 months behind the US frontier, slowing down puts us at risk of losing the frontier.&lt;/p&gt;

&lt;p&gt;This is costly, but perhaps might also serve as a signal. How can we better demonstrate our commitment to AI safety?&lt;/p&gt;

&lt;p&gt;AI labs have frequently say that they want AI regulation. I also look at this bill as an invitation to the labs: help us figure out how to make AI mutually beneficial for society, and then you can go on building the data centers you want.&lt;/p&gt;

&lt;p&gt;My largest quibble is with some of the most concrete details. To me one of the benefits of a sloppy pause are that it gives us time to contemplate what better legislation might look like. Enforcing that AI data center development be done with union labor while nice, seems far from necessary and I’d prefer a bill with less provisions about what is necessary to end the moratorium.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I’m confident that &lt;a href=&quot;https://ifanyonebuildsit.com&quot;&gt;If Anyone Builds It, Everyone Dies&lt;/a&gt;. Will we be able to stop, or are the rewards from training better and better AI models too tempting? How long would it take us to stop even if policy makers unanimously agreed that we should?&lt;/p&gt;

&lt;p&gt;Perhaps we should slow down as much as we can now.&lt;/p&gt;
</description>
      <pubDate>Wed, 29 Apr 2026 06:51:00 +0000</pubDate>
      <link>https://unformeddelta.wiki/LOtEGaimIxO2/for-even-a-bad-pause</link>
      <guid isPermaLink="true">https://unformeddelta.wiki/LOtEGaimIxO2/for-even-a-bad-pause</guid>
      
      <category>inkhaven</category>
      
      <category>recommended</category>
      
      <category>ai</category>
      
      <category>ai-safety</category>
      
      <category>pause</category>
      
    </item>
    
    <item>
      <title>First impressions of Lean</title>
      <description>&lt;p&gt;Since reading &lt;a href=&quot;https://alok.github.io/lean-pages/perfectable-lean/&quot;&gt;a perfectable programming language&lt;/a&gt; I started getting the itch to try actual dependently typed programming languages again.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/GEbCU1EGqkQU/an-expressive-programming-language&quot;&gt;Haskell is my favorite programming language&lt;/a&gt; because it provides one of the strongest type system but my most common frustrations in Haskell are from not having access to stronger types. &lt;a href=&quot;https://ghc.serokell.io/dh&quot;&gt;Dependent types in Haskell&lt;/a&gt; are an active research project, but still far away. So when I’ve wanted more power I’ve had to make do with Coq (now Roqc) plus a little bit of dabbling in Idris and Agda.&lt;/p&gt;

&lt;p&gt;In my usual fashion, I dove right in without reading the tutorial, hoping my experience with similar languages would take me far enough.&lt;/p&gt;

&lt;h2 id=&quot;first-steps&quot;&gt;First steps&lt;/h2&gt;
&lt;p&gt;I started out by just typing out some definitions.&lt;/p&gt;
&lt;div class=&quot;language-lean highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;Int&lt;/span&gt; := &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; : &lt;span class=&quot;kt&quot;&gt;Type&lt;/span&gt; := &lt;span class=&quot;n&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; := &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I was surprised that the last example failed to compile:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;▼ 2:14-2:15: error:
failed to synthesize instance of type class
  OfNat x 1
numerals are polymorphic in Lean, but the numeral &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; cannot be used in a context where the expected type is
  x
due to the absence of the instance above&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This was fixable by using:&lt;/p&gt;
&lt;div class=&quot;language-lean highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; := (&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;Int&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I had a bit of trouble figuring out that Eq.refl needed an argument, but nicely &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_&lt;/code&gt; allows inferring the type:&lt;/p&gt;
&lt;div class=&quot;language-lean highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; : &lt;span class=&quot;kt&quot;&gt;Type&lt;/span&gt; := &lt;span class=&quot;n&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;Int&lt;/span&gt; := &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Int&lt;/span&gt; := &lt;span class=&quot;n&quot;&gt;Eq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;refl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Of course, I later discovered that there’s a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rfl&lt;/code&gt; tactic that allows avoiding this boilerplate.&lt;/p&gt;

&lt;p&gt;I also ran into some other surprising sharp edges:&lt;/p&gt;
&lt;div class=&quot;language-lean highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decrement&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;Nat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Nat&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Doesn’t compile but this does:&lt;/p&gt;
&lt;div class=&quot;language-lean highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decrement&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;Nat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Nat&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s cool that it’s possible to pattern match on syntax like this, but it’s annoying that it’s a bit inconsistent.&lt;/p&gt;

&lt;h2 id=&quot;lambda-calculus-confluence&quot;&gt;Lambda Calculus Confluence&lt;/h2&gt;
&lt;p&gt;Basic syntax out of the way, I started implanting the simply typed lambda calculus.&lt;/p&gt;

&lt;p&gt;Debrujin indexes:&lt;/p&gt;
&lt;div class=&quot;language-lean highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;inductive&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Term&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;where&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;var&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;Nat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Term&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lam&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;Term&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Term&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;Term&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Term&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Term&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Of course, I can’t implement a full interpreter because I can’t solve the halting problem, so I implement single step semantics:&lt;/p&gt;
&lt;div class=&quot;language-lean highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;step_cbn&lt;/span&gt; (&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;Term&lt;/span&gt;) : &lt;span class=&quot;n&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Term&lt;/span&gt; :=
  &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lam&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Maybe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nothing&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Maybe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nothing&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; (&lt;span class=&quot;n&quot;&gt;Term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lam&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;) &lt;span class=&quot;n&quot;&gt;t2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;Maybe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;just&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shift_down&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; (&lt;span class=&quot;n&quot;&gt;subst&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; (&lt;span class=&quot;n&quot;&gt;shift&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t2&lt;/span&gt;) &lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;)
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;step_cbn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Maybe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;just&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t1&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Maybe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;just&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t1&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t2&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Maybe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nothing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;step_cbn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Maybe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nothing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Maybe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nothing&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Maybe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;just&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t2&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Maybe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;just&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t2&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There’s several different evaluation orders for the simply typed lambda calculus. I recall that Church-Rosser theorem proves that when a term converges, it always converges to the same term regardless of evaluation order.&lt;/p&gt;

&lt;div class=&quot;language-lean highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;inductive&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConvergesCBN&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;Term&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Term&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;where&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;step_cbn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Maybe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nothing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConvergesCBN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;step&lt;/span&gt;  : &lt;span class=&quot;n&quot;&gt;step_cbn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Maybe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;just&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConvergesCBN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConvergesCBN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;inductive&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConvergesCBV&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;Term&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Term&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;where&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;step_cbv&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Maybe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nothing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConvergesCBV&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;step&lt;/span&gt; : &lt;span class=&quot;n&quot;&gt;step_cbv&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Maybe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;just&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConvergesCBV&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConvergesCBV&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;noncomputable&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cbv_implies_cbn_convergence&lt;/span&gt; :
  &lt;span class=&quot;n&quot;&gt;ConvergesCBV&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConvergesCBN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; := &lt;span class=&quot;n&quot;&gt;sorry&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I didn’t end up making that much progress. I also tried big step semantics, but that ended up not being much easier, and after Codex and Claude found several holes in my definitions, that made the theorem unprovable as stated, I gave up.&lt;/p&gt;

&lt;h2 id=&quot;ecosystem&quot;&gt;Ecosystem&lt;/h2&gt;
&lt;p&gt;Lean’s ecosystem still feels fairly immature.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;parser libraries: I use megaparsec/attoparsec in Haskell
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/fgdorais/lean4-parser&quot;&gt;fgdorais/lean4-parser&lt;/a&gt;: this provides decent parser combinators, but none of the fancier recovery or error handling offered by megaparsec.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;C bindings are possible, but you’ll likely need to implement them yourself&lt;/li&gt;
  &lt;li&gt;effects: monad transformers are the default way of representing effects; usable, but a far cry from Haskell’s wide variety&lt;/li&gt;
  &lt;li&gt;tooling quite good, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lean --server&lt;/code&gt; provides top good tooling even in Neovim. I appreciated this compared with using&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;a-meetup&quot;&gt;A meetup&lt;/h2&gt;
&lt;p&gt;People writing Lean seem to be very dedicated to verifying things for verifications sake. I love that. I think this is the standard for what should be demanded of our libraries and tools.&lt;/p&gt;

&lt;p&gt;I’m curious to try diving into metaprogramming, which I hear is pretty good, but that’ll have to wait for another day.&lt;/p&gt;
</description>
      <pubDate>Tue, 28 Apr 2026 06:49:00 +0000</pubDate>
      <link>https://unformeddelta.wiki/Ayg9N1mAL7dd/first-impressions-of-lean</link>
      <guid isPermaLink="true">https://unformeddelta.wiki/Ayg9N1mAL7dd/first-impressions-of-lean</guid>
      
      <category>inkhaven</category>
      
      <category>lean</category>
      
      <category>programming-languages</category>
      
    </item>
    
    <item>
      <title>7 Haskell effect systems</title>
      <description>&lt;p&gt;An overview of Haskell’s effect systems that I’ve used.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This was written pretty hastily for Inkhaven. I hope to return to this and add more details later.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;io&quot;&gt;IO&lt;/h2&gt;
&lt;p&gt;The simplest “effect system” in Haskell that has been around since the beginning. As an effect system, this just divides functions into pure and impure.&lt;/p&gt;

&lt;p&gt;This has a little bit of a special status because Haskell’s main function is declared &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main :: IO ()&lt;/code&gt;, meaning that all other effect systems must eventually delegate to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IO&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;mtl&quot;&gt;mtl&lt;/h2&gt;
&lt;p&gt;Monad transformers allow extending a monad with extra capabilities. This allows creating large stacks of monad transformers with a bunch of different effects, e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StateT AppState (ExceptT AppError (ReaderT Configuration IO a))&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This quickly gets unwieldy because effects from lower layers need to be lifted through the upper layers.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mtl&lt;/code&gt; adds type classes for common kinds of effects, e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MonadState&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MonadError&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MonadReader&lt;/code&gt; which can be implemented generically to avoid needing to lift through monad transformers.&lt;/p&gt;

&lt;p&gt;As an added benefit this also makes it easier to test functions. A function requiring only &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MonadState&lt;/code&gt; can just as easily be implemented using a pure function.&lt;/p&gt;

&lt;p&gt;The worst part about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mtl&lt;/code&gt; is that declaring new effects requires implementing every relevant type class when declaring a new effect. Conversely, implementing a new type class requires adding an implementation for every relevant monad transformer.&lt;/p&gt;

&lt;p&gt;This is called the \(n^2\) instances problem. It’s possible to work around this for the most part with &lt;a href=&quot;/byPuFMGvYUE0/haskell-the-overlappable-monadtrans-instance-pattern&quot;&gt;Haskell: the OVERLAPPABLE MonadTrans instance pattern&lt;/a&gt;, but it still requires more boilerplate than other effect systems we will see.&lt;/p&gt;

&lt;h2 id=&quot;readert-io--unliftio&quot;&gt;ReaderT IO / unliftio&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReaderT IO&lt;/code&gt; makes the observation that most custom effects can easily be represented by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IO&lt;/code&gt; anyways.&lt;/p&gt;

&lt;p&gt;Instead of implementing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MonadState&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StateT&lt;/code&gt; it can just as easily be implemented by manipulating an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IORef&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IO&lt;/code&gt;. Why use separate exceptions from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExceptT&lt;/code&gt; when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IO&lt;/code&gt; exceptions can achieve the same purpose?&lt;/p&gt;

&lt;p&gt;Because extra parameters are still annoying to pass around, it’s common to still use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReaderT&lt;/code&gt; type to remove boilerplate associated with passing them.&lt;/p&gt;

&lt;p&gt;Finally, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unliftio&lt;/code&gt; makes it easier to express higher order operations like bracket. Because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReaderT&lt;/code&gt; isn’t stateful it’s possible to “unlift” it, which makes it possible to represent more generic error handling operations.&lt;/p&gt;

&lt;p&gt;It remains a little bit hard to define custom effects and reinterpret them flexibly with this approach. To implement a pure version of an effect, you still often end up stuck with the complexity of monad transformer stacks and the \(n^2\) instances problem.&lt;/p&gt;

&lt;h2 id=&quot;polysemy&quot;&gt;polysemy&lt;/h2&gt;
&lt;p&gt;Algebraic effect systems attempt to get rid of the boilerplate involved in defining custom type classes for effects once and for all. They also try to implement fancier algebraic effect patterns.&lt;/p&gt;

&lt;p&gt;Based on the weaving pattern introduced by &lt;a href=&quot;https://www.cs.ox.ac.uk/people/nicolas.wu/papers/Scope.pdf&quot;&gt;Effect Handler’s in Scope&lt;/a&gt;, this library is based on free monads, keeping track of an open union of capabilities.&lt;/p&gt;

&lt;h2 id=&quot;fused-effects&quot;&gt;fused-effects&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fused-effects&lt;/code&gt; is pretty much like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;polysemy&lt;/code&gt; but uses type classes instead of an open union. This provides a bit more efficiency at runtime trading off for greater boilerplate.&lt;/p&gt;

&lt;h2 id=&quot;in-other-words&quot;&gt;in-other-words&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;in-other-words&lt;/code&gt; is the most creative effect system I’ve seen so far. It provides a really ergonomic interface by providing granular primitive effects that encapsulate higher order effect patterns. User defined effects can be translated into these effects, which makes gets rid of some of the complexity imposed by polysemy and fused-effect’s weaving pattern.&lt;/p&gt;

&lt;p&gt;In practice its biggest flaw is its lack of documentation, and the raw complexity of the effects it offers. Some of its effects are extremely general, and reasoning through how they can be instantiated into something useful is really hard.&lt;/p&gt;

&lt;h2 id=&quot;effectful&quot;&gt;effectful&lt;/h2&gt;
&lt;p&gt;Effectful is the application of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReaderT IO&lt;/code&gt; / unliftio’s lessons to algebraic effect systems. It implements everything in terms of IO, but wraps it up in a neat interface that makes it easier to work with.&lt;/p&gt;

&lt;p&gt;It’s also able to provide a reasonably safe pure interface.&lt;/p&gt;

&lt;p&gt;This is currently my favorite effect system for new projects.&lt;/p&gt;
</description>
      <pubDate>Mon, 27 Apr 2026 06:40:00 +0000</pubDate>
      <link>https://unformeddelta.wiki/7FzDAf8VJ7Fo/7-haskell-effect-systems</link>
      <guid isPermaLink="true">https://unformeddelta.wiki/7FzDAf8VJ7Fo/7-haskell-effect-systems</guid>
      
      <category>haskell</category>
      
      <category>inkhaven</category>
      
    </item>
    
    <item>
      <title>500mg Niacin</title>
      <description>&lt;p&gt;&lt;img src=&quot;/images/zNOgDl79cBzf-IMG_5704.jpeg&quot; alt=&quot;Niacin bottle label. Description in quote below.&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Experience: Temp full body sunburn&lt;/p&gt;

  &lt;p&gt;“flushing”&lt;/p&gt;

  &lt;p&gt;Niacin is a B-vitamin. Sunburn effects lasts 30-60 mins.&lt;/p&gt;

  &lt;p&gt;You will feel: warm, cozy, itchy.&lt;/p&gt;

  &lt;p&gt;you’re not having an allergic reaction
it’s supposed to be like that&lt;/p&gt;

  &lt;p&gt;-Handwritten on 500mg Niacin bottle at Lighthaven&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I recommend it.&lt;/p&gt;

&lt;p&gt;It didn’t feel like a sunburn to me. You know the feeling of a limb falling asleep? It was like that but only 20% as strong, and a full body experience.&lt;/p&gt;

&lt;p&gt;Taking it was &lt;a href=&quot;/shWm4speAqvp/5-unexpectedly-mindful-activities&quot;&gt;unexpectedly mindful&lt;/a&gt;. I was afraid it would be unpleasant enough to incapacitate me, but to the contrary, it connected me to my bodily sensations.&lt;/p&gt;

&lt;p&gt;As I edit this post, I just took another.&lt;/p&gt;

&lt;p&gt;One tip: no matter how itchy you get, resist itching.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: This is not medical advice. Read the label and exercise appropriate caution.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;experience-log&quot;&gt;Experience Log&lt;/h2&gt;
&lt;p&gt;19:04 took 500mg capsule of Niacin&lt;/p&gt;

&lt;p&gt;19:09 maybe barely starting to feel sore&lt;/p&gt;

&lt;p&gt;19:12 feeling a mild warmth in my stomach, right where the esophagus connects, soreness is definitely a symptom and starting to intensify&lt;/p&gt;

&lt;p&gt;19:16 a bruise on my shoulder from a few weeks ago is throbbing, very similar sensation to getting a shot&lt;/p&gt;

&lt;p&gt;19:18 I’m noticing pain in my lower back that I wasn’t noticing earlier, I’m starting to feel more alert&lt;/p&gt;

&lt;p&gt;19:19 I’m going to drink some Rooibos tea&lt;/p&gt;

&lt;p&gt;19:20 the pain in my stomach has become a bit sharper, it reminds me a little bit of the feeling of a whole Cheez-It going down my esophagus, but in my whole stomach&lt;/p&gt;

&lt;p&gt;19:20 I’m starting to be aware of pain in my upper thigh, just a little bit of tingling&lt;/p&gt;

&lt;p&gt;19:21 I’m noticing that my hands are a bit sore while I’m typing&lt;/p&gt;

&lt;p&gt;19:21 I’m feeling a tingly itchy sensation first on the back of my neck, and now on the front of my chest&lt;/p&gt;

&lt;p&gt;19:22 I also am starting to feel the itchy sensation on the top of my hands&lt;/p&gt;

&lt;p&gt;19:22 my foot is throbbing a little bit, kind of like I pulled a muscle&lt;/p&gt;

&lt;p&gt;19:22 I’m noticing that my eye muscle is just a bit sandy, and starting to be a bit itchy&lt;/p&gt;

&lt;p&gt;19:23 Soreness has extended into my fingertips&lt;/p&gt;

&lt;p&gt;19:25 my hands are definitely a bit sore, as though I typed for a long time already&lt;/p&gt;

&lt;p&gt;19:26 Rooibos tea again. Drinking doesn’t really feel any different&lt;/p&gt;

&lt;p&gt;19:29 I’m feeling quite itchy all over my face, even inside of my nostrils&lt;/p&gt;

&lt;p&gt;19:32 I’m starting to notice that my body kind of feels a bit like after constricting blood flow (“fell asleep”), particularly noticing this sensation in my upper left thigh and around my elbows&lt;/p&gt;

&lt;p&gt;19:33 Swallowing is starting to be a little bit more noticeable, my throat feeling a bit more bloated&lt;/p&gt;

&lt;p&gt;19:33 My left foot is continuing to throb a little bit more&lt;/p&gt;

&lt;p&gt;19:34 I’m noticing my tailbone a bit more&lt;/p&gt;

&lt;p&gt;19:34 I feel a little bit lighter, and picking up my mug feels a little bit more ethereal&lt;/p&gt;

&lt;p&gt;19:35 I’m just starting to notice itchiness on my collarbone, itchiness on my hands feels more intense&lt;/p&gt;

&lt;p&gt;19:36 Noticing itchiness inside of my ear for the first time&lt;/p&gt;

&lt;p&gt;19:36 My right index finger is pretty itchy&lt;/p&gt;

&lt;p&gt;19:37 I finished my Rooibos tea&lt;/p&gt;

&lt;p&gt;19:38 My ears tearing up a bit&lt;/p&gt;

&lt;p&gt;19:38 I’m pretty itchy under my right arm pit&lt;/p&gt;

&lt;p&gt;19:38 My left eye that was previously feeling sandy is now particularly itchy, and starting to water&lt;/p&gt;

&lt;p&gt;19:39 My right eye is also watering, it feels like I’ve been using it for a long time&lt;/p&gt;

&lt;p&gt;19:39 Inside my left elbow is now particularly itchy&lt;/p&gt;

&lt;p&gt;19:40 My muscles are starting to feel a bit sore all over the place&lt;/p&gt;

&lt;p&gt;19:41 My right cheek is also feeling pretty tingly now&lt;/p&gt;

&lt;p&gt;19:41 I’m noticing tingling around the crown of my head&lt;/p&gt;

&lt;p&gt;19:41 My heartbeat is more noticeable&lt;/p&gt;

&lt;p&gt;19:42 The top of my head is now on fire with tingling, my hands are feeling very similar&lt;/p&gt;

&lt;p&gt;19:42 I can feel my neck muscles when I move them, my neck is starting to tingle quite strongly&lt;/p&gt;

&lt;p&gt;19:42 My heartbeat in my neck has fairly high intensity, and the tingling now feels more like fire&lt;/p&gt;

&lt;p&gt;19:43 I’m starting to get quite warm, especially on the back of my hands, my ears, and the back of my neck for now&lt;/p&gt;

&lt;p&gt;19:46 I feel like my body is humming&lt;/p&gt;

&lt;p&gt;19:47 My upper arms are also starting to feel quite warm&lt;/p&gt;

&lt;p&gt;19:47 All over itchiness has given way to buzzing/tingling/burning&lt;/p&gt;

&lt;p&gt;19:47 My hands are noticeably redder&lt;/p&gt;

&lt;p&gt;19:47 I’m feeling some pressure inside of my ear canal like changing altitude&lt;/p&gt;

&lt;p&gt;19:48 My calves feel cooler than usual, but it’s possible that it is just because the rest of my body is flushed&lt;/p&gt;

&lt;p&gt;19:53 I got up and walked around a bit while trying to convince people to take Niacin, when sitting down I noticed tingles in my upper thigh&lt;/p&gt;

&lt;p&gt;19:53 My body is pretty much completely warm now, in a ring around my lungs&lt;/p&gt;

&lt;p&gt;19:54 Redness still hasn’t spread too far past my wrists&lt;/p&gt;

&lt;p&gt;19:57 I now feel like I need to move around to feel the Niacin&lt;/p&gt;

&lt;p&gt;19:57 My eyelids feel a little bit sandy, closing my eyes feels little bit like it does when I have red-eye or my eyes are particularly dry after watching TV for a long time&lt;/p&gt;

&lt;p&gt;19:58 Tingling now only really happens when I move around, just a little bit of tingles wherever I move something&lt;/p&gt;

&lt;p&gt;19:59 The Niacin is now feeling very normal, maybe just a bit of tingling&lt;/p&gt;

&lt;p&gt;20:02 I feel warmth in my stomach in particular again&lt;/p&gt;

&lt;p&gt;20:02 Noticing pressure in my ears&lt;/p&gt;

&lt;p&gt;20:16 I’m starting to get a bit of chills because my body is changing in temperature&lt;/p&gt;

&lt;p&gt;20:19 My skin feels slightly flaky or something when I touch it, I can imagine how itching could quickly intensify the experience and make it much more unpleasant&lt;/p&gt;

&lt;p&gt;20:20 My stomach is starting to feel a bit sore, my eyes are watering again&lt;/p&gt;

&lt;p&gt;20:22 My eyelids definitely still a bit heavy&lt;/p&gt;

&lt;p&gt;20:27 Starting to feel chills all over as the Niacin wears out&lt;/p&gt;

&lt;p&gt;20:28 Noticing the tiniest bit of a headache in my right temple&lt;/p&gt;

&lt;p&gt;20:32 I still get a little bit light headed and tingly, and a bit stomach achy, starting to feel fairly cool, some amount of cold chills are happening all over my body&lt;/p&gt;

&lt;p&gt;20:34 I feel like the symptoms are pretty much all over, just some chills, and a tiny amount of tingles in my belly and tops of my feet + when I move around vigorously&lt;/p&gt;

&lt;p&gt;20:44 Symptoms are almost completely gone by now, only a little bit of warmth in my stomach left&lt;/p&gt;

&lt;p&gt;20:55 I still feel a little bit light headed as an aftereffect&lt;/p&gt;

&lt;p&gt;21:31 My only noticeable symptom at this point is a little bit of a stomach warmth and a little bit of soreness&lt;/p&gt;

&lt;p&gt;21:40 I still feel a little light headed especially when I walk around&lt;/p&gt;
</description>
      <pubDate>Sun, 26 Apr 2026 03:38:00 +0000</pubDate>
      <link>https://unformeddelta.wiki/zNOgDl79cBzf/500mg-niacin</link>
      <guid isPermaLink="true">https://unformeddelta.wiki/zNOgDl79cBzf/500mg-niacin</guid>
      
      <category>inkhaven</category>
      
    </item>
    
    <item>
      <title>I don&apos;t want your skills</title>
      <description>&lt;p&gt;I often notice people advertising their custom skills as a solution to your agentic programming problems. They’ll provide you some genuinely useful advice, then cap it off by offering you skills that operationalizes their advice.&lt;/p&gt;

&lt;p&gt;I found the failure modes and tips identified in &lt;a href=&quot;https://www.youtube.com/watch?v=v4F1gFy-hqg&quot;&gt;Software Fundamentals Matter More Than Ever&lt;/a&gt; insightful. I never thought about having a glossary of shared vocabulary to make communication with AI agents more effective. AI agents outrunning their headlights by doing way too much autonomously provides metaphor for my common experience of having AI agents do underspecified work. Focusing on building deeper modules with a lot of functionality hiding behind a small interface, is a pattern I’ve been thinking around, but haven’t yet been able to put words to.&lt;/p&gt;

&lt;p&gt;But following the insight with skills that will “solve” the problem for you, is the equivalent to giving a tutorial on how to implement &lt;a href=&quot;https://github.com/karpathy/nanogpt&quot;&gt;nanoGPT&lt;/a&gt; and then capping it off by saying: but you can just use &lt;a href=&quot;https://chatgpt.com&quot;&gt;https://chatgpt.com&lt;/a&gt;&lt;sup id=&quot;fnref:disclaimer&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:disclaimer&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Yes, it does seem helpful to have my AI agent &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/grill-me&lt;/code&gt; — asking detailed questions instead of providing corrections to plans reflecting a fundamental misunderstanding of the problem over and over again. Of course, I’d love to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/improve-codebase-architecture&lt;/code&gt;  modularizing my codebase. But running a skill won’t help you understand how it works.&lt;/p&gt;

&lt;p&gt;These skills probably work in simpler codebases. But simpler codebases are also the best environment to understand the principles behind the skills and learn how to build them yourself. And without understanding the principles, you won’t necessarily understand that or how the skill failed in a more complex codebase.&lt;/p&gt;

&lt;p&gt;I’ve noticed this pattern before in discussions with other engineers. I explained to another engineer: just giving Claude Sonnet 4.5 our feature flag documentation plus a list of files that needed to modify was enough for it to make the changes fully autonomously. They responded by asking if I could package that up into an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/add-feature-flag&lt;/code&gt; skill.&lt;/p&gt;

&lt;p&gt;I didn’t see the point. The skill would just be 1-2 sentences of text and a list of files that needed to be modified in order to make changes to the feature flags. The skill would encapsulate nothing but the fact that this task was now easy to automate.&lt;/p&gt;

&lt;p&gt;My recommendation is to engage with content that offers you skills, but try to learn the principles behind the skills instead of using the skills themselves. Try to prompt your AI agent to solve the problem yourself.&lt;/p&gt;

&lt;p&gt;Doing this, I’ve found that after a while, I want to abstract my prompt into my own skill.&lt;/p&gt;

&lt;p&gt;I remember reading an article about adding comments to plan documents inline, instead addressing them one by one in Claude Code’s prompt. I liked this technique and after trying it, ended up building produced &lt;a href=&quot;https://github.com/lehmacdj/.dotfiles/blob/main/llm/address-comments.symskill/SKILL.md&quot;&gt;this skill&lt;/a&gt;. Though I’ve provided a link, I recommend not clicking it.&lt;/p&gt;

&lt;p&gt;Downloading skills won’t make you a good AI engineer. Understanding why they work and operationalizing the principles behind them will.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:disclaimer&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Andrey Karpathy does not do this. &lt;a href=&quot;#fnref:disclaimer&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
      <pubDate>Sat, 25 Apr 2026 04:03:00 +0000</pubDate>
      <link>https://unformeddelta.wiki/aFKl86BhaWNX/i-dont-want-your-skills</link>
      <guid isPermaLink="true">https://unformeddelta.wiki/aFKl86BhaWNX/i-dont-want-your-skills</guid>
      
      <category>recommended</category>
      
      <category>agentic-programming</category>
      
      <category>inkhaven</category>
      
    </item>
    
    <item>
      <title>programming language features (and optimizations)</title>
      <description>&lt;p&gt;My dream programming language would be able to express the syntax and semantics of every other programming language idiomatically. In this framing a good programming language would have few builtins&lt;sup id=&quot;fnref:builtins&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:builtins&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; but would still be able to manifest many more specific features as library definitions.&lt;/p&gt;

&lt;p&gt;I take a very general view of features. Optimizations are included in this list because in order practically exploit the fact that one programming can express the semantics of another, it must be able to match its performance&lt;sup id=&quot;fnref:why-match-performance&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:why-match-performance&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. Thus optimizations are more or less “features” for a programming language; they help determine what the programming language can practically be used for.&lt;/p&gt;

&lt;p&gt;Maximizing which features are expressible as part of the standard library, maximizes what users are able to rewrite. If users don’t like the features the language provides in its standard library they can write their own. Such a language is maximally flexible for users.&lt;/p&gt;

&lt;p&gt;Of course, actually using custom built features comes at the expense of interoperability with the broader ecosystem. But I think it is better to give users the choice of what they need to interoperate with, rather than artificially restricting it to guarantee good interoperability&lt;sup id=&quot;fnref:go-lang&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:go-lang&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;With a sufficient floor of metaprogramming capabilities, any feature could be implemented as a builtin or as part of the standard library. I collect this list so that I can sort/consider which features are more primitive and which are the most useful to be able to reprogram. Each programming language features thus becomes both a test and an axiom for programming language expressivity.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Meta note: I went through and made a bunch of these notes public. There’s still a lot of links that aren’t public. A lot of the pages themselves are stubs and have highly varying levels of research/detail/revision put into them.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;meta-programming&quot;&gt;&lt;a href=&quot;/ncxpONlAUxwN/meta-programming&quot;&gt;meta programming&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Features enabling and enabled by metaprogramming. In some sense these are the most important because they’re what enables implementing features in terms of each other. I’m also interested in evaluating which of these features are the most irreducible.&lt;/p&gt;

&lt;p&gt;Features providing metaprogramming ability:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/NBcoqhpqPI7Q/homoiconicity&quot;&gt;homoiconicity&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/QKeZY0XKOiI6/get-runtime-string-of-compile-time-identifier&quot;&gt;get runtime string of compile-time identifier&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/xWpiR33ashZN/storing-morphological-data-with-identifiers&quot;&gt;storing morphological data with identifiers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/8BHXL4aXonrC/compile-time-execution-of-code-assertion-baking-code&quot;&gt;compile time execution of code assertion / baking code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Features implementable by metaprogramming:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;embedded query languages, e.g. &lt;a href=&quot;/JJkIIMTFCOS2/linq&quot;&gt;LINQ&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;EDSLs in general get better as metaprogramming is better supported by a programming language&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Features kind of like metaprogramming in terms of the expressiveness they provide:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/Z1PKno9u7n88/overloadable-literals&quot;&gt;overloadable literals&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/xHw0NhTYpNsv/first-class-patterns&quot;&gt;first class patterns&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/iJCO4lkr7tNY/first-class-constructor-names&quot;&gt;first class constructor names&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/zgEZe8EylXt3/first-class-modules&quot;&gt;first class modules&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/6lzBYvOGzs77/self-types&quot;&gt;self types&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2glFqLPSCCmX/lambda-with-receiver&quot;&gt;Lambda with receiver&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/gSlE0WOhgelG/contextual-keywords&quot;&gt;contextual keywords&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/CPg3TGdClzgM/raw-identifiers&quot;&gt;raw identifiers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/6lFX3b2wE4N9/functional-tactics-languages-for-proof-assistants&quot;&gt;functional tactics languages for proof assistants&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;working-with-generally-monadic-effects&quot;&gt;working with (generally monadic) effects&lt;/h2&gt;
&lt;p&gt;This category encapsulates language features that make working with effects easier:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;do notation&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/AfQULF8hGowN/monad-extraction&quot;&gt;monad extraction&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/aZQHyB6nrpSg/idiom-brackets&quot;&gt;idiom brackets&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;lifted versions of boolean operators&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/vwO1Erpqe9jg/dedicated-syntax-for-specific-effects&quot;&gt;dedicated syntax for specific effects&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/9prPQE3hGLjS/pattern-match-failures-are-an-effect-parsers-via-pattern-matching&quot;&gt;pattern match failures are an effect / parsers via pattern matching&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/NqZArcVKG3dy/the-runtime-system-should-be-deeply-tied-to-effect-system&quot;&gt;the runtime system should be deeply tied to effect system&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/kX1jiVaBymWv/implicit-conversions-between-effects&quot;&gt;Implicit Conversions Between Effects&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;See also: &lt;a href=&quot;/t1WnMS8gb0uo/effects&quot;&gt;Effects&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;working-with-coeffects&quot;&gt;working with coeffects&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/zOnT5C3LH1V2/method-with-notation&quot;&gt;method (/with) notation&lt;/a&gt;: relatively undeveloped, but interesting&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/0yMXYaW73qbq/coeffects-can-act-as-interpreters-for-effects&quot;&gt;coeffects can act as interpreters for effects&lt;/a&gt;: vague but interesting, method notation has some extra ideas for this&lt;/li&gt;
  &lt;li&gt;See also: &lt;a href=&quot;/mxPjuprza4i8/coeffects-consumer-effects&quot;&gt;coeffects / consumer effects&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;concurrency--distributed-programming&quot;&gt;concurrency / distributed programming&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/Nxtt5aJb3FnJ/structured-concurrency-nurseries&quot;&gt;structured concurrency / nurseries&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/lNKqn420Niw4/async-await&quot;&gt;async/await&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/yKIqGyLcKXQc/controlling-placement-of-logic-onto-specific-machines&quot;&gt;controlling placement of logic onto specific machines&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/dgmN2nnuWwRr/surfacing-semantic-information-about-distributed-behavior&quot;&gt;surfacing semantic information about distributed behavior&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/65rqGUe3XiKm/decomposing-transactional-systems&quot;&gt;decomposing transactional systems&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;working-with-data&quot;&gt;Working with data&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;/GQrJD6Vydss6/pattern-matching&quot;&gt;pattern matching&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/xHw0NhTYpNsv/first-class-patterns&quot;&gt;first class patterns&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/uDadVZnfjFD5/easily-checking-which-sum-case-is-used&quot;&gt;easily checking which sum case is used&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/iJCO4lkr7tNY/first-class-constructor-names&quot;&gt;first class constructor names&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Higher Kinded Data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Accessors / key paths / lenses:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;generic/uniform syntax for arbitrary n-functors/lenses&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;optimizations&quot;&gt;optimizations&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.ashermancinelli.com/csblog/2025-7-20-Ideal-Array-Language.html#why-does-this-matter&quot;&gt;someone’s ideal array programming language: ideas about non-uniform compute + SIMD + etc.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/5JBEx6WCIHoE/stream-fusion&quot;&gt;stream fusion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/mUFaDSi2Kni8/super-compilation&quot;&gt;super compilation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/zncYgtgbNa9x/equality-saturation-e-graphs&quot;&gt;equality saturation (e-graphs)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;evaluation-order&quot;&gt;evaluation order&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/2B407TlcHBup/lazy-evaluation-order-call-by-name&quot;&gt;lazy evaluation order / call by name&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/svrWWFkcUvTd/call-by-push-value&quot;&gt;call by push value&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;types&quot;&gt;types&lt;/h2&gt;
&lt;p&gt;Primitive types:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;basic types: &lt;a href=&quot;/48FOjJ7COOaX/closed-vs-open-types&quot;&gt;closed vs open types&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;/3dDEa8tnSN83/structs-record-types&quot;&gt;structs/record types&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;row types (i.e. extensible records)&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/EdP0HQuZhLDD/coproducts-variants-enums&quot;&gt;coproducts / variants / enums&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/XuvkOLlAiCEm/polymorphic-variants&quot;&gt;polymorphic variants&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/EJjBX51KQ1Yy/recursive-µ-types&quot;&gt;recursive (µ) types&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/qQ783yMXPPbQ/nominative-ν-types&quot;&gt;nominative (ν) types&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/UeA8tt6iF5bq/algebraic-data-types&quot;&gt;algebraic data types&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;dependent types:
    &lt;ul&gt;
      &lt;li&gt;dependent product&lt;/li&gt;
      &lt;li&gt;dependent sum&lt;/li&gt;
      &lt;li&gt;interval / cubic type theory / univalence&lt;/li&gt;
      &lt;li&gt;cumulative universes&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;linear types&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Broader concepts:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/ZS3QCNHImVwZ/type-inference-list-of-methods-elaboration&quot;&gt;type inference (+ list of methods) / elaboration&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/6QbUR4dyX9Wd/completeness-checking&quot;&gt;completeness checking&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/E6doTkK2Znp0/subtypes-subtyping&quot;&gt;subtypes / subtyping&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/o8Dyaxi0ZKPK/structural-types&quot;&gt;structural types&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;gradual typing / migratory typing&lt;/li&gt;
  &lt;li&gt;pure functions, mutability
    &lt;ul&gt;
      &lt;li&gt;ST monad&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Weird/highly non-standard stuff:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/nrO5W22ORJzs/dual-type-operator&quot;&gt;dual type operator&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/6gtykpBojvhd/co-completeness-checking&quot;&gt;co-completeness checking&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/6lzBYvOGzs77/self-types&quot;&gt;self types&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2glFqLPSCCmX/lambda-with-receiver&quot;&gt;Lambda with receiver&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;probably not practical or interesting: &lt;a href=&quot;/Crx6jhw9TK7r/representing-types-as-just-namespaces&quot;&gt;representing types as just namespaces&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;typeclasses--traits&quot;&gt;&lt;a href=&quot;/iKz45KVyICwj/typeclasses-traits&quot;&gt;typeclasses / traits&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Typeclass features:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/MO8UYVyYLUgb/inserting-new-typeclasses-in-between-existing-ones&quot;&gt;inserting new typeclasses in-between existing ones&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/9cmxkzhW9IDE/override-typeclasses-or-implicits&quot;&gt;override typeclasses or implicits&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/3nJYq6q6JOEA/confluent-instance-resolution&quot;&gt;confluent instance resolution&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/TChq81fMCv9p/scoped-typeclasses-or-implicits&quot;&gt;scoped typeclasses or implicits&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/UnwAZzzngQLR/orphan-instances&quot;&gt;orphan instances&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/A2tVR0i9YcsB/givens-scala-3&quot;&gt;givens (Scala 3)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/ddgDTcVHs968/multiparameter-type-classes&quot;&gt;multiparameter type classes&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/I3MsqrihWOL9/auto-derived-type-classes&quot;&gt;auto derived type classes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;standard-library&quot;&gt;standard library&lt;/h2&gt;
&lt;p&gt;The main purpose of a standard library is to define the shared vocabulary that all programs can coordinate around. Because more primitive features are implemented as part of the “standard library”, it places an even larger burden on the design of its standard library.&lt;/p&gt;

&lt;p&gt;Properties the standard library should have:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;layers of primitiveness: that allow giving up progressive amounts of interoperability for the ability to redefine larger parts of the language&lt;/li&gt;
  &lt;li&gt;facilitate migrations between standard library types to make the decision to include/not-include various things as unimpactful as possible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Must haves:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/9q45qzJgPaIz/type-safe-dates-times-durations&quot;&gt;type safe dates/times/durations&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;OSString type&lt;/li&gt;
  &lt;li&gt;theorem proving:
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;/ZMtfpDsFf117/explicitly-unordered-containers&quot;&gt;explicitly unordered containers&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Things to consider adding to a type class hierarchy beyond what Haskell has:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/RoZrSQ0VADCE/partial-equality-ordering&quot;&gt;Partial Equality / Ordering&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/qy3O2KrKgJYU/selective&quot;&gt;Selective&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/nlCzhqXrt5fN/discriminators-contravariant-functor-hierarchy-on-sorting&quot;&gt;Discriminators (contravariant functor hierarchy, O(n) sorting!)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;modules--scoping&quot;&gt;modules / scoping&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/zgEZe8EylXt3/first-class-modules&quot;&gt;first class modules&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/xWpiR33ashZN/storing-morphological-data-with-identifiers&quot;&gt;storing morphological data with identifiers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/x7PUneHXkXAH/flexible-scope-resolution-with-article-like-functions-keywords&quot;&gt;flexible scope resolution with article like functions/keywords&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;limited / more local scopes:
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;/F4TTPLipKTSS/local-type-declarations&quot;&gt;local type declarations&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/TChq81fMCv9p/scoped-typeclasses-or-implicits&quot;&gt;scoped typeclasses or implicits&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/mpYtVwtsssAa/defining-functions-global-variables-over-a-limited-scope&quot;&gt;defining functions/global variables over a limited scope&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;lifetimes--scoping&quot;&gt;lifetimes / scoping&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/dRm9QXhhosuz/raii&quot;&gt;RAII&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/dn7y1F0E7gIR/defer-statement&quot;&gt;defer statement&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/0FSraZkV6OJ7/deconstructors-deinitializers&quot;&gt;deconstructors / deinitializers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;lifetime annotations ala rust&lt;/li&gt;
  &lt;li&gt;borrow checker&lt;/li&gt;
  &lt;li&gt;move semantics (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;consume&lt;/code&gt; in Swift)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;control-flow&quot;&gt;control flow&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/KI7CnXtB4sYS/implementing-control-flow-as-library-functions&quot;&gt;implementing control flow as library functions&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;loops:
    &lt;ul&gt;
      &lt;li&gt;for loops&lt;/li&gt;
      &lt;li&gt;foreach loops&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/sSiTDOesjtyI/while-loop&quot;&gt;while loop&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/n4l4TUphkC42/until-loop&quot;&gt;until loop&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;do while loop&lt;/li&gt;
      &lt;li&gt;unconditional forever loop&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/4hDfrbOYfERt/do-while-with-block-loop&quot;&gt;do while with block loop&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/JwjtjzAsEbm9/if-statements&quot;&gt;if statements&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/Wdj1LjlC97rO/switch-case-analysis-statements&quot;&gt;switch / case analysis statements&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/T2LKKGgNsdGW/allowing-statements-to-be-used-as-expressions&quot;&gt;allowing statements to be used as expressions&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/dn7y1F0E7gIR/defer-statement&quot;&gt;defer statement&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;try { … } catch { … }&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dis-preferred:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/KAvQgJqAafP2/with-using-blocks&quot;&gt;with/using blocks&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/VeqfqfVzppXi/try-finally&quot;&gt;try { … } finally { … }&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;code-location--relocating-code&quot;&gt;code location / relocating code&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;removing indentation from nested code structures&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/DB3xJAOpe0Bf/unit-tests-can-be-co-located-with-code&quot;&gt;unit tests can be co-located with code&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;get calling function location&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/dn7y1F0E7gIR/defer-statement&quot;&gt;defer statement&lt;/a&gt; is useful for putting de-initialization next to initialization logic&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;testing&quot;&gt;testing&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/DB3xJAOpe0Bf/unit-tests-can-be-co-located-with-code&quot;&gt;unit tests can be co-located with code&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;inspection testing&lt;/li&gt;
  &lt;li&gt;unit tests can be discovered at compile time / in the IDE without necessarily running arbitrary code&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;see-also&quot;&gt;See also&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;programming language benchmarks for ways of testing what features are useful for programming tasks&lt;/li&gt;
  &lt;li&gt;my programming language for features that are core enough to warrant consideration as primitives for my programming language design project&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:builtins&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Features implemented with special support in the compiler. Also sometimes called intrinsics (e.g. by the rust compiler) &lt;a href=&quot;#fnref:builtins&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:why-match-performance&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Even though the lambda calculus is Turing complete and can technically implement arbitrary floating point arithmetic, no one is seriously trying to train neural networks using it. &lt;a href=&quot;#fnref:why-match-performance&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:go-lang&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This is my largest problem with the philosophy behind the design of go-lang. While true that a simpler language leads to more uniform programming styles, it also makes it harder to build shared abstractions. &lt;a href=&quot;#fnref:go-lang&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
      <pubDate>Fri, 24 Apr 2026 00:12:00 +0000</pubDate>
      <link>https://unformeddelta.wiki/dCtl1IFIC8VF/programming-language-features-and-optimizations</link>
      <guid isPermaLink="true">https://unformeddelta.wiki/dCtl1IFIC8VF/programming-language-features-and-optimizations</guid>
      
      <category>inkhaven</category>
      
      <category>recommended</category>
      
      <category>programming-languages</category>
      
    </item>
    
    <item>
      <title>My Neovim configuration</title>
      <description>&lt;p&gt;I use Neovim for 95%+ of my writing, both prose and code. I originally picked Vim over Emacs because I liked its modal text editing. Over the following years I’ve honed it to my preferences, building up over ~4000 lines of configuration. I’ve flirted with switching to Emacs with evil-mode for a better plugin ecosystem, but Vim is too deeply engraved in my muscle memory to move away from.&lt;/p&gt;

&lt;h2 id=&quot;lua-vs-vimscript&quot;&gt;Lua vs Vimscript&lt;/h2&gt;
&lt;p&gt;I don’t have a strong preference for Lua/Vimscript. Historically, Vimscript was the only language for configuring Vim&lt;sup id=&quot;fnref:which-are-bad&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:which-are-bad&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; . I generally assume that I will always use Neovim nowadays. Neovim makes Lua a first class language for configuring Vim. In fact, in addition to bridging all of Vim’s APIs to Lua, new APIs (such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.lsp&lt;/code&gt;) are often only offered through Lua.&lt;/p&gt;

&lt;p&gt;Rewriting all of my configuration in Lua just to lose support for Vim completely seems like a waste of time, so I still keep a lot of my configuration in Vimscript. I tend to prefer Vimscript’s syntax for &lt;a href=&quot;https://github.com/lehmacdj/.dotfiles/blob/623ba890da5afff964d72010ab28214edf53e4b7/nvim.symconfig/init.vim#L241-L242&quot;&gt;mappings&lt;/a&gt; and &lt;a href=&quot;https://github.com/lehmacdj/.dotfiles/blob/623ba890da5afff964d72010ab28214edf53e4b7/nvim.symconfig/init.vim#L214-L218&quot;&gt;autocommands&lt;/a&gt; to &lt;a href=&quot;https://github.com/lehmacdj/.dotfiles/blob/af7972a429a12a86649b5671c66a4ecf267b09de/nvim.symconfig/plugin/lsp.lua#L46-L48&quot;&gt;Lua’s&lt;/a&gt; anyways. Lua’s feels a little bit too verbose, and is harder to understand quickly in my opinion.&lt;/p&gt;

&lt;p&gt;Neovim makes it very easy to mix Lua and Vimscript, which makes it possible to maintain interoperability even while maintaining configuration in both.&lt;/p&gt;

&lt;h2 id=&quot;escape-key&quot;&gt;Escape key&lt;/h2&gt;
&lt;p&gt;Because the escape key is far in the top left corner of modern keyboards, mapping &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jj&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jk&lt;/code&gt; to escape in insert mode is fairly common. I used to do this. At some point I learned that Vim and most Vim plugins for other text editors treat &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;C-[&amp;gt;&lt;/code&gt; as escape. Rebinding caps lock to control system wide, made it possible to press &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;C-[&amp;gt;&lt;/code&gt; with my two pinkies simultaneously. An escape key mapping was previously the only configuration I truly couldn’t do without so this has the added benefit of letting me use Vim-mode plugins in other editors (or Vim itself through SSH) well enough without needing to configure them.&lt;/p&gt;

&lt;h2 id=&quot;modularization&quot;&gt;Modularization&lt;/h2&gt;
&lt;p&gt;Because my config has grown quite large, I need to keep it modularized for it to stay maintainable.&lt;/p&gt;

&lt;p&gt;Mostly I rely on the runtime directory structure which allows loading a lot of files flexibly:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init.vim&lt;/code&gt; has logic that needs to run before other configuration, plus a bunch of stuff that I’ve been too lazy to move elsewhere&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plugins.vim&lt;/code&gt; is sourced from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init.vim&lt;/code&gt; and loads plugins. I have this separated out because I use a lot of plugins&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ftsyntax&lt;/code&gt; directories for autocommands improving file type detection, or adding new&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ftplugin/after&lt;/code&gt; directories house language specific configuration to prevent needing to define autocommands for them&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autoload&lt;/code&gt; directories store “library” functions that I use from other pieces of my configuration&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lua/my&lt;/code&gt; modules serve the same purpose, but for Lua code&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plugin&lt;/code&gt; directories for configuration insensitive to loading order&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;plugins&quot;&gt;Plugins&lt;/h2&gt;
&lt;p&gt;I still use vim-plug to manage my plugins because it works well enough, and well written plugins lazy load by design, thus not requiring anything fancier.&lt;/p&gt;

&lt;p&gt;I’m a heavy plugin user so I’ll only go through my favorite plugins. The most notable category is plugins that add generic cross language features to the editor without conflicting with default keybindings:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tpope/vim-repeat&lt;/code&gt; makes it possible to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&lt;/code&gt; with custom actions provided by other plugins. This should really just be a built in Vim feature.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tpope/vim-sleuth&lt;/code&gt; makes indentation behave sanely by default.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tpope/vim-surround&lt;/code&gt; adds a truly essential &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ys&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cs&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ds&lt;/code&gt; text editing verbs for adding/changing/deleting surrounding text&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tommcdo/vim-exchange&lt;/code&gt; provides a very useful &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cx&lt;/code&gt; text editing verb for swapping text&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wellle/targets.vim&lt;/code&gt; adds extra text objects (e.g. for function arguments) and makes existing text objects more flexible (e.g. selecting the next instance of a text object if you aren’t already inside of it)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;overcache/NeoSolarized&lt;/code&gt; for my color scheme because it’s the most modern true color Solarized color scheme that I could find. I use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim-lualine/lualine&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim-tree/nvim-web-devicons&lt;/code&gt; to make the UI a bit prettier.&lt;/p&gt;

&lt;p&gt;For more IDE like features, I mostly rely on language servers, but some extra support is provided by plugins.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hrsh7th/nvim-cmp&lt;/code&gt; for autocomplete though I’m considering switching off this because it is now unmaintained&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LuaSnip&lt;/code&gt; for snippets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Other than that, there’s pretty much just a bunch of syntax plugins.&lt;/p&gt;

&lt;p&gt;I’ve also factored bits of my config as plugins (e.g. &lt;a href=&quot;/Rna31XL7OHqU/vim-magic-link-paste&quot;&gt;vim-magic-link-paste&lt;/a&gt;) plus a syntax plugin for moss-lang. A way to keep it easy to edit these even though they are no longer in my dotfiles repo is to branch on whether the repository exists on my computer:&lt;/p&gt;
&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;isdirectory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;$HOME&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;/src/vim-magic-link-paste&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  Plug $HOME&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;/src/vim-magic-link-paste&apos;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
  Plug &lt;span class=&quot;s1&quot;&gt;&apos;lehmacdj/vim-magic-link-paste&apos;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This way, vim-plug won’t clone them, and I can edit the source and have it stay up to date automatically.&lt;/p&gt;

&lt;h2 id=&quot;making-changes-to-configuration&quot;&gt;Making changes to configuration&lt;/h2&gt;
&lt;p&gt;I find being able to quickly navigate to a specific bit of configuration that I want to tweak important so that I’m able to fix problems / add new configuration without breaking my flow.&lt;/p&gt;

&lt;p&gt;I use mappings that open up a configuration file in a split:&lt;/p&gt;
&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&quot; Edit vimrc&lt;/span&gt;
nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;Leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;ev &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;Cmd&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;split&lt;/span&gt; $MYVIMRC&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;CR&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot; Edit plugins&lt;/span&gt;
nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;Leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ep&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;Cmd&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;split&lt;/span&gt; $VIMHOME/plugins&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;CR&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;My favorite is my one for editing language specific tweaks, it directly opens up the appropriate file for the current file type:&lt;/p&gt;
&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&quot; Edit filetype file&lt;/span&gt;
nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;expr&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;Leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ef&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;Cmd&amp;gt;split &apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;$VIMHOME&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;/after/ftplugin/&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&amp;amp;&lt;span class=&quot;k&quot;&gt;filetype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;.vim&amp;lt;CR&amp;gt;&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;language-specific-tweaks&quot;&gt;Language specific tweaks&lt;/h2&gt;
&lt;p&gt;I most frequently edit my language specific configuration when I’m learning a language, or using a language I haven’t edited in a while. Most commonly, language specific configuration is overrides for my global vim config like &lt;a href=&quot;https://github.com/lehmacdj/.dotfiles/blob/d360d71f7811664994519ca10f18254743364c2e/nvim.symconfig/after/ftplugin/make.vim#L1-L3&quot;&gt;not converting tabs into spaces for Makefile&lt;/a&gt; or &lt;a href=&quot;https://github.com/lehmacdj/.dotfiles/blob/9b6a637f5c17bb9f9895f8fe03d96d4be480a8b4/nvim.symconfig/after/ftplugin/markdown.vim#L39&quot;&gt;setting up soft wrapping for Markdown&lt;/a&gt;. I also include custom keybindings that are only relevant for particular file types, like &lt;a href=&quot;https://github.com/lehmacdj/.dotfiles/blob/9b6a637f5c17bb9f9895f8fe03d96d4be480a8b4/nvim.symconfig/after/ftplugin/markdown.vim#L67-L68&quot;&gt;publishing a note from my wiki&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;wiki-specific-stuff&quot;&gt;Wiki specific stuff&lt;/h2&gt;
&lt;p&gt;For my notes specifically I have a &lt;a href=&quot;https://github.com/lehmacdj/wiki-language-server&quot;&gt;custom language server&lt;/a&gt; that I use providing autocomplete + title transclusion from random ids + go to definition for navigating between notes. I rely heavily on conceal to keep markdown syntax hidden while reading notes in Neovim.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:which-are-bad&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;There also were remote plugins. But they require installing language runtimes, and have a more limited API than exposed through Vimscript. &lt;a href=&quot;#fnref:which-are-bad&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
      <pubDate>Thu, 23 Apr 2026 06:02:00 +0000</pubDate>
      <link>https://unformeddelta.wiki/LylN8Ju8BGfr/my-neovim-configuration</link>
      <guid isPermaLink="true">https://unformeddelta.wiki/LylN8Ju8BGfr/my-neovim-configuration</guid>
      
      <category>vim</category>
      
      <category>recommended</category>
      
      <category>inkhaven</category>
      
      <category>wiki</category>
      
    </item>
    
    <item>
      <title>Metadata patterns not accounted for by music apps</title>
      <description>&lt;p&gt;I hesitated a lot when first getting into anime idol music. I was definitely a little self-conscious that the album art can get fairly suggestive.&lt;/p&gt;
&lt;style&gt;
.img-blur-reveal { position: relative; flex: 1; overflow: hidden; }
.img-blur-reveal img { width: 100%; height: auto; display: block; filter: blur(20px); transition: filter 0.3s; }
.img-blur-reveal:hover img { filter: none; }
.img-blur-reveal .overlay { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; text-align: center; padding: 0.5em; pointer-events: none; transition: opacity 0.3s; }
.img-blur-reveal:hover .overlay { opacity: 0; }
&lt;/style&gt;

&lt;div style=&quot;display: flex; gap: 1em; width: 100%; align-items: flex-start;&quot;&gt;
  &lt;div style=&quot;flex: 1;&quot;&gt;
    &lt;img src=&quot;/images/ihe0bEPXK5ip-Pasted%20image%2020260421234132.png&quot; alt=&quot;Album art from THE IDOLM@STER SHINY COLORS &amp;quot;CANVAS&amp;quot; 06&quot; style=&quot;width: 100%; height: auto; display: block;&quot; /&gt;
  &lt;/div&gt;
  &lt;div class=&quot;img-blur-reveal&quot;&gt;
    &lt;img src=&quot;/images/ihe0bEPXK5ip-Pasted%20image%2020260421234152.png&quot; alt=&quot;Abum art from Duo &amp;amp; Trio Collection CD Vol. 1 Summer Vacation&quot; /&gt;
    &lt;div class=&quot;overlay&quot;&gt;13+ album art with characters wearing swimsuits&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;But more importantly I feared its complexity would render my music cluttered and unnavigable. I mostly engaged with my music &lt;em&gt;navigationally&lt;/em&gt; as opposed to &lt;em&gt;searching&lt;/em&gt;. I liked to select a genre, an artist within that genre, and then pick out an album within that genre to listen to. Instead of staring at an empty search field, wanting music for focusing, I could pick Soundtrack, evaluating that Joe Hisaishi (i.e. Ghibli Soundtracks) was chiller than John Williams (Star Wars), then Spirited Away, deciding Princess Mononoke was too gloomy and I needed a little more whimsy.&lt;/p&gt;

&lt;p&gt;Idol music would seriously upset this balance. Many tracks were only available as singles, and — GASP — would need to learn to organize my music into playlists. But as listening to nightcore music on YouTube transitioned into watching Love Live! Sunshine’s Aqours’ lyrics videos, eventually I decided that the sanctity of my navigable music library would need to be broken, and started adding μ’s and Aqours music to my music library.&lt;/p&gt;

&lt;p&gt;When I got tired of manually importing metadata I discovered &lt;a href=&quot;https://github.com/beetbox/beets&quot;&gt;beets&lt;/a&gt;, a command line tool that automatically tags music with MusicBrainz metadata. This kept my music organized, but once I was listening to a huge number of artists and franchises&lt;sup id=&quot;fnref:which-franchises&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:which-franchises&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, navigability in my music player started to break down, none the less.&lt;/p&gt;

&lt;p&gt;None of these matter when listening to an algorithm generated playlist on Spotify or YouTube Music. But regardless, I still have a strong desire to navigate — I think it helps me feel more intentional about my music listening.&lt;/p&gt;

&lt;p&gt;Classical music once had a lot of similar problems, e.g. the same piece but separate recordings different orchestras/conductors. Eventually, Apple implemented better navigability through specialized services like &lt;a href=&quot;https://classical.music.apple.com/us/browse/catalog&quot;&gt;Apple Music Classical&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These are the metadata patterns I want custom support for when Claude is able to build me a custom music app.&lt;/p&gt;

&lt;h2 id=&quot;character-vs-voice-actor&quot;&gt;Character vs Voice actor&lt;/h2&gt;
&lt;p&gt;Each character is portrayed by a voice actor. Voice actors often also publish music as themselves, and sometimes the same voice actor portrays multiple characters&lt;sup id=&quot;fnref:example-seiyu-overlap&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:example-seiyu-overlap&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. If I want to listen to music by a particular singer because I like their voice, I’d love to be able to jump to all of the music by the voice actor. YouTube Music/Spotify usually doesn’t even show the voice actor (it depends on the franchise).&lt;/p&gt;

&lt;h2 id=&quot;deep-hierarchies&quot;&gt;Deep hierarchies&lt;/h2&gt;
&lt;p&gt;Because idol anime franchises are primarily a vehicle for selling merchandise for a huge number of characters, they end up with tons of characters sorted into different units (groups of characters that perform together). Idolm@ster is a particularly illustrative franchise&lt;sup id=&quot;fnref:see-more&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:see-more&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;: it contains at least 8 sub-franchises, of which Idolm@ster Shiny Colors contains 8 units, of which Noctchill contains 4 members.&lt;/p&gt;

&lt;h2 id=&quot;overlapping-hierarchies&quot;&gt;Overlapping hierarchies&lt;/h2&gt;
&lt;p&gt;Groups aren’t even static a lot of the time. In Idolm@ster Million Live, pretty much every new single features a never-seen-before unit. Fortunately, when credited as artist these units usually include list of their members, which makes it possible to find songs containing a particular character through search.&lt;/p&gt;

&lt;p&gt;So fans are confident their favorite character will get a new song eventually, albums/singles are often sorted into series&lt;sup id=&quot;fnref:series&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:series&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;. I often wish I could navigate between albums in the series while listening to music.&lt;/p&gt;

&lt;h2 id=&quot;tracks-you-typically-dont-want-to-listen-to&quot;&gt;Tracks you typically don’t want to listen to&lt;/h2&gt;
&lt;p&gt;Albums often bundle tracks that don’t make to listen to typically. Most albums include karaoke tracks without vocals, plus there’s often also drama tracks with character story. These are sometimes interesting to listen to, but I don’t typically want my music listening to be interrupted by a podcast.&lt;/p&gt;

&lt;p&gt;Beyond that there’s often variants of the same song: solo versions, short versions (i.e. ~1:30 versions used in rhythm games), and live recordings. MusicBrainz’s data model actually works fairly well for variants, &lt;a href=&quot;https://musicbrainz.org/work/b9b4e98c-36ad-40be-8461-10784a71e235&quot;&gt;linking recordings to a single song&lt;/a&gt;, but I haven’t found a music app that allows navigating these relationships.&lt;/p&gt;

&lt;p&gt;Music apps aren’t able to filter these out for general listening, but still expose them when desired.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:which-franchises&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;nayuta, Idolm@ster, Love Live!, Project SEKAI (especially More More Jump! and Nightcord at 25:00) are my favorites. I’ve even gone to a couple of live shows in Japan. &lt;a href=&quot;#fnref:which-franchises&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:example-seiyu-overlap&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Ruby Kurosawa and Airi Momoi’s voice actor are both Ai Furihata. &lt;a href=&quot;#fnref:example-seiyu-overlap&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:see-more&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://project-imas.wiki&quot;&gt;https://project-imas.wiki&lt;/a&gt; is organizes all this complexity neatly. &lt;a href=&quot;#fnref:see-more&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:series&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;For example there are 7 albums in THE IDOLM@STER SHINY COLORS “CANVAS” series (just numbered 01 through 07). &lt;a href=&quot;#fnref:series&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
      <pubDate>Wed, 22 Apr 2026 06:34:00 +0000</pubDate>
      <link>https://unformeddelta.wiki/ihe0bEPXK5ip/metadata-patterns-not-accounted-for-by-music-apps</link>
      <guid isPermaLink="true">https://unformeddelta.wiki/ihe0bEPXK5ip/metadata-patterns-not-accounted-for-by-music-apps</guid>
      
      <category>navigability</category>
      
      <category>idolm@ster</category>
      
      <category>idol</category>
      
      <category>music</category>
      
      <category>recommended</category>
      
      <category>inkhaven</category>
      
    </item>
    
  </channel>
</rss>
