1 / 22

Chapter 11 - Functional Programming, Part III: Theory

Chapter 11 - Functional Programming, Part III: Theory. Programming Languages: Principles and Practice, 2nd Ed. Kenneth C. Louden. Recursive Functions.

kovit
Download Presentation

Chapter 11 - Functional Programming, Part III: Theory

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Chapter 11 - Functional Programming, Part III: Theory Programming Languages: Principles and Practice, 2nd Ed. Kenneth C. Louden © Kenneth C. Louden, 2003

  2. Recursive Functions • Abstractly, a functionf is a rule that associates to each x in some set X (the domain), a y in another set Y (the range): f: XY. • Alternatively, a function can be viewed as a subset S of the Cartesian product X Y with the property that (x,y), (x,y')  S implies y = y'. • Functions can be given as sets simply by listing their elements (definition by extension). • More usually, functions are given by a formula (definition by comprension), which may or may not be recursive. K. Louden, Programming Languages

  3. Recursive Functions (2) • Chapter 8 shows how to implement recursive functions. But how are such functions mathematically defined? • One way to think abstractly about a recursive definition is to consider it to imply a (countably infinite) union of sets that are built, one element at a time, out of the base case or cases. • Factorial example:fact n = if n = 0 then 1 else n * fact (n-1) • The "base" point is (0,1): fact0 = { (0,1) } • Now consider the formula as a set equation:fact = fact0 U fact', where fact' is the function formed for each n by the formula n * fact (n-1). K. Louden, Programming Languages

  4. Recursive Functions (3) • Unfortunately, we don't yet know either fact or fact'. • But consider what would happen if we used fact0 as an approximation for fact in the formula for fact': • fact1 = fact0 U fact0' , where fact0' = { (n,m) | (n-1,p)  fact0 , m = n*p } = { (1,1) } [since (1-1,1) = (0,1)  fact0] • Then fact1 = { (0,1) } U { (1,1) }. We have a new point! • So apply the equation again, this time using fact1 as an approximation for fact in fact'. We get yet another point! Call this function fact2 . Continue. • Now let fact = Un = 1.. factn . What function is this? K. Louden, Programming Languages

  5. Recursive Functions (4) • If we try the process once again, we find that we get no new points: fact = fact0 U fact '. • The function fact is said to be a fixed point of the recursive equation for fact. • Indeed, fact is the smallest such set with this property and is essentially unique. • So it makes sense to define the fact function to be fact : we say that the recursive definition has least-fixed-point semantics. • Not all sets allow least fixed point solutions to recursive equations. Sets that do are called domains. • Domain theory tells us when recursive definitions will work (and when they won't). K. Louden, Programming Languages

  6. Lambda Calculus • The lambda calculus is an abstraction and simplification of a functional programming language, much as a Turing machine is an abstraction and simplification of a computer. • Lambda calculus is Turing-complete, so it it can be used as a model for computation instead of TMs. • Issues such as delayed evaluation, recursion, and scope can be studied with mathematical precision in the lambda calculus. K. Louden, Programming Languages

  7. abstraction application Syntax of Lambda Calculus • Two sets of basic expressions: • Variables: x,y,z, etc. (essentially identifiers representing parameters) • Constants: numbers like 1, 2, 3; "built-in" functions like +, *, cons. • Two operations: • Abstraction (like lambda expressions in Scheme, ML, or Haskell - anonymous function creation). • Application (like function call). • Grammar:lexprvariable.lexpr | lexpr lexpr | (lexpr ) | variable | constant K. Louden, Programming Languages

  8. Examples of Lambda Calculus Expressions • x . + ((y. (x. x y) 2) x) y • (x . xy) y • ((y. 2) ((x. x x) (x. x x))) • (h. (x. h (x x)) (x. h (x x))) K. Louden, Programming Languages

  9. Notes • Lambda calculus is fully Curried. • Application works left to right, abstraction right to left. • Application has higher precedence than abstraction. • The set of variables is unspecified, but doesn't matter very much, as long as it is (countably) infinite. • The set of constants isn't specified either, and this can make a difference in terms of what you want to express. This set may be infinite (all integers) or finite or even empty (pure lambda calculus). Thus, there are really many kinds of lambda calculus. K. Louden, Programming Languages

  10. Notes (continued) • There are no semantic restrictions on the syntactically legal expressions in the lambda calculus: all expressions given by the syntax are legal. • By the previous statement, there can be no type checking in the lambda calculus. There is in fact an alternate version called the typed lambda calculus that does have types. • Not all lambda expressions make sense as programs: (x x) is legal, and so is (2 x).(Exercise: try typing x . x x in ML or Haskell.) K. Louden, Programming Languages

  11. Semantics of Lambda Calculus • Some expressions are equivalent to others in lambda calculus even though they are syntactically distinct:  x . x is equivalent to  y . y()  x . y x is equivalent to y() ( x . x) y is equivalent to y() • These equivalences have historical names: alpha-conversion (-conversion), eta-conversion (-conversion), and beta-conversion (-conversion). When a conversion simplifies an expression it is called a reduction. K. Louden, Programming Languages

  12. Semantics (2) • Conversion operations depend on the notion of the scope (or binding) of a variable in an abstraction. • The variable x in the expression (x.E) issaid to be bound by the lambda. The scope of the binding is the expression E. • An occurrence of a variable outside the scope of any binding of it by a lambda is a free occurrence. An occurrence that is not free is a bound occurrence. Thus, in the expression x. E,all occurrences of x in E are bound. K. Louden, Programming Languages

  13. Examples of bound and free vars: • In the expression (x . xy) y the variable x is bound and both instances of the variable y are free. • In the expression x . + ((y. (x. x y) 2) x) y both instances of x are bound (but by different lambdas), and the first instance of y is bound, while the second one is free (arrows point to bindings):x . + ((y. (x. x y) 2) x) y K. Louden, Programming Languages

  14. Conversion Rules • First, let E[F/x] represent the expression obtained by substituting all free occurrences of x by F in the expression E. • -conversion:  x . E is equivalent to  y . E[y/x], provided E contains no free occurrences of y. • -conversion: ( x . E) F is equivalent to E[F/x], provided F contains no free variables that are bound in E. • -conversion: x . E x is equivalent to E, provided E contains no free occurrences of x. K. Louden, Programming Languages

  15. Name Capture • Each of the above rules has a side condition which represents a name capture issue: if you substitute an expression with free variables into a lambda, one or more of those free variables may conflict with names bound by lambdas (and be captured by them), giving incorrect results (since variable bound/free status should not change): ():  x . y   y . y (): ( x .  y . x y) y   y . y y ():  x . x x  x K. Louden, Programming Languages

  16. Name Capture (2) • The solution is to use -conversion to change bound variable names that clash with free variables in -reduction:( x .  y . x y) y = ( x .  z . x z) y =  z . y z • In the other two cases, we simply cannot perform that particular conversion. K. Louden, Programming Languages

  17. Semantics (3) • An expression is a normal formif there are no -reductions that can be performed on it. • The semantics of an expression in lambda calculus is expressed by converting it to a normal form, if possible. Such a normal form, if it exists, is unique, by the famous Church-Rosser Theorem. • Not all reduction sequences lead to a normal form: ( y. 2) (( x. xx)( x. xx)) K. Louden, Programming Languages

  18. Normal vs. Applicative Order • A -reduction ( x. E) F => E[F/x]that substitutes F for xbefore reducing F is called a normal-order reduction. It corresponds to the lazy evaluation of Haskell (without the memoization). • If on the other hand, the -reduction ( x. E) F => E[F/x]is performed only after reducing F, it is called an applicative order reduction. This corresponds to the evaluation rule of Scheme, where all arguments are evaluated before a call. K. Louden, Programming Languages

  19. Semantics (4) • Main result (also a consequence of the Church-Rosser Theorem): if a normal form exists, a normal-order sequence of conversions will find it. • Example 1: a normal form for ( y. 2) (( x. xx)( x. xx)) is 2, but an applicative-order -reduction gets into an infinite loop. • Example 2: x . + ((y. (x. x y) 2) x) y reduces to x . + ( 2 x) y using either normal-order or applicative-order. K. Louden, Programming Languages

  20. Recursion • Can recursion be expressed in lambda calculus? Note that lambda calculus has no mechanism for resolving free names, which is the usual way of expressing recursion:fact = n.if n==0 then 1 else n*fact(n-1) • To get rid of the free name in the right-hand side, make it a parameter:Hfact = g.n.if n==0 then 1 else n*g(n-1) • Now if Hfact f = f, then f must be fact! Such an f is called a fixed point of Hfact. • Is there a lambda expression that can produce fixed points? YES! K. Louden, Programming Languages

  21. Recursion (2) • The lambda expression Y = h.(x. h (xx))(x. h (xx)) produces arbitrary fixed points: let H be any lambda expression. ThenY H = (x. H (xx))(x. H (xx)) = H ((x. H (xx)) (x. H (xx))) = H (Y H), so Y H is a fixed point of H. • Unfortunately, Y has no type in ML or Haskell (try it!), but we can fall back on the fixed point property itself as a definition of Y, in either ML, Haskell, or Scheme: y h = h (y h) • To what extent this works in the actual languages is Exercise 11.50. K. Louden, Programming Languages

  22. Implementing standard language features in lambda calculus • Recursion can be implemented (as we have just seen). • So can numbers (Exercise 11.47). • So can lists (Exercise 11.46). • So can Booleans and if-then-else: • true = x. y. x, false = x. y. y,if =x. y. z. x y z, and now(if true E F) = E and (if false EF) = F • Indeed, everything can (with some huffing and puffing, as with Turing Machines)! K. Louden, Programming Languages

More Related