2023 Project Review

17 January, 2024

Reflections on 2023's hobby projects.

Diablo 1 in 2023

14 July, 2023

My experience playing the original Diablo for the first time.

Nominal Sets

4 July, 2023

Developing a variable binding library for Rust, based on the theory of nominal sets.

Nominal Sets: Appendix A (Proofs)

4 July, 2023

The proofs for my Nominal Sets article.

Gear Acquisition Syndrome

28 May, 2023

Over the past few years I’ve become wary of a certain feeling related to my artistic hobbies like drawing and music production: the sense of excitement and “motivation” after I’ve acquired some new art-related material. It’s very easy to spend hours doodling with a new marker, writing in a fresh journal, or twiddling with a synth I’ve just bought. The next day, though, the new tool is a little less exciting, and so on, until it’s as normal as everything else.


Migrating from Jekyll to Hakyll

4 May, 2023

I’ve just finished migrating this site from Jekyll to Hakyll. The only noticeable changes are: slightly prettier page URLs, MathML support, and tweaks to syntax highlighting to compensate for using Pandoc. I paid special attention to preserving the Atom feed identifiers so that feed readers aren’t impacted.

Web Resources I Enjoy

10 January, 2023

In this conversation, Sam Harris and Cal Newport talked about how we use the world wide web, how it has become extremely centralised around a few social media platforms, and the role of recommendation algorithms in this system. Parts of this conversation are starting to influence the way I use the web.


2022 Project Review

27 December, 2022

Reflections this year's hobby projects.

RIP Dream.In.Code

6 July, 2022

Dream.In.Code was a programming help forum that ran from 2001 to the beginning of 2022. It was recently shut down due to hosting costs. My participation in Dream.In.Code, starting from 2009 and ending somewhere in 2013, represents the beginning of my life as a programmer. Over the past 10 or so years, programming has become a huge part of my life. I’d like to acknowledge the role this forum played in my development.

WebGL Slower Than Canvas?

20 May, 2021

I’ve recently been working on web a graphics project where I played a Canvas API implementation against a WebGL implementation. When running the app in Firefox on Linux, I was surprised to find that the WebGL version was 10-30% slower (in frames per second) than the Canvas version.

An Example of Defunctionalisation in Rust

6 February, 2021

I’m an experienced Haskell programmer, and I’ve been writing a lot of Rust lately. I recently ran into a little trouble when porting a simple function from Haskell to Rust. This article is a short description of my journey.

Docker Cleanup Commands

7 November, 2020

I’ve Googled this one too many times, so I’m writing it here for future reference.

Statically Sized Higher-kinded Polymorphism

7 July, 2020

Memory-sensitive languages like C++ and Rust use compile-time information to calculate sizes of datatypes. These sizes are used to inform alignment, allocation, and calling conventions in ways that improve runtime performance. Modern languages in this setting support generic types, but so far these languages only allow parameterisation over types, not type constructors. In this article I describe how to enable parameterisation over arbitrary type constructs, while still retaining compile-time calculation of datatype sizes.

Lambdas are Codatatypes

1 July, 2019

I was first clued into this a while ago by a comment on Bob Harper’s blog that “exponentials are coinductive”, but it only really clicked for me today. Let’s get into it.

Configuring Agda's standard library on NixOS

17 May, 2019

I’ve been using Agda on NixOS for a while (mostly via agda-mode in Emacs), but I remember it was a bit difficult to get going the very first time. Hopefully this becomes a searchable reference to getting it all set up quickly.

Conditional Probabilities and Obnoxious White Guys

5 May, 2019

In this Twitter thread, Eugenia Cheng talks about how she presented at a conference for women in STEM, and was confronted by a white guy who felt ‘called out’ by some of her anecdotes. Apparently, she described interactions with obnoxious individuals in a professional setting, and noted that they were all white guys. Ironically, the guy raised the issue in such a way that he was added to the list of anecdotes.

Learning a Craft

11 February, 2019

I remember when I first learned about computer programming, around 2008 or 2009. I wanted to make games, and asked a search engine. Apparently computer graphics was way too hard, so I decided I wanted to create browser-based static HTML games and text-based roguelikes. Having learned that PHP and MySQL exist, I sat down and brainstormed a setting, classes and roles for characters, and all the other things that come with fantasy RPGs.


29 December, 2018

I think writing can help us think better.

On Programming Language Design

21 November, 2018

In his propositions as types talk, Philip Wadler contrasts programming languages that have been ‘invented’ with those that have been ‘discovered’. “And you can tell!” he exclaims, receiving giggles from the audience. Regardless of how you feel about mathematical platonism, I think Phil is pointing at a meaningful difference in the way certain ideas arise.

Turning bottom-up into top-down with Reverse State

13 June, 2018

I love bound - it makes De Bruijn indices mindlessly easy. I also love Plated for all sorts of whole-program transformations. I think they’re two indispensible tools for working with programming languages. Unfortunately, they’re not compatible.

Comonad Transformers in the Wild

25 February, 2018

A certain algorithmic puzzle website has a problem that goes like this…

Continuations From the Ground Up

6 June, 2017

It’s difficult to learn functional programming without hearing about continuations. Often they’re mentioned while talking about boosting the performance of pure functional code, sometimes there’s talk of control flow, and occasionally with ‘time-travel’ thrown in there to make it all seem more obscure. It’s all true, but let’s start from the beginning.

How to delete old NixOS boot configurations

24 March, 2017

NixOS is a Linux distribution with declarative configuration management. Your system configuration is specified in a set of files, and can run a command to update your system to the current specification. A consequence of this is that your entire system configuration can be versioned.


Introduction to Unification

7 January, 2017

Unification is a vital process in the implementation of Hindley-Damas-Milner type inference. In the original paper it is mentioned in passing as assumed knowledge, so here is an explanation of unification in with a little help from the HM type theory.


Why LINQ (well, C#) is Broken

24 October, 2016

LINQ is a system that provides a flexible query interface for .NET languages. It allows a user to write queries over arbitrary data using an in-built SQL-like syntax. This syntactic sugar is mapped to method calls at compile time, so any data structure that implements the correct methods can be used with LINQ.

Search and Replace in Multiple Files

25 July, 2015

Last semester I had to write a static website by hand with no templating resulting in a lot of duplicated code across multiple pages. I had already finished most of the project when I realised that the main page of the project should be named index.html instead of home.html. I renamed the file, but that left me with countless references to “home.html” that needed to be changed, and I wanted to change them all at once. Enter sed.

The Programming Thought Process: Fizzbuzz

4 March, 2015

With so many programming languages and frameworks at our disposal, it is too easy to believe that knowledge of many tools is the defining characteristic of a good programmer. However, many experienced programmers will assert that it isn’t the languages you know, but your ability to solve problems that defines you as a programmer.

A Practical Introduction to Monad Transformers

1 February, 2015

Monad transformers combine the functionality of two monads into one. They are often used as a way to “flatten” nested monads, but are also used to enable interactions between monads that, when used seperately, would be incredibly difficult to implement.