Haskell for all


Monday, February 2, 2026

My experience with vibe coding

Vibe coding isn't a silver bullet

Tuesday, January 20, 2026

Type-safe eval in Grace

The case for principled eval support

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

Tuesday, June 25, 2024

My spiciest take on tech hiring

Why streamlined interview processes are better

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

Monday, October 2, 2023

My views on NeoHaskell

A rundown and critique of the NeoHaskell project

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

Monday, December 13, 2021

Funding isn't the problem with open source

Capitalism is the problem

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

Thursday, September 9, 2021

Optics are monoids

This post documents my favorite lens trick of all time

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, August 13, 2021

Namespaced De Bruijn indices

An elegant trick for managing bound variables

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

Friday, October 30, 2020

Why I prefer functional programming

Why I'm long on functional programming

Monday, July 27, 2020

The golden rule of software quality

Prefer fixing inputs rather than outputs

Monday, July 13, 2020

Record constructors

Tour of record-related design patterns in Haskell

Tuesday, April 21, 2020

Blazing fast Fibonacci numbers using Monoids

Compute enormous Fibonacci numbers in milliseconds using this one weird trick

Monday, February 10, 2020

Dhall Survey Results (2019-2020)

2019-2020 Dhall language survey results

Friday, January 17, 2020

Why Dhall advertises the absence of Turing-completeness

The case for Turing-incompleteness

Sunday, January 5, 2020

Dhall - Year in review (2019-2020)

2019-2020 Dhall language survey

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

Tuesday, May 14, 2019

Release early and often

Why you should avoid big bang releases

Thursday, February 21, 2019

Dhall Survey Results (2018-2019)

2018-2019 Dhall language survey results

Monday, February 11, 2019

Haskell command-line utility using GHC generics

Motivating use case for GHC generics

Wednesday, January 16, 2019

Dhall - Year in review (2018-2019)

2018-2019 Dhall language survey

Monday, October 8, 2018

Detailed walkthrough for a beginner Haskell program

A simple Haskell program built up step-by-step

Thursday, August 16, 2018

NixOS in production

A production-grade deployment method for NixOS

Monday, May 21, 2018

How I evaluate Haskell packages

How to separate the wheat from the chaff when comparing dependencies

Monday, February 5, 2018

The wizard monoid

Author setup wizards with this one simple trick

Sunday, January 28, 2018

Dhall Survey Results (2017-2018)

The 2017-2018 Dhall language survey results

Tuesday, January 2, 2018

Dhall - Year in review (2017-2018)

2017-2018 Dhall language survey results

Monday, November 27, 2017

Compare Nix derivations using nix-diff

nix-diff 1.0 announcement post

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

Monday, October 16, 2017

Advice for Haskell beginners

How to start off on the right foot

Saturday, October 7, 2017

Why do our programs need to read input and write output?

A rethink of conventional wisdom around IO

Tuesday, September 26, 2017

Type-driven strictness

A window into Dhall's optimizer

Sunday, July 16, 2017

Demystifying Haskell assignment

Demistifying bind vs equals in Haskell

Saturday, June 17, 2017

Dhall is now a template engine

dhall-text 1.0 announcement post

Saturday, June 10, 2017

Translating a C++ parser to Haskell

nix-derivation 1.0 announcement post

Thursday, April 13, 2017

Use Dhall to configure Bash programs

dhall-bash 1.0 announcement post

Monday, February 20, 2017

The Curry-Howard correspondence between programs and proofs

Explanation of the Curry-Howard correspondence using Dhall

Sunday, February 5, 2017

Program JSON and YAML with Dhall

dhall-json 1.0 announcement post

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

Saturday, May 21, 2016

A command-line benchmark tool

bench 1.0 announcement post

Sunday, April 24, 2016

Data is Code

annah 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

Wednesday, November 11, 2015

Haskell-native spreadsheets

typed-spreadsheet 1.0 announcement post

Sunday, October 18, 2015

Explicit is better than implicit

Term-level alternatives to type-level approaches

Wednesday, October 7, 2015

Basic Haskell Examples

Useful Haskell programs that eschew fancy idioms

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

Monday, May 18, 2015

The internet of code

Distributed mutually recursive code

Wednesday, May 6, 2015

