User:Andrew Cave/Combinatory Logic

Completeness of the S-K basis
It is perhaps astonishing that S and K can be composed to produce combinators that are extensionally equal to any lambda term, and therefore, by Church's thesis, to any computable function whatsoever. The proof is to present a transformation, T[ ], which converts an arbitrary lambda term into an equivalent combinator.

The transformation D[ ] converts a combinatory logic term which uses a free variable into one that takes it as input. (Deduction theorem)

D[ ] may be defined as follows:


 * 1)       D[x.x]       => I
 * 2)       D[x.E]       => (K E)         (if x does not occur free in E)
 * 3)       D[x.(E₁ E₂)] => (S D[x.E₁] D[x.E₂])

Alternatively (produces larger terms):


 * 1)       D[x.x]       => I
 * 2)       D[x.y]       => (K y)         (if y ≠ x)
 * 3)       D[x.S]       => (K S)
 * 4)       D[x.K]       => (K K)
 * 5)       D[x.(E₁ E₂)] => (S D[x.E₁] D[x.E₂])

T[ ] may be defined as follows:

This process is also known as abstraction elimination.
 * 1)       T[x]          => x
 * 2)       T[(E₁ E₂)]    => (T[E₁] T[E₂])
 * 3)       T[λx.E]    => D [ x.T [ E ]]

(Everything after this needs appropriate revising)

Conversion of a lambda term to an equivalent combinatorial term
For example, we will convert the lambda term λx.λy.(y x) to a combinator:


 * T[λx.λy.(y x)]
 * = T [ λx.T [ λy.(y x) ]] (by 5)
 * = T[λx.(S T[λy.y] T[λy.x])] (by 6)
 * = T[λx.(S I      T[λy.x])] (by 4)
 * = T[λx.(S I      (K x))] (by 3 and 1)
 * = (S T[λx.(S I)] T[λx.(K x)]) (by 6)
 * = (S (K (S I))  T[λx.(K x)]) (by 3)
 * = (S (K (S I))  (S T[λx.K] T[λx.x])) (by 6)
 * = (S (K (S I))  (S (K K)   T[λx.x])) (by 3)
 * = (S (K (S I))  (S (K K)   I)) (by 4)

If we apply this combinator to any two terms x and y, it reduces as follows:


 * (S (K (S I))  (S (K K)   I) x y)
 * = (K (S I) x (S (K K)   I x) y)
 * = (S I (S (K K)  I x) y)
 * = (I y (S (K K)  I x y))
 * = (y (S (K K)  I x y))
 * = (y (K K x (I x) y))
 * = (y (K (I x) y))
 * = (y (I x))
 * = (y x)

The combinatory representation, (S (K (S I)) (S (K K) I)) is much longer than the representation as a lambda term, λx.λy.(y x). This is typical. In general, the T[ ] construction may expand a lambda term of length n to a combinatorial term of length Θ(3n).

Explanation of the T[ ] transformation
The T[ ] transformation is motivated by a desire to eliminate abstraction. Two special cases, rules 3 and 4, are trivial: λx.x is clearly equivalent to I, and λx.E is clearly equivalent to (K T[E]) if x does not appear free in E.

The first two rules are also simple: Variables convert to themselves, and applications, which are allowed in combinatory terms, are converted to combinators simply by converting the applicand and the argument to combinators.

It's rules 5 and 6 that are of interest. Rule 5 simply says that to convert a complex abstraction to a combinator, we must first convert its body to a combinator, and then eliminate the abstraction. Rule 6 actually eliminates the abstraction.

λx.(E₁ E₂) is a function which takes an argument, say a, and substitutes it into the lambda term (E₁ E₂) in place of x, yielding (E₁ E₂)[x : = a]. But substituting a into (E₁ E₂) in place of x is just the same as substituting it into both E₁ and E₂, so

(E₁ E₂)[x := a] = (E₁[x := a] E₂[x := a])

(λx.(E₁ E₂) a) = ((λx.E₁ a) (λx.E₂ a)) = (S λx.E₁ λx.E₂ a) = ((S λx.E₁ λx.E₂) a)

By extensional equality,

λx.(E₁ E₂)    = (S λx.E₁ λx.E₂)

Therefore, to find  a combinator equivalent to λx.(E₁ E₂), it is sufficient to find a combinator equivalent to (S λx.E₁ λx.E₂), and

(S T[λx.E₁] T[λx.E₂])

evidently fits the bill. E₁ and E₂ each contain strictly fewer applications than (E₁ E₂), so the recursion must terminate in a lambda term with no applications at all—either a variable, or a term of the form λx.E.

η-reduction
The combinators generated by the T[ ] transformation can be made smaller if we take into account the η-reduction rule:

