Last updated: August 30, 2023

There are a lot of excellent Haskell talks and articles out there, and I often need to point people to great explanations of particular concepts. These aren’t be-all end-all expositions of each idea; many are selected to be solid introductions which make it easy to jump off into further learning.

There’s a rough organisation to this page: concepts which are niche
or have more dependencies are listed further down each section (or
subsection). For accessibility’s sake, I have tried to list only free
resources as much as possible. Paid resources are indicated with a
`($)`

.

There’s a sort of “trunk” to learning Haskell, during which a new
Haskell programmer must first pick up a whole lot of (possibly new)
concepts: recursion, folds, problem-solving with pure functions, the
type class abstraction and critical type classes (`Eq`

,
`Ord`

, `Show`

, `Read`

,
`Num`

, `Semigroup`

, `Monoid`

,
`Foldable`

, `Traversable`

, `Functor`

,
`Applicative`

, and `Monad`

, probably), and the
`IO`

type. Links in this section aim to help with these sorts
of challenges.

What I Wish I Knew When Learning Haskell (article - S. Diehl et al.)

A very broad tour of what’s what in Haskell land. What’s a

`ghcup`

?, which extensions are “safe” and which are “scary”? What is “HOAS”? What’s a “free theorem”? Great for skimming and returning to as you learn — don’t try to take it all in at once.Explaining List Folds (talk slides - T. Morris)

Short and correct explanation of

`foldl`

and`foldr`

on lists, and what these functions actually*mean*.`foldr`

performs constructor replacement.Introduction to Haskell Typeclasses (article - G. Dreimanis)

I have sometimes seen students stumble over what a typeclass actually

*is*, what problems the typeclass system allows you to solve, and how defining classes and instances actually works. This article has sometimes helped them.Let’s Program a Calculus Student (article - I. Leal)

A fun exploration of basic calculus in Haskell, starting with syntax trees for mathematical expressions and building out evaluation, substitution, differentiation and so on. While the post is “about” calculus, it’s secretly about exploring Haskell’s numeric hierarchy, syntax trees, fixed points, and infinite data structures. Part 2 is more involved, but automatic differentiation is a really cool trick.

Applied FP Course (workshop - Queensland FP Lab)

This course takes you through building a simple web API. It starts from a minimal

`wai`

`Application`

, and adds (among other things) database storage, configuration, and error handling using monad transformers.I try not to toot my own horn too much on this page, but I helped a colleague develop this course a few years back. Every time we ran it in person, the students would be so engrossed that we’d have to drag them away from their computers to the free lunch. If that’s not an endorsement, I don’t know what is.

State of the Haskell Ecosystem (article - G. Gonzales et al.)

High level overview of where the Haskell ecosystem excels and where it needs work. Very useful during library selection, and deciding whether or not to use Haskell at all.

How I investigate libraries (reddit comment - S. Maguire)

The art of reading Haddocks and gleaning a library’s design is usually a hard-won skill normally encoded as “tacit knowledge”. This post is a pretty good description of what applying that skill actually looks like.

After climbing the trunk, things start to branch out, but there’s still a lot of common folklore, patterns and ideas which tend to show up all over modern Haskell code.

The Data Structure is Always the Last Argument (Elm manual)

A common error made by programmers migrating from OO languages is to make the “main” argument of a function its first argument. In Haskell (as well as Elm), the most important argument is the final one. Example: A partially-applied

`Data.Map.insert`

has type`Ord k => Map k v -> Map k v`

, which is very ergonomic. The rest of the page isn’t necessarily applicable to Haskell, but this point definitely is.Church Encoding (reddit comment - G. Gonzales et al.)

A nice explanation of what we colloquially call “Church Encoding”, complete with some neat ASCII-art diagrams.

What Makes Haskell Unique (talk - M. Snoyman)

Makes the argument that Haskell’s unique power among mainstream languages doesn’t directly come from its key features (laziness, purity, strong typing, &c.), but rather from the way those features interact with each other.

Haskell to Core: Understanding Haskell Features Through Their Desugaring (talk - Vladislav Zavialov)

A fast-moving talk which shows the simpler “Core” language that Haskell source syntax is simplified into, and then shows how to reduce syntactic structures to their corresponding Core. Many advanced language features make a lot more sense once you have some idea of how this desugaring works.

When does laziness help? Post One, Post Two (reddit comment - E. Kmett)

