In case representing pairs as procedures wasn't mind-boggling enough, consider that, in a language that can manipulate procedures, we can get by without numbers (at least insofar as nonnegative integers are concerned) by implementing 0 and the operation of adding 1 as
(define zero (lambda (f) (lambda (x) x))) (define (add-1 n) (lambda (f) (lambda (x) (f ((n f) x)))))
This representation is known as Church numerals, after its inventor, Alonzo Church, the logician who invented the λ calculus.
Define
one and two directly (not in terms of zero and add-1). (Hint: Use substitution to evaluate (add-1 zero)). Give a direct definition of the addition procedure + (not in terms of repeated application of add-1).Let's take the hint and run with it...
(add-1 zero) = (add-1 (lambda (f) (lambda (x) x))) = (lambda (f) (lambda (x) (f (((lambda (f) (lambda (x) x)) f) x)))) = (lambda (f) (lambda (x) (f ((lambda (x) x) x)))) = (lambda (f) (lambda (x) (f x)))That give us a definition for
one:
(define one (lambda (f) (lambda (x) (f x))))And we can do the same to figure out
two:
(add-1 one) = (add-1 (lambda (f) (lambda (x) (f x)))) = (lambda (f) (lambda(x) (f (((lambda (f) (lambda (x) (f x))) f) x)))) = (lambda (f) (lambda(x) (f (((lambda (x) (f x)) x)))) = (lambda (f) (lambda(x) (f (f x))))So
two is:
(define two (lambda (f) (lambda (x) (f (f x)))))Looking at the pattern we can see that the Church numeral representation of the positive integer n is fn(x) (i.e. (f ο f ο…ο f ο f)(x), with n occurrences of f). Also, to assist with the remainder of the exercise, we should note that:
zeroproduces a single-parameter lambda expression that ignores its parameter and returns a single-parameter lambda expression that returns its parameter. So we can convertzeroto its integer equivalent value using the expression((zero f) 0), wherefis any value.oneproduces a single-parameter,f, lambda expression that returns a new single-parameter lambda expression that returns the results of applyingfto its parameter. So, assuming we pass 0 as the parameter to the second lambda expression as withzero, then we can convertoneto its integer equivalent value using the expression((one inc) 0), whereincis the increment procedure defined earlier.twoproduces a single-parameter,f, lambda expression that returns a new single-parameter lambda expression that returns the results of applyingfto the results of applyingfto its parameter. So similar toone, we can converttwoto its integer equivalent value using the expression((two inc) 0).
n, we can convert it to its integer equivalent value using the expression ((n inc) 0). Here's a procedure that encapsulates this logic which we can use to allow easy testing of our work with Church numerals:
(define (unchurch n) ((n inc) 0))For example:
> (unchurch zero) 0 > (unchurch one) 1 > (unchurch two) 2Now onto defining
+ for Church numerals. We know that we want this to produce a valid Church numeral. I.e. a single-parameter lambda expression whose parameter, f, is a procedure and that returns a single-parameter lambda expression. We also know that, given two Church numerals representing the nonnegative integers a and b, we want the evaluation of (((+ a b) f) x) to apply f repeatedly, starting with x as the initial input, for a total of a+b times. How can we do this? Well evaluating ((a f) x) will apply f a total of a times to whatever is passed to it as x, and ((b f) x) will apply f a total of b times to whatever is passed to it as x. So we can produce a composite function that evaluates ((b f) x) and then uses that as the value of x for evaluating ((a f) x) (or vice versa). Here's my definition
(define (+ a b) (lambda (f) (lambda (x) ((a f) ((b f) x)))))And to check it works:
> (unchurch (+ one two)) 3 > (unchurch (+ (+ one two) two)) 5Of course we can go much further with Church numerals - there's a whole raft of definitions for various computations. Just for fun I also defined
* for Church numerals:
(define (* a b) (lambda (f) (lambda (x) ((a (b f)) x))))And here it is in action:
> (unchurch (* (+ one two) two)) 6 > (unchurch (* (+ two two) (+ one two))) 12 > (unchurch (* (* two two) (* one two))) 8
No comments:
Post a Comment