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.
Introduction to Haskell (course - Well-Typed)
A six-part introduction to Haskell by Well-Typed. Each part has several videos, self-test questions and assignments to work through.
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.
Unfortunately, it’s no longer available from Diehl’s website, I’ve linked an archived copy. The source code is also available if you want to try building and browsing it locally.
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 IO in Haskell (video - B. Yorgey)
A short video focusing on how and why Haskell does I/O in the way that it does.
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.
A Dictionary of Single-Letter Variable Names (blog post - J. Kelly)
Often, a function is so polymorphic that it’s hard to give the variables useful names. And yet, a convention has arisen around what single-letter names mean. Knowing this convention helps you read library haddocks, as well as make your libraries easier to read for others.
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.
The List of Monoids Pattern (article - O. Charles)
Whenever a function accepts a monoidal value, the API is often more
ergonomic if it accepts a list of that type and calls
mconcat
internally.
Algebraic Blindness (article - D. Luposchainsky)
“Boolean blindness” is when you have no idea what a Bool
argument means. “Algebraic blindness” generalises this idea to functions
which overuse types like Maybe
and Either
instead of building out domain-specific types.
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.
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.
Prefer
do
Notation over Applicative Operators when Assembling
Records (article - G. Gonzales)
A very clean and robust idiom for assembling records using the
RecordWildCards
extension.
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.
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 comments - 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.
Libraries that show up again and again, and are worth knowing before you try to something out of an esoteric new research project.
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.
Yacc is Dead (paper - M. Might and D. Darais)
The derivative of a language is a clever idea: differentiating a language by a character returns the language describing the remainder of the string. Derivatives for regular languages were defined by Brzozowski in the 1960’s, and this paper generalises the technique to work on context-free grammars and parser combinators.
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.
Abusing Constraints for Automatic Documentation (article - S. Maguire)
Some fantastically evil wizardry to use constraints to track which
foreign APIs are called by a piece of code. The best part is an
unsafeCoerce
applied to an empty typeclass
dictionary.
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.
When trying to write property tests, inventing good properties to test is often the hardest part. These talks provide different mental tools to help prime that pump.
How to Specify it! A Guide to Writing Properties of Pure Functions (talk - J. Hughes)
Hughes discusses heuristics for inventing properties, without falling into the expensive and low-value trap of writing your code twice:
Building on Developers’ Intuitions To Create Effective Property-Based Tests (talk - J. Hughes)
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. I ran this workshop at YOW! Lambda Jam in 2019 with another QFPL colleague and people skipped lunch because they were so hooked.
The Mysteries of Dropbox (talk - J. Hughes)
If QuickCheck falsifies a specification, is it the specification or the code that’s wrong? Hughes uses QuickCheck to black-box test Dropbox, by running the daemon running on several virtual machines in parallel. It’s a good example of how to test a complex system you don’t control, and how to refine a model to agree with the observed behavior of the system under test. The final discrepancies are legitimate and hard-to-trigger bugs in Dropbox’s file synchroniser.
Testing the Hard Stuff and Staying Sane (talk - J. Hughes)
Hughes uses QuickCheck to find some gnarly bugs in real code. He:
dets
.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. It has three main examples: how
DList
improves the performance of chained
(++)
, how Yoneda
does the same for
fmap
, and how Codensity
does 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.
Rhine, FRP with type-level clocks (talk - M. Bärenz)
Rhine is an arrow-based FRP system that looks interesting and practical. It sacrifices theoretical purity in favour of explicit type-level “clocks”, of which some are time-based and others can be thought of as “event sources”.
Rhine Koans (workshop - M. Bärenz)
A great set of small exercises to learn Rhine, with a really thorough test suite to support self-study.
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.
Fun with Semirings (Functional Pearl) (paper - S. Dolan)
Semirings are structures which have analogues to addition and multiplication but not subtraction or division. They show up in all sorts of places, and this paper uses a semiring interface to “calculate transitive closures, find shortest or longest or widest paths in a graph, analyse the data flow of imperative programs, optimally pack knapsacks, and perform discrete event simulations, all by just providing an appropriate underlying closed semiring”.
($) 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.
Who Authorized These Ghosts!? (article - O. Charles)
A sketch of applying the GDP technique to authorisation problems. An API handler should only be able to call into business logic if it has a proof that the user making the API call is allowed to do so.
What’s new in purely functional data structures since Okasaki? (Stack Overflow question)
User jbapple’s response to this question is stunningly thorough, and provides a wealth of jumping-off points for the reader who is interested in learning about more functional data structures.
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.
TriMaps that Match (paper and talk - S. Peyton-Jones)
TrieMaps are a neat data structure for when you want a map with complicated keys, and can do more useful tests on the keys than just pairwise comparison or hashing. The paper and talk bring across this technique from the automated reasoning community, provide a good overview of the data structures involved, and extend them to do matching operations.
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, the WebGear
HTTP API library, and a few FRP libraries. 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.
15-150: Principles of Functional Programming (course - B. Wu)
Standard ML is not Haskell, but they share a lot of ideas. These course materials are very well-presented, and I’d recommend them to any student of functional programming regardless of language. I personally learned a lot from his lecture on continuation-passing style (CPS).
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.
Input and Output in Hoon (blog - P. Monk)
A discussion about different approaches to I/O in functional languages, mostly focused on the tradeoffs between state-machine (Elm-style) I/O and monadic (Haskell-style) I/O. State machines are robust and upgradable, but their control flow can become unclear in complex cases. Monadic I/O can specify control flow more clearly, but it is harder to upgrade running I/O actions in-place.