Every programmer learns early that types catch mistakes. Pass a string where a number is expected and the compiler complains before the program ever runs. That is type-checking: a mechanical proof that the data shapes match.
But ordinary types are surprisingly vague. A list in most languages has type List<Int> — a list of integers. It says nothing about how many integers. So when you write head(myList) — grab the first element — the compiler waves it through even if myList might be empty. The crash happens at runtime, in production, on a user's machine.
Dependent types fix this by letting a type depend on a value. Instead of "list of integers" you can write "list of exactly n integers" and put the actual number inside the type. The compiler then knows statically that head on a length-0 list is impossible — not because you wrote a test for it, but because the types make it unrepresentable.
The idea is old: Per Martin-Löf introduced Martin-Löf type theory in the 1970s, connecting types to logic through what is now called the Curry-Howard correspondence: a type is a proposition, a program that has that type is a proof. Dependent types take this all the way — a type can encode any mathematical statement, and writing a program of that type is proving the statement.
This article explores what that means, why it matters, and how you can see it in action with a simple interactive demo.
Comments
Loading comments...