Lambda calculus

Introduction to Lambda Calculus

Reading preferences

Optional display controls need JavaScript. All reading content and navigation work without it.

Source file content/lambda-calculus/introduction/introduction.tex

Editorial

This chapter consists of Jeremy's original concise notes on the lambda calculus. The sections need to be combined, and the material on lambda definability merged with the material in the separate, more detailed chapter on lambda definability.

Source file content/lambda-calculus/introduction/overview.tex

Overview

The lambda calculus was originally designed by Alonzo Church in the early 1930s as a basis for constructive logic, and not as a model of the computable functions. But it was soon shown to be equivalent to other definitions of computability, such as the Turing computable functions and the partial recursive functions. The fact that this initially came as a small surprise makes the characterization all the more interesting.

Lambda notation is a convenient way of referring to a function directly by a symbolic expression which defines it, instead of defining a name for it. Instead of saying “let ffsource be the function defined by f(x)=x+3f(x) = x + 3source,” one can say, “let ffsource be the function λx.(x+3)\lambd[x][(x + 3)]source.” In other words, λx.(x+3)\lambd[x][(x+3)]source is just a name for the function that adds three to its argument. In this expression, xxsource is a dummy variable, or a placeholder: the same function can just as well be denoted by λy.(y+3)\lambd[y][(y + 3)]source. The notation works even with other parameters around. For example, suppose g(x,y)g(x, y)source is a function of two variables, and kksource is a natural number. Then λx.g(x,k)\lambd[x][g(x,k)]source is the function which maps any xxsource to g(x,k)g(x, k)source.

This way of defining a function from a symbolic expression is known as lambda abstraction. The flip side of lambda abstraction is application: assuming one has a function ffsource (say, defined on the natural numbers), one can apply it to any value, like 2. In conventional notation, of course, we write f(2)f(2)source for the result.

What happens when you combine lambda abstraction with application? Then the resulting expression can be simplified, by “plugging” the applicand in for the abstracted variable. For example,

(λx.(x+3))(2)(\lambd[x][(x + 3)])(2)source

can be simplified to 2+32 + 3source.

Up to this point, we have done nothing but introduce new notations for conventional notions. The lambda calculus, however, represents a more radical departure from the set-theoretic viewpoint. In this framework:

  1. Everything denotes a function.

  2. Functions can be defined using lambda abstraction.

  3. Anything can be applied to anything else.

For example, if FFsource is a term in the lambda calculus, F(F)F(F)source is always assumed to be meaningful. This liberal framework is known as the untyped lambda calculus, where “untyped” means “no restriction on what can be applied to what.”

Digress

There is also a typed lambda calculus, which is an important variation on the untyped version. Although in many ways the typed lambda calculus is similar to the untyped one, it is much easier to reconcile with a classical set-theoretic framework, and has some very different properties.

Research on the lambda calculus has proved to be central in theoretical computer science, and in the design of programming languages. LISP, designed by John McCarthy in the 1950s, is an early example of a language that was influenced by these ideas.

Source file content/lambda-calculus/introduction/syntax.tex

The Syntax of the Lambda Calculus

One starts with a sequence of variables xxsource, yysource, zzsource, dots and some constant symbols aasource, bbsource, ccsource, dots. The set of terms is defined inductively, as follows:

  1. Each variable is a term.

  2. Each constant is a term.

  3. If MMsource and NNsource are terms, so is (MN)(MN)source.

  4. If MMsource is a term and xxsource is a variable, then (λx.M)(\lambd[x][M])source is a term.

Terms of the form (MN)(MN)source are called applications and those of the form (λx.M)(\lambd[x][M])source abstractions.

The system without any constants at all is called the pure lambda calculus. We'll mainly be working in the pure λ\lambdsource-calculus, so all lowercase letters will stand for variables. We use uppercase letters (MMsource, NNsource, etc.) to stand for terms of the λ\lambdsource-calculus.

We will follow a few notational conventions:

