In the last lecture, Eric showed you the future [INAUDIBLE], and that means they have a FlatMap operation. And he also showed you that it's quite advantageous to write your code in terms of FlatMap, rather than the pedestrian uncompleted, that you've seen before. But overall, this, it was a bit mystical what this FlatMap is, and how it hangs together, you know complete. So I thought I wanted to fill that in and what I want to do is take a closer look at flatMap, and how it could be implemented in terms of onComplete. Now in actual fact, the actual implementation of flatMap in the Futures library is a little bit involved, it uses execution contexts. Which we have omitted so far, and it has to do some thread scaling. So what we are looking at here something simpler, simplified but a complete implementation of FlatMap. And what's nice about it that implementation is in fact almost automatic, all we need to do is follow the types. So let's get started. So we have our trait future, and we call this in the future self, for future reference. In the future there is the operation flat map. With the type that we have seen here. What can we do with it? We have to produce a future. Well, let's just start by creating a new future. And when we create a new future, what do we have to do next? Well, we have to give it an on complete method. So here's a type of the on complete method. So how would we implement on complete. Well, what can we do when we in the future. The only thing we can do really is to call on complete on ourself. So let's do that. The on complete method here now is an implementation that we set self, that means the current future on complete. And here are the two cases. So we now need to fill in the success case and the failure case. What do we do in case of success? Well if incase of success we get a value x, so what can we do with x? The only thing we actually do here with an x of type T is call f on it. That's really the only thing that's available to us. So that will give us a Future[S]. Good. What we need is the result type of onComplete a unit so how do we go from a future of s to unit. Well we have to use call back. So let's try that. And write f(x).onComplete(callback) so we compute the future f of x called on complete and pass the result. Along to call back. There's really no other thing we could have done given the types we have in hand. Now in the second case when we have a failure with exception E what can we do? Well, the only thing we really can do is pass that failure on to the call back. That completes the implementation of flat map on future. You see how it can be written in terms of onComplete. And furthermore you've seen that essentially once we settled on the types and a general strategy, we didn't really have any choice in each particular step. We just had to follow the types and the code route itself. In fact the actual implementation is somewhat more involved since it also has to handle the thread scheduling. But at least the implementation you see here can serve as a good reference model to really understand what flat map on a future does. And how it can be implemented in terms of on complete.