Introduction to lambda calculus Part 3

Similar documents
Functional Programming

11/6/17. Functional programming. FP Foundations, Scheme (2) LISP Data Types. LISP Data Types. LISP Data Types. Scheme. LISP: John McCarthy 1958 MIT

Principles of Programming Languages 2017W, Functional Programming

Organization of Programming Languages CS3200/5200N. Lecture 11

Lambda Calculus. Variables and Functions. cs3723 1

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

CS 314 Principles of Programming Languages

Functional Programming. Pure Functional Languages

1.3. Conditional expressions To express case distinctions like

CS 6110 S14 Lecture 1 Introduction 24 January 2014

FP Foundations, Scheme

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

Functional Programming. Pure Functional Languages

Introduction to Scheme

Programming Languages

Functional Programming. Big Picture. Design of Programming Languages

Documentation for LISP in BASIC

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

Functional Programming. Pure Functional Programming

Introduction to LISP. York University Department of Computer Science and Engineering. York University- CSE V.

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

Functional Programming Languages (FPL)

Recursive Functions of Symbolic Expressions and Their Application, Part I

Project 2: Scheme Interpreter

Scheme: Data. CS F331 Programming Languages CSCE A331 Programming Language Concepts Lecture Slides Monday, April 3, Glenn G.

COP4020 Programming Languages. Functional Programming Prof. Robert van Engelen

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

Intro. Scheme Basics. scm> 5 5. scm>

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

Symbolic Programming. Dr. Zoran Duric () Symbolic Programming 1/ 89 August 28, / 89

Polymorphic lambda calculus Princ. of Progr. Languages (and Extended ) The University of Birmingham. c Uday Reddy

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

Topic III. LISP : functions, recursion, and lists References: Chapter 3 of Concepts in programming languages by J. C. Mitchell. CUP, 2003.

CSCC24 Functional Programming Scheme Part 2

FUNKCIONÁLNÍ A LOGICKÉ PROGRAMOVÁNÍ 2. ÚVOD DO LISPU: ATOMY, SEZNAMY, FUNKCE,

Functional Languages. Hwansoo Han

Scheme: Expressions & Procedures

Handout 10: Imperative programs and the Lambda Calculus

Chapter 15. Functional Programming Languages

CSE413: Programming Languages and Implementation Racket structs Implementing languages with interpreters Implementing closures

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

Comp 411 Principles of Programming Languages Lecture 7 Meta-interpreters. Corky Cartwright January 26, 2018

Announcements. The current topic: Scheme. Review: BST functions. Review: Representing trees in Scheme. Reminder: Lab 2 is due on Monday at 10:30 am.

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

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

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

15 Unification and Embedded Languages in Lisp

Functional programming in LISP

SOFTWARE ARCHITECTURE 6. LISP

Lambda Calculus. Gunnar Gotshalks LC-1

CPS 506 Comparative Programming Languages. Programming Language Paradigm

Symbolic Reasoning. Dr. Neil T. Dantam. Spring CSCI-561, Colorado School of Mines. Dantam (Mines CSCI-561) Symbolic Reasoning Spring / 86

Imperative, OO and Functional Languages A C program is

Fundamentals and lambda calculus

Principles of Programming Languages Topic: Functional Programming Professor L. Thorne McCarty Spring 2003

Languages with Contexts II: An Applicative Language

Lisp. Versions of LISP

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

INF4820: Algorithms for Artificial Intelligence and Natural Language Processing. Common Lisp Fundamentals

Type Systems Winter Semester 2006

CITS3211 FUNCTIONAL PROGRAMMING

PROGRAMMING IN HASKELL. Chapter 2 - First Steps

Fundamentals of Artificial Intelligence COMP221: Functional Programming in Scheme (and LISP)

C311 Lab #3 Representation Independence: Representation Independent Interpreters

Reasoning About Programs Panagiotis Manolios

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

Functional programming with Common Lisp

Lambda Calculus. Lecture 4 CS /26/10

Lambda Calculus see notes on Lambda Calculus

