Church encoding
In mathematics, Church encoding is a means of embedding data and operators into the lambda calculus, the most familiar form being the Church numerals, a representation of the natural numbers using lambda notation. The method is named for Alonzo Church, who first encoded data in the lambda calculus this way.
Terms that are usually considered primitive in other notations (such as integers, booleans, pairs, lists, and tagged unions) are mapped to higher-order functions under Church encoding; the Church-Turing thesis asserts that any computable operator (and its operands) can be represented under Church encoding.
Many students of mathematics are familiar with Gödel numbering members of a set; Church encoding is an equivalent operation defined on lambda abstractions instead of natural numbers.
Church numerals
Church numerals are the representations of natural numbers under Church encoding. The higher-order function that represents natural number is a function that maps any function to its n-fold composition. In simpler terms, the "value" of the numeral is equivalent to the number of times the function encapsulates its argument.
All Church numerals are functions that take two parameters. Church numerals 0, 1, 2, ..., are defined as follows in the lambda calculus:
Then starting with zero, being not applying the function, then one being applying the function, ...
Number | Function definition | Lambda expression |
---|---|---|
0 | ||
1 | ||
2 | ||
3 | ||
... | ||
n |
Intuitively, Church numeral 3 is a function that performs any supplied function three times. The supplied function is first applied to a supplied parameter and then successively to its own result. It is important to remember that the end result is not the numeral 3 (unless the supplied parameter happens to be 0 and the function is a successor function). The function itself, and not its end result, is the Church numeral 3. As a further intuitive simplification, Church numeral 3 means simply to do anything three times. Furthermore, it contains within its definition an ostensive demonstration of what is meant by "three times".
Computation with Church numerals
In the lambda calculus, numeric functions are representable by corresponding functions on Church numerals. These functions can be implemented in most functional programming languages (subject to type constraints) by direct translation of lambda terms.
The addition function plus(m,n)=m+n uses the identity .
- plus ≡
λm.λn.λf.λx. m f (n f x)
The successor function succ(n)=n+1 is β-equivalent to (plus 1).
- succ ≡
λn.λf.λx. f (n f x)
The multiplication function mult(m,n)=m*n uses the identity .
- mult ≡
λm.λn.λf. m (n f)
The exponentiation function exp(m,n)=m^n is straightforward by the definition of Church numerals.
- exp ≡
λm.λn. n m
The predecessor function works by generating an -fold composition of functions that each apply their argument g
to f
; the base case discards its copy of f
and returns x
.
- pred ≡
λn.λf.λx. n (λg.λh. h (g f)) (λu. x) (λu. u)
The function is probably the most difficult of the basic operations to understand. To gain insight into the operation of it is instructive to look at the expansion of its body when it is applied to the first few Church numerals.
Use abbreviations constx
for (λu. x)
, Evalx
for (λu. (u x))
and G for
- (λg.λh. h (g f)).
Then
- G constx ≡ Evalx,
- G Evalx ≡ Evalf x.
The last rule may be chained, so
- G (G Evalx) ≡ Evalf (f x)
etc. So for N > 0,
- GN constx ≡ EvalfN-1 x.
Applying the above right-hand sides to the identity function (which is the last part of the body of pred
) and including the formal parameters at the beginning gives the predecessor Church numeral for each of the numbers.
The subtraction function can be written based on the predecessor function.
- sub ≡
λm.λn. (n pred) m
Successor
The successor adds one more call to the function f.
Number | Function definition | Lambda expression |
---|---|---|
Addition
To add two numbers n and m first apply the function n times and then apply it m.
Number | Identity | Function definition | Lambda expression | n * Successor |
---|---|---|---|---|
n + m |
Multiplication
Multiplication is also trivial in this encoding. Apply the function f m times to create a function. Then apply this function n times.
Number | Identity | Function definition | Lambda expression | Simplified |
---|---|---|---|---|
Power
Raising to a power is multiplying a number n by itself m times. Composing n with m achieves this.
Number | Function definition | Lambda expression | Simplified |
---|---|---|---|
Predecessor
The predecessor function used in the Church Encoding is,
.
To build the predecessor we need a way of applying the function 1 less time. A numeral n applies the function f n times to x. The predecessor function must use the numeral n to apply the function n-1 times.
Before implementing the predecessor function, here is a scheme that wraps the value in a container function. We will define new functions to use in place of f and x, called inc and init. The container function is called value. The left hand side of the table shows a numeral n applied to inc and init.
Number | Using init | Using const |
---|---|---|
0 | ||
1 | ||
2 | ||
3 | ||
... | ... | ... |
n |
The general recurrence rule is,
If there is also a function to retrieve the value from the container (called extract),
Then extract may be used to define the samenum function as,
The samenum function is not intrinsically useful. What we want is the initial value to skip an application of f. Call this new initial container const. The right hand side of the above table shows the expansions of n inc const. Then by replacing init with const in the expression for the same function we get the predecessor function,
As explained below the functions inc, init, const, value and extract may be defined as,
Which gives the lambda expression for pred as,
Value container
The value container applies a function to its value. It is defined by,
so,
Extract
The value may be extracted by applying the identity function,
Using I,
so,
Inc
The inc function should take a value containing v, and return a new value containing f v.
Letting g be the value container,
then,
so,
Const
To implement pred the init function is replaced with the const that does not apply f. We need const to satisfy,
Which is satisfied if,
Or as a lambda expression,
Subtraction
Then subtraction is defined using pred.
Operation | Lambda expression |
---|---|
Note that minus returns zero if m > n.
Translation with other representations
Most real-world languages have support for machine-native integers; the church and unchurch functions convert between nonnegative integers and their corresponding church numerals. The functions are given here in Haskell, where the \
corresponds to the λ of Lambda calculus. Implementations in other languages are similar.
type Church a = (a -> a) -> (a -> a)
church :: Integer -> Church Integer
church 0 = \f -> \x -> x
church n = \f -> \x -> f (church (n-1) f x)
unchurch :: Church Integer -> Integer
unchurch n = n (\x -> x + 1) 0
Church booleans
Church booleans are the Church encoding of the boolean values true and false. Some programming languages use these as an implementation model for boolean arithmetic; examples are Smalltalk and Pico. Boolean logic may be considered as a choice. Given two parameters and two values, a true function could choose the first parameter, and the false. The two definitions are known as Church Booleans.
Note that this definition allows predicates (i.e. functions returning logical values) to directly act as if-clauses, e.g. if predicate is a unary predicate,
- predicate x then-clause else-clause
evaluates to then-clause if predicate x evaluates to true, and to else-clause if predicate x evaluates to false.
Because true and false choose the first or second parameter they may be combined to provide logic operators,
- - This is only a correct implementation if the evaluation strategy is applicative order.
- - This is only a correct implementation if the evaluation strategy is normal order.
Some examples:
Predicates
A predicate is a function that returns a Boolean value. The most fundamental predicate is , which returns if its argument is the Church numeral , and if its argument is any other Church numeral:
The following predicate tests whether the first argument is less-than-or-equal-to the second:
- ,
Because of the identity,
The test for equality may be implemented as,
Church pairs
Church pairs are the Church encoding of the pair (two-tuple) type. The pair is represented as a function that takes a function argument. When given its argument it will apply the argument to the two components of the pair.
Formal definition in lambda calculus:
For example,
List encodings
An encoding of (immutable) lists of varying length must define a constructor for creating an empty list (nil), an operation testing whether or not a list is empty (isnil), an operation to prepend a given value to a (possibly empty) list (cons), and two operations to determine the first element and the list of the remaining elements of a nonempty list (head and tail).
Church pairs
A nonempty list can basically be encoded by a Church pair with the head of the list stored in the first component of the pair and the tail of the list in the second component. However, special care is needed to unambiguously encode the empty list. This can be achieved by encapsulating any individual list node within the second component of another pair whose first component contains a Church boolean which is true for the empty list and false otherwise, similar to a tagged union. Using this idea the basic list operations can be defined like this:[1]
- nil ≡ pair true true
- isnil ≡ fst
- cons ≡ λh.λt.pair false (pair h t)
- head ≡ λz.fst (snd z)
- tail ≡ λz.snd (snd z)
The second component of the pair encoding nil is never used provided that head and tail are only applied to nonempty lists.
Alternatively, one can define [2]
- cons ≡ pair
- head ≡ fst
- tail ≡ snd
- nil ≡ false
- isnil ≡ λl.l (λh.λt.λd.false) true
where the last definition is a special case of the general
- process-list ≡ λl.l (λh.λt.λd. head-and-tail-clause) nil-clause
Higher-order function
As an alternative to the encoding using Church pairs, a list can be encoded by identifying it with its right fold function. For example, a list of three elements x, y and z can be encoded by a higher-order function which when applied to a combinator c and a value n returns c x (c y (c z n)).
- nil ≡
λc.λn.n
- isnil ≡
λl.l (λh.λt.false) true
- cons ≡
λh.λt.λc.λn.c h (t c n)
- head ≡
λl.l (λh.λt.h) false
- tail ≡
λl.fst (l (λx.λp.pair (snd p) (cons x (snd p))) (pair nil nil))
See also
- Lambda calculus
- System F for Church numerals in a typed calculus
- Mogensen–Scott encoding
References
- Directly Reflective Meta-Programming
- Church numerals and booleans explained by Robert Cartwright at Rice University
- Theoretical Foundations For Practical 'Totally Functional Programming' (Chapters 2 and 5) All about Church and other similar encodings, including how to derive them and operations on them, from first principles
- Some interactive examples of Church numerals
- ^ Pierce, Benjamin C. (2002). Types and Programming Languages. MIT Press. p. 500. ISBN 978-0-262-16209-8.
- ^ John Tromp, Binary Lambda Calculus and Combinatory Logic, in Randomness And Complexity, from Leibniz To Chaitin, ed. Cristian S. Calude, World Scientific Publishing Company, October 2008. (pdf version)