Lambda Calculus by Dustin Mulcahey

3,956 views

Published on

This is a friendly Lambda Calculus Introduction by Dustin Mulcahey. LISP has its syntactic roots in a formal system called the lambda calculus. After a brief discussion of formal systems and logic in general, Dustin will dive in to the lambda calculus and make enough constructions to convince you that it really is capable of expressing anything that is "computable". Dustin then talks about the simply typed lambda calculus and the Curry-Howard-Lambek correspondence, which asserts that programs and mathematical proofs are "the same thing".

Published in: Technology, Education

Lambda Calculus by Dustin Mulcahey

  1. 1. Lambda Calculus Dustin Mulcahey
  2. 2. First, a crash course in mathematical logic...
  3. 3. First, a crash course in mathematical logic...
  4. 4. First, a crash course in mathematical logic...
  5. 5. First, a crash course in mathematical logic...
  6. 6. For computer scientists, the most interesting part of this discussion is Hilbert’s Entscheidungsproblem.
  7. 7. For computer scientists, the most interesting part of this discussion is Hilbert’s Entscheidungsproblem.
  8. 8. For computer scientists, the most interesting part of this discussion is Hilbert’s Entscheidungsproblem. Entscheidungsproblem: Given a mathematical statement, is there an algorithm that will compute a proof or a refutation of that statement?
  9. 9. For computer scientists, the most interesting part of this discussion is Hilbert’s Entscheidungsproblem. Entscheidungsproblem: Given a mathematical statement, is there an algorithm that will compute a proof or a refutation of that statement? At the time of its statement by Hilbert, there was no formalization of “algorithm”.
  10. 10. Fast-forward to the late 1920s...
  11. 11. Fast-forward to the late 1920s... Schoenfinkel: “Bound variables are bad. (or, at least, unnecessary)”
  12. 12. Schoenfinkel defined the basic combinators that form the “combinatory logic” (SKI). We’ll define these in terms of the lambda calculus, once we’ve defined that.
  13. 13. Schoenfinkel defined the basic combinators that form the “combinatory logic” (SKI). We’ll define these in terms of the lambda calculus, once we’ve defined that. Haskell Curry also formulated the concept of “combinator” in his efforts to unambiguously define substitution, which had been rather loosely described up until his time (and continues to be loosely described up to this day).
  14. 14. Schoenfinkel also seems to have originated the notion of “currying” (named after Haskell Curry). This is the idea that you can take a two argument function F (x, y ) and express it as a one argument function that is valued in functions: (f (x))(y )
  15. 15. Finally, on to Alonzo Church! Goal: a new formal system for logic based upon the notion of function application. He wanted something “more natural” than Russell-Whitehead or ZF.
  16. 16. The formal system that he developed is called the lambda calculus. Here is the identity function expressed in the lambda calculus:
  17. 17. The formal system that he developed is called the lambda calculus. Here is the identity function expressed in the lambda calculus: λx.x
  18. 18. Why use λ for function abstraction?
  19. 19. Why use λ for function abstraction? Whitehead and Russell used x for class abstraction. ˆ If you move the hat off the x, you get ∧x. Apparently, λx was easier to print than ∧x.
  20. 20. Why use λ for function abstraction? Whitehead and Russell used x for class abstraction. ˆ If you move the hat off the x, you get ∧x. Apparently, λx was easier to print than ∧x. At least, that’s how Church told it at one point. Later in life, he claimed that he needed a symbol and he just happened to choose λ.
  21. 21. In a formal system, we must give clear rules about what sequence of symbols can be produced and how they can be transformed. It’s very similar to designing a programming language.
  22. 22. To formulate the lambda calculus, we must first fix a set of letters that we will use for variables. Typically, we denote these by x, y (we rarely need more than two). Once this has been done, we inductively define valid lambda terms: If x is a variable, then x is a valid lambda term. If t is a valid lambda term and x is a variable, then (λx.t) is a valid lambda term. (Lambda Abstraction) If t, s are valid lambda terms, then (t s) is a valid lambda term. (Application)
  23. 23. That’s it! We can now construct all sorts of lambda terms: x (λx.x) y (y y ) ((λx.x)(y y )) (λy .((λx.x)(y y ))) (variable) (lambda abstraction) (variable) (application) (application) (lambda abstraction)
  24. 24. While I have given the intuition behind the above constructs, they are mere scribblings on paper until we give rules for manipulating the terms. From a proof-theoretic perspective, meaning arises from the reduction rules of the language.
  25. 25. While I have given the intuition behind the above constructs, they are mere scribblings on paper until we give rules for manipulating the terms. From a proof-theoretic perspective, meaning arises from the reduction rules of the language. This is quite different from other notions of meaning, such as Tarski’s definition of truth or denotionation semantics (in fact, we shall see that denotational semantics turns out to be an interesting problem for the lambda calculus).
  26. 26. There are three rules for manipulating lambda terms: α-equivalence: renaming variables β-reduction: how function application “works” η-conversion: two functions are “the same” if they do the same thing (extensionality)
  27. 27. α-equivalence lets us convert λx.x to λy .y .
  28. 28. α-equivalence lets us convert λx.x to λy .y . Makes sense, right? They are both the identity function. Generally, α-equivalence lets us rename any bound variables.
  29. 29. As programmers, we use α-equivalence to reason about lexical scoping: x = 0 f = function(x, y) { return x + y; } print f(3,4);
  30. 30. is equivalent to: x = 0; f = function(a, b) { return a + b; } print f(3,4);
  31. 31. As you can imagine, formally defining α-equivalence is a bit tricky. We want λx.x α-equivalent to λy .y , but we do not want λx.(λy .x) α-equivalent to λy .(λy .y ).
  32. 32. As you can imagine, formally defining α-equivalence is a bit tricky. We want λx.x α-equivalent to λy .y , but we do not want λx.(λy .x) α-equivalent to λy .(λy .y ). (The first takes a value and produces the constant function at that value, while the second returns the identity function no matter what’s passed to it.)
  33. 33. β-reduction captures the notion of function application. However, to formally define it, we run in to the substitution problem again!
  34. 34. β-reduction captures the notion of function application. However, to formally define it, we run in to the substitution problem again! Intuitively, we would like (f x) to denote the application of a function f to an input x. Of course, in this world, everything has the same “type”, so we are really applying one lambda term to another.
  35. 35. For a simple example of β-reduction, let’s apply the identity function to something. ((λx.x)(λy .(y y ))
  36. 36. For a simple example of β-reduction, let’s apply the identity function to something. ((λx.x)(λy .(y y )) ought to reduce to (λy .(y y ))
  37. 37. How about the other way around? ((λy .(y y ))(λx.x)
  38. 38. How about the other way around? ((λy .(y y ))(λx.x) ((λx.x)(λx.x))
  39. 39. How about the other way around? ((λy .(y y ))(λx.x) ((λx.x)(λx.x)) (λx.x)
  40. 40. We define β-reduction as follows. Let ((λx.t) s) be a valid lambda term with t and s lambda terms and x a variable. The above reduces to t[s/x] where t[s/x] denotes the result of replacing every occurrence of x in t by s.
  41. 41. Problem: what if our usage of variables is a bit too incestuous?
  42. 42. Problem: what if our usage of variables is a bit too incestuous? Example: t = (λz.(x y )) s =z
  43. 43. Problem: what if our usage of variables is a bit too incestuous? Example: t = (λz.(x y )) s =z Now apply β-reduction: ((λx.t) s) ((λx.(λz.(x y ))) z) (λz.(z y ))
  44. 44. Whereas if we first did α-equivalence: t = (λw .(x y )) s =z
  45. 45. Whereas if we first did α-equivalence: t = (λw .(x y )) s =z
  46. 46. Whereas if we first did α-equivalence: t = (λw .(x y )) s =z And then apply β-reduction: ((λx.t) s) ((λx.(λw .(x y ))) z) (λw .(z y )) The function on the previous slide applies its parameter to the free variable y , whereas the function on this slide does nothing with its parameter!
  47. 47. So, obviously some care is needed when defining substitution. We need to ensure that in ((λx.t) s) that s does not contain a free variable that becomes bound when s is substituted for x in t.
  48. 48. The next and final reduction expresses the mathematical principle of extensionality.
  49. 49. The next and final reduction expresses the mathematical principle of extensionality. Informally, we say that two functions are extensionally equal if they do the same thing.
  50. 50. The next and final reduction expresses the mathematical principle of extensionality. Informally, we say that two functions are extensionally equal if they do the same thing. That is, f (x) =x +2 g (x) = x + 1 + 1 are two different functions as I have written them, but extensionally equal.
  51. 51. However (as an aside), 2 −4 f (x) = xx−2 g (x) = x + 2 Are neither equal nor extensionally equal, but algebraically reduce to the same thing.
  52. 52. η-conversion captures this notion by stating that, for lambda expressions f not containing the variable x, (λx.(f x)) is equivalent to f
  53. 53. That’s enough math! Let’s do some programming.
  54. 54. Well, I can do what any beginning (or intermediate, or advanced) programmer does: ((λx.(x x))(λx.(x x)))
  55. 55. Well, I can do what any beginning (or intermediate, or advanced) programmer does: ((λx.(x x))(λx.(x x))) Let’s apply β-reduction:
  56. 56. Well, I can do what any beginning (or intermediate, or advanced) programmer does: ((λx.(x x))(λx.(x x))) Let’s apply β-reduction: ((λx.(x x))(λx.(x x))) Yay! An infinite loop! So we see that the true strength of the lambda calculus is the speed at which we can write down infinite computations.
  57. 57. Or, even better:
  58. 58. Or, even better: (λx.((x x) x)(λx.((x x) x)
  59. 59. Or, even better: (λx.((x x) x)(λx.((x x) x) (((λx.((x x) x) (λx.((x x) x)) (λx.((x x) x))
  60. 60. Or, even better: (λx.((x x) x)(λx.((x x) x) (((λx.((x x) x) (λx.((x x) x)) (λx.((x x) x)) ((((λx.((x x) x) (λx.((x x) x)) (λx.((x x) x)) (λx.((x x
  61. 61. Or, even better: (λx.((x x) x)(λx.((x x) x) (((λx.((x x) x) (λx.((x x) x)) (λx.((x x) x)) ((((λx.((x x) x) (λx.((x x) x)) (λx.((x x) x)) (λx.((x x . . . This example shows that not all lambda terms normalize. That is, given a lambda term, you can’t always just whack it with β-reduction until it settles into something!
  62. 62. To make things that are more interesting than non-terminating programs, we need to define some basic things. I will now define the following: numbers
  63. 63. To make things that are more interesting than non-terminating programs, we need to define some basic things. I will now define the following: numbers booleans and conditionals
  64. 64. To make things that are more interesting than non-terminating programs, we need to define some basic things. I will now define the following: numbers booleans and conditionals recursion
  65. 65. The standard formulation of the natural numbers is called the system of Church Numerals.
  66. 66. The standard formulation of the natural numbers is called the system of Church Numerals. Intuition: The number n is n-fold composition.
  67. 67. The standard formulation of the natural numbers is called the system of Church Numerals. Intuition: The number n is n-fold composition. (Speaking of non-termination...)
  68. 68. Less cyclic: The number n is a function that takes a function and returns the nth-fold composite of that function.
  69. 69. Less cyclic: The number n is a function that takes a function and returns the nth-fold composite of that function. (Hmm, still looks cyclic to me.)
  70. 70. Less cyclic: The number n is a function that takes a function and returns the nth-fold composite of that function. (Hmm, still looks cyclic to me.) That is, n(f ) = f ◦ f ◦ f ◦ . . . ◦ f
  71. 71. Less cyclic: The number n is a function that takes a function and returns the nth-fold composite of that function. (Hmm, still looks cyclic to me.) That is, n(f ) = f ◦ f ◦ f ◦ . . . ◦ f which we can denote as f ◦n .
  72. 72. Formally, 0 ≡ f → id ≡ λf .(λx.x)
  73. 73. Formally, 0 ≡ f → id 1 ≡f →f ≡ λf .(λx.x) ≡ λf .(λx.(f x))
  74. 74. Formally, 0 ≡ f → id 1 ≡f →f 2 ≡ ≡ λf .(λx.x) ≡ λf .(λx.(f x))
  75. 75. Formally, 0 ≡ f → id ≡ λf .(λx.x) 1 ≡f →f ≡ λf .(λx.(f x)) 2 ≡f →f ◦f
  76. 76. Formally, 0 ≡ f → id ≡ λf .(λx.x) 1 ≡f →f ≡ λf .(λx.(f x)) 2 ≡ f → f ◦ f ≡ λf .(λx.(f (f x))
  77. 77. Formally, 0 ≡ f → id ≡ λf .(λx.x) 1 ≡f →f ≡ λf .(λx.(f x)) 2 ≡ f → f ◦ f ≡ λf .(λx.(f (f x)) and so on...
  78. 78. There are two rules for constructing natural numbers:
  79. 79. There are two rules for constructing natural numbers: 0 ≡ λf .(λx.x)
  80. 80. There are two rules for constructing natural numbers: 0 ≡ λf .(λx.x) and if n is a natural number, then n+1≡
  81. 81. There are two rules for constructing natural numbers: 0 ≡ λf .(λx.x) and if n is a natural number, then n + 1 ≡ succ(n) ≡
  82. 82. There are two rules for constructing natural numbers: 0 ≡ λf .(λx.x) and if n is a natural number, then n + 1 ≡ succ(n) ≡ λf .λx.(f ((n f ) x)
  83. 83. Is this definition consistent with what I’ve shown you? 1≡
  84. 84. Is this definition consistent with what I’ve shown you? 1 ≡ succ(0)
  85. 85. Is this definition consistent with what I’ve shown you? 1 ≡ succ(0) λf .λx.(f ((0 f ) x))
  86. 86. Is this definition consistent with what I’ve shown you? 1 ≡ succ(0) λf .λx.(f ((0 f ) x)) λf .λx.(f ((λf .λx.x) f ) x))
  87. 87. Is this definition consistent with what I’ve shown you? 1 ≡ succ(0) λf .λx.(f ((0 f ) x)) λf .λx.(f ((λf .λx.x) f ) x)) λf .λx.(f ((λx.x) x))
  88. 88. Is this definition consistent with what I’ve shown you? 1 ≡ succ(0) λf .λx.(f λf .λx.(f λf .λx.(f λf .λx.(f ((0 f ) x)) ((λf .λx.x) f ) x)) ((λx.x) x)) x)
  89. 89. You’ll notice that I’ve suddenly started using the symbol ≡
  90. 90. You’ll notice that I’ve suddenly started using the symbol ≡ If a ≡ b, I’m declaring by the powers of notation that wherever you write a, you can also write b (and vice versa).
  91. 91. Also note that succ is itself a lambda term: succ ≡ λn.λf .λx.(f ((n f ) x)) Here, n is not boldface because I’m using it as a variable. The user of our succ function could put anything there! Of course, we only gaurantee good behavior on an input that is equivalent to a natural number (as we have defined them).
  92. 92. Okay, we have natural numbers. How about addition?
  93. 93. Okay, we have natural numbers. How about addition? Intuition: n + m takes a function and composes it n + m times.
  94. 94. Okay, we have natural numbers. How about addition? Intuition: n + m takes a function and composes it n + m times. Strategy: Let’s write a lambda term that applies f m times, “and then”applies it n times.
  95. 95. Okay, we have natural numbers. How about addition? Intuition: n + m takes a function and composes it n + m times. Strategy: Let’s write a lambda term that applies f m times, “and then”applies it n times. In the world of functions, “and then” means composition! So addition corresponds to composition.
  96. 96. Okay, we have natural numbers. How about addition? Intuition: n + m takes a function and composes it n + m times. Strategy: Let’s write a lambda term that applies f m times, “and then”applies it n times. In the world of functions, “and then” means composition! So addition corresponds to composition. add ≡ (λn.λm.λf .λx.((n f ) ((m f ) x)))
  97. 97. Theorem: ((add 2) 2) is equivalent to 4 Proof: (I’m going to use a mixture of definitional equality and reductions) ((add 2) 2)
  98. 98. Theorem: ((add 2) 2) is equivalent to 4 Proof: (I’m going to use a mixture of definitional equality and reductions) ((add 2) 2) (((λn.λm.λf .λx.((n f ) ((m f ) x))) 2) 2)
  99. 99. Theorem: ((add 2) 2) is equivalent to 4 Proof: (I’m going to use a mixture of definitional equality and reductions) ((add 2) 2) (((λn.λm.λf .λx.((n f ) ((m f ) x))) 2) 2) ((λm.λf .λx.((2 f ) ((m f ) x))) 2)
  100. 100. Theorem: ((add 2) 2) is equivalent to 4 Proof: (I’m going to use a mixture of definitional equality and reductions) ((add 2) 2) (((λn.λm.λf .λx.((n f ) ((m f ) x))) 2) 2) ((λm.λf .λx.((2 f ) ((m f ) x))) 2) (λf .λx.((2 f ) ((2 f ) x))) (λf .λx.(((λf .λx.(f (f x)) f ) ((λf .(λx.(f (f x)) f ) x)))
  101. 101. Theorem: ((add 2) 2) is equivalent to 4 Proof: (I’m going to use a mixture of definitional equality and reductions) ((add 2) 2) (((λn.λm.λf .λx.((n f ) ((m f ) x))) 2) 2) ((λm.λf .λx.((2 f ) ((m f ) x))) 2) (λf .λx.((2 f ) ((2 f ) x))) (λf .λx.(((λf .λx.(f (f x)) f ) ((λf .(λx.(f (f x)) f ) x))) (λf .λx.((λx.(f (f x)) (λx.(f (f x)) x)))
  102. 102. Theorem: ((add 2) 2) is equivalent to 4 Proof: (I’m going to use a mixture of definitional equality and reductions) ((add 2) 2) (((λn.λm.λf .λx.((n f ) ((m f ) x))) 2) 2) ((λm.λf .λx.((2 f ) ((m f ) x))) 2) (λf .λx.((2 f ) ((2 f ) x))) (λf .λx.(((λf .λx.(f (f x)) f ) ((λf .(λx.(f (f x)) f ) x))) (λf .λx.((λx.(f (f x)) (λx.(f (f x)) x))) (λf .λx.((λx.(f (f x)) (f (f x))))
  103. 103. Theorem: ((add 2) 2) is equivalent to 4 Proof: (I’m going to use a mixture of definitional equality and reductions) ((add 2) 2) (((λn.λm.λf .λx.((n f ) ((m f ) x))) 2) 2) ((λm.λf .λx.((2 f ) ((m f ) x))) 2) (λf .λx.((2 f ) ((2 f ) x))) (λf .λx.(((λf .λx.(f (f x)) f ) ((λf .(λx.(f (f x)) f ) x))) (λf .λx.((λx.(f (f x)) (λx.(f (f x)) x))) (λf .λx.((λx.(f (f x)) (f (f x)))) (λf .λx.(λf .(f (f (f (f x)))))) 4
  104. 104. As you can see, doing arithmetic with Church numerals is both simple and fun. What about multiplication?
  105. 105. Intuition: (n ∗ m) takes a function and returns the n ∗ mth fold composite of the function with itself. Strategy: Make the mth composite of f n times.
  106. 106. Intuition: (n ∗ m) takes a function and returns the n ∗ mth fold composite of the function with itself. Strategy: Make the mth composite of f n times. mult = λn.λm.λf .λx.((n (m f )) x)
  107. 107. Theorem: ((mult 2) 2) is equivalent to 4
  108. 108. Theorem: ((mult 2) 2) is equivalent to 4 Proof: This is left as an exercise for the reader.
  109. 109. Exponentiation is also straightforward: Strategy: To get mn , apply n to m. Remember that m takes a function and returns the mth fold composite. So now we take the nth fold composite of the function that takes a function and returns the mth fold composite. So now we have a function that takes a function and returns the mn th fold composite.
  110. 110. Exponentiation is also straightforward: Strategy: To get mn , apply n to m. Remember that m takes a function and returns the mth fold composite. So now we take the nth fold composite of the function that takes a function and returns the mth fold composite. So now we have a function that takes a function and returns the mn th fold composite. Clear, right? How about this:
  111. 111. Exponentiation is also straightforward: Strategy: To get mn , apply n to m. Remember that m takes a function and returns the mth fold composite. So now we take the nth fold composite of the function that takes a function and returns the mth fold composite. So now we have a function that takes a function and returns the mn th fold composite. Clear, right? How about this: (n m)f = (m ◦ m ◦ · · · ◦ m)f
  112. 112. Exponentiation is also straightforward: Strategy: To get mn , apply n to m. Remember that m takes a function and returns the mth fold composite. So now we take the nth fold composite of the function that takes a function and returns the mth fold composite. So now we have a function that takes a function and returns the mn th fold composite. Clear, right? How about this: (n m)f = (m ◦ m ◦ · · · ◦ m)f (Remember that composition corresponds to addition.)
  113. 113. In lambda form: exp ≡ λm.λn.λf λx.(((n m) f ) x)
  114. 114. Subtraction is much trickier. The most understandable way to do it (that I know of) is to use pairing. Idea: Instead of incrementing x to x + 1, let’s take the pair (n, m) to the pair (m, m + 1). If we start at (0, 0), we’ll get the following sequence:
  115. 115. Subtraction is much trickier. The most understandable way to do it (that I know of) is to use pairing. Idea: Instead of incrementing x to x + 1, let’s take the pair (n, m) to the pair (m, m + 1). If we start at (0, 0), we’ll get the following sequence: (0, 0) → (0, 1) → (1, 2) → (2, 3) · · ·
  116. 116. Subtraction is much trickier. The most understandable way to do it (that I know of) is to use pairing. Idea: Instead of incrementing x to x + 1, let’s take the pair (n, m) to the pair (m, m + 1). If we start at (0, 0), we’ll get the following sequence: (0, 0) → (0, 1) → (1, 2) → (2, 3) · · · So, to get the predecessor of n, we just do the above process n times and then take the first coordinate of the result. How’s that for efficiency?
  117. 117. Okay, how do we make pairs?
  118. 118. Okay, how do we make pairs? Well, it will help to first define booleans and conditionals.
  119. 119. A few definitions:
  120. 120. A few definitions: true ≡ λx.λy .x
  121. 121. A few definitions: true ≡ λx.λy .x false ≡ λx.λy .y
  122. 122. A few definitions: true ≡ λx.λy .x false ≡ λx.λy .y cond ≡ λc.λt.λf .((c t) f
  123. 123. A few definitions: true ≡ λx.λy .x false ≡ λx.λy .y cond ≡ λc.λt.λf .((c t) f
  124. 124. To make a pair of lambda terms, we will store them both in a cond. To get the first, we apply cond to true. To get the second, we apply cond to false.
  125. 125. To make a pair of lambda terms, we will store them both in a cond. To get the first, we apply cond to true. To get the second, we apply cond to false. pair ≡ λf .λs.λc.(((cond c)s)t)
  126. 126. To make a pair of lambda terms, we will store them both in a cond. To get the first, we apply cond to true. To get the second, we apply cond to false. pair ≡ λf .λs.λc.(((cond c)s)t)
  127. 127. What about my pair increment function? paircrement ≡ λp.((pair (p false))(succ (p true)))
  128. 128. So, the predecessor function looks like:
  129. 129. So, the predecessor function looks like: pred ≡ λn.(((n paircrement) ((pair 0) 0) true)
  130. 130. Also, we can detect when something is zero: isZero ≡ λn.((n(λx. false)) true)
  131. 131. Phew! We now have conditionals and arithmetic.
  132. 132. Phew! We now have conditionals and arithmetic. ... and with pairs, we could go ahead and define the rationals right now. But I’m not going to.
  133. 133. Phew! We now have conditionals and arithmetic. ... and with pairs, we could go ahead and define the rationals right now. But I’m not going to. Instead, I want to plunge into recursion!
  134. 134. Okay, to do recursion, I need a function to call itself.
  135. 135. Okay, to do recursion, I need a function to call itself. Except in our formal system of lambda calculus, there is no notion of variable binding. All we have are ways of constructing lambda terms and ways of reducing them to other lambda terms.
  136. 136. Okay, to do recursion, I need a function to call itself. Except in our formal system of lambda calculus, there is no notion of variable binding. All we have are ways of constructing lambda terms and ways of reducing them to other lambda terms. How do we do this?
  137. 137. Yes, this is where we start talking about the Y combinator.
  138. 138. Yes, this is where we start talking about the Y combinator. There are a bunch of explanations of this thing, and what follows is one of them.
  139. 139. Let’s start with a recursive function: fact ≡ λn. ((((cond (isZero n)) 1) ((mult n) (fact (pred n))))
  140. 140. Let’s start with a recursive function: fact ≡ λn. ((((cond (isZero n)) 1) ((mult n) (fact (pred n)))) This would only make sense if we could make recursive definitional equalities. But, if you think about it, if we could, then we would just be writing forever...
  141. 141. Well, we can’t refer to a function by name (except in the very limited sense of ≡). But what if we could pass a function to itself? fact ≡ λf . λn. ((((cond (isZero n)) 1) ((mult n) (f (pred n)))) Well, it wouldn’t make much sense to reduce (fact fact), since we would have to reduce (fact (pred n)), which doesn’t make sense.
  142. 142. But what if we had a magic function g such that g is equivalent to (fact g )? Then, the following would happen (for example):
  143. 143. But what if we had a magic function g such that g is equivalent to (fact g )? Then, the following would happen (for example): ((fact g ) 4)
  144. 144. But what if we had a magic function g such that g is equivalent to (fact g )? Then, the following would happen (for example): ((fact g ) 4) ((λf . λn. ((((cond (isZero n)) 1) ((mult n) (f (pred n)))) g ) 4)
  145. 145. But what if we had a magic function g such that g is equivalent to (fact g )? Then, the following would happen (for example): ((fact g ) 4) ((λf . λn. ((((cond (isZero n)) 1) ((mult n) (f (pred n)))) g ) 4) λn. ((((cond (isZero n)) 1) ((mult n) (g (pred n)))) 4)
  146. 146. But what if we had a magic function g such that g is equivalent to (fact g )? Then, the following would happen (for example): ((fact g ) 4) ((λf . λn. ((((cond (isZero n)) 1) ((mult n) (f (pred n)))) g ) 4) λn. ((((cond (isZero n)) 1) ((mult n) (g (pred n)))) 4) ((((cond (isZero 4)) 1) ((mult n) (g (pred 4))))
  147. 147. But what if we had a magic function g such that g is equivalent to (fact g )? Then, the following would happen (for example): ((fact g ) 4) ((λf . λn. ((((cond (isZero n)) 1) ((mult n) (f (pred n)))) g ) 4) λn. ((((cond (isZero n)) 1) ((mult n) (g (pred n)))) 4) ((((cond (isZero 4)) 1) ((mult n) (g (pred 4)))) ((mult n) (g (pred 4)))
  148. 148. But what if we had a magic function g such that g is equivalent to (fact g )? Then, the following would happen (for example): ((fact g ) 4) ((λf . λn. ((((cond (isZero n)) 1) ((mult n) (f (pred n)))) g ) 4) λn. ((((cond (isZero n)) 1) ((mult n) (g (pred n)))) 4) ((((cond (isZero 4)) 1) ((mult n) (g (pred 4)))) ((mult n) (g (pred 4))) ((mult n) (g 3))
  149. 149. But what if we had a magic function g such that g is equivalent to (fact g )? Then, the following would happen (for example): ((fact g ) 4) ((λf . λn. ((((cond (isZero n)) 1) ((mult n) (f (pred n)))) g ) 4) λn. ((((cond (isZero n)) 1) ((mult n) (g (pred n)))) 4) ((((cond (isZero 4)) 1) ((mult n) (g (pred 4)))) ((mult n) (g (pred 4))) ((mult n) (g 3)) ((mult n) ((fact g ) 3))
  150. 150. Such a magic g is the fixed point of fact.
  151. 151. Such a magic g is the fixed point of fact. A fixed point of a function f is a value x such that f (x) = x
  152. 152. Such a magic g is the fixed point of fact. A fixed point of a function f is a value x such that f (x) = x For example: if f (x) = x 2 then 0, 1 are the fixed points of f .
  153. 153. In the lambda calculus, there is a lambda term that will compute the fixed point of any other lambda term. This is referred to as the Y -combinator. Note that there are several flavors of Y combinator.
  154. 154. Here’s one: Y = λf .((λx.(f (x x)))(λx.(f (x x))))
  155. 155. Theorem: for any lambda term h, (Y h) is equivalent to (h (Y h)). Proof:
  156. 156. Theorem: for any lambda term h, (Y h) is equivalent to (h (Y h)). Proof: (Y h)
  157. 157. Theorem: for any lambda term h, (Y h) is equivalent to (h (Y h)). Proof: (Y h) (λ f. ((λ x. (f (x x))) (λ x. (f (x x)))) h)
  158. 158. Theorem: for any lambda term h, (Y h) is equivalent to (h (Y h)). Proof: (Y h) (λ f. ((λ x. (f (x x))) (λ x. (f (x x)))) h) ((λ x. (h (x x))) (λ x. (h (x x)))
  159. 159. Theorem: for any lambda term h, (Y h) is equivalent to (h (Y h)). Proof: (Y h) (λ f. ((λ x. (f (x x))) (λ x. (f (x x)))) h) ((λ x. (h (x x))) (λ x. (h (x x))) (h ((λ x. (h (x x)) (λ x. (h (x x))))
  160. 160. Theorem: for any lambda term h, (Y h) is equivalent to (h (Y h)). Proof: (Y h) (λ f. ((λ x. (f (x x))) (λ x. (f (x x)))) h) ((λ x. (h (x x))) (λ x. (h (x x))) (h ((λ x. (h (x x)) (λ x. (h (x x)))) (h (Y h))
  161. 161. So really, factorial is defined in two steps: fact’ ≡ λf . λn. ((((cond (isZero n)) 1) ((mult n) (f (pred n)))) fact ≡ (Y fact’)
  162. 162. Which is definitionally equivalent to this: ((λf . ((λx. (f (x x))) (λx. (f (x x)))) (λf . λn. ((((λc.λt.λf . ((c t) f (λn. ((n (λx. (λx.λy .y ))) (λx.λy .x)) n)) (λf .λx.(fx))) (((λn.λm.λf . (n (m (f )))) n) (f ((λn. (((n (λp. (((λf .λs.λc. ((((λc.λt.λf .((c t) f ) c) s) t)) (p (λx.λy .y ))) ((λf .λx. (f ((n f ) x)) (p (λx.λy .x)))))) (((λf .λs.λc. ((((λc.λt.λf .((c t) f ) c) s) t)) (λf .λx.x)) (λf .λx.x)) (λx.λy .x))) n))))))
  163. 163. Now that we’ve defined the lambda calculus and written a program in it, I want to discuss some properties of the system as a whole.
  164. 164. The Church-Turing Thesis Any algorithm that performs a computation can be expressed in the λ-calculus, or by a Turing machine, or by a recursive function (in the sense of recursion theory).
  165. 165. Undecidability of Equivalence There does not exist an algorithm that decides whether or not two arbitrary lambda terms are equivalent.
  166. 166. The Church-Rosser Theorem In the λ-calculus, given terms t1 and t2 gotten from a common term t by a sequence of reductions, there exists a term s that t1 and t2 both reduce to.
  167. 167. The Church-Rosser Theorem In the λ-calculus, given terms t1 and t2 gotten from a common term t by a sequence of reductions, there exists a term s that t1 and t2 both reduce to. t /t /s t2 1
  168. 168. Equivalence of the λ-calculus and combinatory logic. Define combinators: I = λx.x K = λx.λy .x S = λx.λy .λz.((x z) (y z)) Then these combinators suffice to construct any lambda term, up to equivalence.
  169. 169. Equivalence of the λ-calculus and combinatory logic. Define combinators: I = λx.x K = λx.λy .x S = λx.λy .λz.((x z) (y z)) Then these combinators suffice to construct any lambda term, up to equivalence. For example, Y = S (K (S I I)) (S (S (K S) K) (K (S I I)))
  170. 170. Correspondence between SK and propositional logic Consider the axiom of propositional logic: a =⇒ (b =⇒ a)
  171. 171. Correspondence between SK and propositional logic Consider the axiom of propositional logic: a =⇒ (b =⇒ a) Now look at the K combinator again: λa.λb.a
  172. 172. Correspondence between SK and propositional logic Consider the axiom of propositional logic: a =⇒ (b =⇒ a) Now look at the K combinator again: λa.λb.a Now repeat this to yourself: “If I have a proof of a, then given a proof of b, I still have a proof of a”
  173. 173. Now consider the axiom: (a =⇒ (b =⇒ c)) =⇒ ((a =⇒ b) =⇒ (a =⇒ c))
  174. 174. Now consider the axiom: (a =⇒ (b =⇒ c)) =⇒ ((a =⇒ b) =⇒ (a =⇒ c)) Now look at the S combinator again: λf .λg .λa.((f a)(g a))
  175. 175. Now consider the axiom: (a =⇒ (b =⇒ c)) =⇒ ((a =⇒ b) =⇒ (a =⇒ c)) Now look at the S combinator again: λf .λg .λa.((f a)(g a)) Now, repeat this to yourself: “If I have a way f of turning proofs of a into proofs that b implies c, then given a proof g that a implies b, I can make a proof that a implies c.”
  176. 176. Really, the only sane way to think about this stuff is to appeal to category theory.
  177. 177. Really, the only sane way to think about this stuff is to appeal to category theory. The proposition a =⇒ (b =⇒ a)
  178. 178. Really, the only sane way to think about this stuff is to appeal to category theory. The proposition a =⇒ (b =⇒ a) Corresponds to an object (“function space”). Think of A as the set of proofs of the proposition a. (AB )A
  179. 179. Really, the only sane way to think about this stuff is to appeal to category theory. The proposition a =⇒ (b =⇒ a) Corresponds to an object (“function space”). Think of A as the set of proofs of the proposition a. (AB )A Which, in nice categories is isomorphic to A(A×B)
  180. 180. Really, the only sane way to think about this stuff is to appeal to category theory. The proposition a =⇒ (b =⇒ a) Corresponds to an object (“function space”). Think of A as the set of proofs of the proposition a. (AB )A Which, in nice categories is isomorphic to A(A×B) (All I’ve done here is uncurry.)
  181. 181. The latter function space contains the first projection (which looks an awful lot like K). The existence of this first projection shows that the type AA×B is inhabited, and thus the original proposition a =⇒ (b =⇒ a) is valid.
  182. 182. The correspondence between lambda expression, logical formulas, and objects in categories is called the Curry-Howard-Lambek correspondence.
  183. 183. Thanks!

×