So how often do you actually think about the invisible architecture of the Internet when you do something really simple, like say a Google search.
I mean probably never, right, You just want your answer right exactly.
You type in a query, hit enter, and boom, billions of records are just sifted through to hand you a result in literally milliseconds. We treat it like magic.
Oh absolutely, But you know, peaking under the hood reveals something entirely unexpected.
Yeah, you won't just find like miles of fiber optic cables or massive server farms. You actually find this intense, unresolved mathematical debate from the nineteen.
Thirties and the remnants of a totally failed nineteen eighties software revolution.
Too, which is wild and well. It all points to a completely alien philosophy regarding how computers should solve problems in the first place.
It really is a fundamental shift in logic. I mean, anybody who has written even a few lines of say Python or JavaScript, they intuitively understand computers as machines that just follow sequential instructions.
Like step one, do this, step two, check that.
Exactly, step three, update this counter. But there is an entire parallel universe of programming that completely abandons that step by step logic, basically rips the clock out of the computer entirely.
And we are dissecting that universe today through our deep dive into Greg Michaelson's book An Introduction to Functional Programming through Lambda.
Calculus, a fantastic albeit heavy.
Read, oh definitely heavy. We're specifically looking at his foundational chapters and that rather candid twenty eleven Prephecy wrote, and you know, the objective here isn't just to learn a new coding language.
No, no, it's way bigger than that, right.
It's to understand what functional programming actually is mechanically, like, why this incredibly dense, seventy five year old math concept breaks our standard rules of computing, and.
How it quietly became the load bearing pillar for the biggest distributed systems on the planet.
So to appreciate this functional approach, we really have to isolate the underlying flaw in how we normally write software.
Yeah, we do so. The most commercial code is written in what we call imperative languages. So thinks ce Java, Python, usual suspects, right, and they are built on this concept of mutating state. You issue an imperative command to change the value of a.
Variable, like giving the computer in order.
Exactly, you tell the system, hey, X is currently five, but now I command you to make x equal to.
Six, which I mean that seems entirely logical to me. We are commanding the machine to update its memory.
It does seem logical, well, until you try to do a million things at once.
Aw the scale issue.
Right. Because imperative programming is entirely reliant on state mutation, it creates this terrifying vulnerability known as a side effect.
Okay, let's unpack this. Yeah, what exactly does a side effect look like in action?
Well, imagine you have a variable tracking a user's bank balance, okay, and thread A is reading that balance to display it on a screen for you. But at that exact millisecond, thread B in the background mutates that variable to process a subscription fee.
Oh wow, so thread A suddenly grabs the wrong number.
Exactly. In an imperative program the state is the shared, constantly shifting battleground. Anyone can change it, so.
It's basically like a chalkboard where you keep erasing and rewriting a running tally, and if someone erases it while you're looking away, you're messed up.
That is a perfect analogy.
Yes, so functional programming then basically removes the.
Eraser precisely, it takes the eraser completely out of the equation.
In this paradigm, a variable isn't a storage container you can just overwrite. It's more like a prominent mathematical binding. It's like carving a number into a stone tablet.
I like that carved in stone. So once X is tied to the value of five, it is five forever.
And if you want a new state, like if the bank balance changes.
You don't mutate X. You have to evaluate a completely new expression that outputs a new value. You carve a new tablet.
So you never actually change the data.
Nope, you only pass it through functions to create new data.
But how does that actually help with the bank balance problem.
Well, that permanent binding changes the literal physics of the software. Because you never erase or mutate anything. You completely eliminate those side effects we talked about.
Oh, because nothing can sneak in and change the data behind your back exactly.
A function in this world is mathematically pure. It receives an input, does its calculation, and returns an output.
It's totally isolated.
Right, it's a hermetically sealed unit of logic. It cannot secretly reach outside of itself and mess with a global counter or access a database in the background.
Okay, hold on, I understand the security of a hermetically sealed function. But and here's the catch. In a physical machine, things physically have to happen one after another in.
Our standard view of time.
Yes, right, If I write a program in an imperative language, the order of my commands is life. Rather, if I swap lines of code, the program.
Just crashes because line three depends on the mutated state created by line two exactly.
Sequence dictates.
Well, that's the imperative prison. Right. You are basically chained to time. But because functional programming prohibits mutation entirely, time loses its authority over the code. Wait really, yeah, execution order simply ceases to matter.
That sounds physically impossible. How can a machine process logic without a sequence. Doesn't the program need to know what to execute first to feed into the next step.
It relies on this really elegant mathematical principle called the Church Rosser theorem. Okay, way on me, Let's look at a basic arithmetic expression, say two plus three in parentheses multiplied by four plus five in parentheses.
Right.
Because these are pure values with no hidden side effects, it genuinely does not matter if you calculate the two plus three first or if you calculate the four plus five.
First, because they don't impact each other.
Exactly, you will arrive at forty five either way.
Okay, that makes sense in a small scale.
Well, the church Rosso theorem mathematically proves that if a functional program terminates, it will yield the exact same final result regardless of the order in which its sub expressions are evaluated.
Ah So, because the functions are pure, they just don't care who finishes first. They aren't waiting on some global variable to change somewhere else.
What's fascinating here is what happens when you scale that concept up. You suddenly see why massive tech companies like Google and Amazon care deeply about this.
Oh, because if execution order doesn't matter, you aren't limited to running your program on just one processor exactly.
You can take a massive functional program, shatter it into a million independent pieces, and farm those pieces out to tens of thousands of cheap servers simultaneously.
That is incredible, and Michaelson actually notes this in his twenty eleven preface right that Google's map produce framework is built directly on these concepts.
He does, map reduce is the engine that made their search indexing so incredibly fast.
How does that actually map to functional programming? Though?
So the map function processes data independently across thousands of machines without any shared state, and then the reduced function aggregates all those pure outputs.
So there are no locks, no race conditions, no side effects, none.
It's perfectly parallel.
Okay, I see how that enables massive parallel processing for a tech giant. But let me challenge the everyday utility of this for a second.
Go for it.
If I have no sequence and I'm not allowed to mutate a variable, how do I actually do something repetitive? How do I iterate?
Give me an example?
Okay, say I want to search through a list of a million log files to find one specific error code. In normal imperative code, I write a standard for loop. I use a counter variable what's called I, and I mutate I from one to a million, checking the list each time.
The classic approach.
Sure, right, So how do you loop without a counter.
Well you don't. You don't use loops at all.
Wait what no loops?
No loops. Loops inherently require state mutation. You have to update that counter instead. Functional programming relies on recursion.
Okay, recursion, how does that work? In this context?
You have a function that processes the very first item in the list, just the first one. If it's not the error code you're looking for. The function calls a brand new, pristine copy of itself. Oh, I see it, and it passes the remainder of the list to that new copy.
Okay, let me make sure I'm visualizing this right. So instead of one runner running a million laps and checking a stopwatch every time, you basically have a relay race with a million distinct runners.
Yes, that's a great way to put it.
Each runner only runs one step, looks at the data, and passes the baton to a totally new clone of themselves.
That's a very solid way to visualize it. Every recursive call creates a completely fresh execution context. You never change the original list.
You just keep peeling off the first element and passing the rest for.
Us exactly, and this forces a radically different approach to data structures as a whole because there's no assignment. There are no arrays where you can just tweak element number four.
Right, because you can't mutate it.
You have to explicitly pass entire nested structures through these recursive chains, and you rely heavily on abstraction to keep the logic clean.
Which brings us to chapter two. Michaelson dedicates that whole chapter to the concept of abstraction, and it seems really pivotal here.
It is without abstraction, this whole system collapses under its own weight.
Because abstraction isn't just about hiding complexity, right, It's about shifting from concrete values to generalized rules exactly.
Michaelson gives a great simple example. If you are calculating the cost of a shopping cart. You don't hard code nine items times ten cents.
You introduce names like quantity in price, right.
You abstract the specific operation into a general, pure rule.
Here's where it gets really interesting, though. Functional programming takes this a step further. It doesn't just abstract data, it abstracts the operations themselves.
Yes, functions are tree as first class citizens.
Which sounds fancy, but what does it actually mean.
In practice, it means functions are treated exactly like data. You can pass a function into another function as.
An argument, like passing a number.
Exactly the same. You can even write a function whose only job is to dynamically construct and spit out an entirely new function based on the input it received.
That is wild. You are manipulating logic the exact same way you manipulate integers.
It is a total paradigm shift.
And the ultimate expression of that is Lisp right list processing. I know it's one of the earliest languages to adopt these concepts.
Oh LSP is legendary for this because.
In LASP, the syntax you write to create the program is literally just a nested list itself.
Right, So the command add two three is mathematically the same fundamental data structure as a list of groceries like Apple's milk bread.
The code is data and the data is code. I think the technical term is homo econicity.
Homo econicity. Yes, it's a bit of a mouthful, but it basically it means an Lisp program can effortlessly read, rewrite, and generate other Lisp programs.
On the fly, mind bending.
It creates this incredible fluidity. Imperative languages which strictly separate the compiled instructions from the memory heap, they simply cannot mimic that.
But you know what makes this so compelling isn't just the architecture itself. It's the origin story.
Oh, the history is fascinating.
Right, because this entirely alien way of structuring computation was not invented by some modern computer scientists trying to optimize cloud networkloads.
Not at all. It's way older than that.
It was born from a profound philosophical crisis among mathematicians in the nineteen thirties.
We really have to rewind the tape to understand this. Long before silicon ships even existed, mathematicians were obsessed with a seemingly.
Simple question, is math unbreakable?
Exactly? Is it perfect? So in the nineteen twenties, the German mathematician David Hilbert proposed what became known as Hilbert's program.
Okay, what was his goal?
He wanted to formally prove that mathematics was both consistent and complete.
Those words probably have very strict definitions in this context.
Very strict consistent means you can never use the rules of math to prove a contradiction like you can't logically prove that one equals two.
That makes sense and complete.
Complete means that every single true mathematical statement has a definitive proof that can be derived from the foundational axioms.
So no mysteries, everything can be proven right.
Hilbert wanted to build a perfect mechanized system of logic where literally any problem could eventually be solved just by turning the crank of mathematical rules.
A beautiful dream, and then Kirk Godel totally shattered that dream in nineteen thirty one.
He utterly obliterated it with his incompleteness theorems how did you do it? Godel realized that if a formal system is complex enough to handle basic arithmetic, it can actually be made to talk about itself.
Okay, this is getting a bit meta.
It is. He developed this brilliant technique called Godal numbering, where he assigned a unie nique numerical code to every mathematical symbol and operation.
So he basically turned mathematical equations into a kind of programming language that could output statements about its own code.
Yes, and using that he encoded a mathematical statement that translated essentially to this statement cannot be proven.
Oh wow. It's a classic liar's.
Paradox, but weaponized against arithmetic itself. Think about it. If the statement is false, it means it can be proven, which means math just proved a falsehood, making the entire field of mathematics inconsistent.
And if the statement is true.
If the statement is true, it means there is a true mathematical fact that lacks a proof, meaning mathematics is fundamentally incomplete.
Wow. So there are true things we can never mathematically prove exactly.
It's a devastating realization for mathematicians.
I can imagine. Yeah, but the ashes of Hilbert's program triggered this incredible race, didn't.
It It did. If math has limits, mathematicians urgently needed to define exactly what could be computed, Like what are.
The strict boundaries of mechanical calculation?
Right? And in nineteen thirty six, two brilliant thinkers published two completely different road maps for computability.
This is where the timeline of human technology literally splits.
It really does. On one side, you have Alan Turing. Turing defined computability using a theoretical.
Machine, the famous Turing machine.
Right picture an infinite tape divided into squares with a read right head, moving left and right, erasing and rewriting symbols one step at a time based on a set of rules.
And that tape inherently implies sequence. It moves forward, it moves backward, It updates the state of the squares during basically formalized the imperative model we talked about earlier. Do this change that?
Move here exactly. And on the other side of this you have Alonzo Church, who is actually Turing's doctoral advisor.
Oh really, I didn't know that.
Yeah, and Church didn't care about tapes or machines or sequence. He created lambda calculus.
Which is the foundation of functional programming.
Yes, it is a formal system based entirely on stateless function, abstraction and variable substitution. No tape, no time, no mutation, just.
Pure expressions evaluating other expressions.
If we connect this to the bigger picture, the ultimate plot twist here is Church's thesis. Turing and Church actually prove that their completely divergent systems were mathematically equivalent.
Wait, really, the tape and the stateless equations are the same.
Yes, anything you can compute on Turing's sequential tape, you can compute using Church's timeless lambda equations. They defined the exact same universe of computability. They were just speaking two completely different dialects.
But those dialects had massive real world implications.
Huge implications Turing's model maps beautifully onto physical.
Reality because a read write head moving along a tape is conceptually identical to an electrical switch turning on and off to update a memory register exactly.
So when engineers built the first digital computers, they basically built physical Turing machines, and.
So imperative programming languages like Fortran and c were designed to orchestrate those physical state changes.
While Church's lambda calculus, despite being mathematically pure and beautiful, was just too abstract for early hardware. It got relegated to academia.
Well until the nineteen eighties.
Anyway, Right the eighties changed things.
Michaelson's twenty eleven preface spends a lot of time dissecting this massive resurgence of functional programming during that era.
What happened the tech industry hit a wall. It was widely known as the software crisis.
Because of the side effects. We talked about.
Exactly, because imperative programs rely on mutating shared state. As programs grew larger and larger, the side effects became impossible for humans to manage.
I'm guessing bugs were just multiplying exponentially. Code was crashing left and right.
There was a genuine panic in the industry. The Japanese government actually launched the Fifth Generation Computing Initiative, aiming to build machines that ran entirely on pure.
Logic, and the UK responded to that right they did.
The ALVI program. They heavily funded functional languages like Hope, mL and eventually Haskell.
Because a pitch was incredibly alluring. Just abandoned imperative state, adopt Church's timeless mathematics, and your code will be theoretically bug free and mathematically provable.
It was touted as a total silver bullet.
So what does this all mean? If it was mathematically superior, why did it fail to take over the industry, Why did messy imperative languages like C plus plus and Java end up winning the war?
Well, Michael Sola is refreshingly honest about this in his preface. Pure declarative and functional languages were basically overhyped because they ignored the fundamental nature of reality, meaning what exactly, meaning the physical world is inherently stateful. Time exists, oh or right, when a human interacts with a computer, clicking a button, typing a word, saving a file to a hard drive, those are sequential events. They literally mutate the state of the world.
Ah. If pure functional programming doesn't allow side of it effects or state changes, how do you even update a database or draw a pixel on a screen?
You see the problem. It becomes incredibly cumbersome. You have to invent these hugely complex mathematical workarounds, things called monads, just to allow a pure function to interact with the messy, time bound reality of a user interface.
So pure functional programming is brilliant beyond time, but it is deeply awkward when forced to operate within time.
That's a great summary. Therefore, imperative languages maintain their dominance for writing operating systems, desktop applications, and user interfaces.
But the narrative doesn't just end in the eighties, obviously, since we're still talking about it today.
No, it doesn't, because the Internet changed the scale of software completely.
Right. We move from desktop apps running on a single CPU to these distributed cloud systems running across ten thousand nodes, and.
Suddenly we hit the limits of Turing's tape all over.
Again, because when you have a million users hitting at database simultaneously, imperative state mutation becomes your biggest bottleneck.
Exactly, you spend all your processing power just trying to lock variables so that all those different threads don't overwrite each other, like try and keep.
A million people from erasing that jockboard at the same time.
Yes, and to solve this, the industry quietly surrendered to Alonzo Church.
Which is amazing. We see it everywhere now. Telcom giants use erlang, which is a deeply functional language to manage millions of concurrent phone calls without crashing.
Yep. Microsoft baked f sharb into their entire enterprise framework.
And even the biggest imperative heavyweights like Python, c Sharp, Java, they have aggressively adopted functional features over the years.
They absolutely had to. They absorbed lambda expressions, higher order functions, and map produce paradigms specifically to handle parallel processing safely.
So it's really a hybrid reality now very much so.
We use Turing's sequential state mutating logic for the boundaries of our applications, you know the UI, the direct database rights the things humans physically touched.
But for the massive concurrent data crunching core, we rely on Church's stateless pure functions.
It's the best of both worlds.
Well, we've covered a staggering amount of theory today. We really have We impact how the simple act of forbidding a variable to change, basically banning the eraser on the chalkboard, completely eliminates side effects.
And we examine how the Church Rosser theorem proves that pure functions don't care about execution order at all, which opened the door for massive parallel computing.
We trace those origins all the way back to the shattering of Hilbert's program by Kurt Guttle, which led to the defining computability race between Turing's physical tape and Church's mathematical lamb to calculus.
And then we looked at how the nineteen eighties failed to force a purely stateless model onto a very stateful world, leading to today's pragmatic hybrid architecture that we use every day.
It really leaves a fascinating philosophical.
Questions on the table I know where you're going with this.
Right, Because we default to imperative coding because it mirrors our day to day sequential experience of time. We do this, then we do that.
It feels natural to us.
But if lambda calculus is actually a cleaner, more mathematically pure way to process complex logic across a massive network, how does our own neural network operate?
This raises an important question. Are our brains imperative machines constantly overwriting localized memory states as we experience time step by step?
Or is human cognition actually a functional web evaluating infinitely nested concepts in parallel, completely independent a sequence. Have a great time mulling that over
