Chapter 1 said "a category is things and arrows." Now we say exactly which things and which arrows the programmer cares about — and meet the three tiniest types that do most of the heavy lifting.
Last chapter we built the stage: objects and arrows. We waved at the idea that "in programming, objects look like types and arrows look like functions." This chapter we stop waving.
We're going to nail down which functions actually count as arrows (spoiler: not all of them), and then we'll meet three tiny types whose entire job is to teach us something deep about uniqueness — that some arrows write themselves.
A function is pure if it gives the same output for the same input and does nothing else. That's it. Same in, same out, no surprises on the side.
Math people have a fancier name — referential transparency — but it just means: you can replace the call with its result and your program still does the same thing. square(3) is interchangeable with 9, anywhere, forever.
Why do we care for category theory? Because the laws from Chapter 1 quietly assume this. "g ∘ f equals the function you get by running f then g" only makes sense if running them produces an answer determined by the input alone. The moment a function reads a clock or writes to disk, the equation breaks — the two sides might differ depending on when you run them, or what else has happened.
So the category programmers actually live in has:
Int, String, List[User], …)You'll hear it called Hask in Haskell circles, or just "types and total pure functions." For everything in this chapter, that's our world.
IO bolted onto its return type, so the compiler keeps it visible. Either way, the "honest arrows" of our category are the pure ones.Numbers have tiny building blocks — 0, 1, 2 — that show up everywhere. Types have three that play the same role. They look almost too small to matter, but they're the seeds the whole "algebra of types" grows from.
Nothing; in Haskell it's Void (from Data.Void).(). The room with one chair. Once you know the room, you know who's in it. In Scala this is Unit; in Haskell it's () (yes, also written like that).true and false. Two chairs.The number of values a type has is its cardinality. Here they are, side by side:
Bool → Bool has 4 possibilities (one output choice for each of 2 inputs: 2² = 4). A function Bool → Unit has just 1. This counting game IS the algebra of types, and we'll lean on it again next chapter.Here's where it gets surprising. Unit and Void each force the existence of exactly one arrow for every other type — no choice, no freedom, the type signature alone determines the function.
UnitPick any type A. How many pure functions A → Unit are there? Well, the output has to be a value of Unit, and there's only one such value: (). So whatever the input, the function returns (). There's only one way to throw all the information away.
Try it: click any of the inputs below. They all land in the same place.
VoidNow flip it. How many pure functions Void → A are there? Sounds absurd — how do you write a function whose input has no possible value?
Here's the trick: you don't have to. The function exists as a type signature, and the type checker is happy, because you'll never be called on to actually produce an A — there's no Void to feed in. It's an arrow you can write, never call, and that's fine. There's only one such arrow per target type (since there are no inputs to disagree about), and it has a name: absurd.
Think of it like this: if you ever did have a Void in your hands, you could conjure anything from it — including a contradiction. You never will, so the function is safe.
Unit is the place everything uniquely flows into — the math name is terminal object. Void is the place everything uniquely flows out of — the math name is initial object. You don't need the names yet. You just need to feel that "exactly one arrow" pattern. We'll come back to it.Two languages, same ideas. Scala calls Void Nothing (it's the bottom of Scala's type hierarchy, which is why it cleanly stands in for "no values"). Haskell needs to import Void from Data.Void. Beyond that, the shapes line up.