Convention

  1. When parentheses are left out, application takes place from left to right. For example, if MMsource, NNsource, PPsource, and QQsource are terms, then MNPQMNPQsource abbreviates (((MN)P)Q)(((MN)P)Q)source.

  2. Again, when parentheses are left out, lambda abstraction is to be given the widest scope possible. From example, λx.MNP\lambd[x][MNP]source is read (λx.((MN)P))(\lambd[x][((MN)P)])source.

  3. A lambda can be used to abstract multiple variables. For example, λxyz.M\lambd[xyz][M]source is short for λx.λy.λz.M\lambd[x][\lambd[y][\lambd[z][M]]]source.

For example,

λxy.xxyxλz.xz\lambd[xy][xxyx \lambd[z][xz]]source

abbreviates

λx.λy.((((xx)y)x)(λz.(xz))).\lambd[x][\lambd[y][((((xx)y)x)(\lambd[z][(xz)]))]].source

You should memorize these conventions. They will drive you crazy at first, but you will get used to them, and after a while they will drive you less crazy than having to deal with a morass of parentheses.

Two terms that differ only in the names of the bound variables are called α\alphasource-equivalent; for example, λx.x\lambd[x][x]source and λy.y\lambd[y][y]source. It will be convenient to think of these as being the “same” term; in other words, when we say that MMsource and NNsource are the same, we also mean “up to renamings of the bound variables.” Variables that are in the scope of a λ\lambdsource are called “bound”, while others are called “free.” There are no free variables in the previous example; but in

(λz.yz)x(\lambd[z][yz])xsource

yysource and xxsource are free, and zzsource is bound.

Source file content/lambda-calculus/introduction/reduction.tex

Reduction of Lambda Terms

What can one do with lambda terms? Simplify them. If MMsource and NNsource are any lambda terms and xxsource is any variable, we can use M[N/x]\Subst{M}{N}{x}source to denote the result of substituting NNsource for xxsource in MMsource, after renaming any bound variables of MMsource that would interfere with the free variables of NNsource after the substitution. For example,

(λw.xxw)[yyz/x]=λw.(yyz)(yyz)w.\Subst{(\lambd[w][xxw])}{yyz}{x} = \lambd[w][(yyz)(yyz)w].source

Digress

Alternative notations for substitution are [N/x]M[N/x]Msource, [x/N]M[x/N]Msource, and also M[x/N]M[x/N]source. Beware!

Intuitively, (λx.M)N(\lambd[x][M])Nsource and M[N/x]\Subst{M}{N}{x}source have the same meaning; the act of replacing the first term by the second is called β\betasource-contraction. (λx.M)N(\lambd[x][M])Nsource is called a redex and M[N/x]\Subst{M}{N}{x}source its contractum. Generally, if it is possible to change a term PPsource to PP'source by β\betasource-contraction of some subterm, we say that PPsource β\betasource-reduces to PP'source in one step, and write PPP \redone P'source. If from PPsource we can obtain PP'source with some number of one-step reductions (possibly none), then PPsource β\betasource-reduces to PP'source; in symbols, PPP \red P'source. A term that cannot be β\betasource-reduced any further is called β\betasource-irreducible, or β\betasource-normal. We will say “reduces” instead of “β\betasource-reduces,” etc., when the context is clear.

Let us consider some examples.

  1. We have

    (λx.xxy)λz.z(λz.z)(λz.z)y(λz.z)yy.(\lambd[x][xxy]) \lambd[z][z] & \redone (\lambd[z][z])(\lambd[z][z]) y \\ & \redone (\lambd[z][z]) y \\ & \redone y.source
  2. “Simplifying” a term can make it more complex:

    (λx.xxy)(λx.xxy)(λx.xxy)(λx.xxy)y(λx.xxy)(λx.xxy)yy(\lambd[x][xxy])(\lambd[x][xxy]) & \redone (\lambd[x][xxy])(\lambd[x][xxy])y \\ & \redone (\lambd[x][xxy])(\lambd[x][xxy])yy \\ & \redone \dotssource
  3. It can also leave a term unchanged:

    (λx.xx)(λx.xx)(λx.xx)(λx.xx).(\lambd[x][xx])(\lambd[x][xx]) \redone (\lambd[x][xx])(\lambd[x][xx]).source
  4. Also, some terms can be reduced in more than one way; for example,

    (λx.(λy.yx)z)v(λy.yv)z(\lambd[x][(\lambd[y][yx]) z]) v \redone (\lambd[y][yv]) zsource

    by contracting the outermost application; and

    (λx.(λy.yx)z)v(λx.zx)v(\lambd[x][(\lambd[y][yx]) z]) v \redone (\lambd[x][zx]) vsource

    by contracting the innermost one. Note, in this case, however, that both terms further reduce to the same term, zvzvsource.

