Lambda calculus definition

Short description: Mathematical formalism

For a general introduction, see Lambda calculus.

The lambda calculus is a formal mathematical system consisting of constructing lambda terms and performing reduction operations on them. The definition of a lambda term is simply a variable, a lambda abstraction, or a function application, but a formal presentation can be somewhat lengthy. The focus of this article is to present a full and complete definition of the lambda calculus, specifically the pure untyped lambda calculus without extensions, although a lambda calculus extended with numbers and arithmetic is used for explanatory purposes.

## Contents

* 1 Lambda terms
* 1.1 Free and bound variables
* 1.2 Notation
* 2 Transformation and reduction
* 2.1 α-conversion
* 2.2 Substitution
* 2.3 β-reduction
* 2.4 η-reduction
* 3 Evaluation and normalization
* 4 Notes
* 5 References

## Lambda terms

The lambda calculus consists of a language of lambda terms, that are defined by a certain formal syntax. The syntax of the lambda calculus defines some expressions as valid lambda calculus expressions and some as invalid, just as some strings of characters are valid computer programs and some are not. A valid lambda calculus expression is called a "lambda term". In the simplest form of lambda calculus, terms are built using only the following three rules. These rules give an inductive definition that can be applied to build all syntactically valid lambda terms, and produce expressions such as: (λx.λy.(λz.(λx.z x) (λy.z y))(x y)).[1]

1. A variable x is a character or string representing a parameter, itself a valid lambda term.
2. A lambda abstraction (λx.M) is a function definition, taking as input the bound variable x (between the λ and the punctum/dot .) and returning the body M. The definition of a function with an abstraction merely "sets up" the function but does not invoke it. An abstraction denotes an anonymous function that takes a single input x and returns M. The syntax (λx.M) binds the variable x in the term M. For example, λx.(x2+2) is an abstraction representing the anonymous function x↦x2+2. More concretely, we might give this function the name f, and then we could write f(x)=x2+2,, although this name f is superfluous when using the lambda calculus.
3. An application (M N) represents the application of a function M to an argument N. Both M and N are lambda terms. The application represents the act of calling function M on input N to produce M(N).

In Extended Backus-Naur Form, this might be summarized as e::=v∣(λv.e)∣(ee), where the variables v come from an infinite set v1,v2,v3,…, and the other symbols consist of lambda 'λ', dot '.', and parentheses '(' and ')'. A more formal and permissive presentation of the grammar might be as follows:

Name | BNF | Description

|
|

Expression |

<expression> ::= <abstraction> | <application> | <variable> | <bracket>

| A lambda term is either an abstraction, an application, a variable, or a bracketed expression.
Abstraction |

<abstraction> ::= λ <variable-list> . <expression>

| Anonymous function definition.
Variable list |

<variable-list> ::= <variable> , <variable-list> | <variable>

| A comma separated list of variables.
Application |

<application> ::= <expression> <expression>+

| An application (function call) is two or more expressions in a row.
Variable |

<variable> ::= <alpha> (<alpha> | <digit> | '_')*

| A variable name, e.g. x, y, fact, sum, ...
Grouping |

<bracket> ::= ( <expression> )

| Expression bracketed with parentheses.

The set of lambda expressions is defined inductively, for example as a set Λ, where the results of applying rules 1-3 are all and only the elements of Λ. In the strictest sense, nothing else is a lambda term. That is, a lambda term is valid if and only if it can be obtained by repeated application of these three rules. Formally:

1. If x is a variable, then x ∈ Λ.
2. If x is a variable and M ∈ Λ, then (λx.M) ∈ Λ.
3. If M, N ∈ Λ, then (M N) ∈ Λ.

Instances of rule 2 are known as abstractions and instances of rule 3 are known as applications.[2]

It is also common to extend the syntax presented here with additional operations, for example introducing terms for mathematical constants and operations, which allows making sense of terms such as λx.x2. The untyped lambda calculus is flexible in that it does not distinguish between different kinds of data. For instance, there may be a function intended to operate on numbers. However, in the untyped lambda calculus, there is no way to prevent a function from being applied to truth values, strings, or other non-number objects. Depending on the encoding of the data, this may lead to nonsensical results, or work as intended.

