introduction to the l-calculusmainpage.nwu.edu.cn/hkg/docs/pi/cs345-lecture-05.pdf · nj. hartley...

30
Introduction to the l-calculus CS345 - Programming Languages Dr. Greg Lavender Department of Computer Sciences The University of Texas at Austin

Upload: vukhuong

Post on 02-Aug-2018

222 views

Category:

Documents


0 download

TRANSCRIPT

Introduction to the l-calculus

CS345 - Programming Languages

Dr. Greg LavenderDepartment of Computer SciencesThe University of Texas at Austin

10/1/03 07:21 CS345 - Programming Languages 2

l-calculus in Computer Science

n a formal notation, theory, and model of computationn Church’s thesis => l-calculus is equivalent to Turing Machines

n equivalence was proved by Kleene

n foundation for the functional style of programmingn ISWIM, Lisp, Scheme, ML, Haskell, …

n natural model for many computational objectsn higher-order functions, variables, block scopes, expressions,

ordered pairs, lists, records, recursionn calling conventions: call-by-value, call-by-need, call-by-name

n type inferencing & polymorphic type systemsn Roger Hindley & Robin Milner (Turing award)

n notation for Scott-Strachey denotational semanticsn Domain theory of Dana Scott (Turing award)

10/1/03 07:21 CS345 - Programming Languages 3

Historical Origins

n Foundations of Mathematics (1879-1936)n Paradoxes of set theory

n Cantor, Frege, Russell’s paradoxn Axiomatic systems, mathematical logic & type theory

n Hilbert, Bernays, Brouwer, Russell, Tarski, Zermelo, Fraenkel, …n Gödel’s Incompleteness Theoremn Metamathematics => a theory of computable functions

n combinators, “currying” – Moses Schönfinkel (1924)n combinatory logic - Haskell Curry (1930)n l-calculus – Alonzo Church (1934)n m-recursive functions – Stephen Kleene (1936)n turing machines – Alan Turing (1936)n others: Herbrand, Kolmogorov, Post, …

10/1/03 07:21 CS345 - Programming Languages 4

Alonzo Church

n PhD from Princeton University, 1927n Advisor was Oswald Veblen (who advised R.L. Moore of UT)n Studied with David Hilbert, Paul Bernays & L.E.J. Brouwer in Germanyn PhD students are “founding fathers” of theoretical computer science

n Stephen Kleene, 1934 (recursive function theory)n J. Barkley Rosser, 1934 (logic, Church-Rosser theorem)n Alan Turing, 1938 (computational logic & computability)n Leon Henkin, 1947 (logic, completeness proofs)n Martin Davis, 1950 (logic, computability theory)n J. Hartley Rogers, 1952 (recursive function theory)n Michael Rabin, 1956 (probabilistic algorithms – Turing award)n Dana Scott, 1958 (prob. algorithms, domain theory – Turing award)n Raymond Smullyan, 1959 (logic, tableau method, formal systems)n Simon Kochen, 1959 (Kochen-Specker theorem in QM)n Peter B. Andrews, 1964 (logic, type theory)

10/1/03 07:21 CS345 - Programming Languages 5

Computers and Programming

“The computer and programming languages were invented by logicians asthe unexpected by-product of their unsuccessful effort to formalize[mathematical] reasoning completely. Formalism failed for reasoning, butit succeeded brilliantly for computation. In practice, programmingrequires more precision than proving theorems!”

- Gregory J. Chaitin, co-founder of Algorithmic Information Theory

Quoted from: A Hundred Years of Controversy Regarding theFoundations of Mathematics, in the The Unknowable, Springer-Verlag,1999.

10/1/03 07:21 CS345 - Programming Languages 6

Computation and Information

n What constitutes a computation?n a mechanical rearrangement of symbols

n based on well-defined syntactic transformation rules (a calculus)n what do the symbols mean and what is a meaningful

computation? what is information anyway?n how do humans (or machines) interpret the result constructively

n A simple but powerful answern symbolic term rewriting

n substitution of terms according to well-defined rulesn reduction of resulting intermediate expressions to a normal formn the result is called a computation