The final outcome in the last example is not a coincidence, but rather illustrates a deep and important property of the lambda calculus, known as the “Church--Rosser property.”

Source file content/lambda-calculus/introduction/church-rosser.tex

The Church--Rosser Property

The Church Rosser property

Let MMsource, N1N_1source, and N2N_2source be terms, such that MN1M \red N_1source and MN2M \red N_2source. Then there is a term PPsource such that N1PN_1 \red Psource and N2PN_2 \red Psource.

Uniqueness of normal form

Suppose MMsource can be reduced to normal form. Then this normal form is unique.

Proof

If MN1M \red N_1source and MN2M \red N_2source, by the previous theorem there is a term PPsource such that N1N_1source and N2N_2source both reduce to PPsource. If N1N_1source and N2N_2source are both in normal form, this can only happen if N1PN2N_1 \ident P \ident N_2source.

Finally, we will say that two terms MMsource and NNsource are β\betasource-equivalent, or just equivalent, if they reduce to a common term; in other words, if there is some PPsource such that MPM \red Psource and NPN \red Psource. This is written M=βNM \equal[\beta] Nsource. Using the Church Rosser theorem, you can check that =β\equal[\beta]source is an equivalence relation, with the additional property that for every MMsource and NNsource, if MNM \red Nsource or NMN \red Msource, then M=βNM \equal[\beta] Nsource. (In fact, one can show that =β\equal[\beta]source is the smallest equivalence relation having this property.)

Source file content/lambda-calculus/introduction/currying.tex

Currying

A λ\lambdsource-abstract λx.M\lambd[x][M]source represents a function of one argument, which is quite a limitation when we want to define function accepting multiple arguments. One way to do this would be by extending the λ\lambdsource-calculus to allow the formation of pairs, triples, etc., in which case, say, a three-place function λx.M\lambd[x][M]source would expect its argument to be a triple. However, it is more convenient to do this by Currying.

Let's consider an example. We'll pretend for a moment that we have a ++source operation in the λ\lambdsource-calculus. The addition function is 22source-place, i.e., it takes two arguments. But a λ\lambdsource-abstract only gives us functions of one argument: the syntax does not allow expressions like λ(x,y).(x+y)\lambd[(x,y)][(x+y)]source. However, we can consider the one-place function fx(y)f_x(y)source given by λy.(x+y)\lambd[y][(x+y)]source, which adds xxsource to its single argument yysource. Actually, this is not a single function, but a family of different functions “add xxsource,” one for each number xxsource. Now we can define another one-place function ggsource as λx.fx\lambd[x][f_x]source. Applied to argument xxsource, g(x)g(x)source returns the function fxf_xsource---so its values are other functions. Now if we apply ggsource to xxsource, and then the result to yysource we get: (g(x))y=fx(y)=x+y(g(x))y = f_x(y) = x+ysource. In this way, the one-place function ggsource can do the same job as the two-place addition function. “Currying” simply refers to this trick for turning two-place functions into one place functions (whose values are one-place functions).

Here is an example properly in the syntax of the λ\lambdsource-calculus. How do we represent the function f(x,y)=xf(x,y) = xsource? If we want to define a function that accepts two arguments and returns the first, we can write λx.λy.x\lambd[x][\lambd[y][x]]source, which literally is a function that accepts an argument xxsource and returns the function λy.x\lambd[y][x]source. The function λy.x\lambd[y][x]source accepts another argument yysource, but drops it, and always returns xxsource. Let's see what happens when we apply λx.λy.x\lambd[x][\lambd[y][x]]source to two arguments:

