Misplaced Pages

Lambda lifting: Difference between revisions

Article snapshot taken from Wikipedia with creative commons attribution-sharealike license. Give it a read and then ask your questions in the chat. We can research this topic together.
Browse history interactively← Previous editNext edit →Content deleted Content addedVisualWikitext
Revision as of 13:19, 3 November 2013 edit182.237.4.57 (talk) Minor fix - removed " before closure link← Previous edit Revision as of 07:39, 4 November 2013 edit undoThepigdog (talk | contribs)Extended confirmed users5,174 edits Lamba-abstract transform of a function definition to lambda expressionNext edit →
Line 311: Line 311:


First the lambda expression for each function name is found. Then the function name is replaced by the expression in the body of the let. First the lambda expression for each function name is found. Then the function name is replaced by the expression in the body of the let.
* <math> \operatorname{lambda-abstract} = \operatorname{lambda-abstract} </math> * <math> \operatorname{lambda-abstract} = \operatorname{lambda-convert}]] </math>

* <math> \operatorname{lambda-abstract} = \operatorname{lambda-abstract} \operatorname{in} \operatorname{let} C \operatorname{in} E] </math>
Split into separate lets,
* <math> \operatorname{lambda-abstract} = \operatorname{lambda-abstract} </math>
* <math> \operatorname{lambda-abstract} = E </math> (where E is not a let expression) * <math> \operatorname{lambda-preprocess} = \operatorname{let} A \operatorname{in} \operatorname{lambda-preprocess} </math>
* <math> \operatorname{lambda-preprocess} = \operatorname{let} A \operatorname{in} E] </math>

Turn functions into lambdas,
* <math> \operatorname{lambda-process} = \operatorname{lambda-process} </math>
* <math> \operatorname{lambda-process} = \operatorname{let} \operatorname{abstract} \operatorname{in} \operatorname{lambda-process} </math>
* <math> \operatorname{lambda-process} = E </math> - ''E'' is not a let expression.

Turn lets into lambdas,
* <math> \operatorname{lambda-convert} = (\lambda F.E)\ (\operatorname{lambda-convert}) </math>
* <math> \operatorname{lambda-convert} = E </math> - ''E'' is not a let expression.

Note there are some let expressions that cannot be converted into lambda expressions.


==== Lambda expression for a function ==== ==== Lambda expression for a function ====

Revision as of 07:39, 4 November 2013

Lambda lifting is the process of eliminating free variables from local function definitions from a computer program. The elimination of free variables allows the compiler to hoist local definitions out of their surrounding contexts into a fixed set of top-level functions with an extra parameter replacing each local variable. By eliminating the need for run-time access-links, this may reduce the run-time cost of handling implicit scope. Many functional programming language implementations use lambda lifting during compilation.

The term "lambda lifting" was first introduced by Thomas Johnsson around 1982.

Lambda lifting is not the same as closure conversion. Lambda lifting requires all call sites to be adjusted (adding extra arguments to calls) and does not introduce a closure for the lifted lambda expression. In contrast, closure conversion does not require call sites to be adjusted but does introduce a closure for the lambda expression mapping free variables to values.

The reverse operation is called lambda dropping.

Algorithm

The following algorithm is one way to lambda-lift an arbitrary program in a language which doesn't support closures as first-class objects:

  1. Rename the functions so that each function has a unique name.
  2. Replace each free variable with an additional argument to the enclosing function, and pass that argument to every use of the function.
  3. Replace every local function definition that has no free variables with an identical global function.
  4. Repeat steps 2 and 3 until all free variables and local functions are eliminated.

If the language has closures as first-class objects that can be passed as arguments or returned from other functions, the closure will need to be represented by a data structure that captures the bindings of the free variables.

Example

The following OCaml program computes the sum of the integers from 1 to 100:

let rec sum n =
  if n = 1 then
    1
  else
    let f x =
      n + x in
    f (sum (n - 1)) in
