User blog:Upquark11111/An Explanation of Loader's Number

[ UNDER CONSTRUCTION ]

I couldn't find a good explanation of Loader's number anywhere online, so I decided to make one of my own. Specifically, I hope to explain what's going on in loader.c and how it is able to generate such large numbers. I was mostly inspired by the incompleteness of LittlePeng9's analysis. For reference, Loader's commented version of his code can be found here. So, without further ado...

Calculus of Constructions
Loader's number is defined by diagonalizing over the Calculus of Constructions (often shortened as λPω, CoC, and sometimes C). So, before we can even talk about Loader's number, we need to understand what the Calculus of Constructions is.

The Calculus of Constructions is a typed lambda calculus that happens to be both highly expressive and strongly normalizing. But that doesn't really mean anything to anyone that isn't well learned in type theory. So I'll be explaining each of these terms.

Type theory is an alternative to set theory in serving as the foundation upon which we describe all of mathematics. Set theory goes about this by having the basic unit of everything being a list of objects (order does not matter). These lists are called sets, and can only contain sets. So, naturally, we can only begin building our universe in set theory with an empty set. From this empty set, you can build definitions for anything in math, like natural and ordinal numbers (due to von Neumann), booleans, functions, vectors, etc.

Type theory, on the other hand, does this by having the basic unit of everything being terms. Terms can be a name, a variable, or a bunch of terms joined with symbols. Every term has a type. This is a mostly intuitive concept that is exactly like how it sounds. For example, the type of two is a natural number. This fact is called a typing judgement, and is expressed in symbols as $$2 : \upright{Nat}$$.

Lambda calculus is another system of mathematical logic that can be used to model computation. Terms are constructed using a combination of three things: variables, function definitions, and function application. However, in lambda calculus, functions have no names. Instead, functions are defined at the same place that they are applied. The usual syntax for a lambda function is $$\lambda x.M$$, where x is the parameter and M is the body. The application of a function to some input is notated as $$(f N)$$.

Lambda calculus has a rule for evaluating the value of terms be reducing them down to an irreducible form. This form is called a normal form, and this rule of reduction is called β-reduction. This rule states that $$((\lambda x.M) E)$$ can be evaluated to $$M[x:=E]$$. That is, the entire term is equivalent to M, but with every instance of x replaced with E.

Typed lambda calculus is very similar. It is a merger between lambda calculus and type theory, where all terms in lambda calculus must have a type. This includes variables, lambda functions, and the variables bound as parameters. When defining a function, you now have to specify the type that the parameter must be. For example, the successor function in typed lambda calculus is written as $$\upright{succ} = \lambda n:\upright{Nat}.\lambda A:*.\lambda f:A\rightarrow A.\lambda x:A.(f (((n A) f) x))$$.

Since lambda functions must also have types, typed lambda calculus introduces new symbols and concepts. One of these concepts is the dependent type. Dependent types are basically the types judged to functions. Dependent types are composed of a variable x, a type A, and a family of types B(x). By a family of types, I mean an association of each term a:A with a type B(a). Symbolically, such a dependent type is represented as $$\Pi x:A.B(x)$$. Any function that takes in parameters of type A and returns a type B(x) have the this dependent type. E.g., the successor function is typed as $$\upright{succ} : \Pi x:\upright{Nat}.\upright{Nat}$$. Dependent types are often referred to as pi-types and product types.