### Free and bound variables

Following the mathematical concepts of free variables and bound variables, the abstraction operator, λ, is said to bind its variable wherever it occurs in the body of the abstraction. Variables that fall within the scope of an abstraction are said to be bound, and the part λx is often called the binder of x. Variables that are not bound are called free. For example, the function definition f(x)=x+y could be represented as the lambda term λx.(x+y), which contains two variables, x and y. The variable x is bound by the lambda abstraction, while y is free. The free variable y has not been defined and is considered an unknown. The abstraction λx.(x+y) is a syntactically valid term and represents a function that adds its input to the yet-unknown y. Also note that a variable is bound by its "nearest" abstraction. In the following example the single occurrence of x in the expression is bound by the second lambda: λx.y(λx.z x) A variable may occur both free and bound in a term; for example y in y(λy.y).

More formally, the sets of free variables and bound variables of a lambda expression, M, are denoted as FV⁡(M) and BV⁡(M) and can be defined by recursion on the structure of the terms, as follows:[3][4]

FV⁡(M) \- Free Variable Set  | Comment  | BV⁡(M) \- Bound Variable Set  | Comment

|
|
|

FV⁡(x)={x} | where x is a variable. In words, the free variables of x are just x.  | BV⁡(x)=∅ | where x is a variable
FV⁡(λx.M)=FV⁡(M)∖{x} | Free variables of M, but with x removed  | BV⁡(λx.M)=BV⁡(M)∪{x} | Bound variables of M plus x.
FV⁡(M N)=FV⁡(M)∪FV⁡(N) | Union of the free variables from the function and the parameter  | BV⁡(M N)=BV⁡(M)∪BV⁡(N) | Union of the bound variables from the function and the parameter

An expression that contains no free variables is said to be closed. Closed lambda expressions are also known as combinators and are equivalent to terms in combinatory logic. It is common to restrict discussion to only closed terms, and some presentations of the lambda calculus only consider closed terms. For example, the lambda term representing the identity λx.x has no free variables and is closed.

### Notation

For convenience, parentheses can be dropped if the expression is unambiguous. For example, the outermost parentheses can always be dropped—M N instead of (M N). However, not all parentheses can be eliminated. For example,

1. λx.((λx.x)x) is of form λx.B and is therefore an abstraction, while
2. (λx.(λx.x))x is of form MN and is therefore an application.

The examples 1 and 2 denote different terms, differing only in where the parentheses are placed. They have different meanings: example 1 is a function definition, while example 2 is a function application. The lambda variable x is a placeholder in both examples.

Here, example 1 defines a function λx.B, where B is (λx.x)x, an anonymous function (λx.x), with input x; while example 2, M N, is M applied to N, where M is the lambda term (λx.(λx.x)) being applied to the input N which is x. Both examples 1 and 2 would evaluate to the identity function λx.x.

To allow further concision in these situations, the following conventions are usually applied:

* Applications are assumed to be left-associative: M N P may be written instead of ((M N) P)[5]
* The body of an abstraction extends as far right as possible: λx.M N means λx.(M N) and not (λx.M) N. Said another way, a lambda abstraction has a lower precedence than an application.
* A sequence of abstractions is contracted: λx.λy.λz.N is abbreviated as λxyz.N[6][7][5]
* When all variables are single-letter, the space in applications may be omitted: MNP instead of M N P.[8]

## Transformation and reduction

The meaning of lambda expressions is defined by how expressions can be transformed and reduced.[9]

There are three kinds of transformation:

* α-conversion: changing bound variables (alpha);
* β-reduction: applying functions to their arguments (beta), calling functions;
* η-reduction: which captures a notion of extensionality (eta).

We also speak of the resulting equivalences: two expressions are β-equivalent, if they can be β-converted into the same expression, and α/η-equivalence are defined similarly.

The term redex, short for reducible expression, refers to subterms that can be reduced by one of the reduction rules. For example, (λx.M) N is a β-redex in expressing the substitution of N for x in M; if x is not free in M, λx.M x is an η-redex. The expression to which a redex reduces is called its reduct; using the previous example, the reducts of these expressions are respectively M[x:=N] and M.

### α-conversion