10/1/03 07:21 CS345 - Programming Languages 7

A computational point of view

n a function in set theory is a graphn characterized solely by an input->output relation

n extensional equality - two functions f,g are equal iff they have thesame graph, i.e., {(x,y) | y = f(x) = g(x) }

n this doesn’t work too well in programming!n in what way are two sorting functions equivalent?

n intensional equality – equivalent algorithmic complexity

n how the function computes its result is importantn in CS we characterize a function by its algorithm:

n E.g., a O(n2) vs O(n log2 n) sorting algorithm

10/1/03 07:21 CS345 - Programming Languages 8

Some functional notations

Set Theoretic:

{(x,y) | Vx,y e NN: y = x2}

Algebraic:f: NN->NNf(x) = x2;

Type-free l-notation:

lx.x * x

Typed l-notation:

lx:int.x * x

Polymorphic l-notation:

lx:a.x * x

Scheme:(define square (lambda (x) (* x x)))

Algol:integer procedure square(x); integer x;begin square := x * x end;

Pascal:function square (x:integer) : integer;begin square := x * x end;

K&R C:square(x) int x; { return (x * x); }

StdC/C++/Java:int square(int x) { return (x * x); }

ML97:fun square x = x * x;fun square (x:int) = x * x;val square = fn x => x * x;

Haskell:square :: Int->Intsquare x = x * xmap (\x -> x * x) [0..][(x,y) | x <- [0..], y <- [x * x]]

10/1/03 07:21 CS345 - Programming Languages 9

Definitions

n l-calculus is a formal notation for defining functionsn expressions in this notation are called l-expressionsn every l-expression denotes a function that is “out there”n a l-expression consists of 3 kinds of terms:

n variables: x,y,z, etc.n we use V, V1, V2, etc., for arbitrary variables

n abstractions: lV.En Where V is some variable and E is another l-term

n applications: (E1 E2)n Where E1 and E2 are l-terms

n applications are sometimes called combinations

10/1/03 07:21 CS345 - Programming Languages 10

Formal Syntax in BNF

<l-term> ::= <variable>| l <variable> . <l-term>| (<l-term> <l-term>)

<variable> ::= x | y | z | …

Or, more compactly:

E ::= V | lV.E | (E1 E2)

V :: = x | y | z | …

Where V is an arbitrary variable and Ei is an arbitrary l-expression.

We call lV the head of the l-expression and E the body.

10/1/03 07:21 CS345 - Programming Languages 11

Variables

n variables can be bound or freen the l-calculus assumes an infinite universe of free variablesn they are bound to functions in an environmentn they become bound by usage in an abstraction

n for example, in the l-expression: lx.x*y

x is bound by l over the body x * y, but y is a free variable. I.e.,lexically scoped. Compare this to scheme:

(define z 3)(define x 2)(define y 2)(define multi-by-y (lambda (x) (* x y)))(multi-by-y z) => 6

10/1/03 07:21 CS345 - Programming Languages 12

Abstractions

n if lV.E is an abstractionn V is a bound variable over the body En it denotes the function that when given an actual argument ‘a’,

evaluates to the function E’ with all occurrences of V in E replacedwith ‘a’, written E[a/V]

n For example the abstraction: lx.x

is the identity function (lx.x)1 => 1 (lx.x)a => a

(lx.x)(lx.x) => (lx.x)

10/1/03 07:21 CS345 - Programming Languages 13

Applications

n If E1 and E2 are l-expressions, so is (E1 E2)n application is basically function evaluationn apply the function E1 to the argument E2

n E1 is called the rator (ope-rator)n E2 is called the rand (ope-rand)

n For example:(lx.xx) 1 => 11(lx.xx) a => aa

(lx.xx)(lx.xx) => (lx.xx)(lx.xx)

this last example is a quine, and it doesn’t terminate! It keepsduplicating itself ad infinitum. In this example, we don’t care, but inreal programming we do care about non-terminating evaluations!

10/1/03 07:21 CS345 - Programming Languages 14

Conversion/reduction rules

n a-conversionAny abstraction lV.E can be converted to

lV.E[V’/V] iff [V’/V] in E is valid

