A LISP interepreter for the Lambda Calculus Functional Programming

Slides:



Advertisements
Similar presentations
Substitution & Evaluation Order cos 441 David Walker.
Advertisements

09 Examples Functional Programming. Tower of Hanoi AB C.
CS 63 LISP Philip Greenspun's Tenth* Rule of Programming:
Lisp. Versions of LISP Lisp is an old language with many variants Lisp is alive and well today Most modern versions are based on Common Lisp LispWorks.
Elements of Lambda Calculus Functional Programming Academic Year Alessandro Cimatti
1 Programming Languages (CS 550) Lecture Summary Functional Programming and Operational Semantics for Scheme Jeremy R. Johnson.
Lambda Calculus and Lisp PZ03J. Lambda Calculus The lambda calculus is a model for functional programming like Turing machines are models for imperative.
School of Computing and Mathematics, University of Huddersfield CAS810: WEEK 3 LECTURE: LAMBDA CALCULUS PRACTICAL/TUTORIAL: (i) Do exercises given out.
Lisp. Versions of LISP Lisp is an old language with many variants –LISP is an acronym for List Processing language Lisp is alive and well today Most modern.
Copyright © 2006 The McGraw-Hill Companies, Inc. Programming Languages 2nd edition Tucker and Noonan Chapter 14 Functional Programming It is better to.
CMSC 471 LISP. Why Lisp? Because it’s the most widely used AI programming language Because it’s good for writing production software (Graham article)
CSC321: Programming Languages14-1 Programming Languages Tucker and Noonan Chapter 14: Functional Programming 14.1 Functions and the Lambda Calculus 14.2.
Symbolic Expressions (S Expressions) Syntax: Opening and Closing parenthesis having elements in between. List represented in LISP: (A B2 C3 Shahid) (A.
COMP 205 – Week 11 Dr. Chunbo Chu. Intro Lisp stands for “LISt Process” Invented by John McCarthy (1958) Simple data structure (atoms and lists) Heavy.
PPL Syntax & Formal Semantics Lecture Notes: Chapter 2.
Functional Programming 02 Lists
Basic Lisp CIS 479/579 Bruce R. Maxim UM-Dearborn.
Common lisp A functional programming language. Useful URL:
CSE S. Tanimoto Lambda Calculus 1 Lambda Calculus What is the simplest functional language that is still Turing complete? Where do functional languages.
LISP Data Types Functional Programming Academic Year Alessandro Cimatti
Types and Programming Languages Lecture 6 Simon Gay Department of Computing Science University of Glasgow 2006/07.
Milos Hauskrecht (PDF) Hieu D. Vu (PPT) LISP PROGARMMING LANGUAGE.
Functional Programming: Lisp MacLennan Chapter 10.
CSE 425: Functional Programming I Programs as Functions Some programs act like mathematical functions –Associate a set of input values from the function’s.
Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L03-1 September 14, 2006http:// -calculus: A Basis for.
Artificial Intelligence and Lisp Lecture 6 LiU Course TDDC65 Autumn Semester,
Chapter 2: Lambda Calculus
CS5205: Foundations in Programming Languages
CS 550 Programming Languages Jeremy Johnson
Unit – 3 :LAMBDA CALCULUS AND FUNCTIONAL PROGRAMMING
Section 15.4, 15.6 plus other materials
Carlos Varela Rennselaer Polytechnic Institute September 5, 2017
Example of formula (defun roots (a b c) (list
Modern Programming Languages Lecture 20 Fakhar Lodhi
CS 326 Programming Languages, Concepts and Implementation
More on Lambda Calculus
CS 611: Lecture 9 More Lambda Calculus: Recursion, Scope, and Substitution September 17, 1999 Cornell University Computer Science Department Andrew Myers.
September 4, 1997 Programming Languages (CS 550) Lecture 6 Summary Operational Semantics of Scheme using Substitution Jeremy R. Johnson TexPoint fonts.
Getting Started with Lisp
LISP A brief overview.
Proving Properties of Recursive List Functions
Your turn (Review) What does a lambda expression return when it is evaluated? the value of a lambda expression is a procedure What three things are in.
Carlos Varela Rennselaer Polytechnic Institute September 6, 2016
Lesson2 Lambda Calculus Basics
Carlos Varela Rennselaer Polytechnic Institute September 4, 2015
Programming Languages and Compilers (CS 421)
FP Foundations, Scheme In Text: Chapter 14.
Class 36: The Meaning of Truth CS200: Computer Science
Announcements Quiz 6 HW7 due Tuesday, October 30
Modern Programming Languages Lecture 20 Fakhar Lodhi
Carlos Varela Rennselaer Polytechnic Institute September 8, 2017
CS 611: Lecture 10 More Lambda Calculus September 20, 1999
LISP A brief overview.
Announcements Exam 2 on Friday, November 2nd Topics
L Calculus.
Programming Languages and Compilers (CS 421)
Programming Languages and Compilers (CS 421)
Class 31: Universal Turing Machines CS200: Computer Science
Functional Programming: Lisp
CSE S. Tanimoto Lambda Calculus
CS 611: Lecture 10 More Lambda Calculus September 20, 1999
To understand recursion, one must first understand recursion.
Common Lisp II.
Programming Languages
Lisp.
Carlos Varela Rennselaer Polytechnic Institute September 8, 2015
The general format of case is the following: (case <key form>
List manipulation Consider student database, where each student is represented by the following list: * (setf student1 '((Paul Bennett) ((hw1 4.3) (hw2.
Carlos Varela Rennselaer Polytechnic Institute September 6, 2019
Carlos Varela Rennselaer Polytechnic Institute September 10, 2019
Presentation transcript:

A LISP interepreter for the Lambda Calculus Functional Programming Academic Year 2005-2006 Alessandro Cimatti cimatti@itc.it

Homework Write a program to normalize expressions for lambda calculus Suggested steps: Define the ADT for lambda terms constructors recognizers Define substitution primitive Define recognizer for redex’s Define beta-reduction rule Define the normalizer: recursively traverse the term looking for redex, and reduce careful with infinite looping!! Some remarks homework due by december 20 oh, it’s today  try to use recursive definitions homework is closely related to course project!!!

Syntax Expressions have the following syntax e is either Notation x a variable λx.e a lambda abstraction e1 e2 application Notation for variables we use x, y, z, w for expressions we use e, e’, e1, e2, ...

The ADT for Expressions ; ; e ::= v | l | a ; v ::= symbolp ; a ::= ( e e ) ; l ::= ( lam v e ) (defun mk-v (sym) sym) (defun is-v (e) (symbolp e)) (defun mk-l (v b) (list 'lam v b)) (defun is-l (e) (and (consp e) (= (length e) 3) (equal 'lam (first e)) (is-v (second e)))) (defun l-get-v (l) (second l)) (defun l-get-b (l) (third l)) (defun mk-a (f a) (list f a)) (defun is-a (e) (and (consp e) (= (length e) 2))) (defun a-get-f (a) (first a)) (defun a-get-a (a) (second a))

Generalized Recognizer ; takes arbitrary sexp in input ; (defun is-e (e) (cond ((is-v e) t) ((is-a e) (and (is-e (a-get-f e)) (is-e (a-get-a e)))) ((is-l e) (and (is-e (l-get-v e)) (is-e (l-get-b e)))) (t nil)))

Free variables The set of free variables in e, denoted as FV(e), is defined as FV(x) = { x } FV(e1 e2) = FV(e1) U FV(e2) FV(λx.e) = FV(e) – { x } e is a closed λ-term iff FV(e) is empty

Free variables ; Return the free variables of an expression ; (defun fv (e) (cond ((is-v e) (list e)) ((is-a e) (append (fv (a-get-f e)) (fv (a-get-a e)))) ((is-l e) (remove (l-get-v e) (fv (l-get-b e)))) (t (error "Unknown lambda term type")))) (defun free-in (v e) (member v (fv e)))

Alpha Renaming λ-terms are equivalent up to renaming of bound variables all occurrences of x are replaced by y The rule of α-conversion λx.e ≡α λy.[y/x]e provided that y is not free in e For instance, λx.x ≡α λy.y λx.y x ≡α λz.y z But not λx.y x ≡α λy.y y

Equivalence up to Alpha-conversion (defun alpha-equivalent (e1 e2) (alpha-equivalent1 e1 e2 nil nil)) (defun alpha-equivalent1 (e1 e2 rpl1 rpl2) (cond ((is-v e1) (and (is-v e2) (let ((new1 (cdr (assoc e1 rpl1))) (new2 (cdr (assoc e2 rpl2)))) (if (and (null new1) (null new2)) (equal e1 e2) (equal new1 new2))))) ((is-a e1) (and (is-a e2) (alpha-equivalent1 (a-get-f e1) (a-get-f e2) rpl1 rpl2) (alpha-equivalent1 (a-get-a e1) (a-get-a e2) rpl1 rpl2))) ((is-l e1) (and (is-l e2) (let* ((new (freshvar)) (old1 (l-get-v e1)) (old2 (l-get-v e2)) (newrpl1 (cons (cons old1 new) rpl1)) (newrpl2 (cons (cons old2 new) rpl2))) (alpha-equivalent1 (l-get-b e1) (l-get-b e2) newrpl1 newrpl2))))))

Substitution: [e’ / x] e Replace free occurrences of x in e with e’ No problem when free variables are replaced by term that “does not clash” [λz.z w / x] λy.x = λy.λz.z w However, there may be a problem if there is name capture/clash [λz.z w / x] λx.x is not the same as λx.λz.z w replacement of a bound variable! [λz.z w / x] λw.x is not the same as λw.λz.z w free variable w is now bound!

Definition of Substitution [e’/x]x = e’ [e’/x]y = y [e’/x](e1 e2) = ([e’/x]e1) ([e’/x] e2) [e’/x](λx.e) = λx.e [e’/x](λy.e) = λy.e if x not in FV(e) [e’/x](λy.e) = λy.[e’/x]e if x in FV(e), y not in FV(e’) [e’/x](λy.e) = λz.[e’/x][z/y]e if x in FV(e), y in FV(e’)

Substitution (defun subst-with-in (x e1 exp) (cond ((is-v exp) (if (equal x exp) e1 exp)) ((is-a exp) (mk-a (subst-with-in x e1 (a-get-f exp)) (subst-with-in x e1 (a-get-a exp)))) ((is-l exp) ; say exp is (lam y e) (let ((y (l-get-v exp)) (e (l-get-b exp))) ((equal x y) exp) ((not (free-in x e)) exp) ((and (free-in x e) (not (free-in y e1))) (mk-l y (subst-with-in x e1 e))) ((and (free-in x e) (free-in y e1)) (let ((z (freshvar))) (mk-l z (subst-with-in x e1 (subst-with-in y z e))))))))))

Beta Reduction An application whose LHS is an abstraction An expression of the form ((λx. e1) e2) is called redex (reducible expression) A redex evaluates to the body of the abstraction with parameter substitution Examples (λx.(x y)) z →β z y (λx. y) z →β y (λx.x x) y →β y y (λx.x x) (λx.x x) →β (λx.x x) (λx.x x) Beta-reduction (λx. e1) e2 →β [e2/x]e1

Beta Reduction (defun is-rdx (e) (and (is-a e) (is-l (a-get-f e)))) (defun rdx-get-v (rdx) (l-get-v (a-get-f rdx))) (defun rdx-get-b (rdx) (l-get-b (a-get-f rdx))) (defun rdx-get-a (rdx) (a-get-a rdx)) ; Beta reduce: (a (l v e) e1) ==> [e1 / v] e (defun beta-reduce (rdx) (subst-with-in (rdx-get-v rdx) (rdx-get-a rdx) (rdx-get-b rdx))) ; Beta reduce if possible (defun beta-reduce-if-redex (e) (if (is-rdx e) (beta-reduce e) e))

Properties of Beta Reduction If e1 → β e2, then (e e1) →β (e e2) (e1 e) →β (e2 e) (λx.e1) →β (λx.e2) The transitive closure of →β e1 →β e2 →β ... →β en e1 reduces to en The induced equivalence relation is denoted ≡β

β-Normal Form A λ-term is in β-normal form if it does not have any redex as subexpression meaning: there is no way to apply beta reduction A λ-term e has a β-normal form if for some e’ e ≡β e’ e’ is a β-normal form Some λ-terms do not have any normal form: (λx.xx)(λx.xx) →β [(λx.xx)/x]xx = (λx.xx)(λx.xx) Intuition? loop for ever

Beta Reduction (outer) ; Iterate beta reduction on outermost redex ; (defun beta-reduce-outer (e &optional (lim 100)) (cond ((< lim 0) e) ((is-rdx e) (beta-reduce-outer (beta-reduce e) (- lim 1))) ((is-v e) e) ((is-a e) (mk-a (beta-reduce-outer (a-get-f e)) (beta-reduce-outer (a-get-a e)))) ((is-l e) (mk-l (l-get-v e) (beta-reduce-outer (l-get-b e))))))

Beta Reduction (inner) ; Iterate beta reduction on inntermost redex ; (defun beta-reduce-inner (e &optional (lim 100)) (cond ((< lim 0) e) ((is-v e) e) ((is-a e) (beta-reduce-if-redex (mk-a (beta-reduce-inner (a-get-f e) lim) (beta-reduce-inner (a-get-a e) lim)))) ((is-l e) (mk-l (l-get-v e) (beta-reduce-inner (l-get-b e) lim)))))

Beta Normalization (defun beta-normalize-outer (e &optional (lim 100)) (beta-normalize-param e 'beta-reduce-outer lim)) (defun beta-normalize-inner (e &optional (lim 100)) (beta-normalize-param e 'beta-reduce-inner lim)) (defun beta-normalize-param (e fn &optional (lim 100)) (let* ((res (apply fn (list e lim))) (use-alpha-equivalent t) (stop (if use-alpha-equivalent (alpha-equivalent res e) (equal res e))) (if stop res ; fix point reached (beta-normalize-param res fn))))

Properties of Lambda Calculus If e has a normal form, then this is unique (up to renaming) The β-reduction satisfies the so-called Church-Rosser property if e reduces to e1 and e reduces to e2 then there exists e3 such that e1 reduces to e3 and e2 reduces to e3 Confluence

Top level normalization ; try with the two different strategies ; and compare results ; (defun beta-normalize (e) (let ((res-inner (beta-normalize-inner e 10)) (res-outer (beta-normalize-outer e 10))) (if (alpha-equivalent res-outer res-inner) (progn (format t "All right!~%") (format t "Inner: ~A~%" res-inner) (format t "Outer: ~A~%" res-outer)) (format t "Uh oh... results not equivalent!!!") (format t "Outer: ~A~%" res-outer) (error "error in beta-normalize")))))

Additional Remarks no distinction between loaded code and submitted code lisp is not case sensitive, use dashes AGetV versus a-get-v use comments (from ; to eol) and indentation submit also the test cases you used to test your program if you don’t have any, this is not a good sign... normalization has to look for redexes on all the term, not only at top level (x (x ((lambda y y) x))) has a redex no need to be destructive unless clearly identified bottleneck! no (quit) at end of file, otherwise interpreter is exited