A father's experiment teaching his six-year-old free theorems exposes something surprising about how we learn (and fail to learn) functional programming concepts, regardless of age.

Brent Yorgey, an Associate Professor of Computer Science at Hendrix College, recently shared a conversation with his six-year-old son that started with a simple question: "What are you reading?" The answer turned into an impromptu lesson on free theorems, function types, and eventually, a game that has become a family staple.
The conversation, posted on his blog, begins with Brent explaining functions as machines: put something in one end, something comes out the other. His son catches on quickly, even jumping ahead to the idea of functions that take other functions as inputs. But the real insight comes later, when they start playing the "function machine game" together.
The game is straightforward. One player thinks of a function. The other guesses inputs and observes outputs, then tries to reverse-engineer what the function does. It is, essentially, black-box testing with a playful twist. Brent's son guessed functions like double, add2, and the slightly trickier square. But one function stumped him: constant functions, where the output stays the same no matter what input you provide.
That stumped moment is the story's most revealing detail. Brent notes that many students in his functional programming class at Hendrix College also struggled with constant functions during their lambda calculus unit. They expected the input to appear somewhere in the output. The idea that a function could simply ignore its input felt wrong, almost like a cheat.
This pattern suggests something interesting about how humans reason about computation. We are wired to expect causality. Input causes output. If the output does not change, we assume we have done something wrong, or that the function is broken. The concept of a constant function is technically trivial. It is a single line in most languages. But cognitively, it requires accepting that a function can exist without transformation, that doing nothing is still doing something.
Brent's son eventually did guess the constant function correctly. And he went further, creating his own functions for his father to guess. One was inspired by his kindergarten lesson on pairs of numbers that add up to ten, a function that takes a number and returns its complement to ten. A four-year-old might call this "making ten." A Haskell programmer would recognize it as partial application waiting to happen.
The post also touches on Brent's attempt to explain free theorems, a concept from polymorphic type theory. He got as far as defining a function machine and its type before his son's attention moved on. Free theorems are, as Brent admits, "only interesting when polymorphism is involved," which makes them a tough sell for a kindergartener. But the fact that Brent even tried says something about the instinct to share ideas you find beautiful, regardless of whether the audience is ready.
This story lands in an interesting cultural moment. Functional programming has moved from academic curiosity to mainstream practice. Languages like Rust, Elixir, and even modern JavaScript borrow heavily from functional concepts. The community has spent years arguing about whether functional programming is too hard for beginners, or whether it is actually simpler once you remove the mental overhead of mutable state.
Brent's experiment suggests a third possibility. The core ideas are not inherently difficult. They are just unfamiliar. A six-year-old can grasp the concept of a function as a machine. He can play a game based on input-output relationships. What he cannot do yet is accept that some functions break his intuitive expectations about how inputs and outputs should relate. And that, arguably, is the same障碍 that trips up adult learners.
There is a counter-argument here worth considering. Teaching a six-year-old to guess functions is not the same as teaching him to write code. Brent's son is playing a pattern-recognition game. He is not reasoning about side effects, data structures, or concurrency. The jump from "function machine game" to writing actual Haskell is enormous. Some would argue that oversimplifying functional programming for children (or beginners) risks creating a false sense of mastery that collapses when you encounter real complexity.
That critique has merit, but it misses the deeper point. The game is not about mastery. It is about building intuition. Brent's son is learning that functions are things with predictable behavior, that types describe what a function can accept and produce, that some functions surprise you. These are foundational ideas. The fact that they can be taught through play, without a computer, without syntax, without error messages, suggests that our approach to teaching programming might be too focused on tools and not enough on concepts.
Brent's post is a small, personal story. It is not a manifesto for a new educational philosophy. But it is a reminder that the hardest parts of functional programming are not the monads or the type classes. They are the moments where your intuition says one thing and the code says another. If a six-year-old can learn to trust the machine over his intuition, perhaps there is hope for the rest of us.

Comments
Please log in or register to join the discussion