T[λx.(E x)] = T[E]  (if x is not free in E)

λx.(E x) is the function which takes an argument, x, and applies the function E to it; this is extensionally equal to the function E itself. It is therefore sufficient to convert E to combinatorial form.

Taking this simplification into account, the example above becomes:

T[λx.λy.(y x)] = ...       = (S (K (S I))   T[λx.(K x)]) = (S (K (S I))  K)                 (by η-reduction)

This combinator is equivalent to the earlier, longer one:

(S (K (S I))  K x y) = (K (S I) x (K x) y) = (S I (K x) y) = (I y (K x y)) = (y (K x y)) = (y x)

Similarly, the original version of the T[ ] transformation transformed the identity function λf.λx.(f x) into (S (S (K S) (S (K K) I)) (K I)). With the η-reduction rule, λf.λx.(f x) is transformed into I.

One-point basis
There are one-point bases from which every combinator can be composed extensionally equal to any lambda term. The simplest example of such a basis is {X} where:

X ≡ λx.((xS)K)

It is not difficult to verify that: X (X (X X)) =ηβ K and X (X (X (X X))) =ηβ S.

Since {K, S} is a basis, it follows that {X} is a basis too. The Iota programming language uses X as its sole combinator.

Another simple example of a one-point basis is:

X' ≡ λx.(x K S K) with (X' X') X' =β K and X' (X' X') =β S

X'  does not need η contraction in order to produce K and S.

Combinators B, C
In addition to S and K, Schönfinkel's paper included two combinators which are now called B and C, with the following reductions:

(C f x y) = (f y x) (B f g x) = (f (g x))

He also explains how they in turn can be expressed using only S and K.

These combinators are extremely useful when translating predicate logic or lambda calculus into combinator expressions. They were also used by Curry, and much later by David Turner, whose name has been associated with their computational use. Using them, we can extend the rules for the transformation as follows:


 * 1)       T[x]          => x
 * 2)       T[(E₁ E₂)]    => (T[E₁] T[E₂])
 * 3)       T[λx.E]       => (K T[E])         (if x is not free in E)
 * 4)       T[λx.x]       => I
 * 5)       T[λx.λy.E]    => T [ λx.T [ λy.E ]] (if x is free in E)
 * 6)       T[λx.(E₁ E₂)] => (S T[λx.E₁] T[λx.E₂]) (if x is free in both E₁ and E₂)
 * 7)       T[λx.(E₁ E₂)] => (C T[λx.E₁] T[E₂]) (if x is free in E₁ but not E₂)
 * 8)       T[λx.(E₁ E₂)] => (B T[E₁] T[λx.E₂]) (if x is free in E₂ but not E₁)

Using B and C combinators, the transformation of λx.λy.(y x) looks like this:

T[λx.λy.(y x)] = T [ λx.T [ λy.(y x) ] ] = T[λx.(C T[λy.y] x)]    (by rule 7) = T[λx.(C I x)] = (C I)                  (η-reduction) = C*(traditional canonical notation : X* = X I) = I'(traditional canonical notation: X' = C X)

And indeed, (C I x y) does reduce to (y x):

(C I x y) = (I y x) = (y x)

The motivation here is that B and C are limited versions of S. Whereas S takes a value and substitutes it into both the applicand and its argument before performing the application, C performs the substitution only in the applicand, and B only in the argument.

The modern names for the combinators come from Haskell Curry's doctoral thesis of 1930 (see B,C,K,W System). In Schönfinkel's original paper, what we now call S, K, I, B and C were called S, C, I, Z, and T respectively.

The reduction in combinator size that results from the new transformation rules can also be achieved without introducing B and C, as demonstrated in Section 3.2 of.

CLK versus CLI calculus
A distinction must be made between the CLK as described in this article and the CLI calculus. The distinction corresponds to that between the λK and the λI calculus. Unlike the λK calculus, the λI calculus restricts abstractions to:
 * λx.E where x has at least one free occurrence in E.

As a consequence, combinator K is not present in the λI calculus nor in the CLI calculus. The constants of CLI are: I, B, C and S, which form a basis from which all CLI terms can be composed (modulo equality). Every λI term can be converted into an equal CLI combinator according to rules similar to those presented above for the conversion of λK terms into CLK combinators. See chapter 9 in Barendregt (1984).

Reverse conversion
The conversion L[ ] from combinatorial terms to lambda terms is trivial:

L[I]      = λx.x L[K]      = λx.λy.x L[C]      = λx.λy.λz.(x z y) L[B]      = λx.λy.λz.(x (y z)) L[S]      = λx.λy.λz.(x z (y z)) L[(E₁ E₂)] = (L[E₁] L[E₂])

Note, however, that this transformation is not the inverse transformation of any of the versions of T[ ] that we have seen.