6a528a23c943a8f0b3a0e909f999092f657f900d
[lambda.git] / assignment4.mdwn
1 #Reversing a list#
2
3 <OL>
4 <LI>How would you define an operation to reverse a list? (Don't peek at the
5 [[lambda_library]]! Try to figure it out on your own.) Choose whichever
6 implementation of list you like. Even then, there are various strategies you
7 can use.
8
9 (See [[hints/Assignment 4 hint 1]] if you need some hints.)
10 </OL>
11
12
13 #Comparing lists for equality#
14
15
16 <OL start=2>
17 <LI>Suppose you have two lists of integers, `left` and `right`. You want to
18 determine whether those lists are equal: that is, whether they have all the
19 same members in the same order. (Equality for the lists we're working with is
20 *extensional*, or parasitic on the equality of their members, and the list
21 structure. Later in the course we'll see lists which aren't extensional in this
22 way.)
23
24 How would you implement such a list comparison?
25
26 (See [[hints/Assignment 4 hint 2]] if you need some hints.)
27 </OL>
28
29
30 #Enumerating the fringe of a leaf-labeled tree#
31
32 First, read this: [[Implementing trees]]
33
34 <OL start=3>
35 <LI>Write an implementation of leaf-labeled trees. You can do something v3-like, or use the Y combinator, as you prefer.
36
37 You'll need an operation `make_leaf` that turns a label into a new leaf. You'll
38 need an operation `make_node` that takes two subtrees (perhaps leaves, perhaps
39 other nodes) and joins them into a new tree. You'll need an operation `isleaf`
40 that tells you whether a given tree is a leaf. And an operation `extract_label`
41 that tells you what value is associated with a given leaf. And an operation
42 `extract_left` that tells you what the left subtree is of a tree that isn't a
43 leaf. (Presumably, `extract_right` will work similarly.)
44
45 <LI>The **fringe** of a leaf-labeled tree is the list of values at its leaves,
46 ordered from left to right. For example, the fringe of this tree:
47
48                 .
49            / \
50           .   3
51          / \
52         1   2
53
54 is `[1;2;3]`. And that is also the fringe of this tree:
55
56                 .
57            / \
58           1   .
59              / \
60         2   3
61
62 The two trees are different, but they have the same fringe. We're going to
63 return later in the term to the problem of determining when two trees have the
64 same fringe. For now, one straightforward way to determine this would be:
65 enumerate the fringe of the first tree. That gives you a list. Enumerate the
66 fringe of the second tree. That also gives you a list. Then compare the two
67 lists to see if they're equal. 
68
69 Write the fringe-enumeration function. It should work on the
70 implementation of trees you designed in the previous step, and it
71 should make use of the list comparison function you wrote for question
72 2.  Thus you'll have to make sure you only use Church numerals as the
73 labels of your leaves, though nothing enforces this self-discipline.
74
75 </OL>
76
77
78
79 #Mutually-recursive functions#
80
81 <OL start=5>
82 <LI>(Challenging.) One way to define the function `even` is to have it hand off
83 part of the work to another function `odd`:
84
85         let even = \x. iszero x
86                                         ; if x == 0 then result is
87                                         true
88                                         ; else result turns on whether x's pred is odd
89                                         (odd (pred x))
90
91 At the same tme, though, it's natural to define `odd` in such a way that it
92 hands off part of the work to `even`:
93
94         let odd = \x. iszero x
95                                         ; if x == 0 then result is
96                                         false
97                                         ; else result turns on whether x's pred is even
98                                         (even (pred x))
99
100 Such a definition of `even` and `odd` is called **mutually recursive**. If you
101 trace through the evaluation of some sample numerical arguments, you can see
102 that eventually we'll always reach a base step. So the recursion should be
103 perfectly well-grounded:
104
105         even 3
106         ~~> iszero 3 true (odd (pred 3))
107         ~~> odd 2
108         ~~> iszero 2 false (even (pred 2))
109         ~~> even 1
110         ~~> iszero 1 true (odd (pred 1))
111         ~~> odd 0
112         ~~> iszero 0 false (even (pred 0))
113         ~~> false
114
115 But we don't yet know how to implement this kind of recursion in the lambda
116 calculus.
117
118 The fixed point operators we've been working with so far worked like this:
119
120         let X = Y T in
121         X <~~> T X
122
123 Suppose we had a pair of fixed point operators, `Y1` and `Y2`, that operated on
124 a *pair* of functions `T1` and `T2`, as follows:
125
126         let X1 = Y1 T1 T2 in
127         let X2 = Y2 T1 T2 in
128         X1 <~~> T1 X1 X2 and
129         X2 <~~> T2 X1 X2
130
131 If we gave you such a `Y1` and `Y2`, how would you implement the above
132 definitions of `even` and `odd`?
133
134                                         
135 <LI>(More challenging.) Using our derivation of Y from the [Week3
136 notes](/week3/#index4h2) as a model, construct a pair `Y1` and `Y2` that behave
137 in the way described.
138
139 (See [[hints/Assignment 4 hint 3]] if you need some hints.)
140
141 </OL>
142