Home / Haskell
Haskell
Haskell beyond the basics: functors, applicatives, monads, transformers, laziness, deeper typeclasses and IO, plus two projects. All examples verified with the real compiler.
Haskell Intermediate takes the pure functions you already write and shows how they scale. Functors map inside any wrapper, applicatives combine wrapped values, monads chain steps that can fail, and transformers stack effects without tangling them. Fifty lessons, each one checked by the real compiler, carry you from fmap to a working task tracker.
Course contents
Work top to bottom — the sidebar is the course. Topics later in the list assume the ones before them.
Haskell Intermediate Introduction
Intermediate · ⏱ 3 min · standalone lesson
Functors
- Haskell Functor Class
- Haskell Fmap over Lists
- Haskell Fmap over Maybe
- Haskell Functor Laws
- Haskell Fmap Composition
- Haskell Custom Functor Instances
Applicatives
- Haskell Applicative Class
- Haskell Pure and Apply
- Haskell Applicative Maybe
- Haskell Applicative Lists
- Haskell Applicative Laws
Monads
- Haskell Monad Class
- Haskell Bind and Return
- Haskell Do Notation Desugaring
- Haskell Maybe Monad
- Haskell List Monad
- Haskell Monad Laws
- Haskell Sequence and Traverse
Transformers
Start: Haskell Monad Transformers ❯Laziness and Strictness
- Haskell Lazy Evaluation
- Haskell Infinite Lists
- Haskell Thunks
- Haskell Seq and Strictness
- Haskell Strict Folds
- Haskell Strict Fields
Typeclasses in Depth
- Haskell Deriving in Depth
- Haskell Multi-Parameter Typeclasses
- Haskell Typeclass Constraints
- Haskell Custom Typeclasses
- Haskell Default Methods
IO in Depth
- Haskell Files in Depth
- Haskell File Handles
- Haskell Bracket Cleanup
- Haskell IO Exceptions
- Haskell IORef State
Errors in Depth
- Haskell Either Patterns
- Haskell Maybe Combinators
- Haskell Error Accumulation
- Haskell Pure Errors versus IO Exceptions
Performance Notes
- Haskell Benchmarking with Counts
- Haskell Collection Choices
- Haskell Profiling Notes
- Haskell String Building
Haskell Project: Log Analyzer
Intermediate · ⏱ 4 min · standalone lesson
Haskell Project: Task Tracker
Intermediate · ⏱ 4 min · standalone lesson
Haskell at the intermediate level
Beginner Haskell taught you to write plain programs: bindings, functions, pattern matching, recursion, lists, custom types, Maybe and Either at first sight, do notation, and modules. Intermediate Haskell teaches the abstractions that let those programs grow without turning into a tangle. A functor is a wrapper you can map over. An applicative lets a wrapped function meet wrapped arguments. A monad chains steps where each step can fail, branch, or consult earlier results.
The course treats the famous laws as checkable facts, not slogans. Functor identity and composition, applicative identity and homomorphism, and the three monad laws all appear as small programs that print True for concrete values. When a law holds, you can refactor with confidence: replacing one spelling with another cannot change the result.
Fifty lessons in twelve groups move from functors through applicatives and monads to ReaderT and StateT transformers, then into laziness, strictness, deeper typeclasses, deeper IO, deeper error handling, and performance notes. Two closing projects put the pieces together: a log analyzer that reads a file and reports what it found, and a task tracker that threads state through a stack. Lesson times total 163 minutes.
What you will learn
Follow the groups in order and you will pick up:
- Map a function inside Maybe, lists, Either, and your own wrapper types with fmap
- Combine wrapped values with pure and apply, and check the applicative laws as programs
- Chain fallible steps with bind and return, and read do notation as bind spelled readably
- Sequence and traverse collections of wrapped values without hand-rolled recursion
- Share read-only configuration with ReaderT and thread changeable state with StateT
- Lift inner actions into a transformer stack and peel the layers in the right order
- Predict when Haskell computes: thunks, infinite lists, seq, strict folds, and strict fields
- Derive instances, write multi-parameter classes, stack constraints, and set default methods
- Handle files through handles, guarantee cleanup with bracket, and catch IO failures with try
- Keep IORef state tidy, fold Either results, combine Maybe values, and collect every validation problem
- Tell pure errors apart from runtime exceptions, and choose the right shape for each
- Judge performance by counted work: strictness choices, collection choices, and string building
- Finish a log analyzer that writes, reads, and summarizes a log file in one program
- Finish a task tracker that runs fixed commands through a state transformer and prints the final list
Who this Haskell course is for
This course assumes the beginner course, or the equivalent: you can already write bindings and functions, match patterns, recurse over lists, read type signatures, and use do notation for simple IO. If Maybe and Either still feel new, start with the beginner course and return; nothing here re-teaches that ground.
Programmers arriving from other languages often meet Haskell through map and filter, then stall at the question of what a monad is. This course answers that question by construction: functors first, applicatives second, monads third, each one a small, verified step past the previous. No category theory background is needed at any point.
Expect two hours and forty-three minutes of lesson time in total. The groups build on each other, so reading in order matters more here than in the beginner course; skipping ahead to transformers before monads will cost you the thread.
How this course works
Order is the pedagogy. Functors come before applicatives because apply generalizes map; applicatives come before monads because bind generalizes apply; transformers come after monads because a transformer is a monad with an extra effect bolted on. Laziness lands after transformers, once you have enough machinery for strictness to matter.
Every example was compiled and run twice with GHC 9.10.3, and the stated output is the output the compiler produced. That matters more at this level than at the beginner level: a transformer stack that typechecks but runs in the wrong layer order is a subtle bug, and the lessons show both the right order and the result it prints.
Each lesson ends with an exercise, and each answer carries a reasoned explanation. Several exercises ask you to predict an output before reading on, which is the fastest way to find out whether an abstraction has actually landed.
Progress is stored in your own browser, so you can leave mid-group and resume later without an account. There is no charge for any lesson, project, or explained exercise answer.
Frequently asked questions
Do I need Haskell Beginner before this course?
In practice, yes. This course assumes bindings, functions, pattern matching, recursion, lists, type signatures, Maybe and Either at first sight, do notation, and modules. The beginner course covers exactly that ground, and this course builds on it from lesson one.
What is a monad, in plain terms?
A monad is a typeclass for chaining steps where each step produces a wrapped value. Bind feeds a wrapped value into a function that returns a wrapped value; Maybe is the clearest case, where a Nothing anywhere short-circuits the chain. Do notation is the readable spelling of the same chain.
How do Functor, Applicative, and Monad differ?
They form a ladder of power. A functor maps one plain function inside a wrapper. An applicative applies a wrapped function to wrapped arguments. A monad chains steps where each later step can inspect earlier results. Each rung can do everything below it, plus one new thing.
Are monad transformers as hard as they sound?
They are gentler than their reputation. ReaderT adds one shared read-only value, StateT adds one changeable value, and lift runs an action from the layer below. The stack lesson peels a ReaderT over StateT over IO in order and prints both the result and the final state.
Why does laziness get its own group?
Because Haskell computes only on demand, and that changes how programs behave. Thunks explain why an unused division by zero never crashes, infinite lists explain why take is safe, and seq, strict folds, and strict fields explain how to stop unevaluated work from piling up.
How long does the Haskell intermediate course take?
Lesson times total 163 minutes. The monad and transformer groups repay a second reading, so plan on more than one pass through those.
What can I build after this course?
Trustworthy command-line tools with a pure core and IO at the edges. The log analyzer and task tracker projects show the pattern end to end: read input, compute purely, print a summary.
Next steps
- Haskell Beginner ❯ — The level before this one: bindings, functions, pattern matching, lists, types, Maybe and Either, IO and modules — the ground this course stands on.
- Scala Intermediate ❯ — Scala intermediate step: type bounds, context parameters, extractors, asynchronous Futures, and safe resource handling, in a second typed functional language.