Lambda Calculus
This post is my note for What is seminar on Lambda Calculus.
Lambda calculus was created by Alonzo Church in the 1930s, and was used by him to solve Entscheidungsproblem in 1936, which is related to Hilbert's tenth problem. In the same year, Alan Turing independently solved Entscheidungsproblem using his invention Turing machine. Shortly after, Turing realized that these two models are actually equivalent as models of computation.
In this note, I will first give the formal definition of lambda expressions. Then with the help of Python, I am going to show how to do Boolean algebra and basic arithmetic using lambda calculus, which to some extend gives an illustration that Turing machine and lambda calculus are equivalent.
Definition
Lambda calculus consists of lambda expressions and operations on them. There are three basic elements in Lambda expression:
- variables: x, y, z, ...
- symbols in abstraction: λ and .
- parentheses for association: ()
The 2nd rule should be thought of definitions of functions, while the 3rd rule should be regraded as evaluations of functions. Let's look at some examples.
Example 1. λx.x
By 1st rule, x
is a lambda expression, then by 2nd rule, λx.x
is also a lambda expression. This expression is equivalent to the identity function: id(x)=x, which means the function that takes x
as an input then gives x
as an output. From this example, we should notice that 2nd rule is just a way to define a function anonymously.
Example 2. (λx.xx)y
λx.xx
is a function that takes x
as an input then output xx
. What xx
means here is ambiguous, because we have not defined what it means to put two variables together. Let's put this aside for now. A similar argument as in Example 1 can show that λx.xx
is a lambda expression. Applying 3rd rule, we know (λx.xx)y
is a lambda expression. But the 3rd rule is evaluations of functions, we have that (λx.xx)y
is the same as yy
.
In Example 2, the idea of evaluation is actually one of two important operations on lambda expression, which is called β-reduction.
Example 3. Lambda expressions in Python.
(lambda x: x+x)(3)
(lambda x: x+x)('hello')
Python has a very good implementation of lambda expression. From now on, I am going to write lambda expressions in Python language. In Example 2, we do not specify what xx
means. Here, we define xx
to be x+x
in Python. Now β-reduction allows us to deduce that
(lambda x: x+x)(3) = 6
(lambda x: x+x)('hello') = 'hellohello'
Boolean Algebra
Boolean algebra requires Boolean values "True" and "False". In Turing machine, they are represented by 0 and 1. But we can define them to be anything, as long as they respect all Boolean operations.
T = lambda x, y: x
F = lambda x, y: y
AND = lambda x, y: x(y, F)
OR = lambda x, y: x(T, y)
NOT = lambda x: x(F, T)
In lambda calculus, "True" is define to be a lambda expression that takes two arguments and return the first argument. On the other hand, "False" is similarly defined, but return the second argument. There are three basic operations: and
, or
and not
in Boolean algebra. All these are defined in the above Python code.
Let's examine and
operator.
- AND(T, T) = T(T, F) = T
- AND(T, F) = T(F, F) = F
- AND(F, T) = F(T, F) = F
- AND(F, F) = F(F, F) = F
This is the correct and
operator! One can easily check that the above OR
and NOT
are the correct or
and not
operators.
Basic Arithmetic
What is more interesting is that we can do arithmetic using lambda calculus. First of all, let's define all natural numbers. In lambda calculus, we do this via the number of iterations:
ZERO = lambda f, x: x
ONE = lambda f, x: f(x)
TWO = lambda f, x: f(f(x))
THREE = lambda f, x: f(f(f(x)))
...
All natural numbers are lambda expressions taking two arguments, f
and x
, where f
is some lambda expression which has one argument. The number is then encoded in the number of iterations of f
on x
. This number system is called Church numerals. Let's see how to define some basic arithmetic operators.
SUCC = lambda n: lambda f, x: f(n(f, x))
PLUS = lambda n, m: n(SUCC, m)
MULT = lambda n, m: lambda f, x: n(lambda x: m(f, x), x)
SUCC
is a lambda expression to find the successor of a number n
. According to our definition of numbers, we just need to do one more iteration of f
. PLUS
is addition of two numbers, which is achieved by applying SUCC
n
times to m
. Lastly, MULT
is multiplication of two numbers. Since m
is a lambda expression with f
iterating m
times, the idea is to repeat m
n
times. Then f
is iterated nm
times.
To test these arithmetic operators, we need to convert Church numerals to standard integers. In Python, we can set f
to be f(x)=x+1
with x=0
, then Church numerals will be converted to integers. Putting all together, we can play with the following codes.
ZERO = lambda f, x: x
ONE = lambda f, x: f(x)
TWO = lambda f, x: f(f(x))
THREE = lambda f, x: f(f(f(x)))
SUCC = lambda n: lambda f, x: f(n(f, x))
PLUS = lambda n, m: n(SUCC, m)
MULT = lambda n, m: lambda f, x: n(lambda x: m(f, x), x)
INT = lambda n: n(lambda x: x+1, 0)
FOUR = SUCC(THREE)
FIVE = PLUS(ONE, FOUR)
SIX = MULT(TWO, THREE)
numbers = [ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX]
print map(INT, numbers)
To see more arithmetic operators implemented in lambda calculus, check out a Wikipedia article Church encoding.