Lambda Calculus and Extensions as Foundation of Functional Programming

LECTURE 16. Functional Programming

From the λ-calculus to Functional Programming Drew McDermott Posted

Modern Programming Languages. Lecture LISP Programming Language An Introduction

Notes on Higher Order Programming in Scheme. by Alexander Stepanov

Lecture Notes: Control Flow Analysis for Functional Languages

CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures. Dan Grossman Autumn 2018

Lambda Calculus and Lambda notation in Lisp II. Based on Prof. Gotshalks notes on Lambda Calculus and Chapter 9 in Wilensky.

Common LISP-Introduction

COP4020 Programming Assignment 1 - Spring 2011

Concepts of programming languages

Programming Systems in Artificial Intelligence Functional Programming

Note that in this definition, n + m denotes the syntactic expression with three symbols n, +, and m, not to the number that is the sum of n and m.

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

CIS 500 Software Foundations Fall September 25

ALISP interpreter in Awk

Formal Semantics. Chapter Twenty-Three Modern Programming Languages, 2nd ed. 1

6.184 Lecture 4. Interpretation. Tweaked by Ben Vandiver Compiled by Mike Phillips Original material by Eric Grimson

The Untyped Lambda Calculus

Comp 311: Sample Midterm Examination

CSC 533: Programming Languages. Spring 2015

Lambda Calculus LC-1

Functional Programming and λ Calculus. Amey Karkare Dept of CSE, IIT Kanpur

Scheme in Scheme: The Metacircular Evaluator Eval and Apply

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

Fundamentals and lambda calculus. Deian Stefan (adopted from my & Edward Yang s CSE242 slides)

The PCAT Programming Language Reference Manual

CMSC 330: Organization of Programming Languages. Operational Semantics

Recursive Definitions, Fixed Points and the Combinator

CS 360 Programming Languages Interpreters

Week 4: Functional Programming

Transcription:

Introduction to lambda calculus Part 3 Antti-Juhani Kaijanaho 2017-01-27... 1 Untyped lambda calculus... 2 Typed lambda calculi In an untyped lambda calculus extended with integers, it is required that any value, whether a function or a number, must be treatable as a function or as a number. Thus, in an untyped language, both 5(λx x) and 5+(λx x) must have a specified result (even if it is the undefined value ). In most contexts, however, such usage is a mistake. There are a number of ways to add types to lambda calculus. It rarely makes any sense to do this to the pure lambda calculus, so all my examples will have some extensions to the pure language. For a history of the concept of a type, see Kaijanaho (2015, Section 2.4.2). 2.1 Dynamically typed lambda calculus with integers Here is an abstract syntax for a lambda calculus with integers. Minor changes made afterward. Last changed 2017-01-30 10:58:49+02:00. 1

c, d Const x, y, z Var t, u Term t, u ::= x c t u λx t t + u t u t u t / u For the denotational semantics, dynamic typing means that it must define what terms have type errors, and distinguish between type errors and other kinds of undefinedness. In this language, there are two principal kinds of type errors: calling a numeric value and performing arithmetic on functions. Thus, we must be able to distinguish between numbers and functions at the value level. We need two domains for the denotational semantics: Num is the domain of integers. Fun is the domain of suitable functions D D. Saying that these are domains means that each has an undefined value called bottom. Specifically, there is the undefined integer Num and the undefined function Fun (for which Fun (x) = D holds for all x D). Further, domain theory means that Fun contains only some functions D D, not all of them, but there will be sufficiently many for the purposes of garden variety denotational semantics. We will further assume that all common numeric operations such as addition are defined in Num with the supposition that if any operand is Num, the result is also Num. In other words, the operations are strict in all parameters. We will also assume the existence of a function V : Const Num that takes each literal constant to its numeric value. Now, let us assume that no number is a function and no function is an error, and no error is a number. Then we can define D = Num Fun wrong, D } We need an ultimate bottom D as distinct from the bottoms of each domain to indicate that we do not even know the domain the value belongs to. The value wrong indicates a type error. 2

