n λxy.x n y, [inc] [add] [mul] [exp] λn.λxy.x(nxy) λmn.m[inc]0 λmn.m([add]n)0 λmn.n([mul]m)1

Similar documents
A Quick Overview. CAS 701 Class Presentation 18 November Department of Computing & Software McMaster University. Church s Lambda Calculus

Introduction to the λ-calculus

1.3. Conditional expressions To express case distinctions like

Lambda Calculus and Computation

Lambda Calculus. CS 550 Programming Languages Jeremy Johnson

4/19/2018. Chapter 11 :: Functional Languages

VU Semantik von Programmiersprachen

λ-calculus Lecture 1 Venanzio Capretta MGS Nottingham

Pure Lambda Calculus. Lecture 17

11/6/17. Outline. FP Foundations, Scheme. Imperative Languages. Functional Programming. Mathematical Foundations. Mathematical Foundations

Elixir, functional programming and the Lambda calculus.

Introduction to the Lambda Calculus. Chris Lomont

Functional Languages. Hwansoo Han

dynamically typed dynamically scoped

CMSC 330: Organization of Programming Languages. Lambda Calculus Encodings

One of a number of approaches to a mathematical challenge at the time (1930): Constructibility

Programming Language Features. CMSC 330: Organization of Programming Languages. Turing Completeness. Turing Machine.

CMSC 330: Organization of Programming Languages

CITS3211 FUNCTIONAL PROGRAMMING. 10. Programming in the pure λ calculus

CMSC 330: Organization of Programming Languages

MATH Iris Loeb.

Formal Semantics. Aspects to formalize. Lambda calculus. Approach

Lecture 5: The Untyped λ-calculus

λ calculus Function application Untyped λ-calculus - Basic Idea Terms, Variables, Syntax β reduction Advanced Formal Methods

CMSC 330: Organization of Programming Languages

CS 6110 S14 Lecture 1 Introduction 24 January 2014

Lecture 5: The Halting Problem. Michael Beeson

COP4020 Programming Languages. Functional Programming Prof. Robert van Engelen

The Lambda Calculus. notes by Don Blaheta. October 12, A little bondage is always a good thing. sk

Chapter 5: The Untyped Lambda Calculus

Recursive Definitions, Fixed Points and the Combinator

Chapter 11 :: Functional Languages

CIS 500 Software Foundations Fall September 25

Lambda Calculus and Type Inference

Introduction to Lambda Calculus. Lecture 7 CS /08/09

3.1 λ-calculus: Syntax

Nano-Lisp The Tutorial Handbook

COMP 1130 Lambda Calculus. based on slides by Jeff Foster, U Maryland

Summer 2017 Discussion 10: July 25, Introduction. 2 Primitives and Define

Type Systems Winter Semester 2006

Introduction to the Lambda Calculus

CMSC 330: Organization of Programming Languages

Denotational Semantics. Domain Theory

Lambda Calculus. Type Systems, Lectures 3. Jevgeni Kabanov Tartu,

Harvard School of Engineering and Applied Sciences CS 152: Programming Languages. Lambda calculus

Functions as data. Massimo Merro. 9 November Massimo Merro The Lambda language 1 / 21

Chapter 5: The Untyped Lambda Calculus

Recursively Defined Functions

SCHEME 8. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. March 23, 2017

Programming Languages

Spring 2018 Discussion 7: March 21, Introduction. 2 Primitives

Programming Language Pragmatics

SCHEME 7. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. October 29, 2015

COMP80 Lambda Calculus Programming Languages Slides Courtesy of Prof. Sam Guyer Tufts University Computer Science History Big ideas Examples:

LECTURE 16. Functional Programming

Introductory Example

Fall 2017 Discussion 7: October 25, 2017 Solutions. 1 Introduction. 2 Primitives

Principles of Programming Languages 2017W, Functional Programming

Scheme Tutorial. Introduction. The Structure of Scheme Programs. Syntax

Concepts of programming languages

Fundamentals and lambda calculus

6.001 Notes: Section 4.1

CMSC330. Objects, Functional Programming, and lambda calculus

Fall 2018 Discussion 8: October 24, 2018 Solutions. 1 Introduction. 2 Primitives

Lambda Calculus. Variables and Functions. cs3723 1

Lambda Calculus. Lambda Calculus

Pure (Untyped) λ-calculus. Andrey Kruglyak, 2010

Lecture 9: More Lambda Calculus / Types

