Home >> Science >> Math >> Logic and Foundations >> Computational Logic >> Combinatory Logic and Lambda Calculus


  Formulae-as-Types Correspondence
       


Combinative logic occurs as notation introduced by Moses Schönfinkel and Haskell Curry to eliminate the want for variables in mathematical logic. It has sir thomas more recently been utilized inside computing as a theoretical model of computation & as well as a basis for the project of functional programing language.

Combinatory logic in mathematics

Combinative logic was designed as a elementary 'pre-logic' which would clarify a meaning of variables within logical notation, & indeed eliminate a require for the babies.

Understand Curry, 1958-72.

Combinatory logic in computing

Around computing, combinative logic is utilized as a simplified model of computation, used within computability theory (the learn of what may be computed) & proof theory (the learn of what may be mathematically proven.) The theory, despite its simplicity, captures several essential features of the nature of computation.

Combinative logic may be scanned at as a variation of the lambda calculus, in which lambdthe expressions (utilized to provide functional abstraction) come replaced by a limited placed of combinators, primitive functions which contain there is no free variables. These are easily to transform lambda expressions into combinator expressions, & since combinator reduction is tremendously simpler than lambda reduction, it hwhen been utilized as a basis for the implementation of a bit of non-strict functional programming languages in software package & hardware.

It can too exist as surfed at around a total of more manners, by having numbers of early papers showing the equivalence of various combinators to various logic axioms [Hindley and Meredith, 1990].

Summary of the lambda calculus

For complete details just about a lambda calculus, see a article under it head. You may summarize on this text. A lambda calculus is caring using objects known as lambda-terms, which are then strings of symbols of one of a below forms:

v λv.E1 (E1 E2)

in which v occurs as variable title drawn from either the predefined infinite placed of variable list, & E1 & E2 come lambda-terms. Terms of the form λv.E1 come known as abstractions. A variable v is known as a formal parameter of the abstraction, and E1 is the body of a abstraction.

A term λv.E1 is a work which, applied to an argument, binds a formal parameter five to the argument and then computes a resultant value of E1---that is, it is restored E1, by having each occurrence of v replaced per argument.

Terms of the form (E1 E2) come known as applications. Applications model work invocation or even execution: a function delineate by E1 is to become invoked, sustaining E2 when its argument, & a symptom is computed. Whenever E1 (periodically known as the applicand) is an abstraction, a term can be reduced: E2, a argument, can be substituted into a body of E1 in situ of a formal parameter of E1, & a effect occurs as recently lambda term which is same to the old a single. Whenever the lambda term contains no subterms of the form (λv.E1 E2) so it just can't become reduced, & is said to exist as within normal form.

A expression E[v := a] is a symptom of ingesting a term E & replacing whole loose occurrences of v by having a. So i write

By convention, you choose (the b 100 d ... z) when short for (...(((the b) one hundred) d) ... z). (we.e., application is left associative.)

A motivation for this definition of reduction is that it captures a essential behavior of 100% mathematical functions. E.g., assume the work that computes a square of a total. I personally might write

(Applying "*" to imply multiplication.) x on this text is the formal parameter of the function. To evaluate the square for a particular argument, say Trio, i insert it into a definition in situ of the formal parameter:

To evaluate a consequent expression 3*3, i would stand to resort to my noesis of multiplication & a total Ternion. Since any computation is only the composition of the evaluation of suitable functions in suitable primitive arguments, this elementary substitution principle suffices to capture a essential mechanism of computation. What is more, in the lambda calculus, notions like 'Deuce-ace' & '*' can be delineate forswearing any require for externally defined primitive operators or even constants. These are conceivable to identify terms in the lambda calculus, which, whilst appropriately interpreted, behave rather the total Ternary & rather a multiplication operator.

A lambda calculus is known to become computationally same around power to numbers of more plausible system for computation (including Turing machines); that is, any calculation that can be accomplished in any one more system may be expressed in the lambda calculus, and the other way around. Based on data from a Church-Turing thesis, both models could express any imaginable computation.

These are mayhap surprising that lambda-calculus might represent any conceivable computation applying lone a elementary notions of function abstraction & application according to elementary textual substitution of terms for variables. However possibly other remarkable is that abstraction is non potentially involved. Combinative logic occurs as model of computation same to the lambda calculus, however while forgoing abstraction.

