author Jim Pryor Sun, 19 Sep 2010 12:46:30 +0000 (08:46 -0400) committer Jim Pryor Sun, 19 Sep 2010 12:46:30 +0000 (08:46 -0400)
Signed-off-by: Jim Pryor <profjim@jimpryor.net>
 week3.mdwn patch | blob | history

index 613981d..0129f2a 100644 (file)
@@ -126,7 +126,7 @@ With sufficient ingenuity, a great many functions can be defined in the same way

##However...##

-Some computable functions are just not definable in this way. The simplest function that *simply cannot* be defined using the resources we've so far developed is the Ackermann function:
+Some computable functions are just not definable in this way. The simplest function that *simply cannot* be defined using the resources we've so far developed is the [[!wikipedia Ackermann function]]:

A(m,n) =
| when m == 0 -> n + 1
@@ -136,7 +136,7 @@ Some computable functions are just not definable in this way. The simplest funct
A(0,y) = y+1
A(1,y) = y+2
A(2,y) = 2y + 3
-       A(3,y) = 2^(y+3) -3
+       A(3,y) = 2^(y+3) - 3
A(4,y) = 2^(2^(2^...2)) [where there are y+3 2s] - 3
...

@@ -162,7 +162,7 @@ Call that formula `H`. Now what would happen if we applied `H` to itself? Then w

\lst. (isempty lst) zero (add one (... (extract-tail lst)))

-where any occurrences of `h` inside the `...` were substituted with `H`. Call this `F`. `F` looks pretty close to what we're after: a function that takes a list and returns zero if it's empty, and so on. And `F` is the result of applying `H` to itself. But now inside `F`, the occurrences of `h` are substituted with the very formula `H` we started with.So if we want to get `F` again, all we have to do is apply `h` to itself---since as we said, the self-application of `H` is how we created `F` in the first place.
+where any occurrences of `h` inside the `...` were substituted with `H`. Call this `F`. `F` looks pretty close to what we're after: a function that takes a list and returns zero if it's empty, and so on. And `F` is the result of applying `H` to itself. But now inside `F`, the occurrences of `h` are substituted with the very formula `H` we started with. So if we want to get `F` again, all we have to do is apply `h` to itself---since as we said, the self-application of `H` is how we created `F` in the first place.

So, the way `F` should be completed is:

@@ -178,19 +178,21 @@ Instead of writing out a long formula twice, we could write:

(\x. x x) LONG-FORMULA

-and the initial `(\x. x x)` is just what we earlier called the <code>&omega;</code> combinator (lower-case omega, not the non-termination <code>&Omega;</code>). So the self-application of `H` can be written:
+and the initial `(\x. x x)` is just what we earlier called the <code>&omega;</code> combinator (lower-case omega, not the non-terminating <code>&Omega;</code>). So the self-application of `H` can be written:

<pre><code>&omega; (\h \lst. (isempty lst) zero (add one ((h h) (extract-tail lst))))</code></pre>

and this will indeed implement the recursive function we couldn't earlier figure out how to define.

-In broad brush-strokes, `H` is half of the `get_length` function we're seeking, and H has the form:
+In broad brush-strokes, `H` is half of the `get_length` function we're seeking, and `H` has the form:

\h other-arguments. ... (h h) ...

We get the whole `get_length` function by applying `H` to itself. Then `h` is replaced by the half `H`, and when we later apply `h` to itself, we re-create the whole `get_length` again.

-Now suppose you wanted to wrap this up in a pretty interface, so that the programmer didn't need to write `(h h)` but could just write `g` for some function `g`. How could you do it?
+##Neat! Can I make it easier to use?##
+
+Suppose you wanted to wrap this up in a pretty interface, so that the programmer didn't need to write `(h h)` but could just write `g` for some function `g`. How could you do it?

Now the `F`-like expression we'd be aiming for---call it `F*`---would look like this:

@@ -200,7 +202,7 @@ or, abbreviating:

\lst. ...g...

-Here we have just a single `g` instead of `(h h)`. We'd want `F*` to be the result of self-applying some `H*`, and then binding to `g` that very self-application of `H*`. We'd get this if `H*` had the form:
+Here we have just a single `g` instead of `(h h)`. We'd want `F*` to be the result of self-applying some `H*`, and then binding to `g` that very self-application of `H*`. We'd get that if `H*` had the form:

\h. (\g lst. ...g...) (h h)

@@ -247,7 +249,7 @@ who knows what we'd get back? Perhaps there's some non-number-representing formu

Yes! That's exactly right. And which formula this is will depend on the particular way you've implemented the successor function.

-Moreover, the recipes that enable us to name fixed points for any given formula aren't *guaranteed* to give us *terminating* fixed points. They might give us formulas X such that neither `X` nor `f X` have normal forms. (Indeed, what they give us for the square function isn't any of the Church numerals, but is rather an expression with no normal form.) However, if we take care we can ensure that we *do* get terminating fixed points. And this gives us a principled, fully general strategy for doing recursion. It lets us define even functions like the Ackermann function, which were until now out of our reach. It would let us define arithmetic and list functions on the "version 1" and "version 2" implementations, where it wasn't always clear how to force the computation to "keep going."
+Moreover, the recipes that enable us to name fixed points for any given formula aren't *guaranteed* to give us *terminating* fixed points. They might give us formulas X such that neither `X` nor `f X` have normal forms. (Indeed, what they give us for the square function isn't any of the Church numerals, but is rather an expression with no normal form.) However, if we take care we can ensure that we *do* get terminating fixed points. And this gives us a principled, fully general strategy for doing recursion. It lets us define even functions like the Ackermann function, which were until now out of our reach. It would also let us define arithmetic and list functions on the "version 1" and "version 2" implementations, where it wasn't always clear how to force the computation to "keep going."

OK, so how do we make use of this?

@@ -257,7 +259,7 @@ Recall again our initial, abortive attempt above to define the `get_length` func

where this very same formula occupies the `...` position."

-If we could somehow get ahold of this formula, as an additional argument, then we could take the argument and plug it into the `...` position. Something like this:
+If we could somehow get ahold of this very formula, as an additional argument, then we could take the argument and plug it into the `...` position. Something like this:

\self (\lst. (isempty lst) zero (add one (self (extract-tail lst))) )

@@ -331,7 +333,7 @@ Isn't that cool?

##Okay, then give me a fixed-point combinator, already!##

-Many fixed-point combinators have been discovered. (And given a fixed-point combinators, there are ways to use it as a model to build infinitely many more, non-equivalent fixed-point combinators.)
+Many fixed-point combinators have been discovered. (And given a fixed-point combinator, there are ways to use it as a model to build infinitely many more, non-equivalent fixed-point combinators.)

Two of the simplest:

@@ -396,7 +398,3 @@ then this is a fixed-point combinator:
L L L L L L L L L L L L L L L L L L L L L L L L L L

-
-[TODO: Explain how what we've done relates to the version using lower-case &omega;.]
-
-