Haskell becomes easier to understand when its syntax, types, and evaluation rules are introduced together. This series starts with ordinary expressions and functions, then builds toward type classes, monads, and programs that interact with the outside world.
The main posts follow the tutorial one block at a time. No background in functional programming or category theory is assumed. Each main post includes worked examples and exercises; read them in order, and try the examples in GHCi as you go. A companion article after Part 8 explores mapping with multiple type parameters.
The series
| Part | Post | What you will learn |
|---|---|---|
| 1 | Expressions and functions | Expressions, definitions, function application, substitution, and a first GHCi session. |
| 2 | Types and type inference | Function types, currying, polymorphism, inference, and numeric constraints. |
| 3 | Conditionals, local bindings, and guards | Choosing values with if, introducing names with let and where, and writing guarded equations. |
| 4 | Lists, pattern matching, and recursion | Building and decomposing lists, recursive functions, comprehensions, and infinite lists. |
| 5 | Algebraic data types | Sum and product types, Maybe, Either, trees, records, and expression evaluators. |
| 6 | Higher-order functions and composition | Lambdas, partial application, map, filter, folds, operators, and composition. |
| 7 | Type classes and dictionary passing | Overloaded operations, instances, constraints, deriving, and dictionaries of method implementations. |
| 8 | Functors and the laws of mapping | Type constructors, kinds, fmap, standard instances, and the identity and composition laws. |
| 8 supplement | Functors with multiple type parameters | Fixing type parameters, specializing fmap, and using Bifunctor to map two parameters independently. |
| 9 | Applicative functors and monads | Applying contextual functions, sequencing dependent computations, do notation, join, and the laws. |
| 10 | IO and real Haskell programs | IO action values, main, input parsing, sequencing, file access, and separating pure code from effects. |
How to work through the examples
Keep a source file open beside a GHCi session. Put complete definitions in the source file, load it with :load, and enter expressions at the prompt. Use :type to ask GHCi for an expression’s type, and :reload after editing the file.
ghci> :load Lesson.hs
ghci> :type square
ghci> square 5
ghci> :reloadExamples within different sections are often independent: a later section may redefine a name or introduce a different version of a data type. Try those examples separately instead of pasting every code block into one module. Code marked as an error is there to explain a boundary of the language, rather than to be included in a working program.
Attempt the exercises before opening their solutions. When a result surprises you, distinguish three questions: how the expression is parsed, what type it has, and how it evaluates.
For a local Haskell environment, see the official GHCup installation guide. The GHCi manual explains the interactive commands, and the Haskell 2010 Language Report provides a formal reference for the language introduced here.
Source
The first eight posts adapt a GPT-generated Haskell tutorial into standalone articles. Later posts and the Part 8 supplement use additional tutorial material supplied by the author. The expanded explanation of dictionary passing is incorporated into Part 7. Chat-specific diagrams and exercise widgets have been converted into Markdown, tables, and worked solutions.