Combinatory calculi

Since abstraction is the single way to manufacture functions in the lambda calculus, something must replenish it in the combinatory calculus. Instead of abstraction, combinative calculus will bring a limited placed of primitive functions away from which more functions may be built.

Combinatory terms

a combinative term has one of the as a result forms: v P (E1 E2) in which v occurs as variable, P is one of a primitive functions, & E1 & E2 come combinative terms. A primitive functions themselves come combinators, or even functions that contain there are no free variables.

Examples of combinators

the simplest lesson of a combinator is We, a identity combinator, defined by

for tons terms x. A second elementary combinator is One thousand, which manufactures constant functions: (One thousand x) is the work which, for any argument, comes back x, then i say

for a lot terms x & y. Or even, as a consequence a equivalent convention for multiple application when in the lambda-calculus,

The third combinator is S, which occurs as generalized version of application:

S applies x to y fallowing number 1 subbing z into both of the two.

Given S & K, I personally itself is unneeded, since it can become built from either a more ii:

for any term x. Note that although ((S One thousand K) x) = (We x) for any ten, (S One thousand K) itself is non capable I personally. You say a terms come extensionally equal. Extensional equality captures the mathematical notion of the equality of functions: that ii functions come 'match' whenever it universally make a equivalent final result for the same arguments. Within direct contrast, a terms themselves capture a notion of intensional equality of functions: that ii functions come 'peer' single whenever it own monovular implementations. There are numerous ways to implement an identity work; (S 1000 K) & I come among these ways. (S Thousand S) is eventually a second. We may utilize a word same to show extensional equality, reserving peer for monovular combinatorial terms.

The supplementary interesting combinator is the fixed point combinator or Y combinator, which can be utilized to implement recursion.

Completeness of the S-K basis

These are the mayhap astonishing fact that S & K can be composed to green goods combinators that come extensionally equal to any lambda term, & so, by Church's thesis, to any estimable work whatsoever. the proof is to present a transformation, T[ ], which converts an arbitrary lambda term into an equivalent combinator.