(λx.λy.x)MNβ(λy.M)NβM(\lambd[x][\lambd[y][x]])MN \bredone & (\lambd[y][M])N \\ \bredone & Msource

In general, to write a function with parameters x1x_1source, dots, xnx_nsource defined by some term NNsource, we can write λx1.λx2.λxn.N\lambd[x_1][\lambd[x_2][\ldots\lambd[x_n][N]]]source. If we apply nnsource arguments to it we get:

(λx1.λx2.λxn.N)M1Mnββ((λx2.λxn.N)[M1/x1])M2Mn(λx2.λxn.N[M1/x1])M2MnβP[M1/x1][Mn/xn](\lambd[x_1][\lambd[x_2][\ldots\lambd[x_n][N]]]) M_1 \dots M_n \bredone\\ \begin{aligned} \bredone {} & (\Subst{(\lambd[x_2][\ldots\lambd[x_n][N]])}{M_1}{x_1}) M_2 \dots M_n\\ \eqs {} & (\lambd[x_2][\ldots\lambd[x_n][\Subst{N}{M_1}{x_1}]]) M_2 \dots M_n \\ \vdots & \\ \bredone {} &\Subst{\Subst{P}{M_1}{x_1}\ldots}{M_n}{x_n} \end{aligned}source

The last line literally means substituting MiM_isource for xix_isource in the body of the function definition, which is exactly what we want when applying multiple arguments to a function.

Source file content/lambda-calculus/introduction/lambda-definability.tex

lambda definable Arithmetical Functions

How can the lambda calculus serve as a model of computation? At first, it is not even clear how to make sense of this statement. To talk about computability on the natural numbers, we need to find a suitable representation for such numbers. Here is one that works surprisingly well.

Definition of Church numerals

For each natural number nnsource, define the Church numeral n¯\num{n}source to be the lambda term λx.λy.(x(x(x(x(y)))))\lambd[x][\lambd[y][(x(x(x(\dots x(y)))))]]source, where there are nnsource xxsource's in all.

The terms n¯\num{n}source are “iterators”: on input ffsource, n¯\num{n}source returns the function mapping yysource to fn(y)f^n(y)source. Note that each numeral is normal. We can now say what it means for a lambda term to “compute” a function on the natural numbers.

Lambda definability of a partial function

Let f(x0,,xk1)f(x_0, \dots, x_{k-1})source be an nnsource-ary partial function from \Natsource to \Natsource. We say a λ\lambdsource-term FFsource lambda-defines ffsource iff for every sequence of natural numbers n0n_0source, dots, nk1n_{k-1}source,

Fn0¯n1¯nk1¯f(n0,n1,,nk1)¯F\, \num{n_0}\, \num{n_1} \dots \num{n_{k-1}} \red \num{f(n_0, n_1, \dots, n_{k-1})}source

if f(n0,,nk1)f(n_0, \dots, n_{k-1})source is defined, and F,n0¯n1¯nk1¯F, \num{n_0}\, \num{n_1} \dots \num{n_{k-1}}source has no normal form otherwise.

Lambda definability characterizes partial computability

A function ffsource is a partial computable function if and only if it is lambda-defined by a lambda term.

Explain

This theorem is somewhat striking. As a model of computation, the lambda calculus is a rather simple calculus; the only operations are lambda abstraction and application! From these meager resources, however, it is possible to implement any computational procedure.

Source file content/lambda-calculus/introduction/lambda-computable.tex

lambda definable Functions are Computable

Lambda definable partial functions are computable

If a partial function ffsource is lambda-defined by a lambda term, it is computable.

Proof

Suppose a function ffsource is lambda-defined by a lambda term XXsource. Let us describe an informal procedure to compute ffsource. On input m0m_0source, dots, mn1m_{n-1}source, write down the term Xm¯0m¯n1X \num m_0 \ldots \num m_{n-1}source. Build a tree, first writing down all the one-step reductions of the original term; below that, write all the one-step reductions of those (i.e., the two-step reductions of the original term); and keep going. If you ever reach a numeral, return that as the answer; otherwise, the function is undefined.

