Sort that list and then unlines which is another library function which takes a list of strings, slams new lines into them and throws it all together All right So, the first line should be like dead clear, right? I don’t see anyone looking strange you can like, okay, everything is nodding yes, so good Okay. now, I know I had to take you back to high school and everyone hates that but in high school you hate algebra because, you know, you learn this, right? F of G of X can be written as this funky thing with a dot in the middle All right This is function composition F of G of X, all right, so you can see that While in Haskell, it turns out, that’s actually a programming language feature So in the same way, we can do that up here, we can fact it–we can sort of rewrite this, this way All right So, the function process of some text t is applied to that text t, the function lines composed with sort composed with unlines, all right So that data operator is exactly like it was in algebra All it just means is apply the thing on the left to the result of having applied the thing on the right, so unlines it then sort it, I mean, lines it then sort it then unlines it All right It reads kind of right to left which might seem kind of strange to you because bash things go in the other direction But look up here, right? I mean, it’s just getting rid of all these parenthesis Okay Now, here comes the real [INDISTINCT] We can actually do algebraic simplification or sort of the equivalent So, work with me here If process of–it takes some input, right? Process a function applied to some input t and all it is, is this composite function, these three things applied in sequence to t–in Haskell you should get rid of the t’s because we can say, Well, process–by the way, the tip marks are just valid characters for identifiers and I had to name them all three different things so they can go on the same file The process double tip mark is a function that is just the composition of these three functions Have I lost anyone yet? Good Onward Okay So we can code a bunch of other ones We can say sorting lines is unlines.sort lines, right? Compose those three We can reverse lines, we can take the first two lines because take two is a–no, it does what you think, right? So, anyone see a pattern? It’s a pattern, it’s algebra, we can factor it So, we can actually write a function called by lines which takes a function F and it’s equal to–we just write the same expression but stick our variable in the middle, right? So by lines of F is the same as having written unlines.f.lines So, now I can rewrite those three functions Sort lines write by line sort Reverse lines, by lines reverse First two lines, by lines take two Yes, yes, no, there you go, [INDISTINCT] that’s good All right Let’s write our own Okay I’m going to write a new function, sort of from scratch here it’s called indent This funny line at the top is a tight declaration, it says indent is a function that starts with a string, takes a string argument and turns it in to a string as a string result It’s kind of very functional style in notation, oddly enough All right Anyone noticed that this is the first type I have shown you anywhere? All the other code is completely 100% valid Haskell you’ll find it in the–in the files that are with the repo exactly as I wrote it here with no additional typing So, Haskell is a language that is really strongly typed and yet we didn’t have to type any types because Haskell is type [INDISTINCT] which means that when you type some–when you write on a code, the expression, Haskell figures out what type that must be when you write a type to a first order of approximation, 98% of time The type is for you, not for the compiler In fact, the compiler ignores what you write as a type, figures out what the type is on its own and then says, Did I get it right? Now, you might think that’s kind of crazy like aren’t–like, it shouldn’t be, but no The compiler it’s there because we write the types as communication between programmers and the communication of our intent and the compiler is actually checking us Checking to make sure we’re honest Okay So indent is a function from string to string, it’s really complicated, it takes an argument S, ended up pens at the double plus operator, a bunch of spaces to the front Great So, we should be able to follow our pattern All right By line sort by lines reverse and say by lines and dent, anyone want to guess? Boom, it doesn’t work And the worst problem is if you put this in the [INDISTINCT] you’ll see this horrible thing down there That is the Haskell compilers idea of poetry, it’s writing you a kind of a love poem but it’s from a compiler and so, as a consequence, we ignore it Do you agree with that?

