Skip navigation

Six years ago, I taught a class called “Lambda Calculus and Applications” at U. Iowa. When I was preparing the course, I was thinking that I would try not to sweep the issue of renaming variables under the rug, which is what is universally done by everyone, except:

  • people trying to formalize a language with bound variables in a theorem prover, and then they use de Bruijn indices (unless they have the happiness to have higher-order abstract syntax available to them, and then they definitely use that).
  • the tiny group of interesting people who actually want to reason about alpha equivalence itself.

Three years ago, I taught the class again. I didn’t quite remember how things went the first time. It had been covid time, I had three children I was mostly caring for. I did have a nagging memory there was some snag…

I talked about beta-reduction. I talked about alpha-equivalence.

And then I started the proof of confluence of…

Something involving beta-reduction and alpha-equivalence?

And then you know what? I remembered that the class eight years ago had run right off the rails in a fireball as I floundered trying to prove confluence with explicit alpha-equivalence. With renewed energy, I tried it again in the class of six years ago. The fireball was bigger this time, because I drove the alpha train with more determination.

I had to set the problem aside for a bit, but I returned to it last year, with a focus on the theorem I ran into which broke the whole program: confluence with explicit alpha-equivalence. Well, we “know” how to do that, because Church and Rosser proved it already. But their proof is not so easy to follow, and the modern way to do the proof, namely the Tait-Martin-Loef method (possibly as improved by Takahashi), hasn’t been extended to explicit alpha-equivalence, to my knowledge. So I set out to do this.

And had a miserable time of it, again. I gave up for another year. The issue was in considering all combinations of alpha-steps and beta-steps from a starting term. It just became intractable.

This summer, feeling pretty positive I guess, I returned to the problem. And I am happy to report that this time, there was progress! (There is a moral to the story of research misery here…!)

The Tait-Martin-Loef proof of confluence relies on a notion of parallel reduction. We can reduce any of the redexes in a term, and their residuals, in one parallel step. The reductions all must be capture-avoiding, of course, which we must state explicitly with named variables. But we cannot reduce any redexes that get created. The proof of confluence follows easily from the central theorem about parallel reduction, that it has the diamond property: if a term t parallel reduces to terms s1 and s2, then those terms parallel reduce to a common term t’. In fact, Takahashi showed that s1 and s2 will both reduce to a term t* computed from t by contracting all the redexes in t. So we have the so-called triangle property: if t parallel reduces to s, then s parallel reduces to t*. (As a corollary, t parallel reduces to t*, since t parallel reduces to itself.)

Now, how to incorporate alpha-equivalence? I am having good success by making alpha-steps part of parallel reduction. So to parallel reduce s to t, you can contract redexes in s or their residuals, and you can also rename bound variables (in a capture-avoiding way) of lambda-terms that are not part of contracted redexes.

To extend Takahashi’s approach, I am using a function acanon, which puts terms t into alpha-canonical form, by computing fresh names (in a canonical way) for the bound variables in t. Canonicity arises because we compute fresh names deterministically from the set of current possibly free variables of the term.

I am happy to report that with this approach, I have completed a proof of a version of a well-known theorem in lambda-calculus with explicit alpha. The theorem says that if variables in a term t are suitably distinct, then t parallel reduces to t* without any alpha-steps. I formulate this as follows: given any term t, the alpha-canonization a of t can be parallel-reduced to a*. This implies that no capture takes place when computing a*, because if it did, a would not be able to parallel-reduce to a*, as parallel-reduction (as I define it) forbids capture.

The repo for my development is here.

My next target is to prove a suitable form of the triangle property: if t parallel-reduces to s, then s parallel-reduces to (acanon t)*. Initial exploration suggests that this will have to be formulated in a somewhat more general way, to account for alpha.

I gave this talk at NEPLS this morning! It was fun, and seemed to get people curious about this problem.

I am releasing a podcast episode where I discuss some parts of the paper “Gödel’s system T revisited”, and here is a brief note with some of the definitions I tried to talk through:

In 2005, I believe it was, I watched Phil Wadler and Frank Pfenning perform a dramatic version of the proof, under Curry-Howard and following Griffin, of the Law of Excluded Middle. Amazing to see Frank in horns. This way of understanding Curry-Howard for LEM has stuck with me ever since. For my spring class, I wrote a script for a version of this story, with (I think) a fun twist at the end. Here it is:

The key to the parable is to connect F in F \vee \neg F with the offer of a billion dollars, and \perp (which is implicit in \neg F, as this is really just F \rightarrow \perp) with a wish. The latter makes sense because if you have a proof of \perp, then you can deduce anything you want (using the elimination rule for \perp), just the way (in stories) a wish gives you the ability to obtain anything you want.

RTA Open Problem 19 asks for a measure-based proof of termination for beta-reduction of simply typed terms. I thought hard about this in the fall (2024) and got… nowhere really. One good thing that came out of the head-banging exercise was finding this paper:

In it, de Vrijer gives a measure-based proof of termination for a related relation, namely reduction of finite developments in untyped lambda calculus. Here, we must mark some redexes in a term, and are only allowed to reduce those redexes or their residuals. A residual redex is one that can be traced back through reduction to a marked redex in the original term.

The paper is very nicely written, and presupposes little background. I found two notable points along the way to the result. First, there is a very easy way to define residual redexes. We just have marked redexes. These are redexes (applications of lambda abstractions to arguments) with some special syntactic mark, like a prime on the lambda. Then reduction is only allowed to reduce marked redexes. Critically, a lambda abstraction by itself cannot be marked, and so if a redex is created by substituting a lambda abstraction for an applied variable, that redex will not be marked, and hence cannot be reduced.

Second, the paper defines a measure based on what the author calls the multiplicity of a variable x in a term t. The interesting part of the definition is that if x occurs as an argument in a marked redex, then the multiplicity needs to include not just the sum of the multiplicities of x in the subterms of that redex, but also we must multiply the multiplicity of x in the argument by the multiplicity of the bound variable of the redex in the body of the abstraction. This is expressed in this equation from the definition of multiplicity of x in t:

Using this notion of multiplicity, it is then straightforward to define a decreasing measure. What we see happening here is a little bit of dataflow analysis: we have to keep track not just of x, but of where x could go if substituted for a variable y. The dataflow analysis is very simple, because we will not reduce created redexes.

Could a fancier dataflow analysis help with Open Problem 19? Will this post be continued…?