Laziness is a natural consequence of wanting both immutable data structures and code reuse.

Followed by two great big posts about how laziness helps, particularly in Kmettverse projects. Examples range from from

`where`

clauses, to the classic`take 10 . sort`

, to optics that correctly handle infinite data structures.Point-Free or Die: Tacit Programming in Haskell and Beyond (talk - A. Shah)

Provides an overview of point-free style, advice on transforming into and out of point-free, and discusses when to tastefully use it to better communicate intent.

Making Impossible States Impossible (talk - R. Feldman)

This is a good ideal to have in mind when designing data structures: design your types so that they can never represent an invalid state.

Parse, Don’t Validate (article - A. King)

A great follow-up: instead of writing “validation” functions which check validity and return

`Bool`

, write “parsing” functions which return a`Maybe`

of a more restrictive type. This avoids large classes of “oops, I forgot to validate” bugs.

`mtl.md`

(article - Queensland FP Lab)A short summary of the payoff that MTL provides, and a step-by-step derivation with exercises.

Plucking Constraints (article - M. Parsons)

How do you go from

`(MonadReader Foo m, MonadError Bar m, MonadState Baz m) => m ()`

back to an`IO ()`

? By “plucking” (discharging) the constraints one-at-a-time, simplifying the remaining type at each step. This technique appears in a few places, but most Haskellers first encounter it with MTL. A useful read if you haven’t yet internalised how the`runFoo`

functions interact with`MonadFoo`

constraints.Next Level MTL (talk - G. Wilson)

Overview of the “classy lenses + MTL” pattern, which underlies an overwhelming majority of serious Haskell programs. Uses constraints like

`(MonadReader r m, HasFoo r, MonadError e m, AsFooError e)`

to avoid depending on specific environment/error types.Writer Monads and Space Leaks (article - G. Ritter)

A good explanation for how the “

`WriterT`

space leak” happens. Its`WriterishT`

type was added to`transformers`

in`0.5.6.0`

(2019-02) as the “continuation-passing”`Control.Monad.Trans.Writer.CPS.WriterT`

, and the corresponding`MonadWriter`

instance was added in`mtl-2.3`

(2022-05-07).

The Extended Functor Family (talk - G. Wilson)

An excellent introduction to some very important typeclasses used in modern Haskell code:

`Functor`

,`Bifunctor`

,`Contravariant`

,`Profunctor`

. There’s also a compact explanation of the terms “positive position” and “negative position” starting at 8:08.Contravariant Functors: The Other Side of the Coin (talk - G. Wilson)

The sequel to

*The Extended Functor Family*, serving as a gentle introduction to the contravariant analogues of`Applicative`

(`Divisible`

) and`Alternative`

(`Decidable`

). If`Applicative`

s are great for building parsers, then`Decidable`

s should be a great abstraction for building pretty-printers, right?The Functor Combinartorpedia (article - J. Le)

“Functor combinators” take one or more functors as an argument and enhance them with some additional structure. This lets you to build up the functor you actually want incrementally, using primitives that have interesting, domain-specific behaviour and combinators that provide additional-but-uninteresting structure. This article is a tour of combinators from all over the ecosystem, as collected and re-exported by the

`functor-combinators`

library.

Lenses: Compositional Data Access and Manipulation (talk - S. Peyton-Jones)

This is the only lens introduction I’ve seen that starts with get/set lenses and successfully motivates the jump to the

`forall f . Functor f => ...`

form. (Many lens introductions pull it from out of nowhere and say “trust me”.) The talk itself is classic SPJ, complete with heaps of enthusiasm and slides in Comic Sans. Asking “what does a lens do under different`Functor`

s?” really helps build an understanding of what’s actually going on.($) Optics By Example (book - C. Penner)

This book made me relax my “free resources only” policy for this wiki page — it’s just that good. After watching the SPJ talk, working through some exercises will help you become comfortable with lenses. Optics By Example draws a great path through the forest of different optics (lenses, folds, traversals, prisms, and isos) and contains frequent exercises to ensure you understand what you’ve just read. I thought I was pretty good at lenses when I first opened this book, and I learned an absolute truckload.

Let’s Lens (workshop - T. Morris)

If you don’t want to shell out for Optics By Example (even though you should), then I’d work through these exercises. I didn’t “get”

`lens`

until I ground through these exercises, though it’s probably unnecessary to work through all four modules: start with`Lens.GetSetLens`