This is just crazy moon poetry and you just have to deal with the fact that it’s there and most of the time you just figure what line number it is and go looking at them Okay What is the problem? The problem is, all our other functions sort and reverse took a list of lines and did something to them but we wrote something which takes a string Okay So, we’re going to use something called map Map to the rescue now, you probably all at this day and age program did a language that has a collections library and that collections library has either a four each or a map function, right? And usually map takes a functional argument, a function pointer or it depends on the language your working in and iterates through the collection applying the function and gathering up all the results and returning you a new collection This is nothing new Map exist and you–I’m certain everyone here has been exposed to a map function and just to make sure we are to realize what we’re talking about I gave you some examples, compare if we map reverse over this list of strings, right, it reverses each individual string versus mapping reverse to the list of strings which map reverses the list itself, got it? All right The same thing is like sorting some of you might at this point be scratching your nose and go, Wait, does reverse work on a list of strings or does reverse work on a string? The answer to that question is, yes it does both Okay So, to indent each line of our poem, right? I have to do something by lines but I better map, all right, by lines expects a function over a list So, I’m going to map indent over that list By lines map indent I could also factor that whole pattern out because we had a thing called by lines, have it each line, given a function–now, I’ve written this–now I’ve written a type Given a function from a string to a string, notice the parenthesis and the string return a new string So, let’s–let’s look at what’s going to happen, each line F is going to take this–it’s going to take a string, apply lines to it, give us a list of lines, map our function F over each individual line and then unlines the result back together into one big string to return So, each line is now useful utility function which does something–apply something to each individual line Yes? >> When you write maps space indent is that the same as indent.map? >> LENTCZNER: No, it is not So, the question was when you write maps space indent is that the same as indent.map? No, it is not We are passing indent as a function, as an argument to map >> Okay Map is a function >> LENTCZNER: Map is a function, right There’s no period or object There’s no receiver in this language It is not object oriented So, map is just a pure function at the top there but we’re going to–you’re getting close to a problem Anyway, close to [INDISTINCT] so indent line, we can do it this way or we can use this combinator of this thing we just build called each line–each line indent and then if you run them either you get indeed an indented poem, it’s very exciting But wait, where is the second argument to map? I told you back here, map takes a function and a list and returns a list In fact, at this point, looking at that top line should hopefully be kind of clear that that’s what that says It takes, right? It starts with it takes a function from A to B, a list of As and gives you a list of Bs but in this code up here, there is no second argument to map Where is it? All right Because it’s not there Because map of F–so look at map this way, we can say map takes a function from A to B and because [INDISTINCT] just trust me I can parenthesize the remainder So you can think of map as taking a function from A to B and turning it into a function from list of A to list of B, got that? If I just applied map to the first argument, I get back a new function it’s called [INDISTINCT] it’s [INDISTINCT] and I get back a new function, a function list of A to B, it turns, our indent which only works on a string to a version of indent which works on a list of strings We call this lifting or lifting up, map is kind of bringing our simple function up into the world of lists and that’s what’s going on All right And we’ll write some more code here, quickly I want to yell because we like yelling, right? So, this is another function from string to string and so, I’m going to yell and I’m going to map this function called to operate from the library listed uppercases characters And I map that over the string and I append a bunch of exclamations, and I’m going to