An appeal to Church's thesis tells us that this function is computable. A better way to prove the theorem would be to give a recursive description of this search procedure. For example, one could define a sequence primitive recursive functions and relations, “IsASubterm\fn{IsASubterm}source,” “Substitute\fn{Substitute}source,” “ReducesToInOneStep\fn{ReducesToInOneStep}source,” “ReductionSequence\fn{ReductionSequence}source,” “Numeral\fn{Numeral}source,” etc. The partial recursive procedure for computing f(m0,,mn1)f(m_0, \dots, m_{n-1})source is then to search for a sequence of one-step reductions starting with Xm0¯mn1¯X \num{m_0} \dots \num{m_{n-1}}source and ending with a numeral, and return the number corresponding to that numeral. The details are long and tedious but otherwise routine.

Source file content/lambda-calculus/introduction/computable-lambda.tex

Computable Functions are lambda definable

Computable partial functions are lambda definable

Every computable partial function is lambda-definable.

Proof

We need to show that every partial computable function ffsource is lambda-defined by a lambda term FFsource. By Kleene's normal form theorem, it suffices to show that every primitive recursive function is lambda-defined by a lambda term, and then that the functions lambda-definable are closed under suitable compositions and unbounded search. To show that every primitive recursive function is lambda-defined by a lambda term, it suffices to show that the initial functions are lambda-definable, and that the partial functions that are lambda-definable are closed under composition, primitive recursion, and unbounded search.

We will use a more conventional notation to make the rest of the proof more readable. For example, we will write M(x,y,z)M(x, y, z)source instead of MxyzMxyzsource. While this is suggestive, you should remember that terms in the untyped lambda calculus do not have associated arities; so, for the same term MMsource, it makes just as much sense to write M(x,y)M(x,y)source and M(x,y,z,w)M(x,y,z,w)source. But using this notation indicates that we are treating MMsource as a function of three variables, and helps make the intentions behind the definitions clearer. In a similar way, we will say “define MMsource by M(x,y,z)=M(x,y,z) = \dotssource” instead of “define MMsource by M=λx.λy.λz.M = \lambd[x][\lambd[y][\lambd[z][\dots]]]source.”

Source file content/lambda-calculus/introduction/basic-pr-lambda.tex

The Basic Primitive Recursive Functions are lambda definable

Lambda definability of initial functions

The functions zero\Zerosource, succ\Succsource, and Pin\Proj{n}{i}source are lambda-definable.

Proof

zero\Zerosource is just λx.λy.y\lambd[x][\lambd[y][y]]source.

The successor function succ\Succsource, is defined by Succ(u)=λx.λy.x(uxy)\fn{Succ}(u) = \lambd[x][\lambd[y][x(uxy)]]source. You should think about why this works; for each numeral n¯\num{n}source, thought of as an iterator, and each function ffsource, Succ(n¯,f)\fn{Succ}(\num{n},f)source is a function that, on input yysource, applies ffsource nnsource times starting with yysource, and then applies it once more.

There is nothing to say about projections: Projin(x0,,xn1)=xi\fn{Proj}^n_i(x_0, \dots, x_{n-1}) = x_isource. In other words, by our conventions, Projin\fn{Proj}^n_isource is the lambda term λx0.λxn1.xi\lambd[x_0][\dots \lambd[x_{n-1}][x_i]]source.

Source file content/lambda-calculus/introduction/composition.tex

The lambda definable Functions are Closed under Composition

Closure under composition

The lambda-definable functions are closed under composition.

Proof

Suppose ffsource is defined by composition from hhsource, g0,g_0,source dots, gk1g_{k-1}source. Assuming hhsource, g0g_0source, dots, gk1g_{k-1}source are lambda-defined by HHsource, G0G_0source, dots, Gk1G_{k-1}source, respectively, we need to find a term FFsource that lambda-defines ffsource. But we can simply define FFsource by

F(x0,,xl1)=H(G0(x0,,xl1),,Gk1(x0,,xl1)).F(x_0, \dots, x_{l-1}) = H(G_0(x_0, \dots, x_{l-1}), \dots, G_{k-1}(x_0, \dots, x_{l-1})).source