sum 100

(The let rec declares sum as a function that may call itself.) The function f, which adds sum's argument to the sum of the numbers less than the argument, is a local function. Within the definition of f, n is a free variable. Start by converting the free variable to an argument:

let rec sum n =
  if n = 1 then
    1
  else
    let f w x =
      w + x in
     f n (sum (n - 1)) in
sum 100

Next, lift f into a global function:

let rec f w x =
  w + x
and sum n =
  if n = 1 then
    1
  else
    f n (sum (n - 1)) in
sum 100

The following is the same example, this time written in JavaScript:

// Initial version
function sum (n) {
    function f (x) {
        return n + x;
    }
    if (n == 1) {
        return 1;
    }
    else {
        return f( sum(n - 1) );
    }
}
// After converting the free variable n to a formal parameter w
function sum (n) {
    function f (w, x) {
        return w + x;
    }
    if (n == 1) {
        return 1;
    }
    else {
        return f( n, sum(n - 1) );
    }
}
// After lifting function f into the global scope
function f (w, x) {
    return w + x;
}
function sum (n) {
    if (n == 1) {
        return 1;
    }
    else {
        return f( n, sum(n - 1) );
    }
}

Lambda Lifting in Lambda calculus

This section describes lambda lifting in more detail, and describes the process when used in Lambda Calculus. Lambda lifting may be used to convert a program written in Lambda Calculus into a functional program, without lambdas. This demonstrates the equivalence of programs written in Lambda Calculus and programs written as functions.

Each Lambda Lift takes a lambda abstraction which is a sub expression of a lambda expression and replaces it by a function call (application) to a function that it creates. The free variables in the sub expression are the parameters to the function call. The process is similar to refactoring out code and putting it in a function. Lambda Lifts may be repeated until the expression has no lambda abstractions.

The purpose of lambda lifting

Lambda lifting converts a program with lambda expressions into a program with function calls only. Function calls may be implemented using a stack based implementation, which is simple and efficient.

However a stack based implementation must be strict. A functional language is normally implemented using a lazy strategy, which delays calculation until the value is needed. The lazy implementation strategy gives flexibility to the programmer.

Also Lamba lifting is O(n 2) on processing time for the compiler.

Lambda lifting gives a direct translation of a Lambda calculus program into a functional program. At first site this would indicate the soundness of Lambda calculus as a deductive system. However this is not the case as the eta reduction used in Lambda lifting is the step that introduces cardinality problems into the Lambda calculus, because it removes the value from the variable, without first checking that there is only one value that satisfies the conditions on the variable.

Lambda lifting is useful in understanding the relationship between function definitions and lambda expressions.

Lamba-Lift transform of a lambda expression to functions

This meta-function lambda-lift-tran transforms any lambda expression into a set of functions defined without lambda abstractions. For example,

l a m b d a - l i f t - t r a n [ λ f . ( λ x . f   ( x   x ) )   ( λ x . f   ( x   x ) ) ] let p   f   x = f   ( x   x ) q   p   f = ( p   f )   ( p   f ) in q   p {\displaystyle \operatorname {lambda-lift-tran} \equiv \operatorname {let} p\ f\ x=f\ (x\ x)\land q\ p\ f=(p\ f)\ (p\ f)\operatorname {in} q\ p}

A meta-function is a function that takes a program as a parameter. The program is data for the meta-program. The program and the meta program are at different meta-levels.

The following conventions will be used to distinguish program from the meta program,

  • Square brackets will be used to represent function application in the meta program.
  • Capital letters will be used for variables in the meta program. Lower case letters represent variables in the program.
  • {\displaystyle \equiv } will be used for equals in the meta program.

Calling lambda-lift-tran on a lambda expression gives you a functional program in the form,

  • let M in N

where M is a series of function definitions, and N is the expression representing the value returned.