write yell each line and I’m going to use our each line function to apply this to each line of the poem And indeed what happens? I’ve yelled each line of the poem, not particularly exciting, it’s pretty much what we did before But what if I want to yell each word? Well, we’re very, very lucky, there’s actually like lines and unlines, the library has words and unwords So, we can define equivalently a function called each word that given a function will apply it to each word of the string So, right? We call words which breaks it up into a list of words We map F in this case, yell over that list of words and then we unwords to put it all back together And when we go off and do this, crap it all comes out on one line, right? Because it broke all the words apart all the words got slammed together with spaces and we lost all the lines So, what do we really want to do? We want to yell by words by lines Well, guess what? We can actually write yet another helper function Each word on each line, all right? Given a function F, this will apply to each word on each line by wrapping our function in each word and that we’re calling each word on our function and then calling each line on that And indeed, if I apply that, I get this, right? And I had managed to preserve the lines and do it every single word Notice that I have used the very functions we have defined ourselves as functions to more functions we’ve defined ourselves, right? So, what bus do we just get hit by This is the power of higher order of functions, all right? You can very quickly build yourself up a library for doing higher level manipulations of things and then re-use it very, very, very quickly Onward Okay So, we’ve talked a lot about functions, what about data? You got to have data in the program somewhere so, of course, we’re going to talk about structure data we might as well about list and so, one could use to define list like this This is actually a user defined type, this is not the built in list It’s just a list If you come from a certain persuasion, you might choose to call that mill and cons instead of end of list and link but let’s just read this When you have a piece of data of type of type–yes? >> You work [INDISTINCT] do you actually type what you’re [INDISTINCT] into a compiler? >> LENTCZNER: Either Good question So yes, I actually wrote the alphas because I just wanted to flex that Haskell was actually define in terms of unit code yohoo And so, you can–welcome to use Greek and variable names if you wish Actually, in fact, you’d probably not unlikely to see this, most people do in fact use Latin letters in this particular context So, that is actually a tight variable, tight variable So, this is–so, when you have a list of some type, either note the or sign there Either it’s just the end of the list, the empty list or it is a link of the list with some value of whatever the hell alpha ends up being and then recursively another datum of type list alpha, right? This is just a standard kind of recursive definition of the list Okay So, we can all play around with some obvious types, where we can define the value empty equals the end of the list Notice that we can kind of use these user defined options, we call them constructors–don’t think constructors like C++ or java Empty is end of list, one word is a link of the string apple and the end of the list, right? So that’s a one word list, two words is a link banana and then in parenthesis I create another link of cantaloupe of end of list, right? Kind of sort it should be sort straight forward, be brave, just go for it All right Pop quiz If we’ve given those three things I just typed, what do you think happens with the bottom with one of the first mysteries? So, anyone guess, what is mystery number one? It is a list of A pair It’s one thing, right? So, the first thing this is showing you is that, all right–remember, there is no modification of state in Haskell so when I declare the empty equal to end of list, I can use it just as well anywhere else You might think that’s annoying because like you can’t modify state but it’s actually really nice because things factor really well, like the guy who wrote mystery.1 is like, This is a single element list, I’m certain of it, you know Isn’t a change [INDISTINCT] you think? Mystery two, well, you can compose these things link the string peach and then what? And then some other list, right? Some other item has to be in a list [INDISTINCT] So, mystery two is a two word list, right? Peach apple Mystery three, anyone would guess what mystery three is? Who wants to be brave? >> Pineapples >> LENTCZNER: What? >> Lots pineapple >> LENTCZNER: A lots of pineapples Yes, it’s an infinite list of pineapples Haskell’s perfectly happy with this, completely happy Like you type it in, Haskell’s like, Sure, no problem

It works fine Anyone want guess what mystery four is? >> A tiger >> LENTCZNER: Yes, it’s a tiger, all right Because something that’s others that lists are all right We said it was a list of some type and all these other ones have been a list of string This first link has an integer but the second link has a string and if you looked at the definition you’ll notice that it had the same alpha in both places Yes? >> Okay [INDISTINCT] So, what is like, a context of mystery? >> LENTCZNER: What is the context of mystery? These are type of the top level >> So, I mean, at a point where mystery [INDISTINCT] >> LENTCZNER: Yes >> Okay >> LENTCZNER: Yes So, your names are all on top of the same It’s a mutually reclusive set of definitions Yes, so you can refer to yourself And the reason that this hasn’t go often to infinity at this moment is it’s lazy All right No one’s asked for what happens after the first link of the list so, we haven’t bothered to go look there and the fact that we will eventually go look one step further is fine Okay So, yes, number four isa type error Okay, let’s write some quick functions on list Good, I’m doing great on time All right Here are some examples of how you write functions Notice list back here has two different kinds a datum of type list can have one of two forms, it can be the end of the list that’s one form or it can be a link, that’s the other form So, strangely enough it is common that all our functions on list will have two clauses, yes? >> Going back to the type error >> LENTCZNER: Yes >> Well, [INDISTINCT] >> LENTCZNER: No Not of the type you are used to There are strange, weird, wonderful, odd things which you will be tempted to use in your first weeks of Haskell, you know, that let’s you do this, I really, really need a help, you know, a heterogeneous type And then when you’ve used Haskell for six months, you’re like, I’m so foolish I’ve never needed that heterogeneous type ever So–and this one you’ve got to be brave and like trust that this sounds crazy, that you can’t do this but in fact you really won’t actually need it There are other ways to achieve what you’re trying to achieve which are actually more powerful and more importantly safer Okay So, some functions Because list has two forms, a datum of type list has two forms, almost all functions on it will have two clauses, notice I have two equations for drop one So, we can read this pretty straight forward Drop one takes a list of some type and I don’t know what type it is and returns me a list of the same type If it has the form link first rest [INDISTINCT] pattern match variables they’re just variables for what we’ll be matching in those positions, then it’s just the rest of the list having dropped the first link And what if drop one gets a list of type form end of list, what should I do? Well, I don’t know We’ve decided that dropping one element off an empty list it’s just an empty list That seems like a nice safe thing to do All right, we’ll write end of list And do you want to guess what happens if you leave off that second equation? It is probably like, Dude, you forgot one, your missing out, right? So, one aspect about Haskell is that it’s pretty easy to make sure that you’d caught all the cases, all right >> So, it catches that before you actually [INDISTINCT] use that >> LENTCZNER: It catches it at compile time >> [INDISTINCT] >> LENTCZNER: Yes, at compile time, it’s like, You missed one Like if you really want to miss one, go turn off this warning here but like we really don’t suggest you miss one Why would you–why would you not want to miss one? You don’t want to miss one because–all right If you have all the cases covered, then you’re certain the function always has a well-defined value In fact, this is kind of something subtle, it takes a while to get used to If you have all the cases covered then you’re certain your function never crashes and I mean, never in a much more serious sense than the never that you are used to I mean, it never crashes It can’t Like it has a well-defined value, right? If you covered all the cases and the compiler doesn’t complain, all right, then the only possible problem that the function could have–I mean, it might not implement what you’re trying to do, right? It might have a different function than your computer different result All right The only thing it can really do is go often to, you know, go off diverge, go off an infinite computation That’s the only real error that you could have left It’s just kind of fun Okay Here’s another function called Just One It’s a little weird, it takes a list, it returns a list, if the list is just a link then we return a list of just that the first item, right? And what do we do if there’s nothing in the list? We just want to return, I don’t know it’s got to return something or get that compiler warning which yells at me So, I’ll have it return an empty list Okay It seems kind of weird but there’s a function definition Okay Pull back to reality Actually Haskellers, you know, lists are really common We don’t like to type so much and so, this is from the standard library I want to point out a little bit something amazing here

