;; Identity combinator (define I (lambda (x) x)) ;; Application combinator (define app (lambda (f x) (f x))) ;; Sequencing combinator (normal order) (define seq (lambda (x y) (if x y y))) ;; Curry as combinator (define curry (lambda (f) (lambda (x) (lambda (y) (f x y))))) (define plusc (curry +)) (define plus2 ((curry +) 2)) ;; Recursive definitions in lambda-calculus ;; Defining factorial in pure lambda calculus (no recursive defines or ;; letrec) ;; This expression (call it f) takes a procedure (factorial) that ;; returns a procedure that computes the factorial of a number. (define f (lambda (g) (lambda (n) (if (= n 0) 1 (* n (g (- n 1))))))) ;; What can we apply it to, to get the factorial function? ;; (f f) is not well defined: type of f is (I->I)->(I->I) ;;you can apply it to itself but the resulting fuction cannot be ;;applied to anything. ;; (f I) is well defined: it returns n * (n-1) (for n>0) but it ;; does not return the desired factorial function ;; how do we get factorial? ;; we need a procedure X representing factorial, i.e., ;; (f X) = X ;; In the factorial example, the following lambda-expression does the job: (define X ((lambda (x) ((lambda (g) (lambda (n) (if (= n 0) 1 (* n (g (- n 1)))))) (lambda (y) ((x x) y)))) (lambda (x) ((lambda (g) (lambda (n) (if (= n 0) 1 (* n (g (- n 1)))))) (lambda (y) ((x x) y)))))) ;; Such X can be defined in terms of the recursive function f as follows ;; X = (Y f) ;; where Y is the recursion combinator (define Y (lambda (f) ((lambda (x) (f (x x))) (lambda (x) (f (x x)))))) ;; here in applicative order (after eta-expansion) so that it ;; terminates with applicative order reduction (define Y (lambda (f) ((lambda (x) (f (lambda (y) ((x x) y)))) (lambda (x) (f (lambda (y) ((x x) y))))))) ;; the type of Y is ((I->I)->(I->I))->(I->I) ;; thus, here is the "pure" lambda-calculus expression computing factorial: ;; (assuming that 0, 1, -, *, = have beed defined in the lambda calculus) ((lambda (f) ((lambda (x) (f (lambda (y) ((x x) y)))) (lambda (x) (f (lambda (y) ((x x) y)))))) (lambda (g) (lambda (n) (if (= n 0) 1 (* n (g (- n 1))))))) ;; notice that (Y f) = (f (Y f)) by the construction above. ;; Fortunately, in Scheme, the "define" and "letrec" forms make our ;; life easier for defining recursive procedures. ;; Factorial (define ! (lambda (n) (if (= n 0) 1 (* n (! (- n 1)))))) ;; Exponential (define ^ (lambda (b n) (if (= n 0) 1 (* b (^ b (- n 1)))))) ;; Powers of 2 (define 2^ ((curry ^) 2)) (define rcurry (lambda (f) (lambda (x) (lambda (y) (f y x))))) ;; Square function (define ^2 ((rcurry ^) 2))