The processing of transforming the lambda expression is a series of lifts. Each lift has,

  1. A sub expression chosen for it by the function candidate-prefix-lambda. The sub expression should be chosen so that it may be converted into an equation with no lambdas.
  2. The lift is performed by a call to the lambda-lift meta function, described in the next section,
  • l a m b d a - l i f t - t r a n [ L ] = l a m b d a - p r o c e s s [ let true in L ] ] {\displaystyle \operatorname {lambda-lift-tran} =\operatorname {lambda-process} ]}
  • if  c a n d i d a t e - p r e f i x - l a m b d a [ S , L ]  then  {\displaystyle {\text{if }}\operatorname {candidate-prefix-lambda} {\text{ then }}}
l a m b d a - p r o c e s s [ L ] = l a m b d a - p r o c e s s [ l a m b d a - l i f t [ S , L ] ] {\displaystyle \operatorname {lambda-process} =\operatorname {lambda-process} ]}
 else  {\displaystyle {\text{ else }}}
l a m b d a - p r o c e s s [ L ] = L {\displaystyle \operatorname {lambda-process} =L}

Rules for Lambda lifting

The lambda-lift meta function performs a single lambda lift, which takes an expression and replaces it with a function call.

The lift is given a sub-expression (called S) to be lifted. For S;

  • Create a name for the function that will replace S (called H). Make sure that the name identified by H has not been used.
  • Add parameters to H, for all the free variables in S, to create an expression G (see make-call).

The lambda lift is the substitution of an expression for function application, along with the addition of a definition for the function.

l a m b d a - l i f t [ S , let F in L ] let F d e - l a m b d a [ G = S ] in L [ S := G ] {\displaystyle \operatorname {lambda-lift} \equiv \operatorname {let} F\land \operatorname {de-lambda} \operatorname {in} L}

The new lambda expression has S substituted for G. Note that L means substitution of S for G in L. The function definitions has the function definition G = S added.

In the above rule G is the function application that is substituted for the expression S. It is defined by,

G = m a k e - c a l l [ H , FV [ S ] ] {\displaystyle G=\operatorname {make-call} ]}

where H is the function name, and FV returns a set of variables that are free in the expression. H must be a new variable, i.e. a name not already used in the lambda expression,

H vars [ let F in L ] {\displaystyle H\not \in \operatorname {vars} }

where vars [ E ] {\displaystyle \operatorname {vars} } is a meta function that returns the set of variables used in E.

For example,

F = t r u e {\displaystyle F=true}
L = λ f . ( λ x . f   ( x   x ) )   ( λ x . f   ( x   x ) ) {\displaystyle L=\lambda f.(\lambda x.f\ (x\ x))\ (\lambda x.f\ (x\ x))}
S = λ x . f   ( x   x ) {\displaystyle S=\lambda x.f\ (x\ x)}
G = p   f {\displaystyle G=p\ f}
d e - l a m b d a [ p   f = λ x . f   ( x   x ) ] p   f   x = f   ( x   x ) {\displaystyle \operatorname {de-lambda} \equiv p\ f\ x=f\ (x\ x)}

gives,

l a m b d a - l i f t [ λ x . f   ( x   x ) , let t r u e in λ f . ( λ x . f   ( x   x ) )   ( λ x . f   ( x   x ) ) ] let p   f   x = f   ( x   x ) in λ f . ( p   f )   ( p   f ) {\displaystyle \operatorname {lambda-lift} \equiv \operatorname {let} p\ f\ x=f\ (x\ x)\operatorname {in} \lambda f.(p\ f)\ (p\ f)}

Constructing the call

The function call G is constructed by adding parameters for each variable in the free variable set (represented by V), to the function H,

  • X V m a k e - c a l l [ H , V ] m a k e - c a l l [ H , V ¬ { X } ]   X {\displaystyle X\in V\to \operatorname {make-call} \equiv \operatorname {make-call} \ X}
  • m a k e - c a l l [ H , { } ] H {\displaystyle \operatorname {make-call} \equiv H}