to understand lenses as an abstract data type, and then work through`Lets.Lens`

to understand the van Laarhoven form, and how it enables lenses to compose nicely with other optics like`Fold`

,`Traversal`

, and`Prism`

.Don’t Fear the Profunctor Optics (article series - “foolbar”)

A three-article series which explains profunctor optics by first providing

`get`

/`set`

-style definitions for all of the major optic types (`Lens`

,`Prism`

,`Traversal`

, &c.), defining a`Profunctor`

hierarchy, and showing how each optic can be represented by varying the constraints on the`Profunctor`

.

Design Patterns for Parser Combinators (Functional Pearl) — (talk/paper - J. Willis, N. Wu)

A well-presented roundup of common patterns to help you effectively use parser combinators. The talk’s schtick is great fun — the two authors collaborate on a parsing PR in real time, while CI reveals the shortcomings of their intermediate approaches. Watch it first to get the flavour, and then read the paper for the details. The talk moves too quickly and the paper is very approachable.

Pretty Print Syntax Trees with this One Simple Trick (article - G. Gonzales)

If you have a grammar for a language, you can write a pretty printer which gets the parentheses right by writing out a series of functions which match the grammar’s productions.

Instances for Everyone, Free: Generic Programming in Haskell (talk - A. Kotlyarov)

High-level overview of the problem solved by GHC Generics, a gentle introduction to the actual types GHC uses, and a demonstration of how to use

`Generic`

to automatically derive instances of other typeclasses.

Template Haskell Tutorial (article - M. Karpov)

A thorough medium-length introduction to Template Haskell. It explains what Template Haskell is, why we might want it, and how all the different concepts fit together in a fairly logical order.

These are either some of the amazing galaxy-brained ideas that make Haskell such a fun language to work in, or entry points into library ecosystems which are a bit “off the beaten path”.

Discrimination is Wrong: Improving Productivity (talk - E. Kmett)

Uses the contravariant functor hierarchy, GHC Generics, and the research of F. Henglein to sort, group, join, and build

`Data.Map`

/`Data.Set`

s of all kinds of data structures, all in*O*(*n*) time and with a good interface for the caller. I’ve watched this talk at least half a dozen times and still learn more on each viewing.Teaching New Tricks to Old Programs (talk - C. Elliott)

Mindblowing keynote from YOW! Lambda Jam 2017. Using a mechanical translation that can be performed by a GHC plugin, it’s possible to interpret Haskell functions into many different Cartesian Closed Categories: rendered computation graphs, shader code, automatic differentiation, …

Servant’s Type-Level Domain Specific Language (article - B. Parker)

Explores how Servant’s typeclass machinery turns the type-level description an API into a set of handler functions for the programmer to implement. Explains the various GHC extensions as they are used, too.

Functor Functors (article - B. Hodgson)

A useful trick when dealing with several data structures that have really similar shapes is to parameterise one structure over some

`Functor`

`f`

. This article then lifts familiar classes like`Functor`

and`Traversable`

to work over these structures, which are seen in packages like`rank2classes`

,`conkin`

, and`barbies`

.DMaps for Delightful Dynamism (talk - D. Laing)

`DMap`

, from the`dependent-map`

package, is a principled way of storing heterogeneous values in a map. This talk is light-speed tour of the packages and extensions that make it all possible. While it’s a great way to get the “lay of the land” of this corner of the ecosystem, you’ll probably need to lie down after viewing, and then to go off and play with all the packages yourself to really get how they fit together.

Polysemy: Chasing Performance in Free Monads (talk - S. Maguire)

The whole talk is great if you want to tour effect systems and the guts of an advanced effect system library, but 4:00-9:00 is the best expression of the “dream” of effect-system programming that I’ve seen anywhere. (There’s a written description of the dream and a sample effect handler on Sandy’s Blog, if you prefer text to video.)

Providing an API for Extensible-Effects and Monad Transformers (article - O. Charles)

Start with a GADT

`f`

representing actions in your API. Then`Free (Coyoneda f)`

is a`Monad`

. Then consider a typeclass in the following style, which can be built upon to provide both an effect-system API and a`transformers`

-style API:`class Monad m => MonadFoo m where liftFoo :: Free (Coyoneda FooCall) a -> m a`

This seems pretty good, provided your API doesn’t need to deal with

`m a`

appearing in negative position.Mocking Effects Using Constraints and Phantom Data Kinds (article - C. Penner)

