Haskell for all
Wednesday, January 14, 2026
Chat is the least interesting interface to LLMs
Structured inputs and outputs work work better than prose
Friday, January 9, 2026
Prompting 101: Show, don’t tell
Improve your prompts with better examples rather than better instructions
Wednesday, October 1, 2025
Nix Steering Committee vote of no confidence
Post-mortem on the Nix Steering Committee's recent vote of no confidence
Wednesday, September 17, 2025
Steering Committee Retrospective
A Nix Steering Committee member's critique of the Steering Committee's effectiveness
Wednesday, August 13, 2025
Datatype unification using Monoids
How to infer the types of plain data, including unification
Friday, May 2, 2025
Prompt chaining reimagined with type inference
Using bidirectional type inference to infer JSON schemas for prompts with structured outputs
Thursday, November 14, 2024
The Haskell inlining and specialization FAQ
Answers to common Haskell questions related to inlining and specialization
Thursday, August 29, 2024
Firewall rules: not as secure as you think
A post outlining tricks for firewall privilege escalation
Tuesday, July 23, 2024
Software engineers are not (and should not be) technicians
Why predictable development work is a red flag
Wednesday, July 3, 2024
Quality and productivity are not necessarily mutually exclusive
A focus can quality can sometimes immediately boost productivity
Monday, May 20, 2024
Prefer do notation over Applicative operators when assembling records
A post explaining the advantages of do notation and RecordWildCards over Applicative operators
Wednesday, May 8, 2024
All error messages are necessarily bad to some degree
An explanation of the selection bias that leads to poor error messages
Thursday, February 29, 2024
The siren song of domain-specific languages
The pitfalls software engineers encounter when creating domain-specific languages for less technical users
Thursday, February 22, 2024
Unification-free ("keyword") type checking
A type checking proposal that doesn't employ unification variables.
Wednesday, October 4, 2023
A GHC plugin for OpenTelemetry build metrics
An announcement post for the opentelemetry-plugin Haskell package
Friday, September 8, 2023
GHC plugin for HLint
An announcement post for a maintained GHC plugin for HLint
Monday, April 3, 2023
Ergonomic newtypes for Haskell strings and numbers
A trick to elide newtypes around Haskell strings and numbers
Monday, March 6, 2023
The "open source native" principle for software design
Design proprietary software as if it were open source software
Monday, January 30, 2023
terraform-nixos-ng: Modern terraform support for NixOS
Announcement post for improved terraform bindings for NixOS
Monday, January 23, 2023
Announcing nixos-rebuild: a "new" deployment tool for NixOS
A post explaining how nixos-rebuild is a cross-platform tool that can deploy remote NixOS systems
Friday, December 30, 2022
Nixpkgs support for Linux builders running on macOS
Blog post contextualizing recent work to upstream Linux builders for macOS
Monday, December 19, 2022
Nixpkgs support for incremental Haskell builds
A post explaining the design behind a new Nixpkgs feature for building Haskell packages incrementally
Monday, October 24, 2022
How to correctly cache build-time dependencies using Nix
A guide to uploading Nix dependencies to a cache efficiently and reliably
Thursday, October 20, 2022
What does "isomorphic" mean (in Haskell)
An explanation of isomorphisms in the context of the Haskell programming language
Wednesday, September 7, 2022
nix-serve-ng: A faster, more reliable, drop-in replacement for nix-serve
An announcement post for a Haskell rewrite of nix-serve named nix-serve-ng
Monday, August 29, 2022
Stop calling everything "Nix"
Explanation of the Nix ecosystem's abstraction layers
Sunday, August 28, 2022
Incrementally package a Haskell program using Nix
A tour of progressively more robust ways to package a Haskell file using Nix
Sunday, June 26, 2022
defaultable-map: An Applicative wrapper for Maps
An announcement post for a Haskell package for default-valued Maps
Friday, June 3, 2022
The appeal of bidirectional type-checking
A post explaining why bidirectional type-checking is popular within the programming language theory community
Tuesday, May 31, 2022
Generate web forms from pure functions
Announce post for the Grace browser, which translates functional code to interactive HTML
Monday, May 9, 2022
The golden rule of software distributions
A description of an architectural pattern commonly found in many software distributions
Tuesday, May 3, 2022
Why does Haskell's take function accept insufficient elements?
A blog post that is a long-form answer to a question originally asked on Reddit
Sunday, May 1, 2022
Introductory resources to type theory for language implementers
A post touring resources you can use to learn how to implement a type checker or type inference algorithm
Tuesday, March 29, 2022
Modeling PlusCal in Haskell using Cartesian products of NFAs
This post introduces a Haskell eDSL implementing a subset of PlusCal along with a tour of the implementation
Saturday, March 12, 2022
The hard part of type-checking Nix
An survey on the challenges designing a type system for Nix
Wednesday, March 2, 2022
Applicatives should usually implement Semigroup and Monoid
A post that explains why and when Applicative type constructors should provide lifted Semigroup and Monoid instances
Sunday, February 27, 2022
What is a monad morphism (in Haskell)?
An educational post explaining monad morphisms and their laws
Wednesday, January 26, 2022
Nixpkgs overlays are monoids
Not even Nixpkgs abstractions are safe from category theory
Thursday, October 21, 2021
Co-Applicative programming style
This post showcases an upcoming addition to the contravariant package that permits programming in a co-Applicative style
Thursday, October 14, 2021
Advice for aspiring bloggers
This post contains miscellaneous tips I frequently share with new bloggers
Wednesday, October 6, 2021
The "return a command" trick
A trick that minimizes the change surface of your code
Wednesday, September 29, 2021
Fall-from-Grace: A ready-to-fork functional programming language
A reference implementation of a functional language with JSON-like syntax and Dhall-style imports
Wednesday, September 1, 2021
Forward and reverse proxies explained
The fundamental difference between forward and reverse proxies
Friday, August 27, 2021
Naming function arguments in Dhall
Showcase of Dhall language features that improve the readability of types
Friday, June 4, 2021
Probability for Slay the Spire fanatics
The hypergeometric distribution implemented in Haskell
Wednesday, May 19, 2021
Module organization guidelines for Haskell projects
Tips and tricks for how to organize a Haskell project
Wednesday, May 5, 2021
The trick to avoid deeply-nested error-handling code
This post documents a small trick that I use to avoid deeply-nested error-handling code
Wednesday, April 21, 2021
The end of history for programming
A forward-looking post about where programming is headed
Thursday, April 8, 2021
How to replace Proxy with AllowAmbiguousTypes
A better alternative to Haskell's Proxy type
Saturday, February 6, 2021
Folds are constructor substitution
Generalizing folds to data structures other than collections
Sunday, January 31, 2021
Dynamic type errors lack relevance
Why purity and stack traces aren't a substitute for a type system
Monday, January 4, 2021
The visitor pattern is essentially the same thing as Church encoding
The functional programming analog of an object-oriented design pattern
Friday, December 4, 2020
Recruiting for diversity is not lowering the bar
Diversity actually raises the bar
Thursday, November 19, 2020
How to use NixOS for lightweight integration tests
An example showing how to translate a postgrest tutorial into an automated integration test
Tuesday, November 10, 2020
Pretty-print syntax trees with this one simple trick
A clever trick for converting a parser into a matching prettyprinter
Tuesday, April 21, 2020
Blazing fast Fibonacci numbers using Monoids
Compute enormous Fibonacci numbers in milliseconds using this one weird trick
Friday, January 17, 2020
Why Dhall advertises the absence of Turing-completeness
The case for Turing-incompleteness
Thursday, December 12, 2019
Prefer to use fail for IO exceptions
Stop using error and prefer fail instead
Sunday, June 16, 2019
The CAP theorem for software engineering
A post that explains software engineering tradeoffs through the lens of the CAP theorem for distributed systems
Monday, February 11, 2019
Haskell command-line utility using GHC generics
Motivating use case for GHC generics
Monday, October 8, 2018
Detailed walkthrough for a beginner Haskell program
A simple Haskell program built up step-by-step
Monday, May 21, 2018
How I evaluate Haskell packages
How to separate the wheat from the chaff when comparing dependencies
Friday, November 3, 2017
Semantic integrity checks are the next generation of semantic versioning
An introduction to the Dhall configuration language's support for integrity checks based on the semantic content of code instead of the text
Saturday, October 7, 2017
Why do our programs need to read input and write output?
A rethink of conventional wisdom around IO
Monday, February 20, 2017
The Curry-Howard correspondence between programs and proofs
Explanation of the Curry-Howard correspondence using Dhall
Saturday, January 28, 2017
Typed Nix programming using Dhall
How to use Dhall as a typed front-end for Nix
Monday, December 5, 2016
Dhall - A non-Turing-complete configuration language
dhall 1.0 announcement post
Thursday, October 27, 2016
Electoral vote distributions are Monoids
Modeling independent probability distributions using category theory
Monday, July 4, 2016
Auto-generate service API endpoints from records
server-generic 1.0 announcement post
Sunday, July 3, 2016
list-transformer - A beginner-friendly ListT
list-transformer 1.0 announcement post
Sunday, April 10, 2016
Worst practices should be hard
Best practices should be the path of least resistance
Sunday, April 3, 2016
LambdaConf should reconsider its policy
Open letter protesting LambdaConf's decisions
Saturday, February 27, 2016
Auto-generate a command line interface from a data type
optparse-generic 1.0 announcement post
Sunday, February 21, 2016
State of the Haskell Ecosystem - February 2016 Edition
Update post for the State of the Haskell Ecosystem
Wednesday, February 3, 2016
From mathematics to map-reduce
The connection between category theory and distributed data processing
Wednesday, December 30, 2015
Compile-time memory safety using Liquid Haskell
Showcase of Liquid Haskell
Wednesday, December 9, 2015
How to contribute to the Haskell ecosystem
Easy wins for Haskell beginners
Wednesday, November 18, 2015
Interactive and composable charts
Applicative forms, diagrams, and charts
Sunday, October 18, 2015
Explicit is better than implicit
Term-level alternatives to type-level approaches
Friday, October 2, 2015
Polymorphism for dummies
Explanation of how universal quantification works in Haskell
Thursday, September 17, 2015
How to make your Haskell code more readable to non-Haskell programmers
My Haskell style guide
Monday, August 31, 2015
State of the Haskell ecosystem - August 2015
Overview of the Haskell ecosystem's maturity in various application domains
Monday, June 15, 2015
break-1.0.0: A small library for breaking from loops
break 1.0.0 announcement post
Monday, June 15, 2015
optional-args-1.0.0: Optional function arguments
optional-args 1.0.0 announcement post
Friday, March 27, 2015
Algebraic side effects
How Haskell's support for effects plays nicely with equational reasoning
Saturday, January 10, 2015
total-1.0.0: Exhaustive pattern matching using traversals, prisms, and lenses
total 1.0.0 announcement post
Saturday, December 6, 2014
A very general API for relational joins
The connection between relational database operations and category theory
Sunday, November 23, 2014
How to build library-agnostic streaming sources
The case for MonadPlus as the true ListLike class
Friday, September 12, 2014
Morte: an intermediate language for super-optimizing functional programs
morte 1.0.0 announcement post
Sunday, July 20, 2014
Equational reasoning at scale
How category theory abstractions amplify equational reasoning
Saturday, April 19, 2014
How the continuation monad works
Cute reformulation of the continuation monad's implementation
Friday, April 4, 2014
Scalable program architectures
How to design resilient architectural patterns that last the test of time
Tuesday, April 1, 2014
Worst practices are viral for the wrong reasons
Perverse incentives surrounding best practices
Tuesday, March 25, 2014
Introductions to advanced Haskell topics
Tour of watershed posts and papers for Haskell
Saturday, February 22, 2014
Reasoning about stream programming
Defense of the pipes ecosystem's minimalism
Saturday, February 8, 2014
pipes-http-1.0: Streaming HTTP/HTTPS clients
pipes-http 1.0 announcement post
Sunday, January 19, 2014
Shortcut fusion for pipes
Optimizing stream programming using Haskell's rewrite rule system
Thursday, December 19, 2013
Lift error handling with lens-like syntax
Design sketch for how error-handling could interact with monad transformers
Friday, November 1, 2013
Test stream programming using Haskell's `QuickCheck`
Property-based testing for non-trivial stream programming properties
Saturday, October 12, 2013
An all-atom protein search engine powered by Haskell
My biochemistry PhD project, which was implemented in Haskell
Wednesday, October 9, 2013
How to reimplement the conduit parsing API in 50 lines of pipes code
Conduit utilities implemented using pipes code
Sunday, October 6, 2013
Manual proofs for the `pipes` laws
Formal correctness proofs for the pipes package
Friday, September 20, 2013
Perfect streaming using `pipes-bytestring`
pipes-bytestring 1.0.0 announcement post
Saturday, August 10, 2013
foldl-1.0.0: Composable, streaming, and efficient left folds
foldl 1.0.0 announcement post
Saturday, August 3, 2013
Composable streaming folds
An elegant trick for combining multiple folds into a single fold that still goes over the data in one pass
Friday, August 2, 2013
Sometimes less is more in language design
The case for programming languages that are constrained by default
Saturday, July 13, 2013
Statements vs Expressions
An explanation of how everything is an expression in Haskell
Sunday, June 23, 2013
From zero to cooperative threads in 33 lines of Haskell code
A tiny implementation of coroutines
Thursday, June 6, 2013
pipes-concurrency-1.2.0: Behaviors and broadcasts
pipes-concurrency 1.2.0 announcement post
Sunday, June 2, 2013
pipes-parse-1.0.0: Pushback, delimited parsers, resumable parsing, and lenses
pipes-parse 1.0.0 announcement post
Saturday, May 4, 2013
Program imperatively using Haskell lenses
A tour de force of Haskell's lens package
Sunday, April 21, 2013
pipes and io-streams
How to translate between pipes and io-streams abstractions
Sunday, April 14, 2013
pipes-concurrency-1.0.0: Reactive programming
pipes-concurrency 1.0.0 announcement post
Thursday, March 21, 2013
pipes-3.2: ListT, Codensity, ArrowChoice, and performance
pipes 3.2 announcement post
Thursday, February 14, 2013
Comonads are objects
The connection between comonads and object-oriented programming
Monday, January 14, 2013
pipes-safe-1.0 - Resource management and exception handling for pipes
pipes-safe 1.0 announcement post
Saturday, October 20, 2012
"Hello, core!"
An introduction to inspecting GHC's intermediate core representation
Monday, October 15, 2012
Parsing chemical substructures
Applying parser combinators to chemical substructures
Saturday, October 6, 2012
pipes-2.4: Proxy transformers, extra categories, utilities, and benchmarks
pipes-2.4 announcement post
Wednesday, September 19, 2012
The MonadTrans class is missing a method
Language design discussion related to monad transformers
Saturday, September 15, 2012
The functor design pattern
A programming design pattern inspired by category theory
Friday, September 7, 2012
Concurrency = Lists of Kleisli arrows
A surprising connection between coroutines and category theory
Saturday, August 18, 2012
The category design pattern
A programming design pattern inspired by category theory
Friday, August 10, 2012
Code Example #1
End-to-end example of using Haskell to solve a practical problem
Thursday, July 19, 2012
First-class modules without defaults
A response to another blogger's modules proposal
Sunday, July 1, 2012
pipes-2.1 and index-core-1.0 - Indexed types
pipes-2.1 and index-core-1.0 announcement post
Sunday, May 27, 2012
Conduit bugs
Investigation of bugs in Haskell's conduit package and how they originate from violations of mathematical principles
Wednesday, May 2, 2012
Scrap your type classes
How to implement type classes in terms of term-level data structures
Thursday, March 29, 2012
Haskell for Purists - Pipe Finalization
Design discussion of how stream processing interacts with resource management
Saturday, February 11, 2012
Haskell for Java Programmers - Serialization
Introduction to Haskell binary serialization
Wednesday, January 4, 2012
Haskell for Mainstream Programmers - State
How Haskell models state management
Tuesday, January 3, 2012
Haskell for Intermediate Programmers - Algebraic Data Types
Why Haskell data types are called algebraic data types
Sunday, January 1, 2012
Haskell for C Programmers - For Loops
How to translate imperative for loops to Haskell idioms
Saturday, December 31, 2011
Haskell for Mainstream Programmers - Code reuse
An introduction to Haskell's language features supporting code reuse