α-conversion (alpha-conversion), sometimes known as α-renaming,[10] allows bound variable names to be changed. For example, alpha-conversion of λx.x might yield λy.y. The terms x and y by themselves are not alpha-equivalent, because they are not bound in an abstraction. Terms that differ only by alpha-conversion are called α-equivalent, capturing the intuition that the particular choice of a bound variable, in an abstraction, does not (usually) matter. Frequently in uses of lambda calculus, α-equivalent terms are considered to be equivalent.

The precise rules for alpha-conversion are not completely trivial. First, when alpha-converting an abstraction, the only variable occurrences that are renamed are those that are bound by the same abstraction. For example, an alpha-conversion of λx.λx.x could result in λy.λx.x, but it could not result in λy.λx.y. The latter has a different meaning from the original. This is analogous to the programming notion of variable shadowing.

Second, alpha-conversion is not possible if it would result in a variable getting captured by a different abstraction. For example, if we replace x with y in λx.λy.x, we get λy.λy.y, which is not at all the same. In the De Bruijn index notation, any two α-equivalent terms are syntactically identical, and confusion in this way cannot occur.

See example:

α-conversion  | λ-expression  | de Brujin notation  | Comment

|
|
|

| λz.λy.(z y) | λ.λ.(21) | Original expressions.
correctly rename y to k, (because k is not used in the body)  | λz.λk.(z k) | λ.λ.(21) | No change to de Brujin expression.
naively rename y to z, (wrong because z free in λy.(z y))  | λz.λz.(z z) | λ.λ.(11) | z is captured.

### Substitution

Substitution, written E[V:=R], is the process of replacing all free occurrences of the variable V in the expression E with expression R. Substitution on terms of the lambda calculus is defined by recursion on the structure of terms, as follows (note: x and y are variables while M and N are any λ expression).

* x[x:=N]=N ; with N substituted for x, x becomes N
* y[x:=N]=y if x≠y ; with N substituted for x, y (which is not x) remains y
* (M1 M2)[x:=N]=(M1[x:=N])(M2[x:=N]) ; substitution distributes to both sides of an application
* (λx.M)[x:=N]=λx.M ; a variable bound by an abstraction is not subject to substitution; substituting such a variable leaves the abstraction unchanged
* (λy.M)[x:=N]=λy.(M[x:=N]) if x≠y and y∉FV(N); substituting a variable which is not bound by an abstraction proceeds in the abstraction's body, provided that the abstracted variable y is "fresh" for the substitution term N, meaning it does not appear among the free variables of N.

For example, (λx.x)[y:=y]=λx.(x[y:=y])=λx.x, and ((λx.y)x)[x:=y]=((λx.y)[x:=y])(x[x:=y])=(λx.y)y.

The freshness condition (requiring that y is not in the free variables of N) is crucial in order to ensure that substitution does not change the meaning of functions. The situation where the substituted x was supposed to be free but ended up being bound is a situation known as capturing x. To substitute into a lambda abstraction, it is sometimes necessary to α-convert the expression. For example, this substitution (λx.y)[y:=x]≠λx.(y[y:=x])=λx.x is erroneous because it would turn the constant function λx.y into the identity λx.x. The correct substitution is to rename the bound variable using α-equivalence, in this case (λx.y)[y:=x]=(λz.y)[y:=x]=λz.(y[y:=x])=λz.x.

In general, failure to meet the freshness condition can be remedied by alpha-renaming first, with a suitable fresh variable. Substitution is defined uniquely up to α-equivalence. Most implementations of substitution use alpha-conversion automatically to avoid capture during substitution, an operation called capture-avoiding substitution. In programming languages with static scope, capture-avoiding substitution can be used to implement name resolution by carefully handling variable shadowing in containing scopes. Another strategy is to require alpha renaming in the source program to make name resolution trivial. If De Bruijn indexing is used, then α-conversion is no longer required, as there will be no name collisions. Variable names are also not needed if a universal function is used, such as in Iota and Jot.

### β-reduction