Suppose you are using typeclasses to track granular effects in your program. You can then define a testing monad with a phantom type parameter for each effect, and use data kinds to enumerate the different ways of mocking each effect (“normal DB”, “on-fire DB”, &c.). This allows each mocked effect to vary independently from the others.

The pitch: You can rewrite a recursive data type as the fixed point of some “base” functor. The chosen functor represents one “layer” of the data structure, and recursion schemes let you write functions that produce, consume, or transform whole structures by writing small functions that operate mostly on the “base” functor.

Program Reduction: A Win for Recursion Schemes (article - J. Wiegley)

Great article showing the payoff gained by implementing the core of the

`HNix`

interpreter with recursion schemes. Skim this article first, despite its suggestion to the contray, to see the payoff. Then work through the articles below in detail, and return to this one if necessary.Visualising Prequel Meme Prefix Tries with Recursion Schemes (article - J. Le)

An appetiser before the full course, this article uses recursion schemes to solve a fun problem posed by the Prequel Memes community. This should give you the lay of the land before the really in-depth article series below.

An Introduction to Recursion Schemes (article - P. Thomson)

Extremely thorough step-by-step exploration of recursion schemes. Each one builds on the next, but even the first posts are extremely satisfying.

Generate random inputs to tests, and shrink them down to minimal reproduction examples if the tests fail.

QuickCheck: A Silver Bullet for Testing? (talk - J. W. Norton)

Good overview of property-based testing, and describes some amazingly-obscure bugs found in Google’s leveldb. The issue reporting the bug was migrated to GitHub from Google Code.

Building on Developers’ Intuitions To Create Effective Property-Based Tests (talk - J. Hughes)

When writing property-based tests, coming up with good properties to test is often the hardest part. This talk explores how to use the intuition that inspires unit test cases to come up with effective property-based tests.

Appetite for Dysfunction (talk - A. McMiddlin)

Property State Machine Testing generates

*command sequences*instead of just input data. The test system then runs these sequences against the system under test, looking for the minimal command sequence which causes expected properties to fail. This talk gives an overview of property state-machine testing, and discusses how to apply it against Wordpress.There’s also a good discussion of how to use

`DMap`

to represent heterogeneous JSON structures; see “DMaps for Delightful Dynamism” under Higher-Kinded Data for more.State Machine Testing Course (workshop - Queensland FP Lab)

This workshop in the style of the Applied FP Course builds state machine property tests for an important stateful system - a coffee machine.

Continuations all the Way Down (talk slides - T. Humphries) (reddit discussion)

Mostly a good demonstration of how continuation-passing tricks can make haskell programs fast, most notably how

`DList`

can improve the performance of chained`(++)`

, and`Yoneda`

can do the same for`fmap`

, and`Codensity`

can do the same for chained`(>>=)`

.I had to sit down with a pencil and work through several examples to make it click.

Replacing Functions with Data (talk - B. Milewski)

Defunctionalisation is the process by which functions are replaced by pieces of data, and can be a useful trick to know if you ever need to send a function across a network boundary. Defunctionalising continuations is one way to rewrite recursive imperative code so it doesn’t risk stack overflows.

This talk takes a categorical perspective on defunctionalisation, and sketches out why a normal sum type works to represent a limited number of functions.

FRP — Events and Behaviour, Part 1 (talk - D. Laing)

Talk has poor audio, focuses on

`reactive-banana`

and the slides are only captured by the camera, but this is one of the few FRP talks which actually works through the design of components in a FRP system and its “wiring diagrams” are very useful.Reflex Workshop (workshop - Queensland FP Lab)

If you can get the Nix expression to build the VM (the QFPL nix cache no longer exists), this workshop is a great way to get your hands dirty and understand FRP as used in reflex.

FizzBuzz in Haskell by Embedding a Domain-Specific Language (article - M. Piróg)

A solution to the classic coding interview problem that demonstrates several powerful FP techniques. It first describes the solution’s behaviour using a domain-specific language and a denotational semantics, implements both in Haskell, and then massages the solution into a compact and elegant form using equational reasoning.

A Brief Guide to a Few Algebraic Structures (article - J. Moronuki)

A good cheatsheet to have on-hand when algebra is discussed. It defines most of the algebraic structures Haskell programmers tend to care about, links the mathematical structurs to the libraries which represent them, and provides a glossary of the terms used in the definitions (things like “annihilator”).

