Docsity
Docsity

Prepare for your exams
Prepare for your exams

Study with the several resources on Docsity


Earn points to download
Earn points to download

Earn points by helping other students or get them with a premium plan


Guidelines and tips
Guidelines and tips

Understanding λ Calculus: Functions, Substitutions, and Arithmetic, Study Guides, Projects, Research of Calculus

Explore the fundamental concepts of λ calculus, including functions, bound and free variables, substitutions, and arithmetic operations like addition and multiplication. Learn how to define recursive functions and represent numbers in this formal system.

Typology: Study Guides, Projects, Research

2021/2022

Uploaded on 08/01/2022

hal_s95
hal_s95 🇵🇭

4.4

(620)

8.6K documents

1 / 9

Toggle sidebar

Related documents


Partial preview of the text

Download Understanding λ Calculus: Functions, Substitutions, and Arithmetic and more Study Guides, Projects, Research Calculus in PDF only on Docsity! A Tutorial Introduction to the Lambda Calculus Raúl Rojas∗ FU Berlin, WS-97/98 Abstract This paper is a short and painless introduction to the λ calculus. Originally developed in order to study some mathematical properties of effectively com- putable functions, this formalism has provided a strong theoretical foundation for the family of functional programming languages. We show how to perform some arithmetical computations using the λ calculus and how to define recur- sive functions, even though functions in λ calculus are not given names and thus cannot refer explicitly to themselves. 1 Definition The λ calculus can be called the smallest universal programming language of the world. The λ calculus consists of a single transformation rule (variable substitution) and a single function definition scheme. It was introduced in the 1930s by Alonzo Church as a way of formalizing the concept of effective computability. The λ calculus is universal in the sense that any computable function can be expressed and evaluated using this formalism. It is thus equivalent to Turing machines. However, the λ calculus emphasizes the use of transformation rules and does not care about the actual machine implementing them. It is an approach more related to software than to hardware. The central concept in λ calculus is the “expression”. A “name”, also called a “variable”, is an identifier which, for our purposes, can be any of the letters a, b, c, . . . An expression is defined recursively as follows: <expression> := <name> | <function> | <application> <function> := λ <name>.<expression> <application> := <expression><expression> An expression can be surrounded with parenthesis for clarity, that is, if E is an expression, (E) is the same expression. The only keywords used in the language are λ and the dot. In order to avoid cluttering expressions with parenthesis, we adopt the convention that function application associates from the left, that is, the expression E1E2E3 . . . En ∗Send corrections or suggestions to rojas@inf.fu-berlin.de 1 is evaluated applying the expressions as follows: (. . . ((E1E2)E3) . . . En) As can be seen from the definition of λ expressions given above, a single identifier is a λ expression. An example of a function is the following: λx.x This expression defines the identity function. The name after the λ is the identifier of the argument of this function. The expression after the point (in this case a single x) is called the “body” of the definition. Functions can be applied to expressions. An example of an application is (λx.x)y This is the identity function applied to y. Parenthesis are used for clarity in order to avoid ambiguity. Function applications are evaluated by substituting the value of the argument x (in this case y) in the body of the function definition, i.e. (λx.x)y = [y/x]x = y In this transformation the notation [y/x] is used to indicate that all occurrences of x are substituted by y in the expression to the right. The names of the arguments in function definitions do not carry any meaning by themselves. They are just “place holders”, that is, they are used to indicate how to rearrange the arguments of the function when it is evaluated. Therefore (λz.z) ≡ (λy.y) ≡ (λt.t) ≡ (λu.u) and so forth. We use the symbol “≡” to indicate that when A ≡ B, A is just a synonym of B. 1.1 Free and bound variables In λ calculus all names are local to definitions. In the function λx.x we say that x is “bound” since its occurrence in the body of the definition is preceded by λx. A name not preceded by a λ is called a “free variable”. In the expression (λx.xy) the variable x is bound and y is free. In the expression (λx.x)(λy.yx) the x in the body of the first expression from the left is bound to the first λ. The y in the body of the second expression is bound to the second λ and the x is free. It is very important to notice that the x in the second expression is totally independent of the x in the first expression. Formally we say that a variable <name> is free in an expression if one of the following three cases holds: 2 Our first interesting function is the successor function. This can be defined as S ≡ λwyx.y(wyx) The successor function applied to our representation for zero yields S0 ≡ (λwyx.y(wyx))(λsz.z) In the body of the first expression we substitute all occurrences of w with (λsz.z) and this yields λyx.y((λsz.z)yx) = λyx.y((λz.z)x) = λyx.y(x) ≡ 1 That is, we obtain the representation of the number 1 (remember that variable names are “dummies”). Successor applied to 1 yields: S1 ≡ (λwyx.y(wyx))(λsz.s(z)) = λyx.y((λsz.s(z))yx) = λyx.y(y(x)) ≡ 2 Notice that the only purpose of applying the number (λsz.s(z)) to the arguments y and x is to “rename” the variables used in the definition of our number. 2.1 Addition Addition can be obtained immediately by noting that the body sz of our definition of the number 1, for example, can be interpreted as the application of the function s on z. If we want to add say 2 and 3, we just apply the successor function two times to 3. Let us try the following in order to compute 2+3: 2S3 ≡ (λsz.s(sz))(λwyx.y(wyx))(λuv.u(u(uv))) The first expression on the right side is a 2, the second is the successor function, the third is a 3 (we have renamed the variables for clarity). The expression above reduces to (λwyx.y((wy)x))((λwyx.y((wy)x))(λuv.u(u(uv)))) ≡ SS3 The reader can verify that SS3 reduces to S4 = 5. 2.2 Multiplication The multiplication of two numbers x and y can be computed using the following function: (λxyz.x(yz)) The product of 2 by 2 is then: (λxyz.x(yz))22 which reduces to (λz.2(2z)) The reader can verify that by further reducing this expression, we can obtain the expected result 4. 5 3 Conditionals We introduce the following two functions which we call the values “true” T ≡ λxy.x and “false” F ≡ λxy.y The first function takes two arguments and returns the first one, the second function returns the second of two arguments. 3.1 Logical operations It is now possible to define logical operations using this representation of the truth values. The AND function of two arguments can be defined as ∧ ≡ λxy.xy(λuv.v) ≡ λxy.xyF The OR function of two arguments can be defined as ∨ ≡ λxy.x(λuv.u)y ≡ λxy.xTy Negation of one argument can be defined as ¬ ≡ λx.x(λuv.v)(λab.a) ≡ λx.xFT The negation function applied to “true” is ¬T ≡ λx.x(λuv.v)(λab.a)(λcd.c) which reduces to TFT ≡ (λcd.c)(λuv.v)(λab.a) = (λuv.v) ≡ F that is, the truth value “false”. 3.2 A conditional test It is very convenient in a programming language to have a function which is true if a number is zero and false otherwise. The following function Z complies with this requirement Z ≡ λx.xF¬F To understand how this function works, note that 0fa ≡ (λsz.z)fa = a that is, the function f applied zero times to the argument a yields a. On the other hand, F applied to any argument yields the identity function Fa ≡ (λxy.y)a = λy.y ≡ I 6 We can now test if the function Z works correctly. The function applied to zero yields Z0 ≡ (λx.xF¬F)0 = 0F¬F = ¬F = T because F applied 0 times to ¬ yields ¬. The function Z applied to any other number N yields ZN ≡ (λx.xF¬F)N = NF¬F The function F is then applied N times to ¬. But F applied to anything is the identity, so that the above expression reduces for any number N greater than zero to IF = F 3.3 The predecessor function We can now define the predecessor function combining some of the functions intro- duced above. When looking for the predecessor of n, the general strategy will be to create a pair (n, n− 1) and then pick the second element of the pair as the result. A pair (a, b) can be represented in λ-calculus using the function (λz.zab) We can extract the first element of the pair from the expression applying this function to T (λz.zab)T = Tab = a and the second applying the function to F (λz.zab)F = Fab = b The following function generates from the pair (n, n− 1) (which is the argument p in the function) the pair (n+ 1, n− 1): Φ ≡ (λpz.z(S(pT))(pT)) The subexpression pT extracts the first element from the pair p. A new pair is formed using this element, which is incremented for the first position of the new pair and just copied for the second position of the new pair. The predecessor of a number n is obtained by applying n times the function Φ to the pair (λ.z00) and then selecting the second member of the new pair: P ≡ (λn.nΦ(λz.z00)F Notice that using this approach the predecessor of zero is zero. This property is useful for the definition of other functions. 3.4 Equality and inequalities With the predecessor function as the building block, we can now define a function which tests if a number x is greater than or equal to a number y: G ≡ (λxy.Z(xPy)) 7
Docsity logo



Copyright © 2024 Ladybird Srl - Via Leonardo da Vinci 16, 10126, Torino, Italy - VAT 10816460017 - All rights reserved