The syntax of the square brackets is actually built into the language but the type list isn’t This is actually defined in a library file who’s source code on your installation, you can actually go find and look and inspect In fact, you can copy them to your own modules and create your own version Which is kind of astonishing, right? I mean, it’s actually built in the language There’s nothing magical about how this works So, here’s everything I just wrote but it’s written with this new notation; notice end of list is written at this funny empty square, you know, double square brackets and link is written by an infix operator called Colin, right? So, Colin puts an item the A onto–and this is kind of a funny list of A. Don’t worry about it too much The syntax of list looks pretty much like what you’d expect, in fact, it’s so much like what you expect, what I wrote is Haskellers don’t even type that much And I flip back the words real quickly between these two, wait–stop that There you go The only real deference is on these lines, people like to write lists this way because they don’t like to write the silly Colin, look at the Colin, right? The string apple Colin linked on to the empty list They don’t like to write that, they like to write apple, you know, inside the square brackets it’s purely syntactic sugar that’s all And these are all the same functions and so much for that Okay Two more standard things and then we’ll get to some code, more code, okay A string is just a list of characters, really Here it is And then there’s this funny other type, a datum of type maybe It has two clauses too just like a list had two clauses but it’s even simpler than list; maybe is either a datum of type maybes, some type–it’s either nothing or just a single value Seems kind of crazy a little minor thing, right? This is how you use it, like maybe if this function takes–pick message gets maybe an integer, right? It has to have two clauses because there’s two forms, right? So, we pick message, if it’s just an N then I’m going to construct this string Pick a number like N, you know, show us how you turn a value into a string, you know, display it And then pick message if the value was nothing, I’m going to say a different message So, that’s how you use it, just pattern matching just like we did with lists So, we have this awkward function called just one, right? Remember I said like, what if the list is empty, what should I do? Like what should I return? It’s really awkward because I want the first thing on the list but just one gives me the first thing on the list but damn it, it’s inside another freaking list, right? It’s kind of annoying, right? So, you might be tempted to write the bad function at the bottom, in which case, you would be bad because look at it, it says, if the list is, here’s some cool notation stuff We like to–we don’t like to type a lot as Haskellers, right? If a list consist of a value A and the under bar is, whatever, I don’t care It’s a variable that matches but doesn’t–no one uses it Then it’s just A, just the first thing on the list but if it’s the empty list, well, I can’t like what A would I return? I mean, if A is integer, should I return zero? I don’t know, maybe zero is a useful value I mean, what are you going to return? Well it turns out it’s like nothing you can return in this case and so you write error and error is this magical built-in function which, like, kills your program and crushes it with a message Actually, it does if you end up trying to use it but–so you don’t want to use an error, it’s a bad thing So that’s a very bad thing to have happened So this one, like, shuts the compiler up but you end up using an error into your program So, here’s a better way So, let’s use maybe because the answer is this function maybe has an answer, maybe it doesn’t All right? And so, this is a much more clean way to right this all right? The first one on the list is maybe of something We have had just or nothing Okay Keep your eye on the code very carefully Here’s a real function that finds the first character after a star So, given a string maybe it’s going to return the character maybe [INDISTINCT] Notice we’re getting rid of nulls, there’s no, like, no nulls in this language all right? Find after star Well, if I have a list of a character and another character and then the rest of the list then if that character equals the star, let’s return just D because we found it, we have a character after a star else, let’s just recurs find after star We’ll put D in front of the rest of the list and call it on that list Let’s have another clause, if all else fails–under bar, this is a catch hall, catches everything, then nothing, there is nothing after a star Got it? Anyone confused on how that code works? No Yes?