n b-conversion (b-reduction)Any application (lV.E1) E2 can be converted toE1[E2/V] iff [E2/V] in E1 is valid

n h-conversionAny abstraction lV.(E V) where V has no freeoccurrences in E can be converted to E

10/1/03 07:21 CS345 - Programming Languages 15

Conversion rule notation

aE1 E2

E1 E2b

E1 E2

h

bound variable renaming to avoidnaming conflicts

like a function call evaluation

elimination of irrelevant information

10/1/03 07:21 CS345 - Programming Languages 16

a-redex

aE1 E2

a-reduction is bound variable renamingapplied to an a-redex iff no namingconflicts

redex = reducible expression

lx.xa

ly.y

lx.f xa

ly.f y

(lx.x)[y/x]

(lx.f x)[y/x]

lx.ly.x+ya

ly.ly.f y+y not valid since y is alreadya bound variable in E1

10/1/03 07:21 CS345 - Programming Languages 17

b-redex

E1 E2b

(lx.f x) E bf E

(lx.(ly. x + y)) 3b

ly.3 + y

(ly.3 + y) 4b

3 + 4

10/1/03 07:21 CS345 - Programming Languages 18

Is the l-calculus Turing complete?

n Can we represent the class of Turing computable functions?n yes, we can represent

n Booleans and conditional functionsn numerals and arithmetic functionsn data structures, such as ordered pairs, lists, etc.n recursion

n doing so however is syntactically tedious!n actual programming languages use syntactic sugar for functions

n lambda expressions exist in Scheme, ML, Haskell, and even Pythonn l-calculus is more suitable as an abstract model of a programming

language rather than as a practical programming languagen it is used to study programming languages semantics from a mathematical

perspective called Denotational Semanticsn see the appendix in the Revised Report(5) on the Algorithmic Language Scheme

on course website for the denotational semantics of Scheme

10/1/03 07:21 CS345 - Programming Languages 19

Example of Syntactic Sugar in Scheme

As we have seen, Scheme has let and let* operators for establishinglocal bindings of variables to values over a lexically scoped block. In alet expression, all values in the list of let bindings are evaluated, andthen bound to the local variables. In a let* expression, the values areevaluated and bound to the variables sequentially:(define x 2)

(let ((x 3)(y x)) (* x y)) => 6(let*((x 3)(y x)) (* x y)) => 9

Which are just syntactic sugar for:

((lambda (x y) (* x y)) 3 x) => 6((lambda (x) ((lambda (y) (* x y)) x)) 3) => 9

10/1/03 07:21 CS345 - Programming Languages 20

Church Booleans

n We define booleans and logical operators in the l-calculus as functions:

True = T = lt.lf.t = ltf.t False = F = lt.lf.f = ltf.f AND = lxy.xy(ltf.f) = lxy.xyF

OR = lxy.x(ltf.t)y = lxy.xTyNEG = lx.x(luv.v)(lab.a) = lx.xTF

n Example:NEG True = (lx.x(luv.v)(lab.a))(ltf.t)

=> (ltf.t)(luv.v)(lab.a) => (luv.v) => False

10/1/03 07:21 CS345 - Programming Languages 21

Church Booleans

n We define true and false in the l-calculus asfunctions:

true = lt.lf.t

false = lt.lf.f

We can then define a conditional test function: test = lc.lx.ly.c x y

where test true v w = (lc.lx.ly.c x y) true v w

=>* true v w

= (lt.lf.t) v w

=>* v

10/1/03 07:21 CS345 - Programming Languages 22

Church Numerals

n The natural numbers may be defined using zero andthe successor function:n 0, 1=succ(0), 2=succ(succ(0)), …, etc.

n In the l-calculus, we only have functions, so we definethe natural numbers as functions:n 0 = ls.(lz.z), but we will write this as lsz.z,n then the rest of the natural numbers can be defined as:

n 1 = lsz.s(z), 2= lsz.s(s(z)), 3= lsz.s(s(s(z))), …, etc.

10/1/03 07:21 CS345 - Programming Languages 23

Successor function

n So how do we write a successor function?n S = lwyx.y(wyx)n Let’s test it on zero = lsz.z