β-reduction (beta reduction) captures the idea of function application. β-reduction is defined in terms of substitution: the β-reduction of ((λV.E) E′) is E[V:=E′]. The β-reduction rule states that an application of the form (λx.t)s reduces to the term t[x:=s]. The notation (λx.t)s->t[x:=s] is used to indicate that (λx.t)s β-reduces to t[x:=s]. β-reduction captures the idea of function application (also called a function call), and implements the substitution of the actual parameter expression for the formal parameter variable. β-reduction can be seen to be the same as the concept of local reducibility in natural deduction, via the Curry–Howard isomorphism.

For example, for every s, (λx.x)s->x[x:=s]=s. This demonstrates that λx.x really is the identity. Similarly, (λx.y)s->y[x:=s]=y, which demonstrates that λx.y is a constant function. Assuming some encoding of 2,7,×, we have the following β-reduction: ((λn. n×2) 7)->7×2.

More formally, β-reduction may be performed on the lambda abstraction without alpha renaming only if no variable names are free in the actual parameter and bound in the body:[lower-alpha 1]

FV(y)∩BV(b)={}->(λx.b) y=b[x:=y]

Alpha renaming may be used on b to rename names that are free in y but bound in b, to meet the pre-condition for this transformation. See example:

β-reduction  | λ-expression  | de Brujin notation  | Comment

|
|
|

| (λx.λy.(λz.(λx.z x)(λy.z y))(x y)) | (λ.λ.(λ.(λ.21)(λ.21))(21)) | Original expressions.
Naive beta 1,  | (λx.λy.((λx.(x y)x)(λy.(x y)y))) |  | Correct  | (λ.λ.((λ.(32)1)(λ.(32)1)))

|

Incorrect  | (λ.λ.((λ.(12)1)(λ.(31)1)))
x and y have been captured in the substitution.
Alpha rename inner, x -> a, y -> b  | (λx.λy.(λz.(λa.z a)(λb.z b))(x y)) | (λ.λ.(λ.(λ.21)(λ.21))(21)) |
Beta 2,  | (λx.λy.((λa.(x y)a)(λb.(x y)b))) | (λ.λ.((λ.(32)1)(λ.(32)1))) | x and y not captured.

Looking closer, the key substitutions are

((λx.z x)(λy.z y))[z:=(x y)](blocked - will capture)((λa.z a)(λb.z b))[z:=(x y)](allowed - no capture)

In this example,

1. In the β-redex,
1. The free variables are, FV⁡(x y)={x,y}
2. The bound variables are, BV⁡((λx.z x)(λy.z y))={x,y}
2. The naive β-reduction changed the meaning of the expression because x and y from the actual parameter became captured when the expressions were substituted in the inner abstractions.
3. The alpha renaming removed the problem by changing the names of x and y in the inner abstraction so that they are distinct from the names of x and y in the actual parameter.
1. The free variables are, FV⁡(x y)={x,y}
2. The bound variables are, BV⁡((λa.z a)(λb.z b))={a,b}
4. The β-reduction then proceeded with the intended meaning.

### η-reduction

η-reduction (eta reduction) converts from λx.(fx) to f, given that x does not appear free in f. The problem with using an η-reduction when f has free variables is shown in this example:

η-reduction | Lambda expression | β-reduction

|
|

| (λx.(λy.yx)x)a | aa
Naive  | (λy.yx)a | ax

This improper use of η-reduction changes the meaning by leaving x in λy.yx unsubstituted.

η-reduction | Lambda expression | β-reduction

|
|

| (λx.(λy.xy)x)a | aa
Correct  | (λx.xx)a | aa

η-reduction is often paired with its inverse, η-expansion, which converts from f to λx.(fx), again given that x does not appear free in f. The two processes together are called η-conversion. η-conversion expresses the idea of extensionality,[12] which in this context is that two functions are the same if and only if they give the same result for all arguments. η-conversion can be seen to be the same as the concept of local completeness in natural deduction, via the Curry–Howard isomorphism.

## Evaluation and normalization

The lambda calculus may be seen as an idealized version of a functional programming language, like Haskell or Standard ML. Under this view, β-reduction corresponds to a computational step. This step can be repeated by additional β-reductions until there are no more applications left to reduce. If evaluation does terminate, the result is a lambda expression that cannot be reduced further by β-reduction. This is called the normal form of the expression. A lambda expression that cannot be reduced further by β-reductions is in beta normal form, and similarly if it also cannot be reduced by η-reductions it is in beta-eta normal form. All normal forms that can be converted into each other by α-conversion are defined to be equal. By the Church–Rosser theorem, the normal form is unique if it exists, regardless of the order in which the reductions are performed (the reduction strategy).