Haskell content spinner

Algebraic comment spam

Monday, April 6, 2015

Mathematical APIs

Mathematical interfaces are familiar interfaces

Friday, March 27, 2015

Algebraic side effects

How Haskell's support for effects plays nicely with equational reasoning

Thursday, January 29, 2015

Use Haskell for shell scripting

turtle 1.0 announcement post

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

Sunday, October 26, 2014

How to desugar Haskell code

An overview of Haskell's syntax sugar

Friday, September 12, 2014

Morte: an intermediate language for super-optimizing functional programs

morte 1.0.0 announcement post

Sunday, August 10, 2014

managed-1.0.0: A monad for managed resources

managed 1.0.0 announcement post

Sunday, July 20, 2014

Equational reasoning at scale

How category theory abstractions amplify equational reasoning

Saturday, June 14, 2014

Spreadsheet-like programming in Haskell

mvc-updates 1.0 announcement post

Friday, April 25, 2014

Model-view-controller, Haskell-style

mvc 1.0 announcement post

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

Monday, March 3, 2014

How to model handles with pipes

Stream processors as handles

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

Wednesday, February 5, 2014

pipes-parse-3.0: Lens-based parsing

pipes-parse 3.0 announcement post

Sunday, February 2, 2014

Streaming logging

Logging without buffering in Haskell

Sunday, January 19, 2014

Shortcut fusion for pipes

Optimizing stream programming using Haskell's rewrite rule system

Wednesday, December 25, 2013

Equational reasoning

An introduction to equational reasoning

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, September 7, 2013

pipes-4.0: Simpler types and API

pipes 4.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

Friday, June 28, 2013

The Resource Monad

Applicative resource management

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

Monday, May 6, 2013

pipes-3.3.0: Folds and uniting ListT with Proxy

pipes 3.3.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

Wednesday, April 10, 2013

Defaults

The case for the Monoid type class as the true Default class

Thursday, March 21, 2013

pipes-3.2: ListT, Codensity, ArrowChoice, and performance

pipes 3.2 announcement post

Saturday, March 16, 2013

mmorph-1.0.0: Monad morphisms

mmorph 1.0.0 announcement post

Thursday, February 14, 2013

Comonads are objects

The connection between comonads and object-oriented programming

Monday, January 21, 2013

Introduction to Haskell IO

Love letter to Haskell's support for IO

Monday, January 14, 2013

pipes-safe-1.0 - Resource management and exception handling for pipes

pipes-safe 1.0 announcement post

Sunday, December 30, 2012

The Continuation Monad

Continuation monad tutorial

Wednesday, December 12, 2012

pipes-3.0 - A simpler, unified API

pipes-3.0 announcement post

Wednesday, October 31, 2012

pipes-2.5: Faster and slimmer

pipes-2.5 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

Wednesday, September 5, 2012

pipes-2.3 - Bidirectional pipes

pipes-2.3 announcement post

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

Tuesday, July 31, 2012

Free monad transformers

transformers-free announcement post

Thursday, July 19, 2012

First-class modules without defaults

A response to another blogger's modules proposal

Wednesday, July 18, 2012

Purify code using free monads

How to mock IO actions using free monads

Wednesday, July 11, 2012

Breaking from a loop

How to exit from a loop in Haskell

Sunday, July 8, 2012

errors-1.0: Simplified error handling

errors 1.0 announcement post

Sunday, July 1, 2012

pipes-2.1 and index-core-1.0 - Indexed types

pipes-2.1 and index-core-1.0 announcement post

Saturday, June 16, 2012

GADTs

How to encode GADTs without GADTs

Saturday, June 9, 2012

Why free monads matter

A tour of free monads and their motivating use cases

Sunday, May 27, 2012

Conduit bugs

Investigation of bugs in Haskell's conduit package and how they originate from violations of mathematical principles

Monday, May 21, 2012

pipes 2.0 - Pipe Finalization

pipes 2.0 announcement post

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

Sunday, January 29, 2012

Haskell for Engineers - Unicode

Haskell's support for Unicode variable names

Saturday, January 28, 2012

Lenses

Conceptual explanation of how Haskell lenses work

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


Copyright © 2011 Gabriella Gonzalez. This work is licensed under CC BY-SA 4.0