n S0 = (lwyx.y(wyx))(lsz.z)=> lyx.y((lsz.z)yx) => lyx.y((lz.z)x)=> lyx.y(x)= 1

n Note that lyx.y(x) = lsz.s(z) under a-conversionn the variables names are “dummy variables”

10/1/03 07:21 CS345 - Programming Languages 24

Curried Functions

n Named after Haskell Curry who used them incombinatory logicn but first used by Moses Schonfinkel in the 1920s

n The basic idea is that any n-ary function can bereplaced by a composition of n unary functions.n f(x,y) => (fx)y

n f(x1,x2,…xn) => ((..((fx1)x2)..)xn)

10/1/03 07:21 CS345 - Programming Languages 25

Curried Function in Scheme

n Non-curried sumn (define sum (lambda (x y) (+ x y)))

n (sum 2 3) => 5

n Curried sumn (define sum (lambda (x) (lambda (y) (+ x y))))

n ((sum 2) 3) => 5

n (let ((f (sum 2))) (f 3)) => 5

10/1/03 07:21 CS345 - Programming Languages 26

Lambda and curried functions in MLn A lambda in ML is written as “fn <args> => <body>”

n val sum = fn x => fn y => x + y;

n val it = fn : int -> int -> int

n sum 3 2;

n val it = 5 : int

n A curried versionn fun sum x = fn y => x + y;

n val sum = fn : int -> int -> int

n sum 3;

n val it = fn : int -> int

n it 2;

n val it = 5 : int

n (sum 3) 2;

n val it = 5 : int

n sum 3 2;

n val it = 5 : int

10/1/03 07:21 CS345 - Programming Languages 27

Lambda expressions in Haskell

n Lambdas are written using “\<arg> -> <body>”n succ = \n -> n + 1

n succ 0 => (\n -> n + 1) 0 => 0 + 1 => 1n succ = (\a -> \b -> a + b) 1

n succ 0 => ((\a -> \b -> a + b) 1) 0=> (\b -> 1 + b) 0=> 1 + 0=> 1

n Note the syntactic similarity to the lambda-calculusn but we usually prefer the syntactic sugar form

n succ n = n + 1n succ 0 => 0 + 1 => 1n succ (succ 0) => succ (0+1) => succ 1 => 1+1 => 2

10/1/03 07:21 CS345 - Programming Languages 28

Comparing map & fold using lambda

n Map and foldl are similar across functional languagesn but note the order of the “don’t care” argument in the fold examplesn Scheme (using DrScheme)

n (map (lambda (x) (* x x)) ‘(1 2 3 4 5))) => (1 4 9 16 25)n (foldl (lambda (_ x) (+ 1 x)) 0 ‘(1 2 3 4 5)) => 5

n ML (using SML)n map (fn x => x * x) [1,2,3,4,5]; => [1,4,9,16,25]:int list

n foldl (fn (_,x) => x + 1) 0 [1,2,3,4,5]; => 5 : int

n Haskell (using Hugs)n map (\x -> x * x) [1,2,3,4,5] => [1,4,9,16,25]n foldl (\x _ -> x + 1) 0 [1,2,3,4,5] => 5n foldl (\x _ -> x + 1) 0 “Hello, world” => 12

n note: strings literals in Haskell are just arrays of characters

10/1/03 07:21 CS345 - Programming Languages 29

Homework

n Show the following in the l-calculus:n AND True True => True

n AND True False => False

n OR True False => True

n OR False False => False

10/1/03 07:21 CS345 - Programming Languages 30

Homework

n Show how to express the following in the l-calculus:n S1, S2, S3

n Addition in the l-calculusn let 2S3 represent 2+3n write the l-expression for 2S3

n note that you will have to use a-conversion to avoid name conflictn show that 2S3 reduces to SS3n show that SS3 reduces to S4n show that S4 equals (under a-conversion) the l-expression for 5

n Multiplication is done using the expression: lxyz.x(yz)n show that 2*2 or (lxyz.x(yz)) 2 2 => lsz.s(s(s(s(z)))) = 4 under a-

conversion