For example,

S = λ x . f   ( x   x ) {\displaystyle S=\lambda x.f\ (x\ x)}
FV ( S ) = { f } {\displaystyle \operatorname {FV} (S)=\{f\}}
G m a k e - c a l l [ p , FV [ S ] ] m a k e - c a l l [ p , { f } ] m a k e - c a l l [ p , { } ]   f p   f {\displaystyle G\equiv \operatorname {make-call} ]\equiv \operatorname {make-call} \equiv \operatorname {make-call} \ f\equiv p\ f}

Eta reductions to remove lambda abstractions in lifted expressions

An eta reduction is ,

e t a - r e d e x [ λ x . ( f   x ) ] = f {\displaystyle \operatorname {eta-redex} =f}

If you assume that the eta-redex of an expression equals the expression, this can be rearranged as,

f   x = y f = λ x . y {\displaystyle f\ x=y\iff f=\lambda x.y}

The de-lambda meta function applies eta-reductions to remove lambda abstractions. It is defined by,

d e - l a m b d a [ F = λ X . Y ] d e - l a m b d a [ F   X = Y ] {\displaystyle \operatorname {de-lambda} \equiv \operatorname {de-lambda} }
d e - l a m b d a [ K = E ] K = E {\displaystyle \operatorname {de-lambda} \equiv K=E} if E is not a lamba abstraction

For example,

d e - l a m b d a [ p   f = λ x . f   ( x   x ) ] d e - l a m b d a [ p   f   x = f   ( x   x ) ] p   f   x = f   ( x   x ) {\displaystyle \operatorname {de-lambda} \equiv \operatorname {de-lambda} \equiv p\ f\ x=f\ (x\ x)}

Candidate prefix lambda for lifting

The candidate-prefix-lambda is a meta function that returns a lambda abstraction within an expression whose body does not contain any lambda abstractions. The lambda abstraction may have a number of parameters, as they can be removed by the de-lambda meta function defined previously.

The rules are described below,

  • c a n d i d a t e - p r e f i x - l a m b d a [ S , L ] = l a m b d a - p r e f i x [ S , L , _ ] {\displaystyle \operatorname {candidate-prefix-lambda} =\operatorname {lambda-prefix} }
  • if  l a m b d a - p r e f i x [ S , Y , R ] R  then  {\displaystyle {\text{if }}\operatorname {lambda-prefix} \equiv R{\text{ then }}}
l a m b d a - p r e f i x [ λ X . Y , λ X . Y , t r u e ] {\displaystyle \operatorname {lambda-prefix} }
 else  {\displaystyle {\text{ else }}}
l a m b d a - p r e f i x [ S , λ X . Y , f a l s e ] {\displaystyle \operatorname {lambda-prefix} }
  • if  l a m b d a - p r e f i x [ S , X , R ]  then  {\displaystyle {\text{if }}\operatorname {lambda-prefix} {\text{ then }}}
l a m b d a - p r e f i x [ S , X   Y , f a l s e ] {\displaystyle \operatorname {lambda-prefix} }
 else  {\displaystyle {\text{ else }}}
l a m b d a - p r e f i x [ T , Y , R ] l a m b d a - p r e f i x [ T , X   Y , f a l s e ] {\displaystyle \operatorname {lambda-prefix} \iff \operatorname {lambda-prefix} }
  • ¬ l a m b d a - p r e f i x [ _ , X , f a l s e ] {\displaystyle \neg \operatorname {lambda-prefix} } where x is a variable.

Example

For example the Y combinator,