The denotational semantics is now defined by the following function: E: Term (Var D) D E x σ = σ x (1) E c σ = V c (2) wrong if f Fun or a = wrong E tu σ = (3) f(a) otherwise where f = E t σ and a = E u σ E λx t σ = f, where f : D D E t + u = wrong a + b f(z) = E t (σ[x := z) if a Num or b Num otherwise where a = E t σ and b = E u σ wrong if a Num or b Num E t u = a b otherwise where a = E t σ and b = E u σ wrong if a Num or b Num E t u = a b otherwise where a = E t σ and b = E u σ wrong if a Num or b Num E t / u = Num if a Num and b = 0 otherwise a b where a = E t σ and b = E u σ Example 11 The denotation of (λx x) + 5 is wrong under (5), since E λx x σ is a function, not a numeric value. Reduction uses the standard α and β conversion rules, plus the following arithmetical rules: c + d a v where v = V c + V d (9) c d a v where v = V c V d (10) c d a v where v = V c V d (11) c / d a v (4) (5) (6) (7) (8) where v = V c, if defined (12) V d 3

An arithmetical redex is any term where two numeric constants are operands to an arithmetical operator. For the purposes of reduction order, arithmetical redexes count as redexes. Example 12 Let us compute (λx x+x)(3 3). First, use the normal order: Then the applicative order: (λx x + x)(3 3) β (3 3) + (3 3) a 9 + (3 3) a 9 + 9 a 18 (λx x + x)(3 3) a (λx x + x)9 β 9 + 9 a 18 Exercise 6 Compute (λx (λy (λx x + y))(2 x)) 3 using reductions. 2.2 A model of Lisp The essence of Lisp (see e. g. McCarthy 1960, 1981; McCarthy et al. 1966; Seibel 2005) is a dynamically typed lambda calculus with several extensions: There are atoms, which are akin to constants; every atom has a corresponding atom value which is distinct from every other value. There are at least two atoms: T and NIL. Any two values can be put into an ordered pair, which is itself a value. There is a guarded term for evaluating a term only if the value of another term is not NIL There is a way to combine guarded terms so that it is possible to choose between multiple terms. There is a mechanism for defining values by recursive computation. A real Lisp will also support assignable variables, side effects such as I/O and in-place modification of data structures, metaprogramming using macros, and many other features omitted from this model. 4

Thus, we arrive at the following abstract syntax: a, b, c Atom x, y, z Var t, u Term t, u ::= x a t u λx t µx t recursively defined value t, u ordered pair g g GuardedTerm g ::= t u term guarded by a condition g g 1 g 2 combined guarded term Before defining its semantics or behavior formally, I will explain informally some of the newer constructs. First, µx t (called a label expression in traditional Lisp and a fixpoint term by theorists) is intended to describe recursion, so the value of µx t is the value of t evaluated with x standing for the value of t. Second, a guarded term (t 1 u 1 t 2 u 2 t n u n ) tries each t i in order until one of them evaluates to something other than NIL, in which case the value of the whole guarded term is the value of the corresponding u i ; if all t i evaluate to NIL, then the whole guarded term evaluates to NIL. There is an idiom to chain pairs to form a linked list terminated by the atom NIL, so a, b, c, NIL is a linked list of a, b, and c. It is so ubiquitous an idiom that we will use the following syntactic sugar: [t 1, t 2,..., t n means the same as t 1, t 2,... t n, NIL.... A Lisp program presumes some standard atoms and variables (standing for functions). The standard variables are expected to be defined in the global environment. The most important ones are atoms representing numbers, and the following variables standing for functions: EQ p presumes that p evaluates to a list of atoms; it returns T if they are all the same atom and NIL otherwise. ATOM p returns T if p is an list consisting of a single atom and NIL otherwise. CONS p presumes that p evaluates to a list of two elements and returns a pair of those elements. 5

CAR p presumes that p evaluates to a pair and returns its left component. CDR p presumes that p evaluates to a pair and returns its right component. ADD l presumes that l evaluates to a list of atoms representing numbers and returns their sum. SUB l presumes that l evaluates to a list of atoms representing numbers and subtracts from the first all the rest, and returns the result. MUL l presumes that l evaluates to a list of atoms representing numbers and returns their product. DIV l presumes that l envaluates a list of atoms representing numbers and divides the first by the second, the result by the third, and so on, and returns the final result. Example 13 We may write the factorial function as follows: µf λx (EQ[x, 0 1 T MUL[x, f(sub[x, 1)) For a denotational semantics, we need a domain D that contains all the atoms in Atom, including T and NIL, enough functions D D (which will all belong to the subset Fun), enough pairs from D D (which will all belong to the subset Pair), the type error value wrong, and the undefined value. (Enough in this case means that D must satisfy the requirements of domain theory.) Further, there shall be a domain D f = D fail}, which is used to control selection among guarded terms. The denotational semantics is defined by the following two functions: E: Term (Var D) D E x σ = σ x (13) E a σ = a (14) 6

E tu σ = wrong f(v) if f = or v = else if f Fun or v = wrong otherwise where f = E t σ and v = E u σ E λx t σ = f where f : D D f(z) = E t (σ[x := z) (15) (16) E µx t σ = v where v = E t (σ[x := v) (17) if v = or w = E t, u σ = wrong if v = wrong or w = wrong (18) (v, w) otherwise where v = E t σ and w = E u σ NIL if v = fail E g σ = v otherwise where v = G g σ (19) G: Term (Var D) D f if v = wrong if v = wrong G t u σ = fail if v = NIL E u σ otherwise where v = E t σ G g 2 σ if v = fail G g 1 g 2 σ = v otherwise where v = G g 1 σ (20) (21) The set of free variables and variable substitution are largely similarly computed as with ordinary lambda calculus, except that µx t binds x the same way as λx t does. Exercise 7 Define F V : (Term GuardedTerm) P (Var) and variable substitution (t[x := u) formally for this model of Lisp. Note that you should avoid variable capture even though this was not traditionally done in Lisp. Reduction rules are a bit more complicated. In the rules below, v stands for a term on which no more reductions can be performed. We start with 7

the basic rule of β reduction, restricted to applicative order (requiring the reduction of the argument first): 1 (λx t)v t[x := v (22) Since the x in a recursion term stands for the term itself, we can simply move it inward to simulate one step of recursion. µx t t[x := µx t (23) The reduction rules for guarded terms are suggested by their informal semantics: (NIL u g) g (24) (v u g) u if v NIL (25) (NIL u) NIL (26) (v u) u if t NIL (27) Lisp s traditional reduction order is weak applicative order reduction from left to right: tu t u if t t (28) vu vu if u u (29) t, u t, u if t t (30) v, u v, u if u u (31) (t u g) (t u g) if t t (32) (t u) (t u) if t t (33) Finally, we would need rules for the standard functions, but I will omit them here (you may use them informally to make reduction steps once the arguments are fully reduced). Example 14 Let us compute (µf λx (EQ[x, 0 1 T MUL[x, f(sub[x, 1))) 1 using the reduction rules: ( µf λx ( )) 1 I will no longer subscript the arrow with the type of the reduction. 1 8

λx 1 T MUL x, µf λx (SUB [x, 1) by (23), (28) EQ [1, 0 1 T MUL 1, µf λx (SUB [1, 1) by (22) NIL 1 T MUL 1, µf λx (SUB [1, 1) by EQ, (32) ( [ ( ( )) ) T MUL 1, µf λx (SUB [1, 1) by (24) [ ( ( )) MUL 1, µf λx (SUB [1, 1) by (27) MUL 1, λx (SUB [1, 1) T MUL x, µf λx (SUB [x, 1) by (23), (28), (31),(29) MUL 1, λx T MUL x, µf λx (SUB [x, 1) by SUB, (29), (31),(29) EQ [0, 0 1 MUL 1, T MUL 0, µf λx (SUB [0, 1) by (22), (31),(29) T 1 MUL 1, T MUL 0, µf λx (SUB [0, 1) by EQ, (32), (31),(29) MUL [1, 1 by (25), (31),(29) 1 by MUL There is, however, a further interesting aspect of Lisp. There is a traditional concrete syntax for Lisp data, called S-expressions. The basic idea is that a list is written by listing its elements one by one inside parentheses with nothing (except whitespace if needed) in between; atoms are written as they are. Thus, the list [a, b, [c, d, e is written in S-expression format as (a b (c d e)). Further, a pair is written by listing its two elements in parentheses with a period in between: a, b is written as (a. b). More generally, a sequence of pairs that would be a list except that it terminates in something other than NIL is written like a list except that the terminating thing is separated from the rest of the list with a period; thus a, b, c, d is written as (a b c. d) (this is called a improper list). Atoms are written as themselves. Now, there is a standard way to represent Lisp terms as lisp data, expressed as S-expressions (must be applied recursively): 9

My notation Standard S-expression form t[u 1,..., u n (t u 1 u n ) λx t (LAMBDA x t) µx t (LABEL x t) a (QUOTE a) t, u (QUOTE (t. u)) [t 1,..., t n (QUOTE (t 1 t n ) (t 1 u 1 t n u n ) (COND (t 1 u 1 ) (t n u n )) Further, abstractions are usually written (LAMBDA (X Y Z) ( )) or sometimes even (LAMBDA (X Y. Z) ( )), which allows the S-expression programmer to give names to some or all of the elements of an argument list given to the function. My notation does not support that. Since the QUOTEs get very cumbersome very fast, there is a common abbreviation: we can write instead of (QUOTE ). Quoting of an atom that does not look like a variable (such as a numeric constant) is not necessary. Similarly, do not nest QUOTEs: (QUOTE a (b c) d) is the nested list [a, [b, c, d In classical Lisp, S-expressions were written in upper case letters. Nowadays lower-case letters are more commmonly used, and S-expressions are usually treated as case insensitively (so LAMBDA and lambda are the same atom). Example 15 Here is the factorial function of Example 13 in S-expression form: (label f (lambda (x) (cond ((eq x 0) 1) ( t (mul x (f (sub x 1))))))) Given all this, we can write a Lisp function that reads a Lisp term and an environment represesnted as Lisp data, and performs the reduction. It is not even particularly hard. This function, called eval, is the first ever definitional interpreter written. Practical Lisps usually provide a read-eval-print loop (repl): a command line interface where terms written as S-expressions are input by the user, then evaluated by the Lisp implementation, and finally the value of the expression is printed. Lisps also provide various ways to modify the top-level environment which contains the standard functions for example (define 10

f (lambda )) in Scheme. This is the way programs are also written they are essentially scripts of repl sessions, at least in simple cases. Exercise 8 Write, using either my abstract syntax notation or S-expression notation, a Lisp function that 1. counts the number of elements in a list 2. computes the average of numbers in a list 3. reverses a list You may also use the concrete syntax of a Lisp dialect implementation (but do not use its library funtions beyond the equivalents of the functions listed in this document). In that case, specify which dialect and implementation you used. References Kaijanaho, Antti-Juhani (2015). Evidence-Based Programming Language Design. A Philosophical and Methodological Exploration. Jyväskylä Studies in Computing 222. University of Jyväskylä. url: http://urn.fi/urn: ISBN:978-951-39-6388-0. McCarthy, John (1960). Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I. In: Communications of the ACM 3.4, pp. 184 195. doi: 10.1145/367177.367199. (1981). History of LISP. In: History of programming languages I. New York, NY, USA: ACM, pp. 173 185. isbn: 0-12-745040-8. doi: 10.1145/ 800025.1198360. McCarthy, John et al. (1966). LISP 1.5 Programmer s Manual. 2nd ed. MIT Press. Seibel, Peter (2005). Practical Common Lisp. Apress. url: http://www. gigamonkeys.com/book/. 11