- M ::= v (M M) λv. M - Impure versions add constants, but not necessary! - Turing-complete. - true = λ u. λ v. u. - false = λ u. λ v.

CS 314 Principles of Programming Languages

Recursion defining an object (or function, algorithm, etc.) in terms of itself. Recursion can be used to define sequences

Programming Languages Third Edition

SCHEME 10 COMPUTER SCIENCE 61A. July 26, Warm Up: Conditional Expressions. 1. What does Scheme print? scm> (if (or #t (/ 1 0)) 1 (/ 1 0))

Programming Language Concepts: Lecture 19

Fundamental Concepts. Chapter 1

Untyped Lambda Calculus

Introduction to Lambda Calculus. Lecture 5 CS 565 1/24/08

Documentation for LISP in BASIC

Elementary Recursive Function Theory

Denotational semantics

Recursively Enumerable Languages, Turing Machines, and Decidability

Simple Lisp. Alonzo Church. John McCarthy. Turing. David Hilbert, Jules Richard, G. G. Berry, Georg Cantor, Bertrand Russell, Kurt Gödel, Alan

Formal Systems and their Applications

Functional Programming

More Untyped Lambda Calculus & Simply Typed Lambda Calculus

Functional Languages. CSE 307 Principles of Programming Languages Stony Brook University

Lambda Calculus as a Programming Language

The University of Nottingham SCHOOL OF COMPUTER SCIENCE A LEVEL 4 MODULE, SPRING SEMESTER MATHEMATICAL FOUNDATIONS OF PROGRAMMING ANSWERS

Untyped Lambda Calculus

Lambda calculus. Wouter Swierstra and Alejandro Serrano. Advanced functional programming - Lecture 6

CITS3211 FUNCTIONAL PROGRAMMING

Scheme. Functional Programming. Lambda Calculus. CSC 4101: Programming Languages 1. Textbook, Sections , 13.7

CMSC 330: Organization of Programming Languages. Lambda Calculus

Functional Programming Languages (FPL)

M. Snyder, George Mason University LAMBDA CALCULUS. (untyped)

The Lambda Calculus. 27 September. Fall Software Foundations CIS 500. The lambda-calculus. Announcements

T ::=Nat T T. zero : Nat. This rule can be instantiated for any type T, so it is actually a family of rules, one for each type.

Functional Programming. Big Picture. Design of Programming Languages

CMSC 330: Organization of Programming Languages

CMSC 330: Organization of Programming Languages. Lambda Calculus

Transcription:

LAMBDA CALCULUS 1. Background λ-calculus is a formal system with a variety of applications in mathematics, logic, and computer science. It examines the concept of functions as processes, rather than the usual set-theoretic notion of functions in extension, and it provides an alternative model for computable functions. Functional programming languages like Haskell and ML owe a great deal to lambda calculus for their existence. λ- calculus is itself, in some sense, a very simple programming language, although it would be impractical to implement for most purposes. However, as a programming language, what it lacks in practicality, it makes up for in simplicity, and since it is equivalent to most computer languages, it provides a great way to study their properties. λ-calculus was invented in the 1930 s by Alanzo Church and Stephen Kleene. Originally, in addition to being used to study function theory, λ-calculus was intended to provide a foundation for mathematics, but this system was shown to be inconsistent. Despite this, Church reduced λ-calculus to its functional aspect, which is the system we use today. 2. Description of the Language We will assume familiarity with the basics of λ-calculus, but here we will include a brief description of the language and transformation rules. The language of λ-calculus, Λ, can be defined recursively as follows: λ-terms. T Λ iff one of the following holds: (1) T is a member of a countable set of variables {a, b, c,..., x 1, x 2,...}. (2) T is of the form (MN) where M and N are in Λ. (3) T is of the form (λx.y) where X is a variable and Y is in Λ. Λ is the smallest language with this property. An element of the form (MN) is called an application, and an element of the form λx.y is called an abstraction. In order to reduce parentheses we will assume application is left-associative. Also, instead of saying T is of the form M we will write T M. Example. The following are all examples of λ -terms: (1) λp.pλx.y (2) xλm.λn.nm (3) xλmn.nm -whenever we have consecutive abstractions as in the previous example, we can concatenate them like this. (4) (λp.p(λxy.x))(λm.mab) (5) (λx.xx)(λy.y) 1

2 LAMBDA CALCULUS Example (5) is an instancs of a redex, which is an application with an abstraction on the left. We interpret abstractions λx.p as descriptions of what they do to arguments. The term P describes explicitly what the abstraction will return, using the variable x to represent the term applied to the abstraction. So the abstraction in example (5) takes a term x and outputs 2 copies of it. Hence it takes (λy.y) and returns (λy.y)(λy.y), and we say (λx.xx)(λy.y) contracts to (λy.y)(λy.y), or more succinctly, (λx.xx)(λy.y) 1 (λy.y)(λy.y). If P takes 0 or more contractions to get to the term Q, then we say P reduces to Q, or P Q. We say two terms P and Q are β-equivalent, or P = β Q if they both reduce to a common term. For our purposes, we will drop the β subscript. 3. λ-definability, Church Numerals and Recursion In order to show that λ-calculus is actually useful, we will show that we can encode natural numbers and many of the basic arithmetic operations into the language. There are many possible ways to do this, but we will use the conventional system put forth by Church: Church Numerals. For every natural number n, we associate with it a λ-term n of the form where x n denotes x repeated n times. n λxy.x n y, So we see that each number n, as a Church numeral, takes in two arguments and applies the first argument n times to the second argument. This will make it easy to define basic arithmetic operations, since many of them, like multiplication and exponentiation, are simply repeated applications of a particular function. Definition. A function φ : N k N is λ definable if there is a λ-term F such that for every n 1, n 2,..., n k N, we have that Fn 1... n k = φ(n 1,..., n k ). That is, F is the same as φ, except that it operates on the Church numerals. All of the basic operations on natural numbers are λ-definable. We can build them up quite easily due to the form of the Church numerals: [inc] [add] [mul] [exp] λn.λxy.x(nxy) λmn.m[inc]0 λmn.m([add]n)0 λmn.n([mul]m)1 In [add], [mul], and [exp], we see that the abstractions take a given Church numeral, replace the repeated part by a given function, and replace the end part by a starting value. For instance, in [mul], the repeated part of one of the inputs m is replaced by the function ([add]n) that adds n to a given input, and the end part is replaced by the starting value 0. So we see that [mul] implements multiplication as repeated addition.

LAMBDA CALCULUS 3 In order to define more complex functions, it is useful to create a pairing operator and corresponding selectors. Before, in [add], [mul], and [exp], we could only replace the repeating part of a number by unary operators and replace the end part by a single value. With pairing operators and selectors, however, we could effectively pass multiple values through each repeated function. So we define the [cons], [car], and [cdr] operators (paying tribute to the LISP naming conventions): [cons] λabm.mab [car] λp.p(λxy.x) [cdr] λp.p(λxy.y) We see that the pairing operator [cons] is specifically designed with selectors [car] and [cdr] in mind: [car]([cons]ab) (λp.p(λxy.x))((λabm.mab)ab) (λp.p(λxy.x))(λm.mab) (λm.mab)(λxy.x) (λxy.x)ab A It is clear that [cdr] works the same way, except at the last step it returns B instead of A. So now we can make some more complicated functions, like [fac], which returns the factorial of a given number. Typically, in a program, the factorial function is defined iteratively, with a counter variable that multiplies an accumulated value on each step. Now with our pairing operators, we can create [fac] in an analoguous way, replacing the end part of the input number n by the pair (1,1), and replacing the repeating part of n by the function that takes a pair (a,b) and returns the pair (a+1,a*b). Applied n times, the function will return (n+1,n!), so we need to take the [cdr] at the end. Thus [fac] can be defined as follows: [fac-iter] (λp.[cons]([inc]([car]p))([mul]([car]p)([cdr]p))) [fac] λn.[cdr](n[fac-iter]([cons]1 1)) Continuing on with our development of a useful set of operators, a logical next step would be to create some form of conditional operator, something essential to just about any programming language. Suppose we would like to implement an if-then-else construct that performs a test, and depending on the outcome, returns one of two specified outputs. That is, we want to create an operator [if-then-else] that takes 3 inputs A, B, and C, where A holds a boolean value, and B and C are the two possible outputs. Boolean values can be represented many ways in lambda calculus, but we will represent it with our given Church numerals, where 0 represents false and 1 represents true. So to begin, our function will take B and C, and pair them together with [cons]. Then we will want to find some way to apply [car] to this pair if A is 1 and [cdr] if A is 0. To do this, we can use the fact that 0 ignores its first input, whereas 1 does not:

4 LAMBDA CALCULUS [if-then-else] λabc.a(λx.[car])[cdr]([cons]bc) We can see with a simple reduction that this function works: [if-then-else]0ab 0(λx.[car])[cdr]([cons]AB) [cdr]([cons]ab) B [if-then-else]1ab 1(λx.[car])[cdr]([cons]AB) (λx.[car])[cdr]([cons]ab) [car]([cons]ab) A So far we have been avoiding a rather important operator, the predecessor operator, and now we have enough machinery to define it. Since we do not have negative numbers, we will have the predecessor operator take 0 to 0. [pred-iter] (λp.[cons]1([if-then-else]([car]p)([inc]([cdr]p))0)) [pred] λn.[cdr](n[pred iter]([cons]0 0)) We see that the [pred] operator is similar to [fac] in that it replaces the repeating part of the input number n by a function that operates on and returns pairs. In this case, we replace the end part of n by the pair (0,0) and apply to it n times the function that takes a pair (a,b) and returns (1,0) if a=0 and (1,b+1) if a=1. With [pred] we can now define [monus] which subtracts n from m if n m and returns 0 otherwise: [monus] λmn.n[pred]m Now that we have shown many of the basic arithmetic operations to be λ- definable, we may ask what other natural number functions are definable. Clearly, not all can be defined, since the set of functions from N k to N is uncountable and the set of λ-terms is countable. It can be shown quite easily that all primitive recursive functions are definable, by introducing the recursion operator. But this is far from a desirable set of functions, since there are many computable functions that are not primitive recursive, like Ackerman s function, for instance. Although we will not prove it here, Kleene had shown that every total recursive function is λ-definable. We will use this fact in the next section to derive a general undecidability theorem. 4. The Undecidability Theorem The first undecidability proof in mathematics was given by Alonzo Church in 1936, using λ-calculus. The following proof is a more general form, but proves the same result, that there is no algorithm to decide whether or not two λ-terms are equivalent. To begin, we will make a few major assumptions. First, we assume that there is an algorithm that defines an injective map #:Λ N that associates with every λ-term a natural number. This is called a Godel numbering of the terms, which

LAMBDA CALCULUS 5 allows us to perform computations within λ-calculus on other λ-terms. We also assume that these terms are numbered so that there are total recursive functions τ and ν such that τ(#a, #B) = #(AB) and ν(n) = #n Before we state the theorem, we begin with a few definitions. Definition. Let A and B be disjoint sets of natural numbers. They are called recursively separable iff there is a total recursive function φ such that n A = φ(n) = 1 n B = φ(n) = 0 We say two sets of terms A and B are recursively separable if the sets of Godel numbers associated with A and B are recursively separable. Definition. A set of terms A is closed under equality if P A and P = Q = Q A One more thing: let [X ] denote #X. Scott-Curry Undecidability Theorem. No pair of non-empty sets of terms closed under equality is recursively seperable. Proof. Suppose not. Then there is a total recursive function φ, and a pair of nonempty sets of terms A and B such that φ separates A and B. Since every recursive function is definable in λ-calculus, let F be the λ-term defining φ. That is, (1) (2) X A = F [X ] = 1, X B = F [X ] = 0. Now let T and V be the terms which define the functions τ and ν. Then we have that (3) (4) T [X ][Y ] = [XY ], V n = Now in order to find a contradiction, we will construct, using any two terms A A and B B we want, another term J with the property that [n] (5) (6) F [J ] = 1 = J = B, F [J ] = 0 = J = A. Clearly, both of these statements cannot be true. If F [J ] = 1, then J must be in B, but this implies by the definition of F that F [J ] = 0. Likewise, if F [J ] = 0, we conclude by the same reasoning that F [J ] = 1, so we reach a contradiction. Now to construct J, we will want it to have the following property: (7) J = [if-then-else](f [J ])BA

6 LAMBDA CALCULUS If we construct such a J, then we see that if F [J ] = 1, then J = [if-then-else]1ba = B, and if F [F ] = 0, then J = [if-then-else]0ba = A. So let J H [H ] where H λy.[if-then-else](f(ty(v y))ba Now we perform a simple β reduction to see that J has the desired property (7): J = H [H ] = (λy.[if-then-else](f(t y(v y)))ba)[h ] = [if-then-else](f(t [H ](V [H ])))BA = [if-then-else](f(t [H ][[H ]]))BA = [if-then-else](f([h [H ]]))BA = [if-then-else](f([j ]))BA References [1] Barendregt, H. P., The Lambda Calculus, North-Holland Publishing Company, New York, NY, 1981. [2] Hindley, J. R., Seldin, J. P., Introduction to Combinators and λ-calculus, Cambridge University Press, New York, NY, 1986.