 Hi, and welcome everyone to the session on stumbling overstate by Daniel Steinberg. We're so glad you could join us today Daniel, thank you so much for being here and without any further ado over to you Daniel. Thank you. So, often when we have these concepts that we think we know so well, we forget it what it's like not to know this thing. We get so comfortable with functional programming or monads or whatever. And so I think back to learning a bicycle and what it took to learn it the first time and someone helping us and running along beside us. We forget when we ride a bicycle we think we're just steering straight but we're actually making constant adjustments. And we forget all of these things that we do to make this thing stay up and ride and just do the things natural now we get on a bike and we just go where we want to go. We forget what it's like not to know how to ride a bike. And it turns out, once we can ride a bike, we can pretty much ride any bike. It takes very little for us to learn shift or not shift or handbrakes or coaster brakes or electric or traditional. And so we forget what it's like not to know something and that includes functional programming. And so as we try to explain it to others, we have to put ourselves in their mindset. I remember very well coming to functional programming six, seven years ago. And so many people were very helpful but so many people were very well just figure it out just look at the code and figure it out. So I do want to note that I probably know less about functional programming than than any of you. And these are the thoughts on my journey here and how we can help others follow along with us. So I work in iOS. I teach a lot of iOS like I code a lot of iOS. And so our local gatherings are called Coco heads. And at a recent Coco heads. One of the attendees asked if we can give an example of where we might use generics. And their question was just so general that I was afraid it would be dismissed by the group and yet the group was so kind. And so my answer was the answer that was probably given to me when I something similar and that was in Swift and my examples will be in Swift. So hopefully you can translate into the language you're comfortable in. You can't create an array. You have to create an array of something an array of ints for example. And so we can create an array of ints. And then we can do something without array events we can ask how many inch there are in that collection. And we could create an array of bicycles. However, we do that. And we can also ask our bicycles, how many bikes are there. So whether it was an array of instant array of bicycles we can ask these common questions, but what the array contained. That's what our generic is is describing to us. And so count didn't care what it contained. On the other hand, we have these higher order functions these things like filter would say, you give me an array of ints and I'll tell you which ones stay in and here I'm just going to keep the ones in that are that are multiples of two the even ones. And for bikes, maybe I'll say I just want to keep all bikes in who are less than $300 to buy. And in each case, we've used the type so the collection of ints used a function that took an int. And the, we write it really with the square brackets more commonly, and this collection of bicycles used a function from bicycle. And so we gave her and other cocoa has chimed them and they gave a network example in a parsing example, you know where F was was generic and a and we parsed the data into something of type a and someone demoed code and what was notable to me was the person who demoed code had never spoken to the user group, ever. And they were just so astounded that they could share something with people. And it was just such a great feeling for them. No one said functor, no one said monad, and no one made fun of anybody. We ran beside the person that asked the question, well they learned to ride a bike and we supported them, and then we let go, and we let them ride by themselves. When they fell and we all fall, we rush back over and help them get back on the bike and sent them on their way. And so, I just want to urge you as we go through this material, not to forget what it was like not to know because once we know what a generic is, it just seems natural to us. So as we try to explain to others, that's what I want you to keep in your mind. Now we're remote this year but a number of years ago I was lucky enough to be at funk comp in Bangalore. And at the end of the day, a few of us decided we were going to go to dinner. And dinner was over there. It was across the road and Bangalore traffic. And me being new to this, all I could see was this expansive water with sharks and alligators in it and I had no idea how we were going to cross. But one of our hosts, they saw that if we stepped off the curve and we walked with confidence, we could clearly walk through this. And so having that person to guide you to give you the confidence to take that step, and then to take that step with you. That's the help that I needed to get across the street. For me, I came to programming late my training is as a mathematician. And so I was self taught I wanted to learn some things in Java and then Objective C and then I came to Swift and other languages in between but primarily I was a mathematician I was a differential And one of the things you do to make a living in mathematics is you teach a lot of freshman calculus classes. And so when we teach calculus I remember the first day I walked in this is what was written on the board in the class that I took it I vowed I would never do that to students. It's true. It's the definition of a function. It says for every x there's a unique why such that f of x is why, but that's not helpful. That's the way of getting people to say, I wonder what they're teaching down the hall. A typical calculus class begins with limits. And you talk about limits from the left and limits from the right and the limit from the left equals a limit from the right then the limit exists. We talk about continuity if the limit from the left equals the limit from the right and the equal the value of the function and the functions continuous at that point. And then we use these definitions this definition of derivative and this definition of limits. We use these to calculate derivatives. And the whole time we're doing that. There's someone in the back of the class thinking, this is stupid. I've taken calculus before I know what's coming. And they tell the people around them, don't worry about it there's an easier way. There's a formula for this you don't have to know about limits you don't have to know about continuity. And so, as a teacher I asked what if we start with the easy way. I'm not saying don't teach limits I'm not saying don't teach continuity, just start with the formula, use it to motivate some examples, use these concrete cases to give people context. And then we break out of the context when we need to turns out calculus is built on just a few important ideas. And one is that the graph of a function is a smooth curve near some value of x if that's the case, something like this. That's me drawing a smooth curve. You can see near x not that that red graph the y equals f of x graph is supposed to be a smooth curve, whatever smooth curve means but if that's the case, then it turns out we can approximate the graph of the function your x for the graph of the tangent line. And so, what we're saying is close up that purple line looks something like that red curve, at least really close to x not. And so, near there, since it's so much easier to understand what's going on online than on a curve, we can approximate what's going on the curve by looking at the line. And that was the idea of the derivative the derivative is the slope of this tangent line. So the derivative of effort x not that's the slope of the tangent line, whatever the y intercept happens to be. And that is our first very simple idea in calculus, and we use it for all sorts of things. There's special things that happen when the derivative is zero there's special things that happen when things are increasing or decreasing. But if we have a smooth curve now that word smooth curve means something and there's details that we're kind of leaving out for now that we're going to have to come back to later, because it turns out not all curves are smooth. We can quickly encounter the absolute value of x. And if we look at the absolute value of x we see there's a corner there at the origin. And it turns out then that this smooth curve thing the easy way. It's a good start but it's not enough. When we get to functors and an array will be our way in, but it won't be enough. If you look from the left you can see everything to the left of zero, the slope is negative one, everything to the right of zero the slope is positive one and now we get to that issue where the limit from the left doesn't equal the limit from the right. And so the limit doesn't exist the derivative at x equals zero doesn't exist. All of a sudden we need these more complicated these more formal ideas. So one of the semester in the calculus class one of my favorite things is writing everything they've learned on the blackboard and everything we've learned over an entire semester painstakingly with examples and graphs and formulas can be condensed to just this much. And that's what happens with all of our learning. If you think of what it took for you to understand all these concepts and functional programming, it took quite a while but now that you know it. You see your head and you see these connections, where all you need to know is the chain rule, or the quotient rule, and that's enough to trigger that you can put all these things together. So that's us with functional programming. Now, I mentioned that I use swift there are people in functional programming that roll their eyes at this fortunately, there was a talk yesterday where the talk said what do you need for a functional language. The answer was well ergonomics are better in some languages than other but there's actually very little that you need for a language to be considered functional. And yet I know some people don't consider swift to be necessarily a functional language but you can do functional programming in it. So there are functional practices that we can follow. And there's nothing in the language that forces us to behave. And yet, you're becoming, we're coming to the point where people will say that that's very swifty code that that's more swift like, and one of the things that's driving it is our new UI, Swift UI. So even though Swift doesn't have support for some of the things that you might consider essential like lazy evaluation or partial application or currying. You can do functional programming in Swift. I think of this with the bicycle. Last year, I decided I was very out of shape and I needed to get back on my bicycle and so, instead of driving to places, I should bike there and so I took out my bicycle. And after using it for a couple months I decided to buy an electric bicycle and I felt so guilty, because an electric bicycle. It's not a real bicycle. I'm not really biking it's it's helping me along with the motor. As I pedal it gives me an extra kick, you know functional programming is functional programming. Swift isn't a functional language. And yet what I found when I looked back was in the first four months of last summer. I went 80 miles. And once I had my electric bike, I bike 600 miles. So even though each mile might have been a little easier, it wasn't that factor easier and now I'm more likely to get on the bike to go meet a friend for coffee or go do my grocery shopping, or I'm not in loss. So that extra push got me on the bike, in the same way that using Swift Swift is the language I use. I'm writing apps for the iPhone. And so, even though Swift might not be considered a functional language by some people. It's the language in my pocket. It's like the iPhone is the camera in my pocket. And so, I'm going to do more with functional programming because Swift is the language that I that I use. One of the things driving us in this direction is Swift UI. And so here's how we might create something using Swift UI. It's a little button component. And so I'm going to create a button that has an image on it. So the button will have text and an image. And so if you have a button, a button has two things that you need. Now in Swift UI, a button is a value type. It is immutable. And so we're making this this nod towards doing the right thing, at least from a functional perspective, we're creating these things very inexpensively, and we're not mutating and we're throwing them out. A button needs to do two things. It needs to know what it looks like what is it displaying, and it needs to know what it does when it's tapped. And so I have to input that. So here's the text in the symbol name that I'm entering. And that's what will be displayed. And here's the action that will perform. And this for many in Swift is the magical moment because all of a sudden they realize that a function and a string can both be properties. And this is obvious to people in functional programming, but the people that come from this oh world from a Swift world. This is very new. And so like tangent lines and calculus, we have this very fundamental easy idea. And one of the most easy and important ideas in functional programming is that functions aren't special. Now, we tend to say functions are first class objects but the fact that you can treat a function, the same way you would treat a string or an int, and you can store it in a that's a big step for some people. So let's render our button here's what I want it to look like. And so in Swift UI the way I do that is I conform to view and I implement the body. And so here's my button and my button constructed there's several I'm using the one that takes an action and a label. And the action is a function, and the label is a function. So here is a constructor that accepts as its parameters to functions. And this again is something new. Now we've been talking about map and filter in Swift for years, but a lot of people haven't made that leap to where it's very natural to pass a function in. And so my action in this case I'm passing in as that property name that was passed to me and for the label I'm constructing a label using that text and that symbol name. And in Swift, we tend to use trailing enclosures to make this a little cleaner. And so instead of using that label. We can just use this as a trailing closure. And so this is very typical Swift UI code. So Swift and Swift UI has driven many people that never would have thought of functional programming in the direction of functional programming. There's the immutability there's the first class function. There's a higher order functions and so let's stay with a higher order functions. And let's return to arrays because once we understand higher order functions and Swift UI, maybe we'll reconsider what people have been telling us for years about using them in arrays. So I had this collection here, this array of ints. And I took this collection, and I filtered it. And I filtered it saying you give me an int. And if the int is a multiple of two I return true and I keep it in my collection. And so filter returns a new array with just the even numbers in it. So once I have those, I can further process it. And so I know folks from Haskell work the other direction. But here, I like this because it looks like a bulleted list I take a collection. I filter it, I take the results of that and I map them. So I have even numbers so I might as well take those even numbers and divide them by two. And so I will get back one and two in my final array. And the point is that inside of this closure for the map I have a function that starts with an int and returns an int. And so the map of F takes an array of ints, and returns an array of it's again very natural to us. If we instead have an array of strings, then my map will take a string and do something with strings in this case, I have a function that takes a string and returns the count it returns an int. And the fact that an array of F is taking an array of strings and returning an array of us. And the fact that we can transform and produce a new array. This is new to many people but arrays is our entry point into it. And we're starting with those smooth functions we're starting with the easy cases, like we do in calculus. We can use our closures and in swift instead of doing string and string count, we can use our dollars zero placeholders for the first parameter, or we can use key pass. And we can just say words dot map using slash dot count, and all of a sudden, it's very readable it's very natural we know what we're doing with these things. So we learn map for Ray. And it's as if I give you this question. So on this for you. Here is why equals f of X for X less than X. Not. What happens to the right, how would you continue this graph. Now there are many ways to continue it. I would expect that most of you would do something like this. Because that's the nice smooth graph and, and that's what we're used to. Now we'll return and look at other cases, but this is the array. It says start your understanding with something concrete that you know, start with arrays start with dictionaries start with sets, these all are similar. And so filter and map and reduce and all these higher order functions exist in collections. It's very natural for us. What we're headed is by the end of the talk, we're going to get away from these things that are essentially containers. And that's another huge jump but for now, the huge jump is if I give you this and I tell you to continue the graph. There's nothing that says you couldn't have put an angle in it and continued it this way. Nothing said that the graph had to be smooth and get in our head, we tend to gravitate towards the nice examples. What comes up for us in in swift is optionals or you might think of it as a maybe type in swift and optional is implemented as an enum, it is generic and wrapped. And there are two cases. Either I've got a value in which case it's wrapped inside of the some case, or it's nil, in which case it's formally the none case so we informally talk about this is the nil case. And so that's an optional. So, just as we had an array of strings and we could use map there. I'm going to give you a kind of a dumb example, and we're going to do map for optionals as well. And what's interesting is most people in swift, never reach for an optional map. In fact, many don't know that a map exists for optional so it's hard for them to generalize on this. I have a possible word I have an optional string which we write more like this a string with the question mark. And so that's an optional string. I'll let it be nil just for ease, and I'll use that same function count. And it looks like I'm using the same function map but this is map for optional not map for arrays. And so map for optional takes a nil to a nil. And for a non now it reaches inside transforms the thing using count, and then wraps it back up in an optional. So, count is a function from string to it. So the map of F in this case is a function from an optional string to an optional it. Now, those of us that have been here for a while, we see these connections right away. They aren't easy to make an array doesn't feel anything like an optional. And so, we put this in our list we have an array a dictionary set and now an optional, and we let that sit with people so they can see that working with hand breaks is just a detail. It's different than coaster brakes, but a bicycle is still a bicycle I still essentially ride it the same way. I just have to think of the details a little differently. It's time for me to stop. So here's another question for you. I'm only giving you the value at x, not. And I ask you, create any function y equals f of x, passing through that designated point. This is a big moment. When I asked you to create a type that accepts a map. That's a big moment. So first we learned by looking at map for array and map for optional and now it's time for us to create one. And so we have to see the need. We have to see why that would help us. And so this is a huge step for people. So as an example, I want to look at magic hat. A magic hat contains exactly one item. So it's not like an optional where it can contain something or nothing. A magic hat contains something exactly one item. So it's a struct. It is generic in contents, and it contains contents, which is of that type contents. Now contents could be an int contents could be an array of events contents can be a stringy can be a bike can be anything you want. We're generic in contents. And so I can make one that contains an int. Here's 17 it's a magic hat whose contents are 17. That's a magic hat generic and int. And what's inside of it is the number 17. So what should map do for magic hat. If I have in function from int to something else that the map should go from a magic hat events to a magic hat of that something else, or should we say it, if F is a function from a to B, then the map of F is a function from the magic hat generic and a to the magic hat generic and Now, if we think too much about magic and we think about a magic hat sitting on the stage and a rabbit turns into a scarf or something or a pigeon. Then we forget that actually we're creating a new magic hat. And it will have something of type B in it. So we're not only swapping what's under the magic hat we're actually swapping the magic hats, and that's the immutability. If someone has been motivated this way you can ask them to write map and they can generally figure it out. They've seen map for array for optional and for other types. And so they know that it has to be generic and whatever the target type is. I need that f that transform that takes whatever my type is to that other type. I end up with a magic hat containing that other type, and to implement it, I know that I have to create a magic hat containing be, and all I have to tell you is what are the contents, and the contents are what I get when I apply that transform to the current contents. And again you've done this for years it's very natural to you. It's a big moment when someone can do this for themselves. So, it's, it's like, for those of you that have kids, it's like that moment where you relive the things that you loved as a kid by looking at the joy in your child's eyes when they do something for themselves. When they make their own lunch for themselves when they ride their own bike, when they do something all by themselves, it's a big moment and watching the joy in someone instead of saying well that was easy and obvious. It's, it's wonderful what they've done. Now we can use our new map. I have this magic hat that contains the number 17. So I can take 17 and I can map it using a method that I've created which is, I have a deck of cards. And so a card has a rank in a suit, and a deck is just an array of those things. And I'm just going to count down so many positions and give you the card at that position. And if I have more positions than cards I just get to the end and I start again. And so my card from the fresh deck, I'm getting the magic hat that has 17 in it, and I'm replacing it with the card, which turns out to be the five of diamonds. So what should map do for magic hat. I had card for fresh from fresh deck which took an inch and mapped it to a card. And so the map of the card from fresh deck to become magic hat containing an int and gave me back a magic hat containing a card, still containers. But now you've written your own, you've taken this huge step of creating your own type that has a map, you've written your own bicycle. Now these examples provide context and allow you to learn new things. And so Apple came along a few years ago, and they introduced something called combine and combine was their functional reactive framework. And it looks like they're now phasing it out in favor of an async await and all the friends that go with it, but at the time combined had publishers, excuse me and subscribers, and ways of connecting to them. So these are pipelines from publisher to subscriber, and our maps and our filters in between took one publisher and converted it into another publisher. So this is an example where I write a rock paper scissors application. And when you hit go, you choose rock paper scissors, and you get a response either from the computer or we do a network version. So we get rock paper scissors and then you see your result. So you're choosing rock paper scissors that's a hand position. And so I have a hand class. And inside the hand class, it has the hand position, and that's rock paper scissors. And because that is set, either by you pushing a button, or by the machine, I'm going to publish that result. And so this is a publisher of hand positions. Now, like the result type publishers have a success they have an output type, and they have a failure type and in this case, I'm publishing a hand position and I can never fail. There's never an error. And it's a detail but for this type, you have to have an initial value so initially I'm going to publish a rock. Now what I'd like to do is take that publisher of hand positions that never fails, and somehow transform it into a publisher of strings that never fails, so that I can display it on the screen. I can get the string that represents the image name and I can display it on the screen. And as soon as you see something like that, you can hear the need for a map. And so we're adding to our array, our dictionary or set are optional. The result type we mentioned, the one you created publishers also have a map, and because of your experience using and creating other maps, you're very familiar with this one. And so you say I want to create this image name that is a publisher of strings that never fails. I'm going to start. Now this dollar hand position. That is the publisher of hand positions that never fails. I start with a hand position publisher of hand positions that never fails. It's initially rocks so I throw out the first one. And now I want to convert it to a publisher of strings that never fails, and I can do that using a map. And from my hand position I asked for the image name using this key path. Now it's a technical detail, but the actual type of this is this nasty massive nested generics. And so we use type erasure to clean this up to any publisher. It will get easier and swift, but I've highlighted the main two pieces, the drop first and the erase to any publisher details. The real thing I want you to concentrate on is we had a publisher. Excuse me we had a publisher of hand positions that never failed. And we've converted it to a publisher of strings that never fail. I'm going to duplicate the setup, because I want to look at possibly throwing an error, and I want to do that because we've been looking at map, and I want to look at flat map as well. So I'm doing this for no reason, except to motivate this example. And so instead of picking a hand position, I'm going to pick an integer between one and 100. This divisible by 10 I'll throw an error. So this is completely made up so that I can throw an error. And if I don't throw an error, I will take the integer mod three and assign it to rock paper or scissors. So I have a situation now where an error could be thrown. And I want to show you the first attempt. I start with a publisher of ins that never fails. I start with the first because I had to have an initial value for it. So that's still a publisher of instant never fails. Now, restricted position can throw an error. So instead of map in combine they have us use try map. And this gives me a publisher of hand positions that can throw an error it can throw a divisible by 10 error. And if I throw an error, then combined says, I should catch the air. If I caught an error. I want to come up with some hand position I can give you, but then my types don't match. If my try map was successful. I'm returning a publisher of hand positions. If it's not successful. Right now I'm just returning a hand position. So I have to wrap that random hand position inside a publisher of hand positions, and I do that with something called just. In your language, you may have just or unit or ID. It's a way of taking an element and embedding it in the in the monad. And so, if I have just five and I'm in the world of arrays, then I get an array that contains only the number five. So just random hand position takes my random hand position. It publishes just that random hand position, and then it says, I'm done. I'm not going to publish anything else. So the nice thing is the types match up. I end up with my publisher of what I want, but the first time, a number that's divisible by 10 pops through. The restricted position throws an error. Try map re throws the error. I end up inside of this just, and I'm done. So as soon as I hit my first multiple of 10, I get a random hand position, and then might my process stops I don't get any more hand positions, my game is over. So I'd like to be able to keep going after I hit my first multiple of 10. So let's wrap my try map and my catch inside of something. And so because it dollar and drop first. These are publishers of hand positions that never fail. What comes into my closure is going to be an end streaming in from the top. I want to somehow connect that to my try map. So I take my int my five, and I put it inside of a publisher, and now just it publishes that five that came in, and five falls into try map, and catch, and so on. So, what is that question mark thing that is on the outside of this closure what is the operator that I'm using. Inside the shape of the inside is it's a function that takes an int and returns a publisher of a hand position that never fails. If it was a function from int to hand position, I would use a map. But if I use a map. The problem is, I get a publisher of a publisher, I've double wrapped it. I've taken the inside which gives me back a publisher of hand positions that never fails, and map takes that int and wraps it inside of a publisher, and I get a publisher of a publisher. And as all of you know, this is calling out for instead of that. Going the wrong way, sorry, instead of map a flat map flat map will flatten this out so I go from upstream a publisher of instant never fails to a publisher of hand position that never fails. And what's nice is every time I get a new int. I get something out of this. Just is inside of my flat map. And so the next int that gets published from upstream pops in something will always come out of the inside of my flat map. And so this is, this is where we can handle errors in combine, we keep going after the air is thrown. And so I look at things with map things with flat map include arrays and dictionaries and sets and optionals and results and publishers and maybe something that you create. And so if I look back at introductory calculus I now have map and I have flat map in introductory calculus I have these two operators these higher order functions, and the derivative takes a function returns a function, and the integral takes a function that returns a function. And it turns out the fundamental theorem of calculus relates the two. So once we have map and we have flat map. Another big moment in the lives of people coming to this world is seeing how they connect to each other and I'm just going to use a raised illustrate. Suppose I have a function from string to int. Suppose a function G from string to an array event, but it's a very specific function. I want G to be what I would get if I take F and take a string and produce an int. And then I use just to take that int and embed it into an array of events. So G takes a string and returns an array of int that contains a single int. So what happens if I map F by map F I've lifted that to a function map F from an array of strings to an array of events. And what happens if I map G. I lift that to a function from an array of strings to an array of array of ants and as soon as I see that I think, uh oh, what I really want is to flat map G. So once we have this diagram it motivates our understanding to see that the flat map of G is the same thing as the flat map of doing F, followed by just. And that's just the map of F. In other words, as soon as we have a flat map and adjust, we automatically have a map, and all these things that we were taught were hard and category theory kind of fall out of this so roughly like smooth curves. It's similar about all these types of map. And there's something similar about all these types of flat map, and a type with flat map and just always has a map, and there's some fine print about map and flat map. Now, I give you this curve missing the point x not and I ask you to complete the point. I understand that many people would fill in that dot, but I want to point out that any of those points any of those purple points is a valid answer. And there's many more messy answers than clean answers. So even though we think of graphs as functions as being continuous curves and smooth and well behaved. But they aren't. There's many more bad curves than nice curves. When we think of map and flat map we think of these types we think of containers. And that's because the context we've learned them that. And so, I might have a container of a is, and I want to produce a container of bees, and you know how to do that, you pull something out of the container you map it over and you place it in the container. You've taken your container a and you produce your container be, but what if it's not a container. For example, the reader. The reader doesn't contain anything except a function, and the function goes from something we think of as the environment to a. So this reader monad, which tells us oh it's got map it's got flat map it's got just. And that what it's like not to know something, this is a huge step. And we try to build on what we know from magic hat and do this algorithmically we use our formula. This is what we did for magic hat. So, could we do the same thing for reader. If I had a transform from a to B. How do I get from a reader EA to reader EB. And the answer is I'm going to have to do some sort of a composition that I'm going to have to take this f from e to a, and use the transform to get that a to be, and now I'll get an f from e to be. So my map takes that function from a to be to produce a reader from e to be. By using my transform on f. So if f goes from e to be, then I got my composition. Now let's use reader. So sorry, just a time check it out five minutes to go. Okay. So I use my reader. Let's produce an example with the deck of cards. And so a card has a rank ace through King and a suit. And the deck is an array of cards. And so in this case, I have the 17th card. And so I've got my e and my a and my f to fill in my E is my context as a deck. My a is a card, and my function says, get me the 17th card you give me a deck, and I'll produce the 17th card. Now I won't know the deck to later on. So let's play. I take my 17th card, I use my map to take my card and return a rank. I use my map to take my rank and return a string. Now this thing took a reader deck and card and transformed into a reader of a deck and string, I can try it with different decks. If I use a fresh deck, I get the five of diamonds. If I use face cards I get the king of diamonds. So notice what's different is we passed in this F at the end, we passed in the environment at the end. This is a huge step you're building up this context thing and then adding the specific instance that we're in later. Now what if we wanted the next card. If we want the next card that depends on the deck, and we don't know the deck yet. We just somehow work with the deck that we don't know about, and we don't know which card we're on yet, because that depends on the deck. So here's a helper function for next card. Notice its shape it takes a card and returns a reader of a deck card. Soon as you see that you feel flat map. So somehow I have to return a reader and my function that I produce in reader because that's the only thing reader needs is that function from E to a it's got to go from deck to card. And so my deck to card says, if the card isn't in the deck just return the first card, and if it isn't the deck return the next card. We use it. We take the 17th card, and we flat map it, and that gives us a reader of deck card. And it depends which deck we pass that the environment gets passed in last. It's not a container that contains all the things the head at times. So for the fresh deck we get the six of diamonds, and for the face cards we get the jack of clubs that's the card after the king of diamonds. It's not a reader monad state is similar. It's also not a container. The difference is that instead of it being from E to a, it's from E to a and E again we're modifying it and since we want to think of E is not being the environment but the state we use the letters instead. And so let's deal from our deck and to deal from the deck, we return a tuple the top card and the remaining cards in the deck. So I have my S which is my deck, my a which is my card. And I'll create an instance of state my dealer will be the, the state that I create using this function. This is my function from s to as. My dealer can deal cards like this, I asked you to run, and it returns a card and the rest of the deck. Now this is a pain in the neck, because to get the next card, you have to pass in the deck you just returned the one without the top card on it. And this is kind of exhausted and annoying. Fortunately, we have map and flat map. What it allows me to do is just say, this is an example for dealing cards but I could use it to flip coins. If I get a red card I'll call it heads. If I get a black card I'll call it tails. And now I make my coin flipper from my dealer, and I run it. Now notice, I'm still getting a deck back. And my a is my coin. So map converted the a, but not the s. So that was the map for state. Just quickly to show you the implementation again if I have a function from a to b. And I want to end up with a state I need that run function. The run function says you give me an s, and I give you back an a and an s. Well in this case it's a b and an s, because I'm transforming it. When I run it I get an a and an s, and then I use the transform to get it to be a b and an s. So this is exhausting. I'd like to be able to deal five cards at once, or end cards at once. So if I have my dealer, I'd like to say, give me the first five cards. And it gives me the first five cards. And if I want to keep going, then I take the deck which is what remains after I've dealt the first five cards off of it, and I deal the next five cards. So what is this next, it feels like what we did with handling errors and combined. It's like the next card with reader. I say how many cards I want, and I build up an accumulator and I started with an empty deck of cards. And inside I'm going to flat map because of the shape of this function which says, you give me a. And I'll make sure that I haven't used all the count that I need if I've used all the count that I need, I'll give you my accumulator. Otherwise, I'm going to recur. Otherwise, I'm going to pick another card, add it to my set of cards that I'm going to return to my accumulator, and I decreased by one, I need the flat map because of the shape of the function inside. I'm not going to show you flat map for state of reader. I just want to point out that as we ventured into the world of these monads into these states, we had these hard points we had generics. And that because you're so smart and so experienced but new people who are also smart just not experienced generics functions as first class objects, map concrete examples, these are all new to them, and each step is hard. At the end we can combine it onto the single slide, we saw patterns we created our own functor, we made the leap the flat map, we understood the connection between map and flat map. And we felt we really understood containers and so we took this final leap into reader and state. It's hard. We forget that riding a bicycle is hard. We forget what it's like not to know something. Thank you. It was an amazing, amazing inspiring very inspiring session. Thank you. Thank you. We have a hot take. If you do F from FB right, you get OP for free and vice versa. I think that's dead on. I know people get very religious about that. But I think that if you do what you see mainly from FP people who take on OP people is they take the worst cases and all people who take on it's the same thing but if you're doing either one right, you're factoring into these small reusable testable components. And so I completely agree that at the end we end up the same place in many ways. Right. So we also have a comment from a lady she says really like how it started from the basics of FP to reactive form of FP. And then he says this is a reactive approach with elements and other operators are used to transform the elements. Exactly right. And so in in combine and I assume that's when they were talking in combine the map and the filter are called operators so it's exactly it's exactly the same. Swiss combined comes from reactive streams. So that's the Java library that they derived from. Right. So yeah, they also shared some something here generalizing out of container context is giving me lots of funds to transducer wipes. Now or maybe that's because I spent several sleepless nights on it. And I wish we had transducers and swift I think closure has them and it makes things so much nicer and so I wish we had those there. The cheeky signature for transferring service, whatever input, whatever, go gives whatever input, whatever, and then there's the link that he shared. Right. So, yeah, and yeah, the closures are the poor man's objects after all, that's from other. Thank you all this was a lot of fun. Thank you. Hopefully we'll be there in person again.