 Let's talk. Please welcome Vincent, who's going to tell us how to do monad in Python. Thank you. All right. Try again. Cool. So my name is Vincent and I'm going to talk about monad in Python. So I'm a software engineer and I have around four years of experience in Python. And it happens that I'm a big fan of functional programming. So monads have a pretty bad reputation in the world of programming, but have some goals for this talk is to show that at its core, monad is a simple but powerful concept. And that monad can be leveraged in Python. So have some warning to give. This talk will be more practically inclined than theoretically it goes. So let's start with a motivating example. So let's say that we want to time some functions. That is to measure the time of execution of some functions. One way you can do it is to create a function decorator like this which starts the timer before the execution of the function and ends the timer after the execution and then returns the result and the time of execution. So let's have some functions and let's use our new decorator. So one problem I have is how to change this, how to change those functions and get the total time of execution. So one obvious way to do it would be just to call the function sequentially like this and unpack the results, the intermediary results and the times of execution and just sum the times. So there are some things which could be improved. First, we need to repeat the logic of unpacking the value and time at each step of the computation. As programmers, we don't like repeating things. Something else which we need to repeat, we need to repeat the summation. In this case, we need to sum twice. So let's introduce a function that I call bind and which takes, which says as arguments, a topo of some value and the time of execution and a function f. So you can imagine that the time which is stored in the first argument is the time that has been computed and accumulated so far. So the bind function is just going to apply the function on the value which is stored on the left at the zero index of the topo and compute the new time of execution and then return the result and the time we had before and the new time of execution. So with this bind function which abstracts away the things which were repeated before, we can rewrite our example this way and t contains the total time of execution. Okay. One thing which is less nice here is that we are nesting binds and it can be a bit harder to read. So we can keep this same approach and use a more object-oriented approach instead. So instead of using plane tuples, let's define a class time value which just wraps a value and the time of execution. And let's define a bind method which does the same thing as before but just returns a new time value object this way. So we have to update our previous decorator to take this into account, to take the new class into account. And we can arrive to these results, like write this, solve the problem this way. So it's the same as before but we are changing methods instead of nesting functions which can arguably be easier to read. So what did we just do? We just invented a monad, the time value class. But we still don't know what is a monad. So let's try to get a sense of what it is. So monad is a general concept with time value being one instance of it. It can be seen as a design pattern which helps us compose functions with effects. And in this case, effect means measuring your time of execution. So there is a useful analogy which is to say that you have a monad and you have monadic values. So for instance, a plane value is an integer and a monadic value is a plane value plus time of execution. So it can be useful to see a monadic value as a value plus a context. So what is it good for? So make composition of functions easier. So as we've seen, it made the composition of functions with time measurements easier than before. It avoids repeating computational patterns. And it's particularly useful when you have a pipeline of operations like we had before. So how to define a monad? Okay, so normally you have to define what is called the unit function or constructor. So its role is simply to take a plane value and transform it into a monadic value. Define a bind function which encodes the logic of applying your function to a monadic value. So I just mentioned here that theoretically speaking you should make sure that unit and byte comply with some rules, some laws, but I'm not going to cover that here. It's like those rules are quite intuitive. So if we go back to our time value example, so unit here is simply the constructor that we have. And bind is just the bind effect that we've seen before. So let's go ahead with another example. Okay, so let's imagine that we have a code like this which like we have a sequence of computations and at each step of the computation we can have non-values. And in this case we can find ourselves checking for nones very often. So for instance let's say we are coding a social network and we have a user object and we want to get the friends of the first friend of this user. So in this code sample we have to repeat the if-else non-guards which can be a bit cumbersome. So the question is can we abstract this away with a monad? And yes we can with the so-called maybe monad. So maybe monad is one of the most simple and common monads that you can encounter. So what is the idea behind it? So the idea is that you can have two kind of values either full or empty. Empty corresponds to the non-value. Even empty value is encountered during a computation pipeline. Just re-forward it. Don't even try to bind more functions. And this allows us not to check for non at every step. So I'm going to show you the codes and hopefully this will be more clear. So let's try to define a maybe class. So it's simply going to be a wrapper around a value that we store in an attribute. And unit is simply the constructor bind. So if self.value is none, that means that we had at some point encountered some computation which returns the empty value. So we don't need to do anything more. We can just return it. On the other hand, if the maybe monad is full, we can proceed with applying the f function. So we apply it to the self.value attribute. So here there is a small distinction to make depending whether f returns a maybe value or whether it returns a plain value. So if it returns a maybe value, I just returned the maybe value. If it returns a plain value, I wrap it around the unit constructor. So the reason I do this is to be able to ensure that we return maybes and that we will be able to chain more binds in the computation. So a sum note for monad experts. Here I'm just completing bind and map. And we can rewrite our previous example with the bind method this way. So we just take the initial value props and wrap it into the maybe constructor and apply successive binds on it. So what's nice here is that we can chain functions without non-guards because the non-check is done once and for all in the maybe monad code, in the bind function, in the bind method. Is there a way that we can be more concise? And yes, we can by using the dynamics of Python. So very quickly because I think I'm lacking time. Oh, okay, cool. So, okay, the idea is that instead of doing bind of lambda object method, what I really want to do is maybe unit dot method. This could be more compact. So, and a natural idea that we can have here is to use the get at magic method. So, okay, I'm not going to get into the details here, but by defining get at in some way in the maybe class. So there is some distinction to make if the fields which we are trying to access is a function or not, but the idea is the same. We can rewrite our example this way. One thing to note is that this get at thing is independent of the monad we are considering. So we could use it on other monads. Of course, there is the downside that there is some performance penalty by using such a thing, and it can make the code harder to reason about. So now I'm going to talk about the notion of monad comprehension, which is a bit experimental. So what we are going to see here is not production ready. So let's reconsider our time value example. Everything went well because we had a linear pipeline. By that, I mean, at every step of the computation, we only needed the result of the previous step. But it's not always the case. For instance, here we have a pipeline where we depend the final value that we are interested in is the first value that we computed. So in the non-monadic version of the code, it would be trivial to do so like this. But with the monadic version, it would be more involved because you would need to nest binds in order to create a closure where you can keep x0 in the scope. So can we have something friendlier than that? Okay, so what I really want to write is this. So this might be my bending, but my idea is that I would somehow, I would like to modify the meaning of the least comprehension syntax in order to use it not only on lists, but on any kind of monad. So in this case, the time value would be a time value and not a list. And for x0 in first one, it would read as x0 equal first one dot value. Okay, so this intuition, so I'm not going to get into the details, but this intuition comes from the fact that lists are monads and a least comprehension can be rewritten in terms of unit and bind. And so the idea is to generalize the syntax of list comprehensions to comprehension on any monad. So if some people are used to Haskell, this is very similar to the do notation. But where's the catch? Python doesn't allow us to overload the meaning of comprehensions. So the solution I came up with, I mean, I took inspiration from something, so the solution which was found was to use ASC transformations. So a small reminder, when you are executing a Python program, it goes roughly this way. So you have the Python source code, which is scanned and passed into an abstract syntax tree. It's then compiled into a byte code and it's then interpreted. So by ASC transformation, I mean doing something like this, like taking an ASC, transform it into a new ASC, which corresponds to a new code, and then compile it. So with this technique, you can pretty much make Python do whatever you want. So the way I implemented it is with a function decorator, which expects as argument a class which is expected to have a unit and bind method. And given this class decorates a function and transforms the semantics of these comprehensions. So I haven't put the code of the decorator here, but I can show it to people who are interested afterwards. And it's available on GitHub. So it would work this way. The non-linear pipeline that we had before could be rewritten this way. So we need to put the code in some function F and decorate it with the monad comprehension decorator with the time value class. And this way, what looks like a list comprehension will actually be a time value. So let's see another example with the maybe monad. So here we're just summing maybe five and maybe six, and what we get is maybe 11. So every time the maybe is not a list. And for x in maybe five, it reads as x equal maybe five dot value. Still with the maybe monad, but with one of the value, which is in fact the DMC value, we should get the DMC value in the end. And it's indeed what we get. So now this is a solution to the non-linear pipeline program. So conclusion. Take away. So I hope that you are somehow convinced that monad is not that complicated. Simple monads are simple to implement. And again, what I'm saying is not, here is not absolute truth. There is many ways you could implement monads. Monads are not as alien as one may think. For those of you who know twisted, the deferred object is actually a kind of monad. There are some maybe monads equivalent which are found in other mainstream languages, such as Rust, Java. Promises are kind of monads in JavaScript. The leak-query syntax is very close to monad comprehension in C-sharp. So here are some references from which I took heavy inspiration. You can find the code on GitHub. And thank you. And we have five minutes for questions. If you are leaving the room, please do it quietly so people can see, listen to the questions. Thank you. Excuse me. No, it's me who called him like that. It's just a problem that you have. Monads are the same as C-sharp. Vincent.