Haskell World logo Haskell WorldWrite code, build worlds
Games

What Conway's Game of Life Teaches About Pure Functions

Conway's Game of Life is barely a game in the usual sense. You set up a grid of living and dead cells, press start, and watch it evolve under four tiny rules with no further input from you.

A grid of black and white cells from Conway's Game of Life mid-generation

Conway's Game of Life is barely a game in the usual sense. You set up a grid of living and dead cells, press start, and watch it evolve under four tiny rules with no further input from you. Online versions run it in a browser tab with a single click. I keep coming back to it when teaching functional programming, because beneath the hypnotic patterns sits one of the cleanest demonstrations of a pure function and immutable state that I have ever found. The whole universe of Life is a single function applied over and over, and seeing that makes an abstract idea click.

One function, applied forever

Every generation in Life is produced by applying the same rule to the current grid to get the next grid. There is no hidden memory, no accumulated side effect, no state squirreled away between steps. Give the function a grid and it returns a new grid, and the same grid in always yields the same grid out. That is the textbook definition of a pure function, running in front of you at thirty frames a second. The entire evolving spectacle is nothing more than one honest transformation, repeated, and naming that out loud turns a screensaver into a lesson.

The next grid is new, not edited

A beginner reaching for Life usually mutates the grid in place, flipping cells as they go, and promptly gets wrong answers. The reason is that each cell's fate depends on its neighbours in the current generation, so changing a cell before you have read all of its neighbours corrupts the calculation. The correct approach builds a brand new grid from the old one and never touches the original mid-pass. That is immutability enforced by the problem itself. Life refuses to work unless you treat the current state as read-only, which is the exact discipline functional code asks of you everywhere.

Four rules with no exceptions

The transition rules are total: every cell, in every situation, has a defined outcome based solely on its live neighbour count. There is no undefined case, no special exception, no cell that behaves differently because of history. A pure function aspires to the same completeness, handling every input without reaching outside itself for an answer. Life models that cleanly because the rules cover the whole space of possibilities with four short clauses. Writing the transition as a single expression over neighbour count, rather than a tangle of special cases, is where the functional style and the game meet most obviously.

Referential transparency you can watch

Because the step function is pure, you can replace any generation with a cached copy and the future unfolds identically. Run the same starting pattern twice and you get the same sequence every time, down to the last cell. That property, that an expression can be swapped for its value with no change in behaviour, is referential transparency, and Life lets you see it rather than merely trust it. The determinism is not a coincidence of the game, it is a direct consequence of the step being a pure function, and the two ideas illuminate each other beautifully.

Separating the rule from the clock

A clean Life implementation splits the pure transition from the impure business of looping, drawing, and reading the clock. The function that computes the next grid knows nothing about time or the screen. Something outside it handles the ticking and the rendering. That separation, a pure core wrapped in a thin shell of effects, is the shape of almost every well-structured functional program. Life makes the division concrete: the rule is pure and testable, the animation loop is where the messy outside world lives, and keeping them apart is what keeps the core honest.

Testing a world without running it

Because the step is a pure function, you can test it exhaustively without ever animating anything. Feed it a known pattern, assert the exact next grid, and you have verified the whole engine. A glider should move one step diagonally after four generations, and a pure function lets you check that as a plain equality, no screen required. This is the payoff of purity that beginners underestimate. The hardest-looking part of the program, the evolving universe, becomes the easiest to test, precisely because it is a function from grid to grid and nothing more.

Why I keep teaching with it

Conway's Game of Life earns its place in a functional programming lesson because it makes the central ideas visible. A pure step, immutable generations, total rules, determinism you can watch, a pure core split from an effectful shell, and exhaustive tests that need no animation. Students who struggle with these ideas in the abstract grasp them in an afternoon of watching gliders. The game is old, tiny, and endlessly instructive, and an online version is one click away, which makes it the most convenient teacher of pure functions I know.

Frequently asked questions

Is Conway's Game of Life actually a game? Not in the interactive sense, since you only set the initial cells and then watch. It is a cellular automaton, a system that evolves on its own under fixed rules. The name stuck because of the lifelike patterns that emerge, and online versions let you place cells and run it, which is close enough to play for the comparison to hold.

Why must I build a new grid instead of editing the old one? Because each cell's next state depends on its neighbours in the current generation. If you flip a cell in place, the neighbouring cells you read afterward see the changed value and compute the wrong result. Building a fresh grid from the untouched original preserves correctness, which is immutability enforced by the problem rather than by a language rule.

How does purity make the engine easier to test? A pure step function depends only on its input grid, so you can feed it a known pattern and assert the exact output without animating or involving the screen. Determinism guarantees the same result every time, which means a single equality check verifies the whole transition. The part that looks hardest to test becomes the easiest, precisely because it has no hidden state.

A universe in one function

Conway's Game of Life is a living lesson in pure functions and immutable state. Each generation is one honest transformation of a read-only grid, the rules are total, the outcome is deterministic, and the pure core sits cleanly apart from the drawing loop. Run it online, watch a glider, and the ideas that resist explanation in prose simply become obvious on screen.

FB
Finnian Burke

Finnian Burke spent eight years building distributed systems before leaving to write about the programming patterns that actually hold up under pressure. He has worked with Haskell, Rust, and Go in production, and writes mostly about the parts of functional programming that turn out to be useful regardless of the language you use day to day.

More posts by Finnian

More in Games

01doorganico 084goad 3hot8 4465456 after5internprogram ahandfulofblessings ahmadpc ahomcybersecurity allodialresources annodex antiquesandperiodcollectibles aotc asianworldkashmir beedlectrics bloggertemplatefree bluefeatheragency bodyweightsolution campaign08blog carfixadvisor catstreetcollective cbstvsports cnfanspurchasing committeeof500yearsofdignityandresistance covertopsdjs cs-kaiyuangame cuestacomunicaciontotal cxoutlet dancebetgame deskgearhub destinyvillastay detectmagazine di33 diamondsteelbuildings donmo dyanadropship emarsysfinance emimattl escapechan eskitarih evautoplay everythingweddings-orlando farmzone feedviewerapp foxstudiosscratch gamevui123 gleasongrade greetingsday hacklabasu iw-kaiyun jagoanproperti jilidskripsi joltbusinessfinance juegodepokergratis juegospucca kaeru-festival latestmehndidesigns lestanzediottaviano litemagazines localcommunityhero lustrsazan mariashebets menswheels newwebstechs1 nikkit ootheday oxigenvpn plurfitness prefetial probudgetcarpetcleaning psychicmrsmartin pyaten qvantor rejoignezlogis rexzbot riselayouts ruchin rwxqsgd5 sakaltime shibiaowang shop-bot skrtips strcoding tetapatrium topselller uneplanteartificielle vipertechcr webtech1223411 wo-kygaming yamaha-mekar yeknava yoybuysheets zenunwa yamaha-mekar jilidskripsi ankertoto ankertoto ankertoto ankertoto