1 00:00:06,250 --> 00:00:09,356 So, let's see. Form of the information determines the 2 00:00:09,356 --> 00:00:13,420 type comments. Type comments determine the template. 3 00:00:13,420 --> 00:00:16,010 Template determines the form of the functions. 4 00:00:16,010 --> 00:00:19,650 Then when we have repetitive functions, we can abstract them into an abstract 5 00:00:19,650 --> 00:00:24,478 function. Could there be a way to shorten that 6 00:00:24,478 --> 00:00:28,600 route? In fact, there is. 7 00:00:28,600 --> 00:00:33,352 In fact, there's a way to go from type comments directly to abstract functions, 8 00:00:33,352 --> 00:00:38,980 and then lots of the functions we write, just become very short. 9 00:00:38,980 --> 00:00:42,290 We're not going to take quite that shortcut in this video. 10 00:00:42,290 --> 00:00:45,266 What we're going to do in this video is go directly from templates to abstract 11 00:00:45,266 --> 00:00:49,386 functions. And that will take us all the way back to 12 00:00:49,386 --> 00:00:53,290 something we saw when we first looked at list functions. 13 00:00:53,290 --> 00:00:56,640 Remember the table of list functions, and we just looked at what to fill in to each 14 00:00:56,640 --> 00:01:02,314 position in the template? Now what's going to happen is lots of our 15 00:01:02,314 --> 00:01:06,346 functions on lists and arbitrary arity trees or any other kind of recursive 16 00:01:06,346 --> 00:01:12,162 structure are going to get real short. And generating the abstract function is 17 00:01:12,162 --> 00:01:19,016 going to get real automatic. I'm in fold-functions-starter.rkt, and at 18 00:01:19,016 --> 00:01:24,008 this point in the course the type listof X means list of x is one of empty or cons 19 00:01:24,008 --> 00:01:29,270 x ListOfX, and you know, we interpret that. 20 00:01:29,270 --> 00:01:31,639 What is there to interpret it as, as list of X? 21 00:01:31,639 --> 00:01:36,301 In the template for list of x is the ordinary list template, two cases con, if 22 00:01:36,301 --> 00:01:41,470 it's empty something. Otherwise, dot, dot, dot, the first of 23 00:01:41,470 --> 00:01:46,132 locks, fun for locks, rest of locks, and I've renamed the parameter to locks 24 00:01:46,132 --> 00:01:51,432 because it's a list of x. Now here's the problem, and the problem 25 00:01:51,432 --> 00:01:54,850 is to design an abstract fold function for a list of x. 26 00:01:56,730 --> 00:01:58,970 So you might ask, what the heck's a fold function. 27 00:01:58,970 --> 00:02:02,650 Let me show you. Here's the idea. 28 00:02:02,650 --> 00:02:08,020 The idea is to design an abstract function based directly off the template. 29 00:02:08,020 --> 00:02:12,400 So again, I'm going to work backwards through the steps of HDBO. 30 00:02:12,400 --> 00:02:20,109 I'm going to copy the template. And I'm going to call the function fold. 31 00:02:20,109 --> 00:02:22,639 It's actually going to be the foldr function. 32 00:02:22,639 --> 00:02:27,988 But I'll just call it fold. Then, I'm going to say, gee, there's two 33 00:02:27,988 --> 00:02:31,512 sets of dots. I'm going to introduce one parameter for 34 00:02:31,512 --> 00:02:37,990 each set of dots. And I should give them some good names. 35 00:02:37,990 --> 00:02:45,673 Now, this one is the base case result, so I introduce parameter called b. 36 00:02:46,970 --> 00:02:51,265 And I'll use it in this position. There it is, I'm also getting rid of the 37 00:02:51,265 --> 00:02:58,340 parenths, because b is the final result, it's not the function of no arguments. 38 00:02:58,340 --> 00:03:03,002 So there b is now standing for the first set of dots, and this one is a function 39 00:03:03,002 --> 00:03:07,590 that's called to take the first of the list and combine it with the result of 40 00:03:07,590 --> 00:03:13,986 the natural recursion. So, I'll call that fn and just like 41 00:03:13,986 --> 00:03:20,283 convention we put the function arguments early and abstract functions. 42 00:03:20,283 --> 00:03:25,710 So I ordered the arguments that way you can order them the other way I just want 43 00:03:25,710 --> 00:03:33,600 this to end up being exactly like foldr. So now I've got the function. 44 00:03:35,470 --> 00:03:40,364 Now I've got the function. Now let's do some tests for it some check 45 00:03:40,364 --> 00:03:44,574 expects. Well it's the abstract function for the 46 00:03:44,574 --> 00:03:49,699 list template so I know some of the things that it can do. 47 00:03:49,699 --> 00:03:56,271 If I say fold with plus and zero and list one, two, three, I get The sum of that 48 00:03:56,271 --> 00:04:03,283 list which is 6. If I say fold with times 1 and the list 1 49 00:04:03,283 --> 00:04:09,870 2 3, I get the product of that list which is also 6. 50 00:04:09,870 --> 00:04:12,859 And I could try those to make sure I understand this function properly. 51 00:04:23,250 --> 00:04:26,463 Oh, what happened here is I forgot to rename the recursion and I forgot to add 52 00:04:26,463 --> 00:04:29,050 the parameters to the recursion. Huh. 53 00:04:30,970 --> 00:04:33,088 You're always making mistakes in this business. 54 00:04:33,088 --> 00:04:37,644 Now I've renamed the natural recursion and I added the parameters in the natural 55 00:04:37,644 --> 00:04:42,900 recursion. [SOUND]. 56 00:04:42,900 --> 00:04:46,480 Now, these tests are tests from later in the file. 57 00:04:46,480 --> 00:04:49,228 So we're not going to worry about them. These failing tests are from later in the 58 00:04:49,228 --> 00:04:51,410 file. Let me comment that out, so we won't see 59 00:04:51,410 --> 00:04:55,570 that ugly highlighting. My tests for fold are working. 60 00:04:55,570 --> 00:05:01,810 [SOUND]. So now, what's the purpose? 61 00:05:01,810 --> 00:05:05,320 Well, if you didn't have a more abstract way of writing the purpose. 62 00:05:05,320 --> 00:05:11,040 If you didn't know that this was fold R. It would be enough to say [SOUND] the 63 00:05:11,040 --> 00:05:20,460 abstract fold function for list of X. Because that's what a fold function. 64 00:05:20,460 --> 00:05:25,191 You take the template. We define a function based on the 65 00:05:25,191 --> 00:05:29,349 template with an additional parameter for each set of dots and that's and what a 66 00:05:29,349 --> 00:05:35,380 fold function is. Now let's figure out the signature. 67 00:05:35,380 --> 00:05:41,518 Well, and now that this is an, even though both of these examples are list of 68 00:05:41,518 --> 00:05:47,800 number It started with the list of x template. 69 00:05:47,800 --> 00:05:58,578 So you know that this third parameter is really list of x. 70 00:05:58,578 --> 00:06:01,000 [SOUND]. Now, this makes it quite clear that the 71 00:06:01,000 --> 00:06:05,790 result isn't list of x. It isn't even a list at all. 72 00:06:05,790 --> 00:06:09,263 It's something else. Now it happens to be numbering both of 73 00:06:09,263 --> 00:06:12,980 these cases, so you might just want to put Number there. 74 00:06:12,980 --> 00:06:16,472 But, what you should do instead is think, can I make it do something else? 75 00:06:16,472 --> 00:06:22,574 Can I make it, for example, add up some string? 76 00:06:23,630 --> 00:06:32,630 For example, can I do fold string append with the empty string and the empty zone. 77 00:06:32,630 --> 00:06:34,790 And list a, bc, def. Let's see. 78 00:06:34,790 --> 00:06:50,411 Adding or appending all those strings together should produce abcdef. 79 00:06:50,411 --> 00:06:53,942 And that test it's working. The test that's failing is later in the 80 00:06:53,942 --> 00:06:57,266 file. So that test is working, so that tells me 81 00:06:57,266 --> 00:07:03,290 that the result isn't always a number, it can be something else. 82 00:07:05,580 --> 00:07:10,820 Now in both of these cases it's listof string to string. 83 00:07:10,820 --> 00:07:16,881 So that might make me write X there. Now I gotta try to make it do something 84 00:07:16,881 --> 00:07:20,915 else. I gotta see can I construct an example 85 00:07:20,915 --> 00:07:25,865 where the final result Isn't the same as the type of the elements of the consumed 86 00:07:25,865 --> 00:07:31,280 list. So you could try to construct that 87 00:07:31,280 --> 00:07:35,760 example, or you could look at the code, and say to yourself well, each of these 88 00:07:35,760 --> 00:07:40,355 has to be an x. Those are always. 89 00:07:40,355 --> 00:07:45,269 The type of the first argument of the function, so let me back up here, and say 90 00:07:45,269 --> 00:07:50,554 the first argument of the function has to be an X. 91 00:07:50,554 --> 00:07:57,043 The second argument of the function is the result of the recursion, which of 92 00:07:57,043 --> 00:08:07,056 course is the type of the base. And always the result of the function. 93 00:08:07,056 --> 00:08:12,534 There's nothing here that says that this type and this type really have to be the 94 00:08:12,534 --> 00:08:17,680 same, so this could actually be y and then if, if this whole thing is going to 95 00:08:17,680 --> 00:08:23,241 produce a y Then that means that the type of the second argument to the function is 96 00:08:23,241 --> 00:08:29,692 a y. And the function has to produce a y. 97 00:08:29,692 --> 00:08:37,230 And also, the type of b has to be y. [SOUND]. 98 00:08:37,230 --> 00:08:43,886 So what that says is, give me, give fold. A value of type y, the base case value of 99 00:08:43,886 --> 00:08:48,193 type y, and a list of x in a function that consumes an x, a y, and produces a 100 00:08:48,193 --> 00:08:54,169 y. And it will go through the entire list 101 00:08:54,169 --> 00:08:59,359 producing the final y, and that's in fact the signature for folder. 102 00:09:01,070 --> 00:09:04,425 Now that you have fold, if you didn't have it already, but now that you have 103 00:09:04,425 --> 00:09:07,840 it, you can of course use it in lots of ways. 104 00:09:07,840 --> 00:09:13,180 You've already done some in an earlier video. 105 00:09:13,180 --> 00:09:16,779 So, I'll just pause here and ask you to do it again if you're a little unsure 106 00:09:16,779 --> 00:09:21,424 about how fold is working. Just To improve your confidence that you 107 00:09:21,424 --> 00:09:25,279 understand what fold does. So here's kind of an optional in video 108 00:09:25,279 --> 00:09:36,199 quiz question for you. And here is the result I ended up with. 109 00:09:36,199 --> 00:09:39,371 It of course is exactly equivalent to this first check expect, or it, it's 110 00:09:39,371 --> 00:09:42,775 essentially equivalent to this first check expect. 111 00:09:42,775 --> 00:09:47,876 The function argument to fold is plus. The base case value is zero and the list 112 00:09:47,876 --> 00:09:52,850 argument is the list. Here is a similar one for adding together 113 00:09:52,850 --> 00:09:56,781 a list of images. Do this exercise now. 114 00:09:56,781 --> 00:10:02,757 And here's the definition that I ended up with. 115 00:10:02,757 --> 00:10:08,716 I call fold with beside as the composition with the white, square as the 116 00:10:08,716 --> 00:10:16,784 base, n with the list of images. If you remember all the way back to that 117 00:10:16,784 --> 00:10:20,430 table. Then I showed you in the first week on 118 00:10:20,430 --> 00:10:24,212 list functions -- and I showed you the different ways you could fill in that 119 00:10:24,212 --> 00:10:27,774 table? You can now see the different ways that 120 00:10:27,774 --> 00:10:33,212 you can fill in fold. Plus and zero gives you sum; times and 1 121 00:10:33,212 --> 00:10:39,490 gives you product Beside and a blank square gives you juxtapose. 122 00:10:39,490 --> 00:10:45,442 You can do all sorts of things will fold because fold really is the abstract 123 00:10:45,442 --> 00:10:51,967 function for the list of x type. It's the abstract function for the list 124 00:10:51,967 --> 00:10:54,160 of x type. You take the template. 125 00:10:54,160 --> 00:10:57,920 You add one parameter for each dot dot dot in the template. 126 00:11:02,310 --> 00:11:08,030 There's a funny thing you can do which is to give fold parameters that will just 127 00:11:08,030 --> 00:11:16,410 produce the same result that comes in, so if I just say copy list... 128 00:11:16,410 --> 00:11:21,654 Of lox and I call fold and in the composition position I put cons and in 129 00:11:21,654 --> 00:11:27,082 the base result position I put empty, then this function copy list just 130 00:11:27,082 --> 00:11:38,810 produces whatever result it's given. Copy listof produces empty. 131 00:11:38,810 --> 00:11:43,874 Copy listof list 123 produces list 123. Because we're filling cons into this 132 00:11:43,874 --> 00:11:47,480 combination position of empty into the base position. 133 00:11:48,730 --> 00:11:53,692 And again, going back to that table, the line for copy list is cons and empty. 134 00:11:53,692 --> 00:11:57,272 And that just produces a copy of the list. 135 00:11:57,272 --> 00:12:00,270 List. So that's kind of neat. 136 00:12:00,270 --> 00:12:02,584 That's fold for a list. Now watch this. 137 00:12:02,584 --> 00:12:06,391 Design an abstract fold function for Element. 138 00:12:06,391 --> 00:12:14,902 Remember Element was the arbitrary arity tree that we looked at last week. 139 00:12:16,820 --> 00:12:20,200 Well, there's the template for element, in which I've already grouped it with 140 00:12:20,200 --> 00:12:23,840 local into an outer function and the two inner functions. 141 00:12:24,980 --> 00:12:31,360 So if I start with that, and now I'm going to design this abstract fold 142 00:12:31,360 --> 00:12:35,850 function. >> Let's see I'll put the design down 143 00:12:35,850 --> 00:12:42,100 here. It's going to be called fold element. 144 00:12:42,100 --> 00:12:46,140 I can't call it fold again because I already used that name. 145 00:12:46,140 --> 00:12:54,140 Fold element, and now let's see. There's two function positions. 146 00:12:54,140 --> 00:13:05,195 There's combine one, which will be here, and combine two, which will be here, and 147 00:13:05,195 --> 00:13:15,430 there's one space, which will be here. And there it is. 148 00:13:15,430 --> 00:13:18,727 I've got, I've got the bold function. Well let's see. 149 00:13:18,727 --> 00:13:23,037 What's a check expect for what it can do? Well this is going to be a little bit 150 00:13:23,037 --> 00:13:26,992 more complicated. Because c1 and c2are more interesting 151 00:13:26,992 --> 00:13:30,340 functions. But let's try to do a check expect for 152 00:13:30,340 --> 00:13:33,900 the case. Where we build a list of all the names in 153 00:13:33,900 --> 00:13:37,744 the tray. We're going to need a helper function for 154 00:13:37,744 --> 00:13:44,657 that, so I'm going to start with a local. And we're going to say, fold element, and 155 00:13:44,657 --> 00:13:50,438 in the argument, let's say the argument is going to be D6. 156 00:13:52,470 --> 00:13:53,750 [INAUDIBLE]. That'll be the actual trace. 157 00:13:53,750 --> 00:13:56,889 So now, we need two combination functions. 158 00:13:56,889 --> 00:14:04,248 Let's see, c1 goes right here. And I'm just going to define it here with 159 00:14:04,248 --> 00:14:09,248 that name, define c1. And it consumes three arguments. 160 00:14:09,248 --> 00:14:14,015 It consumes a name, a data. And the result of the natural recursion, 161 00:14:14,015 --> 00:14:19,270 which in this case, of course, is going to be a list of names. 162 00:14:21,660 --> 00:14:25,818 And what does this have to do? Well, it's going to ignore the data and 163 00:14:25,818 --> 00:14:31,851 cons the name onto los. And now, let's see, what does c2 have to 164 00:14:31,851 --> 00:14:36,779 do? The reason I'm defining c1 and c2 using a 165 00:14:36,779 --> 00:14:40,192 local. Is, they're a little bit more 166 00:14:40,192 --> 00:14:43,265 complicated, or perhaps they're more complicated anyways. 167 00:14:43,265 --> 00:14:46,775 But c two has to do is, let's see, both of these natural occurrences are going to 168 00:14:46,775 --> 00:14:50,123 produce a list of names, or a list of strings, and I just have to combine them 169 00:14:50,123 --> 00:14:55,762 together. Oh, well if I've got two lists of 170 00:14:55,762 --> 00:14:58,268 strings, and I want a single list of string. 171 00:14:58,268 --> 00:15:05,040 That's just append c2 isn't really that complicated. 172 00:15:05,040 --> 00:15:11,730 So let's see its fold element c1 append and empty is the base. 173 00:15:11,730 --> 00:15:20,455 And does that produce. What's the result we're after here? 174 00:15:20,455 --> 00:15:29,631 Remember what the tree looks like, and it's D6 comes first, and then D4, and 175 00:15:29,631 --> 00:15:42,301 then F1 and F2, and then D5, and then f3, F3 that would be the result. 176 00:15:42,301 --> 00:15:50,323 Let's see if that works. Whoops, what did I do wrong here? 177 00:15:50,323 --> 00:15:54,589 Cons expects two arguments, but found only one. 178 00:15:56,240 --> 00:15:57,200 Oh, yeah. Huh. 179 00:15:57,200 --> 00:15:59,705 That's not right. I need to cons n onto los. 180 00:15:59,705 --> 00:16:14,820 And this test is failing. It means that this test is succeeding. 181 00:16:14,820 --> 00:16:17,992 So, pretty cool here. I managed to make a list of all the names 182 00:16:17,992 --> 00:16:22,580 in the tree, using the abstract function fold element. 183 00:16:22,580 --> 00:16:29,560 So the purpose is, the abstract fold function for element. 184 00:16:29,560 --> 00:16:33,470 And of course, that means it's also for list of element. 185 00:16:33,470 --> 00:16:40,620 Because that is involved in element. [SOUND]. 186 00:16:40,620 --> 00:16:43,890 Probably just leave that out, because it originally consumes element. 187 00:16:43,890 --> 00:16:48,110 Now we gotta get a signature. let's see. 188 00:16:48,110 --> 00:16:55,040 In this template, I've already got the type produced by these two selectors 189 00:16:55,040 --> 00:17:00,380 annotated here. And I'm going to start by adding two more 190 00:17:00,380 --> 00:17:04,243 annotations. There are these two mutually recursive 191 00:17:04,243 --> 00:17:08,479 functions, and I don't know what types they produce. 192 00:17:08,479 --> 00:17:12,899 I don't know what types they produce yet in the abstract function because they 193 00:17:12,899 --> 00:17:17,660 might produce different things depending on c1 and c2. 194 00:17:17,660 --> 00:17:24,388 I'm going to start by saying fn-for-element in general produces X and 195 00:17:24,388 --> 00:17:32,706 fn-for-loe in general produces Y. I've just introduced two type variables 196 00:17:32,706 --> 00:17:40,190 to let me talk about what fn-for-element produces, and fn-for-loe produces. 197 00:17:40,190 --> 00:17:41,879 Why is that a good idea? Well, why. 198 00:17:43,150 --> 00:17:44,514 [INAUDIBLE]. Now, let's look at the signature fold 199 00:17:44,514 --> 00:17:45,530 element. Well, let's see. 200 00:17:45,530 --> 00:17:49,800 The first argument to fold element is c1. And c1's a function. 201 00:17:49,800 --> 00:17:52,670 So I'll just start by saying, well, it's a function. 202 00:17:52,670 --> 00:17:57,170 So it's going to look like that. Now, let's see. 203 00:17:57,170 --> 00:18:04,459 It's a function of three arguments. The first one is a string. 204 00:18:04,459 --> 00:18:09,186 So I'll say string. The second one is an integer. 205 00:18:09,186 --> 00:18:13,508 The third one is the result of fn-for-loe. 206 00:18:13,508 --> 00:18:18,550 Well what's the type of the result of fn-for-loe? 207 00:18:18,550 --> 00:18:22,670 Well I decided that that was going to be a Y. 208 00:18:22,670 --> 00:18:30,658 So I'll just put y there, so let's see. C1 consumes a string, an integer, and a 209 00:18:30,658 --> 00:18:34,610 y, because it's the fun for loe, and what does it produce? 210 00:18:34,610 --> 00:18:37,560 Well I decided that it was going to produce x, so I'll just put x there. 211 00:18:40,100 --> 00:18:43,598 Now I'm working on the. Second argument to fold element, in other 212 00:18:43,598 --> 00:18:47,990 words c2. c2 is a function, it gets used right 213 00:18:47,990 --> 00:18:55,030 there as a function so I'll just start by putting that, now I'll fill that in. 214 00:18:55,030 --> 00:19:01,183 It's a function of two arguments. The first is a result of fn-for-element 215 00:19:01,183 --> 00:19:07,870 and fn-for-element produces x. So that means the type of the first is x. 216 00:19:07,870 --> 00:19:14,790 The second argument to see, too, is a result of fn-for-loe. 217 00:19:14,790 --> 00:19:20,175 So that means it's type is y. And c2 has to be willing to produce 218 00:19:20,175 --> 00:19:23,915 whatever fn-for-loe is supposed to produce, because c2 is calling in a 219 00:19:23,915 --> 00:19:29,590 result. Position for fn-for-loe. 220 00:19:29,590 --> 00:19:35,320 So that mean c2 has to produce a Y, all right. 221 00:19:35,320 --> 00:19:40,260 That's the c2 argument to fold element. Let's at b, where is b? 222 00:19:40,260 --> 00:19:45,275 Well b is the base case result of fn-for-loe, that means b has to have the 223 00:19:45,275 --> 00:19:51,770 same type as fn-for-loe produces. So that's got to be a Y. 224 00:19:51,770 --> 00:19:58,720 E has to be of type Y. And then I'll delineate E. 225 00:19:58,720 --> 00:20:05,326 Well E of course is an element. And finally, we need the result type of 226 00:20:05,326 --> 00:20:12,215 the entire fold element. Let's see fold element produces whatever 227 00:20:12,215 --> 00:20:18,704 fun for element produces, and fun for element we decided produced x so, this 228 00:20:18,704 --> 00:20:26,004 whole thing is going to produce x. So there you go, there's the signature 229 00:20:26,004 --> 00:20:29,384 for a mutually recursive abstract function, an abstract function operating 230 00:20:29,384 --> 00:20:34,722 on an arbitrary arity tree. And I did it basically the same way that 231 00:20:34,722 --> 00:20:38,880 I’ve been doing the signatures for abstract functions from the beginning, 232 00:20:38,880 --> 00:20:42,774 with the one addition that in this case because there is these two inner 233 00:20:42,774 --> 00:20:46,932 functions, I went ahead fairly early on and gave type parameters for each of 234 00:20:46,932 --> 00:20:53,352 their results. So I said fn-for-element e produces X and 235 00:20:53,352 --> 00:20:57,275 fn-for-loe produces Y. And then I just use the typer inference 236 00:20:57,275 --> 00:21:01,244 reading the types off and building up what I can tell about the types to get to 237 00:21:01,244 --> 00:21:08,172 this signature. Abstract fold functions on more complex 238 00:21:08,172 --> 00:21:11,910 data on types with mutual references are pretty cool. 239 00:21:11,910 --> 00:21:14,600 They let you write some very interesting functions very compactly. 240 00:21:14,600 --> 00:21:17,492 Why don't you play around with them in the exercises coming up... 241 00:21:17,492 --> 00:21:18,667 [SOUND] 242 00:21:18,667 --> 00:21:21,490 [BLANK_AUDIO]