In other words, the language of the lambda calculus is well suited to represent composition.

Source file content/lambda-calculus/introduction/primitive-recursion.tex

lambda definable Functions are Closed under Primitive Recursion

When it comes to primitive recursion, we finally need to do some work. We will have to proceed in stages. As before, on the assumption that we already have terms GGsource and HHsource that lambda-define functions ggsource and hhsource, respectively, we want a term HHsource that lambda-defines the function ffsource defined by

f(0,z)=g(z)f(x+1,z)=h(z,f(x,z),z).f(0, \vec z) & = g(\vec z) \\ f(x+1, \vec z) & = h(z, f(x,\vec z), \vec z).source

So, in general, given lambda terms GG'source and HH'source, it suffices to find a term FFsource such that

F(0¯,z)G(z)F(n+1¯,z)H(n¯,F(n¯,z),z)F(\num{0}, \vec z) & \equiv G(\vec z) \\ F(\overline{n+1}, \vec z) & \equiv H(\num{n}, F(\num{n}, \vec z), \vec z)source

for every natural number nnsource; the fact that GG'source and HH'source lambda-define ggsource and hhsource means that whenever we plug in numerals m¯\num{\vec m}source for z\vec zsource, F(n+1¯,m¯)F(\num{n+1}, \num{\vec m})source will normalize to the right answer.

But for this, it suffices to find a term FFsource satisfying

F(0¯)GF(n+1¯)H(n¯,F(n¯))for every natural number n, whereG=λz.G(z) andH(u,v)=λz.H(u,v(u,z),z).F(\num 0) & \equiv G \\ F(\overline {n+1}) & \equiv H(\num{n},F(\num{n})) \intertext{for every natural number $n$, where} G & = \lambd[\vec z][G'(\vec z)] \text{ and}\\ H(u,v) & = \lambd[\vec z][H'(u,v(u,\vec z),\vec z)].source

In other words, with lambda trickery, we can avoid having to worry about the extra parameters z\vec zsource---they just get absorbed in the lambda notation.

Before we define the term FFsource, we need a mechanism for handling ordered pairs. This is provided by the next lemma.

Representing ordered pairs by a lambda term

There is a lambda term DDsource such that for each pair of lambda terms MMsource and NNsource, D(M,N)(0¯)MD(M,N)(\num{0}) \red Msource and D(M,N)(1¯)ND(M,N)(\num{1}) \red Nsource.

Proof

First, define the lambda term KKsource by

K(y)=λx.y.K(y) = \lambd[x][y].source

In other words, KKsource is the term λy.λx.y\lambd[y][\lambd[x][y]]source. Looking at it differently, for every MMsource, K(M)K(M)source is a constant function that returns MMsource on any input.

Now define D(x,y,z)D(x,y,z)source by D(x,y,z)=z(K(y))xD(x,y,z) = z (K(y))xsource. Then we have

D(M,N,0¯)0¯(K(N))MM andD(M,N,1¯)1¯(K(N))MK(N)MN,D(M,N,\num 0) & \red \num 0 (K(N)) M \red M \text{ and}\\ D(M,N,\num 1) & \red \num 1 (K(N)) M \red K(N) M \red N,source

as required.

The idea is that D(M,N)D(M,N)source represents the pair M,N\tuple{M, N}source, and if PPsource is assumed to represent such a pair, P(0¯)P(\num 0)source and P(1¯)P(\num 1)source represent the left and right projections, (P)0(P)_0source and (P)1(P)_1source. We will use the latter notations.

Closure under primitive recursion

The lambda-definable functions are closed under primitive recursion.

Proof

We need to show that given any terms, GGsource and HHsource, we can find a term FFsource such that

F(0¯)GF(n+1¯)H(n¯,F(n¯))F(\num{0}) & \equiv G \\ F(\num{n+1}) & \equiv H(\num{n}, F(\num{n}))source

for every natural number nnsource. The idea is roughly to compute sequences of pairs