My only quibble is that

`Num`

is not a ring as it is defined here:`(*)`

is not always commutative (though it often is).`Num`

instances with non-commutative`(*)`

include the`matrix`

package (multiplication of square matrices is noncommutative) and quaternions.($) Algebra-Driven Design (book - S. Maguire)

The algebraic structures commonly used by Haskell programmers allow elegant expression of many small-to-medium-sized programming idioms. This is largely because the abstractions have

*well-defined laws*which precisely specify what the abstractions mean. This book shows that it is possible to design entire software systems with this level of compositionality, and the “scavenger hunt server” is the highlight of a very inspiring book.Coyoneda (talk - Loop School)

`Coyoneda`

is the “free`Functor`

”: for any type`f :: Type -> Type`

,`Coyoneda f`

is a`Functor`

, even if`f`

isn’t.`Coyoneda Set`

is probably not the best way to handle the “mapping over`Set`

” problem, but it’s at least a compact demonstration of the idea.Applicative Regular Expressions using the Free Alternative (article - J. Le)

Utter wizardry: describe how to handle primitives, layer on the free Alternative, and suddenly you have a regex engine. A great demonstration of free structures.

The Constraint Trick for Instances (article - C. Done)

Explains the difference between

`instance (var ~ AType) => ClassName (SomeType var)`

and`instance ClassName (SomeType AType)`

— the former matches more easily and provides additional information to the typechecker. This is an important and subtle distinction.Ghosts of Departed Proofs (Functional Pearl) (article - M. Noonan)

Describes an idiom (published as the

`gdp`

library) for attaching proofs to phantom type variables, allowing library code to require proof that its preconditions have been met in a relatively lightweight way.Finger Trees Explained Anew, and Slightly Simplified (talk - K. Claessen)

Finger Trees underlie the

`Data.Sequence`

data type, and give it great amortised performance at both ends of the sequence. This talk shows how you’d get there, by starting with a simple but wrong implementation, and progressively refining it until it meets all the asymptotic performance goals. Very approachable.Algebraic Graphs with Class (Functional Pearl) (paper - A. Mokhov)

Many graph representations in Haskell are unsatisfying because they are full of partial functions. This paper builds up a clever graph toolkit that fits in well with standard FP idioms, based off the following representation:

`class Graph g where type Vertex g empty :: g vertex :: Vertex g -> g overlay :: g -> g -> g connect :: g -> g -> g`

Arrows Tutorial (Webgear manual)

Arrows are very niche these days, and the only places I’ve really seen them are in the

`opaleye`

PostgreSQL binding and the`WebGear`

HTTP API library. They have their own set of tradeoffs compared to both Applicatives and Monads, but are very useful in the right contexts.This tutorial steps through the main typeclasses used, as well as the arrow syntax understood by GHC.

Profunctors, Arrows, and Static Analysis (article - W. Fancher)

A much more thorough article, if you want the depth. It discusses many tools offered by the

`profunctors`

package, as well as the static analysis opportunities offered by arrows.

Monoidal Parsing (talk - E. Kmett)

Suppose you want to parse a programming language in parallel. What concessions do you need from your language design to make this possible? (Partial answer: no multi-line nested comments, and abandon certain dubious layout rules). Also talks about using

`Group`

s to track offsets, without spending all your time recomputing offsets, and using semi-direct products to combine relocatable information about text spans.Opening Keynote: There and Back Again (talk - E. Kmett)

Covers a neat little hierarchy of

`Semigroup => RegularSemigroup => InverseSemigroup => Group`

which support an “inverse-like” operation but aren’t full`Group`

s. Also touches on a bunch of stuff covered in more detail by the above talk: join semilattices, monoid actions, monoids acting on monoids, and semi-direct products while hinting at their application to problems which require incremental update.

The Interpreter Pattern Revisited (talk - R. Bjarnason)

The Design Patterns book contains a pattern for making interpreters. By rewriting the Interpreter Pattern in Scala and pulling on some threads, the talk goes to some very interesting places, eventually ending up with the Free Monad.

Refactoring Ruby with Monads (talk - T. Stuart)

Approaches monads by first looking at abstract data types, operations, and the rules they must follow. After refactoring several Ruby problems to a common interface, it talks about the important features of the monad abstraction: that the operations must follow certain rules, and that it’s possible to write functions that work over any monad.