Curry–Howard Correspondence


The Curry–Howard correspondence (also known as the Curry–Howard isomorphism) is a profound insight that draws a bridge between logic and computation. It establishes a direct correspondence between:

In essence:

“A proof is a program, and a proposition is a type.”


The Core Idea

Curry–Howard reveals a beautiful symmetry:

Programming (Lambda Calculus) Logic (Intuitionistic)
Types in λ→ Formulas in Intuitionistic Logic
Terms (λ-terms / programs) Proofs of those formulas
The correspondence says:

Every type in lambda calculus is a logical proposition,
and every well-typed term is a proof of that proposition.


Examples

λx.x:αα

This is the identity function in lambda calculus, and it corresponds to the logical tautology:

“If α is true, then α is true.”
In logic: αα

✅ This expression is always valid—a tautology.
📌 In programming: the identity function is always safe to use.
📌 In logic: this is always provable.

🧠 Every combinator (no free variables, empty context) in lambda calculus is a tautology in logic.

Why?

I combinator (λx.x)

K combinator (λx.λy.x)

S combinator (λf.λg.λx. f x (g x))


Intuitionistic Logic Calculus and Proof Rules

Let’s explore how logic operates from a syntactic viewpoint, using sequent calculus—a way to formally derive logical statements. The whiteboard and the transcript you're working from outline the basic rules of implication in intuitionistic (constructive) logic, focusing on how implications are introduced, applied, and reasoned with.


Suppose you have a collection of assumptions (sequentions) like:

α1,α2,,αn

These are your axioms, or known truths (called a context, often denoted as Γ). You then derive some new conclusion, say:

Γβ

This means:

“From assumptions Γ, I can prove β.”

But here's a catch!

If your assumptions are contradictory (e.g., α and ¬α), you can “prove” anything—even nonsense. That’s a broken theory.

💥 So it’s your responsibility to make sure your list of assumptions is sound and consistent.


Some Rules of Implication-Only Logic

We’re working with a fragment of logic that deals only with implications (). This system is called implicational logic, a part of intuitionistic logic (aka constructive logic).

Let’s build our logic system using three core rules:


Rule 1: Axiom (Identity Rule)

If something is assumed, you can use it.

Γ,αα

This simply says:

“If α is in your context, then α is provable.”

✅ This is your starting point in any logical derivation.


Rule 2: Modus Ponens (Application Rule)

If you know that αβ is true, and α is true,
then you can conclude β.

ΓαβΓαΓβ

This is the famous rule of Modus Ponens (MP):

“If you say, ‘if it rains, the street will be wet’ and also know that ‘it rains’ — then you can conclude: ‘the street is wet.’”

💡 It's not just how you prove something, but also what you assume in the process.


Rule 3: Implication Introduction

If assuming α leads you to prove β, then you can conclude the implication αβ itself.

Γ,αβΓαβ

This rule is all about building functions (in lambda calculus) or constructing implications (in logic):

“If assuming α allows me to get to β, then I’ll just write down the implication αβ.”

This is how we define implications logically.


Transition to Logic

Let’s now talk about one of the most beautiful insights of the Curry–Howard correspondence — how we move from a lambda term to its logical meaning.

Take the following lambda term:

λx.λy.x

It has the type:

α(βα)

Now here’s the cool part:

🧠 To get the logical formula, you just strip away the lambdas and keep the type!

So:

Lambda term:

λx.λy.x

Type:

α(βα)

The type alone becomes your logical proposition:

α(βα)

✅ This is a tautology in logic — it’s always true.

So the transformation from lambda calculus to logic looks like this:

Lambda Term Logical Proposition
λx.x αα
λx.λy.x α(βα)
λf.λg.λx.f(gx) (βγ)((αβ)(αγ))

Just remove the lambdas, and what remains is the logical skeleton — the type tells you the structure of the reasoning.

The Challenge

Look at this proposition:

α(αα)

It’s clearly a tautology in logic. But now try to construct a lambda term for it. You might write:

λx.λy.x

This makes sense: we take two arguments of type α, and return the first.
So we have:

λx.λy.x:α(αα)

✅ Looks good.

But here's the problem:
That’s Not the Only Possibility!

You could also write:

λx.λy.y

Which gives:

α(αα)

Again! And this is also a valid lambda term, a valid function, but with a different behavior!

And this one:

λx.λy.x(or)λx.λy.yor anything else that returns a value of type α

So multiple different lambda terms can have the same type.


What’s the Issue?

When going from lambda → logic, it's straightforward:
You always get one formula — the type.

But when going from logic → lambda, it's not uniquely determined.


Logic = Specification, Lambda = Implementation

You can think of it this way:

That’s why this direction (Logic → Lambda) is trickier.
You're constructing a program from a proof, and there may be many valid implementations.


Absolutely — let's shift the lens to something more mathematical and familiar: theorems and proofs.


💡 Logic as Theorems, Lambda as Proofs

Imagine you're in a math class.

You see a statement on the board:

“If a number is even, then doubling it is also even.”

This statement is a logical formula. It’s a theorem — something that might be provable.

But how do we prove it? Well, you could:

Each of these is a proof — a specific way of showing the theorem is true.


🧠 In Curry–Howard:


So What’s the Problem Again?

When going from:


🔁 Multiple Proofs, One Theorem

For example:

Theorem:
α(αα)

There are multiple “proofs” (lambda terms) of it:

All valid — all prove the same theorem — but they differ in how they do it.

So:

From a proof, you can always find the theorem it proves.
From a theorem, you must construct a proof — and there may be many ways.


🧪 So What Can We Do With That?

Here's where things get even more interesting:
Since there can be many lambda terms for a single formula, it means:

Now imagine you’re working with a complex classical theorem — like something from number theory or analysis. You could:

  1. Translate that theorem into a type (using Curry–Howard).
  2. Try to construct lambda terms (proofs) for it.
  3. Maybe even brute-force all possible lambda terms of that type.
  4. And who knows? You might discover a simpler proof you hadn’t thought of before.

🧠 Proofs become searchable.
💡 Lambda calculus lets us enumerate and explore proofs as data.
🤖 This opens the door to automated proof discovery — not just verifying, but inventing.


🔄 Beta Reduction Preserves Meaning

And here's an important technical detail:
If you find a lambda term U that has type α, and you simplify it using β-reduction, the simplified version U still has the same type:

UβUU:α  U:α

This is a theorem in lambda calculus:

β-reduction preserves types.

So, you can simplify your lambda term without fear — it remains a proof of the same theorem.
That means:


💡 Final Intuition

Think of it this way:

But maybe, just maybe, there’s a shortcut through the forest 🏞️

Curry–Howard says:

"Let’s map the terrain, explore every route, and maybe discover a simpler way to the truth."