0¯,F(0¯),1¯,F(1¯),,\tuple{\num 0, F(\num 0)}, \tuple{\num 1, F(\num 1)}, \dots,source

using numerals as iterators. Notice that the first pair is just 0¯,G\tuple{\num 0, G}source. Given a pair n¯,F(n¯)\tuple{\num{n}, F(\num{n})}source, the next pair, n+1¯,F(n+1¯)\tuple{\num{n+1}, F(\num{n+1})}source is supposed to be equivalent to n+1¯,H(n¯,F(n¯))\tuple{\num{n+1}, H(\num{n}, F(\num{n}))}source. We will design a lambda term TTsource that makes this one-step transition.

The details are as follows. Define T(u)T(u)source by

T(u)=S((u)0),H((u)0,(u)1).T(u) = \tuple{S((u)_0), H((u)_0,(u)_1)}.source

Now it is easy to verify that for any number nnsource,

T(n¯,M)n+1¯,H(n¯,M).T(\tuple{\num{n}, M}) \red \tuple{\num{n+1}, H(\num{n}, M)}.source

As suggested above, given GGsource and HHsource, define F(u)F(u)source by

F(u)=(u(T,0¯,G))1.F(u) = (u(T,\tuple{\num 0, G}))_1.source

In other words, on input n¯\num{n}source, FFsource iterates TTsource nnsource times on 0¯,G\tuple{\num 0, G}source, and then returns the second component. To start with, we have

  1. 0¯(T,0¯,G)0¯,G\num{0} (T, \tuple{\num 0, G}) \equiv \tuple{\num{0}, G}source

  2. F(0¯)GF(\num{0}) \equiv Gsource

By induction on nnsource, we can show that for each natural number one has the following:

  1. n+1¯(T,0¯,G)n+1¯,F(n+1¯)\num{n+1}(T, \tuple{\num{0}, G}) \equiv \tuple{\num{n+1}, F(\num{n+1})}source

  2. F(n+1¯)H(n¯,F(n¯))F(\num{n+1}) \equiv H(\num{n}, F(\num{n}))source

For the second clause, we have

F(n+1¯)(n+1¯(T,0¯,G))1(T(n¯(T,0¯,G)))1(T(n¯,F(n¯)))1(n+1¯,H(n¯,F(n¯)))1H(n¯,F(n¯)).F(\num{n+1}) & \red (\num{n+1}(T, \tuple{\num 0, G}))_1 \\ & \equiv (T(\num{n} (T, \tuple{\num 0, G})))_1 \\ & \equiv (T(\tuple{\num{n}, F(\num{n})}))_1 \\ & \equiv (\tuple{\num{n+1}, H(\num{n}, F(\num{n}))})_1 \\ & \equiv H(\num{n}, F(\num{n})).source

Here we have used the induction hypothesis on the second-to-last line. For the first clause, we have

n+1¯(T,0¯,G)T(n¯(T,0¯,G))T(n¯,F(n¯))n+1¯,H(n¯,F(n¯))n+1¯,F(n+1¯).\num{n+1} (T, \tuple{\num 0, G}) & \equiv T(\num{n} (T, \tuple{\num 0, G})) \\ & \equiv T( \tuple{\num{n}, F(\num{n})}) \\ & \equiv \tuple{\num{n+1}, H(\num{n}, F(\num{n}))} \\ & \equiv \tuple{\num{n+1}, F(\num{n+1})}.source

Here we have used the second clause in the last line. So we have shown F(0¯)GF(\num 0) \equiv Gsource and, for every nnsource, F(n+1¯)H(n¯,F(n¯))F(\num {n+1}) \equiv H(\num n, F(\num{n}))source, which is exactly what we needed.

Source file content/lambda-calculus/introduction/fixed-point-combinator.tex

Fixed-Point Combinators

Suppose you have a lambda term ggsource, and you want another term kksource with the property that kksource is β\betasource-equivalent to gkgksource. Define terms

diag(x)=xx\fn{diag}(x) = xxsource

and

l(x)=g(diag(x))l(x) = g(\fn{diag}(x))source