T[ ] can be defined when follows:

  • T[V] => V
  • T[(E1 E2)] => (T[E1] T[E2])
  • T[λx.E] => (M T[E]) (whenever x is non loose inside E)
  • T[λx.x] => I
  • T[λx.λy.E] => T[λx.T[λy.E]] (if x is free in E)
  • T[λx.(E1 E2)] => (S T[λx.E1] T[λx.E2])

    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:

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

    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 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.(E1 E2) is a function which takes an argument, say a, and substitutes it into the lambda term (E1 E2) in place of x, yielding (E1 E2)[x : = a]. But substituting a into (E1 E2) in place of x is just the same as substituting it into both E1 and E2, so

    (E1 E2)[x := a] = (E1[x := a] E2[x := a])

    (λx.(E1 E2) a) = ((λx.E1 a) (λx.E2 a)) = (S λx.E1 λx.E2 a) = ((S λx.E1 λx.E2) a)

    By extensional equality,

    λx.(E1 E2) = (S λx.E1 λx.E2)

    Therefore, to find a combinator equivalent to λx.(E1 E2), it is sufficient to find a combinator equivalent to (S λx.E1 λx.E2), and

    (S T[λx.E1] T[λx.E2])

    evidently fits the bill. E1 and E2 each contain strictly fewer applications than (E1 E2), 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.

    Simplifications of the transformation

    η-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.

    Combinators B, C of Curry

    The combinators S and K already figure in the work of Schönfinkel (although symbol C was used instead of present K), Curry introduced the use of B, C, W (and K), already in his doctoral thesis of 1930 (see B,C,K,W System). In Combinatory Logic V. I, we return to S, K but, (via Markov's algorithms) he uses B and C to simplify many reductions. This seems to have been used, much later, by David Turner, whose name has been bound to its computational use. Two new combinators are introduced:

    (C a b c) = (a c b) (B a b c) = (a (b c))

    Using these combinators, we can extend the rules for the transformation as follows:

  • T[V] => V
  • T[(E1 E2)] => (T[E1] T[E2])
  • T[λx.E] => (K T[E]) (if x is not free in E)
  • T[λx.x] => I
  • T[λx.λy.E] => T[λx.T[λy.E]] (if x is free in E)
  • T[λx.(E1 E2)] => (S T[λx.E1] T[λx.E2]) (if x is free in both E1 and E2)
  • T[λx.(E1 E2)] => (C T[λx.E1] E2) (if x is free in E1 but not E2)
  • T[λx.(E1 E2)] => (B E1 T[λx.E2]) (if x is free in E2 but not E1)

    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.

    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[(E1 E2)] = (L[E1] L[E2])

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

    Undecidability of combinatorial calculus

    It is undecidable whether a general combinatory term has a normal form; whether two combinatory terms are equivalent, etc. This is equivalent to the undecidability of the corresponding problems for lambda terms. However, a direct proof is as follows:

    First, observe that the term

    Ω = (S I I (S I I))

    has no normal form, because it reduces to itself after three steps, as follows:

    (S I I (S I I)) = (I (S I I) (I (S I I))) = (S I I (I (S I I))) = (S I I (S I I))

    and clearly no other reduction order can make the expression shorter.

    Now, suppose N were a combinator for detecting normal forms, such that

    (N x) => T, if x has a normal form F, otherwise.

    (Where T and F the transformations of the conventional lambda-calculus definitions of true and false, λx.λy.x and λx.λy.y. The combinatory versions have T = K and F = (K I).)

    Now let

    Z = (C (C (B N (S I I)) Ω) I)

    now consider the term (S I I Z). Does (S I I Z) have a normal form? It does if and only if the following do also:

    (S I I Z) = (I Z (I Z)) = (Z (I Z)) = (Z Z) = (C (C (B N (S I I)) Ω) I Z) (definition of Z) = (C (B N (S I I)) Ω Z I) = (B N (S I I) Z Ω I) = (N (S I I Z) Ω I)

    Now we need to apply N to (S I I Z). Either (S I I Z) has a normal form, or it does not. If it does have a normal form, then the foregoing reduces as follows:

    (N (S I I Z) Ω I) = (K Ω I) (definition of N) = Ω

    but Ω does not have a normal form, so we have a contradiction. But if (S I I Z) does not have a normal form, the foregoing reduces as follows:

    (N (S I I Z) Ω I) = (K I Ω I) (definition of N) = (I I) I

    which means that the normal form of (S I I Z) is simply I, another contradiction. Therefore, the hypothetical normal-form combinator N cannot exist.

    Combinatory terms as graphs

    (TO DO: Add details with illustrations; don't forget to discuss the effect of fixed-point combinators.)

    Applications

    Compilation of functional languages

    Functional programming languages are often based on the simple but universal semantics of the lambda calculus. (Add details.)

    David Turner used his combinators to implement the SASL language.

    (Discuss strict vs. lazy evaluation semantics. Note implications of graph reduction implementation for lazy evaluation. Point out efficiency problem in lazy semantics: Repeated evaluation of the same expression, in, e.g. (square COMPLICATED) => (* COMPLICATED COMPLICATED), normally avoided by eager evaluation and call-by-value. Discuss benefit of graph reduction in this case: when (square COMPLICATED) is evaluated, the representation of COMPLICATED can be shared by both branches of the resulting graph for (* COMPLICATED COMPLICATED), and evaluated only once.)

    Logic

    The Curry-Howard isomorphism implies a relationship between logic and programming: Every valid proof of a theorem of logic corresponds directly to a reduction of a lambda term, and vice versa. Theorems themselves are identified with function type signatures. Specifically, typed combinatory logics correspond to Hilbert systems in proof theory.

    (Add: Demonstration that the axioms

    (a -> a) (a -> b -> a) (a -> b -> c) -> (a -> b) -> (a -> c)

    are complete for the intuitionistic fragment of propositional logic.)

    See also: graph reduction machine supercombinators

  • Dual Identity Combinators
    Article by Katalin Bimbó presented at the 20th World Congress of Philosophy. Investigates the addition of identity combinators, in the formulae-as-types sense, to combinatory logic.

    Kolmogorov Complexity in Combinatory Logic
    Online article by John Tromp. Kolmogorov complexity is a recursion theoretic characterisation of randomness.

    Lambda
    An online introduction to the lambda calculus by Lloyd Allison, complete with a web form that will evaluate lambda expressions.

    Perl Contains the Lambda-Calculus
    Explains why this computer program is well suited to apply to functional application.






    © 2005 GeneralAnswers.org