However, not all lambda expressions have a normal form. For example, consider the term Ω=(λx.xx)(λx.xx). Here (λx.xx)(λx.xx)->(xx)[x:=λx.xx]=(x[x:=λx.xx])(x[x:=λx.xx])=(λx.xx)(λx.xx). That is, the term reduces to itself in a single β-reduction, and therefore the reduction process will never terminate. Typed lambda calculi, such as the simply typed lambda calculus, do not allow the construction of terms like Ω, and therefore all well-typed terms in these systems have a normal form.

## Notes

1. ↑ Barendregt, Barendsen (2000) call this form
* axiom β: (λx.M[x]) N = M[N] , rewritten as (λx.M) N = M[x := N], "where M[x := N] denotes the substitution of N for every occurrence of x in M".[3]: 7 Also denoted M[N/x], "the substitution of N for x in M".[11]

## References

1. ↑ Barendregt, Hendrik Pieter (1984), The Lambda Calculus: Its Syntax and Semantics, Studies in Logic and the Foundations of Mathematics, 103 (Revised ed.), North Holland, Amsterdam., ISBN 978-0-444-87508-2, http://www.elsevier.com/wps/find/bookdescription.cws_home/501727/description -- Corrections
2. ↑ Barendregt, Hendrik Pieter (1984). The Lambda Calculus: Its Syntax and Semantics. Studies in Logic and the Foundations of Mathematics. 103 (Revised ed.). North Holland. ISBN 0-444-87508-5. https://www.elsevier.com/books/the-lambda-calculus/barendregt/978-0-444-87508-2. (Corrections).
3. ↑ 3.0 3.1 Barendregt, Henk; Barendsen, Erik (March 2000), Introduction to Lambda Calculus, https://ftp.science.ru.nl/CSI/CompMath.Found/lambda.pdf
4. ↑ The Lambda Calculus - Its Syntax and Semantics. Studies in Logic and the Foundations of Mathematics. 103. Amsterdam: North-Holland. 1985. ISBN 0444867481. Here: Def.2.1.6, p.24
5. ↑ 5.0 5.1 "Example for Rules of Associativity". Lambda-bound.com. http://www.lambda-bound.com/book/lambdacalc/node27.html.
6. ↑ Selinger, Peter (2008), Lecture Notes on the Lambda Calculus, 0804, Department of Mathematics and Statistics, University of Ottawa, p. 9, Bibcode: 2008arXiv0804.3434S, http://www.mathstat.dal.ca/~selinger/papers/lambdanotes.pdf
7. ↑ "Example for Rule of Associativity". Lambda-bound.com. http://www.lambda-bound.com/book/lambdacalc/node25.html.
8. ↑ "The Basic Grammar of Lambda Expressions". https://softoption.us/node/33. "Some other systems use juxtaposition to mean application, so 'ab' means 'a@b'. This is fine except that it requires that variables have length one so that we know that 'ab' is two variables juxtaposed not one variable of length 2. But we want to labels like 'firstVariable' to mean a single variable, so we cannot use this juxtaposition convention."
9. ↑ de Queiroz, Ruy J. G. B. (1988). "A Proof-Theoretic Account of Programming and the Role of Reduction Rules". Dialectica 42 (4): 265–282. doi:10.1111/j.1746-8361.1988.tb00919.x.
10. ↑ Turbak, Franklyn; Gifford, David (2008), Design concepts in programming languages, MIT press, p. 251, ISBN 978-0-262-20175-9
11. ↑ explicit substitution in nLab
12. ↑ Luke Palmer (29 Dec 2010) Haskell-cafe: What's the motivation for η rules?

0.00

(0 votes)

Original source: https://en.wikipedia.org/wiki/Lambda calculus definition. Read more

|

Retrieved from "https://handwiki.org/wiki/index.php?title=Lambda_calculus_definition&oldid=4413184"