using our notational conventions; in other words, llsource is the term λx.g(xx)\lambd[x][g(xx)]source. Let kksource be the term llllsource. Then we have

k=(λx.g(xx))(λx.g(xx))g((λx.g(xx))(λx.g(xx)))=gk.k & = (\lambd[x][g(xx)])(\lambd[x][g(xx)]) \\ & \red g((\lambd[x][g(xx)])(\lambd[x][g(xx)])) \\ & = gk.source

If one takes

Y=λg.((λx.g(xx))(λx.g(xx)))Y = \lambd[g][((\lambd[x][g(xx)])(\lambd[x][g(xx)]))]source

then YgYgsource and g(Yg)g(Yg)source reduce to a common term; so Ygβg(Yg)Yg \equiv_\beta g(Yg)source. This is known as “Curry's combinator.” If instead one takes

Y=(λxg.g(xxg))(λxg.g(xxg))Y = (\lambd[xg][g(xxg)])(\lambd[xg][g(xxg)])source

then in fact YgYgsource reduces to g(Yg)g(Yg)source, which is a stronger statement. This latter version of YYsource is known as “Turing's combinator.”

Source file content/lambda-calculus/introduction/minimization.tex

The lambda definable Functions are Closed under Minimization

Closure under minimization

Suppose f(x,y)f(x,y)source is lambda-definable. Let ggsource be defined by

g(x)μyf(x,y).g(x) \simeq \umin{y}{f(x,y)}.source

Then ggsource is lambda-definable.

Proof

The idea is roughly as follows. Given xxsource, we will use the fixed-point lambda term YYsource to define a function hx(n)h_x(n)source which searches for a yysource starting at nnsource; then g(x)g(x)source is just hx(0)h_x(0)source. The function hxh_xsource can be expressed as the solution of a fixed-point equation:

hx(n){nif f(x,n)=0hx(n+1)otherwise.h_x(n) \simeq \begin{cases} n & \text{if $f(x,n) = 0$} \\ h_x(n+1) & \text{otherwise.} \end{cases}source

Here are the details. Since ffsource is primitive recursive, it is lambda-defined by some term FFsource. Remember that we also have a lambda term DDsource, such that D(M,N,0¯)MD(M, N, \bar{0}) \red Msource and D(M,N,1¯)ND(M, N, \bar{1}) \red Nsource. Fixing xxsource for the moment, to lambda-define hxh_xsource we want to find a term HHsource (depending on xxsource) satisfying

H(n¯)D(n¯,H(S(n¯)),F(x,n¯)).H(\num{n}) \equiv D(\num{n}, H(S(\num{n})), F(x, \num{n})).source

We can do this using the fixed-point term YYsource. First, let UUsource be the term

λh.λz.D(z,(h(Sz)),F(x,z)),\lambd[h][\lambd[z][D(z,(h(Sz)),F(x,z))]],source

and then let HHsource be the term YUYUsource. Notice that the only free variable in HHsource is xxsource. Let us show that HHsource satisfies the equation above.

By the definition of YYsource, we have

H=YUU(YU)=U(H).H = YU \equiv U(YU) = U(H).source

In particular, for each natural number nnsource, we have

H(n¯)U(H,n¯)D(n¯,H(S(n¯)),F(x,n¯)),H(\num{n}) & \equiv U(H, \num{n}) \\ & \red D(\num{n}, H(S(\num{n})), F(x, \num{n})),source

as required. Notice that if you substitute a numeral m¯\num{m}source for xxsource in the last line, the expression reduces to n¯\num{n}source if F(m¯,n¯)F(\num{m}, \num{n})source reduces to 0¯\num{0}source, and it reduces to H(S(n¯))H(S(\num{n}))source if F(m¯,n¯)F(\num{m}, \num{n})source reduces to any other numeral.

To finish off the proof, let GGsource be λx.H(0¯)\lambd[x][H(\num 0)]source. Then GGsource lambda-defines ggsource; in other words, for every mmsource, G(m¯)G(\num m)source reduces to g(m)¯\overline {g(m)}source, if g(m)g(m)source is defined, and has no normal form otherwise.

Source disclosures