λ f . ( λ x . f   ( x   x ) )   ( λ x . f   ( x   x ) ) {\displaystyle \lambda f.(\lambda x.f\ (x\ x))\ (\lambda x.f\ (x\ x))}
Lambda Expression Function From To Variables
1 λ f . ( λ x . f   ( x   x ) )   ( λ x . f   ( x   x ) ) {\displaystyle \lambda f.(\lambda x.f\ (x\ x))\ (\lambda x.f\ (x\ x))} true λ x . f   ( x   x ) {\displaystyle \lambda x.f\ (x\ x)} p   f {\displaystyle p\ f} { x , f } {\displaystyle \{x,f\}}
2 ( λ f . ( λ x . f   ( x   x ) ) ( λ x . f   ( x   x ) ) ) [ λ x . f   ( x   x ) := p   f ] {\displaystyle (\lambda f.(\lambda x.f\ (x\ x))(\lambda x.f\ (x\ x)))} p   f = λ x . f   ( x   x ) {\displaystyle p\ f=\lambda x.f\ (x\ x)} { x , f , p } {\displaystyle \{x,f,p\}}
3 λ f . ( p   f )   ( p   f ) {\displaystyle \lambda f.(p\ f)\ (p\ f)} p   f   x = f   ( x   x ) {\displaystyle p\ f\ x=f\ (x\ x)} λ f . ( p   f )   ( p   f ) {\displaystyle \lambda f.(p\ f)\ (p\ f)} q   p {\displaystyle q\ p} { x , f , p } {\displaystyle \{x,f,p\}}
4 λ f . ( p   f )   ( p   f ) [ λ f . ( p   f )   ( p   f ) := q   p ] {\displaystyle \lambda f.(p\ f)\ (p\ f)} p   f   x = f   ( x   x ) q   p = λ f . ( p   f )   ( p   f ) {\displaystyle p\ f\ x=f\ (x\ x)\land q\ p=\lambda f.(p\ f)\ (p\ f)} { x , f , p , q } {\displaystyle \{x,f,p,q\}}
5 q   p {\displaystyle q\ p} p   f   x = f   ( x   x ) q   p   f = ( p   f )   ( p   f ) {\displaystyle p\ f\ x=f\ (x\ x)\land q\ p\ f=(p\ f)\ (p\ f)} { x , f , p , q } {\displaystyle \{x,f,p,q\}}

The first sub expression to be chosen for lifting is λ x . f   ( x   x ) {\displaystyle \lambda x.f\ (x\ x)} . This transforms the lambda expression into λ f . ( p   f )   ( p   f ) {\displaystyle \lambda f.(p\ f)\ (p\ f)} and creates the equation p   f   x = f ( x   x ) {\displaystyle p\ f\ x=f(x\ x)} .

The second sub expression to be chosen for lifting is λ f . ( p   f )   ( p   f ) {\displaystyle \lambda f.(p\ f)\ (p\ f)} . This transforms the lambda expression into q   p {\displaystyle q\ p} and creates the equation q   p   f = ( p   f )   ( p   f ) {\displaystyle q\ p\ f=(p\ f)\ (p\ f)} .

And the result is,

let p   f   x = f   ( x   x ) q   p   f = ( p   f )   ( p   f ) in q   p   {\displaystyle \operatorname {let} p\ f\ x=f\ (x\ x)\land q\ p\ f=(p\ f)\ (p\ f)\operatorname {in} q\ p\ }

Because p {\displaystyle p} is a global function, the result could also have been written,

let p   f   x = f   ( x   x ) q   f = ( p   f )   ( p   f ) in q   {\displaystyle \operatorname {let} p\ f\ x=f\ (x\ x)\land q\ f=(p\ f)\ (p\ f)\operatorname {in} q\ }

This would be generated if there was a change to make-call so that only free variables that are not global are added as parameters. More sophisticated versions of the lambda lifting algorithm exist that have processing time O(n 2), and derive the minimum set of parameters required.

Execution

Apply function to,