>> So, you have mentioned matching semantics are likely to [INDISTINCT] >> LENTCZNER: Yes So the question is, “Are the pattern matching semantics in order?” And the answer is yes They write–they trust in the order that you write them None of this funny reordering or any of that stuff it’s, like, exact–just read it in order, that’s how they test it Makes it easy >> Well, how about just [INDISTINCT] >> LENTCZNER: So, just is right back here There’s this type called maybe, it’s a data of type might So, maybe it has two forms If you have a datum of maybe an integer, either you have nothing or you have just an integer So, there’s two forms Just like the list had two forms A [INDISTINCT] and a cons or end of list and a link So, there’s two forms So we can return either kind–all right, here we could return two things Now, in this case you might be asking–I’m not sure this question you’re asking is just acting like a function in this case; it’s acting like a constructive or building a value of type maybe So, this function is going to return a datum that has either two forms: just a character or it’s going to be nothing >> I think that [INDISTINCT] that when you define a type and give a list of constructors and >> LENTCZNER: No >> …constructors all have the same name as the type >> LENTCZNER: Yes >> …has [INDISTINCT] and give it new names for each form >> LENTCZNER: Yes Right Every form has to have a unique name, right? And that’s how we distinquish them and tell them apart All right And in essence, you don’t–in other language the constructive constructors, you know, you have–constructors are just different ways of building up, you know, an instance of that class but, you know, then you just have an instance that class then are all the same This is sort of the other way around right? When you build up and instance of maybe by using the nothing constructor, it is different in structure than the version that has just the value It actually has a different internal structure >> So, [INDISTINCT] >> LENTCZNER: No, no This is user define It’s not–it actually it’s in the library, it’s standard but this is just built out of a language >> Okay The point when you [INDISTINCT] >> LENTCZNER: Because you always need a tag–there’s tags in the front that identify Think of it as a discriminated union This is like a union of different struck and you need to have a tag in the front so you can tell which one you’ve got And you use that tag both when you build it and you use that tag when you tear it apart When do we tear it apart? Pick message here is tearing it apart, it is looking at the union and saying, “Huh, is this value of maybe have a just tag on it? Oh, then of course it’s got a value A that follows the just tag.” Right? And the bottom one says, “Oh, does this value of maybe have just a nothing tag on it?” Well, of course it doesn’t have anything else with nothing; all it’s got is nothing Nada Okay So, here’s the version that does string just find after star And let me change it to find after char, I’m going to make it more generic, I’m going to give it a argument It takes another argument, a character of [INDISTINCT] M to match And so all I did is instead of saying C double equals–all right, so I gave an extra argument M, you can see it up here, there it is All right, you can see that it does now compares against M instead of against the fix character star, I changed the tag signature, takes a character and a string and returns maybe a character so it finds after this character I had to add another thing here for nothing but–otherwise, the code is basically the same Oh, and when I recalled recursively, I had a pass M again Okay I’m going to make this once more generic So, this function, I made it a little more generic by checking for any character Let’s make this a template and make it work for any type not just strings Ready? One, two, three, go Anyone noticed the only thing that changed? Okay The name of the function, find after elem instead of find after char The only thing that changed here is the type declaration That’s it Now, I did add this very funny weird piece of cryptic nonsense, be brave, you know, trust me it’s good All it says is that A is a type that knows how to do equality, that’s all that’s saying But instead of going from char to string, remember string is just a list of char to maybe char, I just made this generic Go from some type A and a list of As and maybe A. Notice that the code is the same The actual body of the code is identical Yes? >> So, is the type line necessary? >> LENTCZNER: Boy, you’re like the, you know, like [INDISTINCT] man from the question Yes, so Mark, what is the deal here, like what–like what is the type line? The answer is, when we wrote this, the compiler compile the bottom code and went, “Wow, this is a nice cool generic function It finds any element after any other elements in a given list Oh man, he wrote this restrictive types signature, oh well, whatever fine, I’ll only let him

