Processing math: 100%

a→ab

computation, game design, and experimentation


front page | about | archives | code dump | c.s. for mere mortals | tags | rss feed

CSMM - Lesson 1.4: Advanced Logic and Arithmetic in the Lambda Calculus

June 29, 2012
tags:  csmmlambda calculusboolean logicpredicateslogicarithmetic

Where we were

Last time, we went over the basics of boolean logic and it's manifestation in the λ-calculus. This time, we'll move those basics into the realm of numbers and start testing for things such as equality and difference. We'll also see the first hint of a data structure: the pair. And we'll provide the missing subtraction function, along the way (division is still too difficult, but we'll get there in time).

A bit of review

Before we start this lesson, it's probably a good idea to collect the various named functions we've encountered up until this point.

First, some basic ones:

I:=λx.x ω:=λx.xx Ω:=ωω

Next up, the Church numerals:

0:=λsz.z 1:=λsz.sz 2:=λsz.s(sz) 3:=λsz.s(s(sz)) ...

And some arithmetic functions for working with Church numerals:

S:=λwyx.y(wyx) +:=λab.aSb ×:=λab.a(+b)0 E:=λab.ba

And finally, some boolean logic:

T:=λxy.x F:=λxy.y ¬:=λx.xFT :=λxy.xyF :=λxy.xTy

Keep these handy, we'll be using most of them for the rest of the λ-calculus lessons.

They come in twos

Alright, moving on to pairs. Pairs are useful for many things, and are fairly simple to use in the λ-calculus.

As with everything else in the λ-calculus, a pair is just a function. Say you wanted to make a pair containing 3 and 1. The function representing this pair would be as follows:

λf.f31

There is a helper function to create such pairs, called Φ. It is defined like this:

Φ:=λabf.fab

Such that creating the pair above would be as simple as:

Φ31 (λabf.fab)31 (λbf.f3b)1 λf.f31

So we can see that we can write a pair of elements x and y as (Φxy), with the parentheses serving to ensure the correct associativity.

So, we know how to create pairs now. How do we get their parts? Turns out, we already have the tools for this in the form of T and F. For example, to get the first part of (Φ31), we do the following:

(Φ31)T ((λabf.fab)31)T ((λbf.f3b)1)T (λf.f31)T T31 (λxy.x)31 (λy.3)1 3

And to get the second, we do this:

(Φ31)F ((λabf.fab)31)F ((λbf.f3b)1)F (λf.f31)F F31 (λxy.y)31 (λy.y)1 1

So, T extracts the first element of a pair, and F can pull out the second. Neat.

So, why the seemingly random diversion? Well... we're about to create a few functions that use pairs to perform some tricky work.

What comes before...

This section will actually step through two functions, one which takes in a pair (m,n) and returns (n,n+1), and one which finds the predecessor of a given Church numeral.

The first function, , operates on pairs, providing a sort of climbing upwards.

:=λx.Φ(xF)(S(xF))

Let's test this out. We're going to provide it the pair (Φ11) and it should return the pair (Φ12). As we've already seen how F works on pairs and how S works on Church numerals, I will not be writing the complete long-form of this β-reduction, rather I will be substituting results in where they belong.

(Φ11) (λx.Φ(xF)(S(xF)))(Φ11) Φ((Φ11)F)(S((Φ11)F)) Φ(1)(S((Φ11)F)) Φ(1)(S(1)) Φ12

And we see it works! For good measure, let's plug that result in, hoping for (Φ23).

(Φ12) (λx.Φ(xF)(S(xF)))(Φ12) Φ((Φ12)F)(S((Φ12)F)) Φ(2)(S((Φ12)F)) Φ(2)(S(2)) Φ23

So, now we can increment a pair of numbers. How does this help us? Well, now we have an easy way to find the predecessor of a Church numeral! There are other formulations for the predecessor function, but this one is in my opinion the easiest to understand once you have the fundamentals down. It's defined like this:

P:=λx.(x(Φ00))T

So... what does this function mean? How does it work?

It takes in a single Church numeral, x, and applies the function x times to the pair (Φ00), and then takes the resulting function and returns the first element. Applying the function to (Φ00) one time gives us (Φ01), applying it another time (for a total of two applications) to that result gives us (Φ12), and applying it x times will give us a result of (Φyx), where y is the Church numeral immediately preceeding x. Taking the first element of this pair will give us y, the predecessor of x!

Here it is in action, finding the predecessor of 3. Again, I've omitted certain details, including the applications of .

P3 (λx.(x(Φ00))T)3 (3(Φ00))T ((((Φ00))))T (((Φ01)))T ((Φ12))T (Φ23)T 2

It works!

One thing to note is that Church encoding has no concept of negative numbers. Our P function handles this in the following way:

P0 (λx.(x(Φ00))T)0 (0(Φ00))T (Φ00)T 0

That is, the predecessor of 0 is 0. This will come in handy later.

Subtraction, at last

With P under our belt at last, subtraction is pretty easy to define now.

:=λab.bPa

This works much like + does, in that to perform 32, you're actually trying to find the second predecessor of three.

32 (λab.bPa)32 (λb.bP3)2 2P3 P(P3) P2 1

And it's done. Simple as cake.

A foundational predicate

Alright, we're going to define our first predicate, which is a function which performs some sort of test on its inputs, and returns either a T or a F. The predicate we are going to define will test whether or not a given Church numeral is equal to 0. It's defined like so:

Z:=λa.aF¬F

Let's test it out:

Z0 (λa.aF¬F)0 0F¬F (λsz.z)F¬F (λz.z)¬F ¬F T

So, it returns T if you provide it 0, as it should. How about other cases?

Z2 (λa.aF¬F)2 2F¬F (λsz.s(sz))F¬F (λz.F(Fz))¬F (F(F¬))F (F((λxy.y)¬))F (F(λy.y))F (FI)F ((λxy.y)I)F (λy.y)F IF F

So, testing on 2, it returns F, as it should. But why?

This again relies upon the inherent properties of the Church numerals. If you provide Z a Church numeral N, then it applies F a total of N times to ¬. But F applied to anything provides you I, the identity function. For any number N which is not 0, ZN will simplify to IF, which simplifies to F. When N equals 0, on the other hand, F is never applied, allowing Z0 to simplify to ¬F, which by definition simplifies to T. Pretty beautiful, huh?

Why did we define this predicate? We'll see soon. It is vital in defining subtraction and many other useful predicates we'll need later.

More predicates, in rapid succession!

Alright, with Z defined, we're ready to make some more predicates. These will all build off of one another in a natural progression, so they shouldn't be too hard to absorb.

Let's start with something that utilizes P's property that P0=0.
How about ?

≤:=λab.Z(ab)

This tests whether a is less than or equal to b, by subtracting b from a. If ab is 0, then we know that b must be equal to or greater than a. Pretty simple.

Here it is showing that 3 is greater than 1 31 (λab.Z(ab))31 (λb.Z(3b))1 Z(31) Z2 F

And here it is showing that 1 is less than or equal to 1.

11 (λab.Z(ab))11 (λb.Z(1b))1 Z(11) Z0 T

As you might imagine, is pretty similar:

≥:=λab.Z(ba)

I'm not going to show in action, as it's extremely similar to .

With both and , we can now test for equality! Since m=n if and only if mn and mn, we have what we need to define =.

=:=λab.(ab)(ab)

Let's test it:

=12 (λab.(ab)(ab))12 (λb.(1b)(1b))2 (12)(12) T(12) TF F

And on one that should pass:

=44 (λab.(ab)(ab))44 (λb.(4b)(4b))4 (44)(44) T(44) TT T

Cool. So, now with , and =, we can define the last two predicates: < and >. They're no surprise, if you realize that a m<n if and only if mm and ¬(m=n). < reflects this:

<:=λab.(¬(=ab))(ab)

Let's give it a shot:

<23 (λab.(¬(=ab))(ab))23 (λb.(¬(=2b))(2b))3 (¬(=23))(23) (¬F)(23) T(23) TT T

How about equality?

<33 (λab.(¬(=ab))(ab))33 (λb.(¬(=3b))(3b))3 (¬(=33))(33) (¬T)(33) F(33) FT F

Again, as you probably have guessed, > is much the same:

>:=λab.(¬(=ab))(ab)

And with that, we have everything we need to keep moving closer to an actual program in the λ-calculus!

Wrapping up

We sure blew through a lot of material with this lesson, and I hope it wasn't too much. But if you've been following along with the previous lessons, nothing here should be too tricky to figure out with a bit of study.

I've posted your homework here.

See you soon for lesson 1.5!

Next lesson: here

blog comments powered by Disqus