K {\displaystyle K}
λ f . ( λ x . f   ( x   x ) )   ( λ x . f   ( x   x ) )   K {\displaystyle \lambda f.(\lambda x.f\ (x\ x))\ (\lambda x.f\ (x\ x))\ K} let p   f   x = f   ( x   x ) q   p   f = ( p   f )   ( p   f ) in q   p     K {\displaystyle \operatorname {let} p\ f\ x=f\ (x\ x)\land q\ p\ f=(p\ f)\ (p\ f)\operatorname {in} q\ p\ \ K}
( λ x . K   ( x   x ) )   ( λ x . K   ( x   x ) ) {\displaystyle (\lambda x.K\ (x\ x))\ (\lambda x.K\ (x\ x))} let p   f   x = f   ( x   x ) q   p   f = ( p   f )   ( p   f ) in p   K   ( p   K ) {\displaystyle \operatorname {let} p\ f\ x=f\ (x\ x)\land q\ p\ f=(p\ f)\ (p\ f)\operatorname {in} p\ K\ (p\ K)}
K   ( ( λ x . K   ( x   x ) )   ( λ x . K   ( x   x ) ) ) )   {\displaystyle K\ ((\lambda x.K\ (x\ x))\ (\lambda x.K\ (x\ x))))\ } let p   f   x = f   ( x   x ) q   p   f = p   f   ( p   f ) in K   ( p   K   ( p   K ) ) {\displaystyle \operatorname {let} p\ f\ x=f\ (x\ x)\land q\ p\ f=p\ f\ (p\ f)\operatorname {in} K\ (p\ K\ (p\ K))}

So,

  • ( λ x . K   ( x   x ) )   ( λ x . K   ( x   x ) ) = K   ( ( λ x . K   ( x   x ) )   ( λ x . K   ( x   x ) ) ) )   {\displaystyle (\lambda x.K\ (x\ x))\ (\lambda x.K\ (x\ x))=K\ ((\lambda x.K\ (x\ x))\ (\lambda x.K\ (x\ x))))\ }

or

  • p   K   ( p   K ) = K   ( p   K   ( p   K ) ) {\displaystyle p\ K\ (p\ K)=K\ (p\ K\ (p\ K))}

The Y-Combinator calls its parameter (function) repeatedly on itself. The value is defined if the function has a fixed point. But the function will never terminate.

Lambda dropping in Lambda calculus

Any "let" expression with function definitions may be transformed into Lambda calculus, and then beta and eta reductions may be performed to restructure them to remove the effect of the lambda lift.

Conversion between let and lambda expression

A let expression may be converted back into a lambda expression by repeated application of the lambda-param and the lambda-equiv law,

Name Law
lambda-param f   x = y f = λ x . y {\displaystyle f\ x=y\equiv f=\lambda x.y}
lambda-equiv f F V ( F ) ( let f = e F in L let F in λ f . L   e ) {\displaystyle f\not \in FV(F)\to (\operatorname {let} f=e\land F\operatorname {in} L\equiv \operatorname {let} F\operatorname {in} \lambda f.L\ e)} (where f is a variable name).

These two laws may be used to convert the function expression back into lambda calculus. The resulting lambda expression keeps the restructuring performed by the lambda lift. All the lambda abstractions are applied to a core expression which is free of lambda abstractions.

Beta and Eta reductions may then be applied to undo the effect of the lambda lift.

Lamba-abstract transform of a function definition to lambda expression

This meta-function lambda-abstract transforms an expression defined using functions with a let expression to a lambda expression. The transformation works when the let condition is structured like a series of functions, but does not work for arbitrary expressions.

For example,

l a m b d a - a b s t r a c t [ let p   f   x = f   ( x   x ) q   p   f = ( p   f )   ( p   f ) in q   p ] ( λ q . ( λ p . q   p )   λ f . λ x . f   ( x   x ) )   λ p . λ f . ( p   f )   ( p   f ) {\displaystyle \operatorname {lambda-abstract} \equiv (\lambda q.(\lambda p.q\ p)\ \lambda f.\lambda x.f\ (x\ x))\ \lambda p.\lambda f.(p\ f)\ (p\ f)}