use it in context of chars and strings.” When I wrote this, the compiler did the same thing It read–looked at the exact same code, came to the same exact conclusion and said, “Ha, his type-line is right That’s exactly right That’s the type of that code This code is–this code will work if and only if A is a type that understands equality.” It figured that out because I used the variable here And it figured out that indeed there better be a list because I used the list constructor here And it figured out that the result better be .maybe because I used Just and Nothing It figured all that automatically That’s all it takes to make your code generic It is really common when writing Haskell to suddenly realize that the thing you just wrote for some particular case is actually complete generic and you just fix the type line and go on >> So you then–when you define string as an array of char, you also >> LENTCZNER: List of char >> Sorry You also manually specify the Maybe and the Just and the Nothing types in terms of that >> LENTCZNER: No, no, no >> [INDISTINCT] >> LENTCZNER: You don’t have to achieve or write that That’s all inferred Maybe was written–so when we were at maybe, right so this is just like, well Okay, so what happened like, there’s Maybe int and Maybe char, but I just wrote this thing called Maybe A. No, that A didn’t mean, oh yeah, when you get around to it, like, type a version with replacing A, that really is a type variable So you write that line, and Maybe is now defined for every type: past, present, and future And it’s already [INDISTINCT] Okay, onward Now, Maybe, actually, is really important Maybe is so important that Maybe is actually the thing that blew my mind This silly little teeny tiny itsy bitsy type, this was like the first thing that, like, [INDISTINCT] my first two weeks back in [INDISTINCT] I was like, “Oh, okay.” This is thing is really useful, okay? These functions–I just wrote there type signatures And you don’t have to really pay too much attention to them because just look at the names, these are all functions you’ve used in libraries all the time “Find the index of an element.” “Look up something on app,” right? “Shoot this prefix from this string,” you know “Get the port out of URI.” Anyone every written that one? Okay, these are all functions which may not have an answer And in almost every language and in every library I have ever seen, gee whiz, we write conventions like, “If the element is not in the list, return -1.” Anyone ever been bitten by that? Ever? Right? That is a sucky design All right, that’s just bad Look how easy it is when you have Maybe, you–because you can declare precisely and so here is the first aha that types in Haskell Types in C and C++, as we know, are for the compiler to make sure it lays it out in memory correctly I mean at least initially Types in Haskell are for you to communicate with other programmers what you mean in a really deep sense In a sense I think that is deeper than others All right, so these are all examples of functions where Maybe is far better than returning Null Did Null mean it wasn’t there? Did Null mean it was an error? I mean what is that Null? Like, I don’t know what that Null means Is the empty string an error? Or did stripping the prefix from the string return me the empty string because it was only the prefix or did–you all see the errors here, right? Okay So let’s look how you use this So it turns out this other fun stuff about Maybe because once you have something of this concept into the language or that you’ve been building language, you can now start building better utilities for using it, all right? So for example, all right Here’s a function called addaweek.day, it comes from a library, right? So we add day 7 to some day object and we get, you know, one week later And imagine I’ve got some list of interesting dates and we’re going to use our first one function which given a list returns Maybe 1, right, because if the list is empty, then you get nothing So I want to find, all right, one week later from that interesting date, I can’t apply addaweek to an interesting date Everyone see why I can’t apply it directly, right? Addaweek takes a day, but interestingdate has a maybe a day, right, because it might be a nothing So how do you do that? Now in most other languages, what we would probably do at this point in our code is we would write an If statement, right? If date equals null then do this, else right Okay, and we would probably propagate that null further up the line, if date equals null, return null Else, add seven to the date, okay? Here, we use fmap What is fmap? Well, you know what map is, right? Map is like a function, like, for example, addaweek And map would apply it to a list of days, adding a week to every single one If map, let’s just take a function of days and apply it to a maybe day