First the lambda expression for each function name is found. Then the function name is replaced by the expression in the body of the let.

  • l a m b d a - a b s t r a c t [ E ] = l a m b d a - c o n v e r t [ l a m b d a - p r o c e s s [ l a m b d a - p r e p r o c e s s [ E ] ] ] {\displaystyle \operatorname {lambda-abstract} =\operatorname {lambda-convert} ]]}

Split into separate lets,

  • l a m b d a - p r e p r o c e s s [ let A B in E ] = let A in l a m b d a - p r e p r o c e s s [ let B in E ] {\displaystyle \operatorname {lambda-preprocess} =\operatorname {let} A\operatorname {in} \operatorname {lambda-preprocess} }
  • l a m b d a - p r e p r o c e s s [ let A in E ] = let A in E ] {\displaystyle \operatorname {lambda-preprocess} =\operatorname {let} A\operatorname {in} E]}

Turn functions into lambdas,

  • l a m b d a - p r o c e s s [ let t r u e in E ] = l a m b d a - p r o c e s s [ E ] {\displaystyle \operatorname {lambda-process} =\operatorname {lambda-process} }
  • l a m b d a - p r o c e s s [ let G = S in E ] = let abstract [ G = S ] in l a m b d a - p r o c e s s [ E ] {\displaystyle \operatorname {lambda-process} =\operatorname {let} \operatorname {abstract} \operatorname {in} \operatorname {lambda-process} }
  • l a m b d a - p r o c e s s [ E ] = E {\displaystyle \operatorname {lambda-process} =E} - E is not a let expression.

Turn lets into lambdas,

  • l a m b d a - c o n v e r t [ let F = S in E ] = ( λ F . E )   ( l a m b d a - c o n v e r t [ S ] ) {\displaystyle \operatorname {lambda-convert} =(\lambda F.E)\ (\operatorname {lambda-convert} )}
  • l a m b d a - c o n v e r t [ E ] = E {\displaystyle \operatorname {lambda-convert} =E} - E is not a let expression.

Note there are some let expressions that cannot be converted into lambda expressions.

Lambda expression for a function

The abstract meta function removes parameters from functions using lambda abstractions. It is defined by,

abstract [ F X = Y ] abstract [ F = λ X . Y ] {\displaystyle \operatorname {abstract} \equiv \operatorname {abstract} }
abstract [ K = E ] K = E {\displaystyle \operatorname {abstract} \equiv K=E} if K is a variable.

For example,

abstract [ p   f   x = f   ( x   x ) ] abstract [ p   f = λ x . f   ( x   x ) ] abstract [ p = λ f . λ x . f   ( x   x ) ] λ f . λ x . f   ( x   x ) {\displaystyle \operatorname {abstract} \equiv \operatorname {abstract} \equiv \operatorname {abstract} \equiv \lambda f.\lambda x.f\ (x\ x)}

Example

Starting with the function definition of the Y-combinator,

let p   f   x = f   ( x   x ) q   p   f = ( p   f )   ( p   f ) in q   p   {\displaystyle \operatorname {let} p\ f\ x=f\ (x\ x)\land q\ p\ f=(p\ f)\ (p\ f)\operatorname {in} q\ p\ }
Transformation Expression
let p   f   x = f   ( x   x ) q   p   f = ( p   f )   ( p   f ) in q   p   {\displaystyle \operatorname {let} p\ f\ x=f\ (x\ x)\land q\ p\ f=(p\ f)\ (p\ f)\operatorname {in} q\ p\ }
lambda-param * 4 let p = λ f . λ x . f   ( x   x ) q = λ p . λ f . ( p   f )   ( p   f ) in q   p {\displaystyle \operatorname {let} p=\lambda f.\lambda x.f\ (x\ x)\land q=\lambda p.\lambda f.(p\ f)\ (p\ f)\operatorname {in} q\ p}
lambda-equiv let q = λ p . λ f . ( p   f )   ( p   f ) in ( λ p . q   p )   ( λ f . λ x . f   ( x   x ) ) {\displaystyle \operatorname {let} q=\lambda p.\lambda f.(p\ f)\ (p\ f)\operatorname {in} (\lambda p.q\ p)\ (\lambda f.\lambda x.f\ (x\ x))}
lambda-equiv let t r u e in ( λ q . ( λ p . q   p )   ( λ f . λ x . f   ( x   x ) ) )   ( λ p . λ f . ( p   f )   ( p   f ) ) {\displaystyle \operatorname {let} true\operatorname {in} (\lambda q.(\lambda p.q\ p)\ (\lambda f.\lambda x.f\ (x\ x)))\ (\lambda p.\lambda f.(p\ f)\ (p\ f))}
drop let ( λ q . ( λ p . q   p )   ( λ f . λ x . f   ( x   x ) ) )   ( λ p . λ f . ( p   f )   ( p   f ) ) {\displaystyle (\lambda q.(\lambda p.q\ p)\ (\lambda f.\lambda x.f\ (x\ x)))\ (\lambda p.\lambda f.(p\ f)\ (p\ f))}

The expression is now a lambda abstraction for the variable q, applied to a lambda abstraction for the variable q, applied to the expression q   p {\displaystyle q\ p} . This expression is still structured with the lambda abstractions lifted to define global variables.

Beta and eta reductions may then be used to return the function to its original structure.

Transformation Expression
beta-redex λ p . ( ( λ p . λ f . ( p   f )   ( p   f ) )   p )   ( λ f . λ x . f   ( x   x ) ) {\displaystyle \lambda p.((\lambda p.\lambda f.(p\ f)\ (p\ f))\ p)\ (\lambda f.\lambda x.f\ (x\ x))}
eta-redex λ p . ( λ f . ( p   f )   ( p   f ) )   ( λ x . λ f . f   ( x   x ) ) {\displaystyle \lambda p.(\lambda f.(p\ f)\ (p\ f))\ (\lambda x.\lambda f.f\ (x\ x))}
beta-redex λ f . ( ( λ f . λ x . f   ( x   x ) )   f )   ( ( λ f . λ x . f   ( x   x ) )   f ) {\displaystyle \lambda f.((\lambda f.\lambda x.f\ (x\ x))\ f)\ ((\lambda f.\lambda x.f\ (x\ x))\ f)}
eta-redex * 2 λ f . ( λ x . f   ( x   x ) )   ( λ x . f   ( x   x ) ) {\displaystyle \lambda f.(\lambda x.f\ (x\ x))\ (\lambda x.f\ (x\ x))}

Which gives back the Y combinator,

λ f . ( λ x . f   ( x   x ) )   ( λ x . f   ( x   x ) ) {\displaystyle \lambda f.(\lambda x.f\ (x\ x))\ (\lambda x.f\ (x\ x))}

See also

References

  1. Attention: This template ({{cite doi}}) is deprecated. To cite the publication identified by doi:10.1145/258994.259007, please use {{cite journal}} (if it was published in a bona fide academic journal, otherwise {{cite report}} with |doi=10.1145/258994.259007 instead.
  2. Johnsson, Thomas (1985), "Lambda Lifting: Transforming Programs to Recursive Equations", Conf. on Func. Prog. Languages and Computer Architecture., ACM Press
  3. Optimal Lambda Lifting in Quadratic Time, pp. pp 37-56, doi:10.1007/978-3-540-85373-2_3, ISBN 978-3-540-85372-5 {{citation}}: |pages= has extra text (help); Cite has empty unknown parameter: |1= (help); Unknown parameter |booktitle= ignored (help)

External links

Categories: