Functional programming design patterns by Scott Wlaschin

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

This is Functional Programming 101, the very basics. It's not "design patterns".

Here are a few good talks on functional design patterns.

And more generally, on programming language theory:

πŸ‘οΈŽ︎ 37 πŸ‘€οΈŽ︎ u/PM_ME_UR_OBSIDIAN πŸ“…οΈŽ︎ Apr 23 2016 πŸ—«︎ replies

Good talk, nice pedagogic ideas and metaphors :)

πŸ‘οΈŽ︎ 10 πŸ‘€οΈŽ︎ u/Asgeir πŸ“…οΈŽ︎ Apr 23 2016 πŸ—«︎ replies

I wish I could find videos of people actually writing complex functional programming code. These talks seem to just reiterate the same things and all example code is too simple for me to be able to visualize using it in our code base to the extreme that they are talking about

πŸ‘οΈŽ︎ 6 πŸ‘€οΈŽ︎ u/battleguard πŸ“…οΈŽ︎ Apr 24 2016 πŸ—«︎ replies

Jesus fuck, that one literally LOLing as loud as he can is really off putting.

πŸ‘οΈŽ︎ 5 πŸ‘€οΈŽ︎ u/SikhGamer πŸ“…οΈŽ︎ Apr 23 2016 πŸ—«︎ replies

This is totally amazing! I guess it is the best resource from someone that comes from an OO background.

He says that there is no equivalent of OO patterns/principles for functional programming. But there are some things, such as the Single Responsibility Principle, that are sort of universal.

πŸ‘οΈŽ︎ 1 πŸ‘€οΈŽ︎ u/fagnerbrack πŸ“…οΈŽ︎ Apr 24 2016 πŸ—«︎ replies

The problem with this type of talk is that it's not useful for anyone.

If you already know functional programming then you already know this and at best it's a reminder.

If you do NOT know functional programming then it does NOT teach you anything because it's too fast and too light.

πŸ‘οΈŽ︎ 1 πŸ‘€οΈŽ︎ u/imright_anduknowit πŸ“…οΈŽ︎ Apr 23 2016 πŸ—«︎ replies
Captions
with can everyone hear me at the back there very good okay so I'm going to this wouldn't be very fast and a very long talk you know you're supposed to only say three things in a presentation I'm going to say about 200 things so I apologize this is super fast and super quick so functional design patterns is basically a brain dump of everything I can think of they can squeeze into the city minutes so my name is gov lotion I have a website F sharp of fun and profit calm and F sharp works as a group of people who do F sharp consulting so if you want their shop insulting come and ask us this was my thing here yo of course my thing is there we go so I was spitting a heading to use the word patterns because obviously there's a lot of overloaded connotations with patents so I thought about using practices or approaches or tips or something but you know what my project my thing is not working I'm going to luckily stick with patents so these are not going of for patterns these are just patterns when you do something over and over and you give it a name it's just kind of replication so before I get started I'm just going to give you a little bit about my background because a lot of people think that functional programmers are very anti Oh and they're very academic and they don't really understand that well and they just hate on oh well for no reason so I'm going to give you my background so as you can tell I've been around a long time this is a childhood photo that's me over in the corner that was a vacation that ended badly so you know like most people I I did the usual things i boring languages like icon and modular 2 and prologue and stuff but ventually I discovered small talk which I totally loved and I still loved to this very day I think it's an awesome language and I think you should all learn small talk if you don't already so I did snort up for quite a while and so I was you know very serious small talk guy and even though I love small talk even the small talk people hated enterprise though right so because that wasn't real our willow a small talk so it's very easy to make fun of enterprise o so even though the functional programmer guys make fun of enterprise o the small talk guys also did and so you know it's like shooting fish in a barrel or shooting green vertebrates in the abstract barrel proxy factory so it's easy to say easy for you to say ok so and then I discovered functional programming a few years ago and I love functional programming too and you know started off kind of innocence and then it got kind of serious and I started doing quite a lot of it and I set up a blog and so on and then one day this guy came and grabbed me he assimilated me and that's what happens when you double too much in front where you get assimilated into the functional programming community and they took me to this ivory tower they didn't take me to the top floor the top floor is reserved for high school programmers I'm an F sharp guy so they put me a bit further down with the old camera guys the Visual Basic people have done in the basement and of course the list people are like on another planet all together so I've escaped from the ivory tower and I've come to tell you the design patterns that I know about so when you're learning a new paradigm you typically want to transfer the knowledge you have from the old paradigm to the new one so you know we're all familiar with these our patterns yada-yada-yada seen them thousands of times before so how do they translate into a functional model so what we were told in the ivory tower is we just answer every question with functions right so single pawns really functional as functions open closed principle is function this dependency inversion principle also functions interface locations functions you know functions so I guess the point of this slide really is that functional patterns are not the same as over patents they're different okay so there's no point trying to transfer oil patents to function of patents I'll give you a couple examples but you really need to change the way you think about programming to be a good functional program so the kind of functional patterns that you're polyol familiar with you know a perm or fizzles and as I go historical people are prisons yeah no I'm not going to talk about those things that's too serious what I'm really going to talk about is core principles of functional design which is functions types composition functions as parameters which is a really sort of the main thing about functions using them in a different way than you might do in object-oriented world functions it's interfaces and as the sort of way of doing abstraction partial application dependency injection continuations and the pyramid of Doom monads especially for error handling and async and things like that and then mapped a little bit on maps and finally mono aids which is a very mathematical sounding word but it actually turns out to be very useful for aggregating data and operations so this talk like I said it's going to be a super quick talk it's like one of those bus tours you go to a city and you try and see all the tourist attractions in five minutes and you don't really get a chance to stop and look at it properly that's what this store is going to be like so might be a little bit frustration if you want to know more about things but at least you've been introduced to the terms hopefully and you can go and find out more about them cuz there's no way you can understand all this stuff in 60 minutes even in a day so don't worry if you don't understand anything it's really just a whistle-stop tour of all the features and maybe to demystify it a little bit so there's a lot of core principles of function program about here's some of my favorites or rather the ones I can fit into 60 minutes so I think it's very important to understand the core principles because again you try to bring in your existing paradigms if you're an oo programmer and it's kind of frustrating you keep saying how do I do this how do I do this if you understand the core principles it actually makes life a lot easier because you will not even attempt to do certain things and you'll do things in a different way if you really understand what's going on so the core principles of functional programming or a couple of them are functions of things right they're not just methods on a class I like to use the well away analogy a lot so I'd like to think of functions as a little bit of railway track and there's a input and output composition everywhere and composition I mean like Lego you take two bits of Lego and you glue them together you get another bigger piece of Lego and you can glue more to that and you get another big piece that's composition and types are not classes so we think of types and classes in our ways basically the same thing they're more like set theory okay it's a different way of thinking about types it actually turns out to be quite powerful so let's start with the functions as things it's a function it's a standalone thing it's not attached to a class not attached to an object there's a little kind of tunnel on this piece of railway track and something goes into the tunnel and it comes out changed it gets transformed so in this particular case I have an Apple turning into a banana and to demonstrate the functions are things this is some F sharp code here so I have a assignment to a number Z equals 1 so I put little one in a box and I give it a name Zed now if I define a function in F sharp I define it a bit of railway track and I go ahead a name add what's interesting is in F sharp and in most language the way you define a function and the way define a value are the same and that's not a coincidence because functions are just things like numbers like strings that you can pass around so that even the way the language syntax works tells you something about how it thinks about functions so functions can be used as inputs and outputs and parameters so let me just give you a really quick example of these things here's a you know I'm not expecting to understand the code or read the code just can look at the pretty pictures so here's a function takes an integer and outputs a new function okay this is generating some function that generates functions as output this function takes a function as input and returns an integer and then this other function here takes an integer in switzer ninja out and it takes another integer it takes another function as a parameter so there's parameterizing what it does using a function as a parameter so this is a function that takes functions this is really common it may make your head spin initially if you're not used to flip to the program but once you get your head around it it actually makes a lot of senses so the next principle composition everywhere so what I mean by function composition here's a thing which takes an apple to banana here's something that turns a banana into cherry how can i glue them together I just glue them together like two bits of railway track right and what I have now is I have a new function that turns apples into cherries now what's cool about this new function is I don't know how it was built I just encapsulated how as-built is just a function I don't really care how it works inside so that's how you kind of get abstraction already I don't care about how functions work I can build new functions some smaller functions so that's a very cool feature about composition and that leads to the first sort of design paradigm which is functions all the way down sometimes people say functions in the small objects in the large I would say functions in the small and functions in the rich you can use functions everywhere and I'll give you an example so you start off with a low-level operation like you know upper casing a string so it has an input and an output and then you take these low-level operations and combine them into servus say an address validation service and it has an input and output and notice that this inputs and outputs it's not requests and responses so it's not a request response model it's an input-output model sounds very similar but it's actually subtly different when you when you get into composition and by the way for people you don't know what the service is everyone knows what a micro service is right so micro service asserts just like a micro service but without the microwave in front so yeah old-school all right so you take a bunch of services and you build them up into a use case and a use case is normally event-driven some request comes in and you do something with it and some response comes out and then you take a bunch of use cases and you compose them in terms for example a web application in this case the input is a HTTP request the output is an HTTP response and inside there you've got all these different use cases and there's some sort of controller dispatcher something that figures out which use case to run based on the input so the same model of composing smaller functions to the big ones works at the low level it also works all the way up to an application at some point you might you know when you have systems you have to start using message queues or something to do a sequence that's when you start getting rid of the functions but then that's where we active functional comes in so composition is sort of fractal fractal maybe not the accurate word self-similar might be a better word but fractals sounds cooler so I'm going to say that composition is fractal it's the same small level as the high level both all right types are not classes so what do I mean by that so here's a class diagram but these are not types these are classes so don't think about eyes when you think about functional programming so what is a type okay so it's quite a lot of debate about what a type is you know from a kind of academic point of view but I'm going to use this analogy that you have a function H as a bunch of inputs and a bunch of outputs a type is just the name given to the set of inputs or the set of outputs for that for function okay all right it's just a label you have a set of things which are valid inputs that's a type that's all it is so if example int is a type okay I could have a set of integers any of those integers of valid input that's a type it doesn't have to be primitive it could be things like a customer so you have a customer object in your domain and that's an input to some sort of function so the entire universe of customers are valid inputs and you can even have functions as inputs right so or outfits it's just a set of all the int functions that's the type as well and we'll be seeing integer function types in a minute so that's what types are it's just a set it's just the name given to a set of values so one of the things about these kinds of functional types is they don't have any behavior so let's say we have a function that map's lists or lists the list is just the data right if I want to do something with it I need another function so I have functions that transform lists are the lists or transform lists as integers or strings whatever those are completely different from the lists themselves the lists have no behavior so the behavior and the data are completely separate the thing about tags is because they don't have any behavior associated with just data they can be composed just like functions so most functional languages have an algebraic type system which is not an oo type system so now Drake type system you start with privileges and you create new types by gluing them together just like you compose functions and there's two basically two two basic ways you can glue them together you can glue them together by multiplying them which sounds kind of strange but here for example have a set of people this and I combined them together and I get a birthday okay so that's called a product type and the alternative way of doing them is to add them together so if I have a cash method or a check method and the credit card method I combined them together as a choice that's a payment method so that's called a choice type or a union type or a sum type so let's talk about how types fit into a quite important principle which is totality so totality is something that functional programmers strive for a lot so totality just means a function for every input for a function there's a valid out alright sounds simple enough so let's look an example so here's a very simple example 12 divided by sort of kind of tall we example 12 divided by 3 is 4 12 divided by 2 is 6 12 divided by 1 is 12 12 divided by 0 is what okay there is no answer this is an undetermined and undefined results this is not a total function as it stands so you might say let me throw an invalid argument exception that might be the low way of doing it actually it's not the other way of doing it it's the C sharp and Java way of doing it I'm going to throw an exception here but you know what happens is I look at the type and this this function says it takes an integer and it spits out an integer and that type signature is a lie okay it's telling me that it will spit out an Internet is wrong because it doesn't always fit on it sometimes it throws an exception so I don't like type signatures that lie to me okay and the thing is if you you're telling me you can handle a zero you tell me you can handle any integer and then if I give you a certain in did you say sorry I can't have this what's up with that you know can't you even write better code that's a really stupid way of writing code so what's the alternative well the first alternative it doesn't do that okay please don't throw exceptions your first alternate is to constrain the input so I'm going to say I'm going to define a new type called nonzero integer and zero is not in that set all right Sierra's missing now sue is missing I don't have to handle it so that's really nice so I don't have any problems this is a total function every input has a good output and if I look at the type signature so as it takes a nonzero integer and gives me an int and that is a true type signature that's not lying to me any access documentation it tells me that you better not pass in a zero in fact a compile a static type language will not let you pass zero into that function so you get compiler if you're trying to find zero in just kind of nice now the other way of doing it is to extend the output so you say okay you can give me a zero and I'm just going to turn nothing I don't know what the answer but then in the only other cases I have to change them to be something so in cases where I dunno what the answers I returned some for some six some 12 so now what we do is you have an option of int all right so sometimes it's something and sometimes there's nothing in this case now zero is a valid input but the output is now optional again if I look at the type signature it says you give me any int I might give you an in back maybe if you're lucky maybe not but again the type signature is telling me the truth and it's acting as documentation for what the type is doing it's not going to lie and pretend that it's always going to give me an integer back so total functions are really nice and this is something that function of programs do strive for and the type system is your friend here because you can define these types like optional int and nonzero int and all kind of things you end up defining all these types to help you define what your functions do so that leads to the next design principle which is to use static types for domain modeling and documentation not just for type checking you can actually use state types to embed business rules in which is hard to believe but it's actually possible to create a situation where things which illegal in the real world are not compiled herbal in your code so the types act as a sort of parm unit test now unfortunately that only works for static type language so sorry closure people and JavaScript people and also I don't have enough time to talk about it I actually have a whole hour long talk on that one topic if you go to my website you'll see a video and slides for that so that's enough of types next functions as parameters prioritize all the things it's the rallying cry of functional programmers let me give you a little example so here we have a something that prints a list of integers and you know typically as a program look at that and say you know what you've hard-coded that number 10 in there that's kind of yucky let's parameterize this and pass in a list so it's sort of second nature to prioritize the data structures we don't like seeing hard-coded constants in our code right there's just second nature to get rid of them and replace them with franchise things but if you have function the program you say oh yeah you've hard-coded the behavior in there too let's franchise that as well so a functional program would immediately create a parameter which is a parameter to do the thing for each item so now what I do is have two parameters one which is the list and one it is the action that I'm going to do in each element and what I've done here is I've completely decoupled the three things I've got I don't care what kind of list it is I don't care what kind of action it is it could be a list of hints it could be a list of strings it could be an action that works on strings or anything so it's infinitely more generic already and we've decoupled the list iteration code from what I do inside the list so this is actually more generic I mean this will often replace you know thousands of methods in an object-oriented thing can be placed as one method in a functional language obviously it's nice if the language can help you by making it easy to parameterize you know if you have to go to the law able to make function parameters it's really painful and you don't do it but if it's really easy like this I can do it in two lines of code so let's look at a real example this is a little bit of a c-sharp kind of snippet obviously c-sharp has linked when I show these examples people c-sharp people say well yeah I can do this with linked in one line Islay yes you can it's called functional programming but I'm going to use traditional I'm going to use traditional style fall it let's pretend this is C or something okay so you have a loop and you say okay this duplicate code here don't repeat yourself we know that this is bad how can we get rid of this duplicate code well what we do is we look at what's in common between the two functions and what's distinct between the two what's unique about the two functions so what's in common is this loop what's distinct is that in one of them you set it to the initial value as one in the other on the initial value of zero and then also the action that you take each time through the loop is different in both cases so we need to preserve the distinctions and get rid of the common boilerplate code and in F sharp that's called list fold and that does the looping for you and all you have to do is pass in the initial value and the action that you want to take and what's nice about this is is you it focuses it helps you focus much more on what you're actually trying to do with your code focusing why is a product different from the Sun the two lines really help you understand the difference you're not bogged down with all this loop code so actually link has the thing linked aggregate is the same thing in c-sharp it's not often used and it's quite complicated understand there's the common code there's the initial value and there's the parameterised action and of course any decent collection Lobby will have thousands of these kinds of things as fold as a map for those reducers collect this select and pick and choose and you know it's worth taking the time to understand the library that your language has because there's probably lot of powerful stuff you can reduce a lot of your code probably down to one or two lines using these collection classes collection functions all right function types are interfaces so what does like what I mean by that I mean that the function types provide the abstraction layer so in in object window program you can use interfaces to force you to program to the interface don't program to the implementation in a functional program you program to the function type right not to the implementation so let's see how that works so here's an interface and oo style interface called a bunch of stuff it's got three different methods in it if we take the single responsibility principle which says you know only one reason to change the interface segregation principle you know don't contaminate interfaces with too many things if you take that to the extreme what do you get you get a rule that every interface should only have one method if it only has one method it's only got one guarantee is only got one reason to change and I guarantee you're not contaminating your interfaces with other interfaces so if you have that as a rule and you get rid of those two methods now your interfaces look like this so all your interface itself exactly one method in it now what's interesting about that is an interface with one method is basically a function type okay so do something takes an integer spits out an integer that's exactly I could have rewritten this in F sharp as a type called bunch of stuff it takes an intimate turns in it so any function which has a which takes an int is compatible with this interface so it add two is compatible and times three they're both compatible and I didn't have to say they inherit on this interface right there automatically compatible by the very fact that they take an intimate turn in it so the strategy pattern in oh oh you have to pass in you know a strategy object in the constructor or something then you have to do it you know assign it to a local field and then use it and so on so forth in functional model you just pass in a function so the strategy is it's just a function that you call so try and do it in pictures see if that helps there's my strategy in pink that's my strategy pattern and I pass it into my my main function as a sort of slot there for it and the nice thing about the functional model again you don't have to predefined any interfaces at all I didn't really have to define an eye bunch of stuff type in F sharp because intent is a sort of built-in type I don't need to define it anything that's in worse so it's very good for doing things after the fact I can say I have something that takes a customer to a customer name or something it's like oh yeah actually I want to use another function that has exactly the same interface and I can just plug it in I don't have to pre-act it proactively define all these interfaces all the time let's have a quick look at the decorator pattern so here's an even function and what I want to do is I want to decorate it with a logger function so again it's got the same input the same output but it's going to like print the input and it's going to print the output then it's going to call the actual internal function okay so it's a decorated version of is even and again because it's an instable function is it can substitute anywhere that I had the original function that's not a form but you know what in practice a functional programmer probably wouldn't write it like that it's a little bit clunky a functional programmer probably use function composition like this so I've got my is even function I stick something in front of it I stick something behind it I compose them together and now I have a new function that has the same thing it takes an int and spits out a bill this new function is also a decorated version of is even and again I can substitute it anywhere that I had the original function alright so there's a problem with all these patterns that we've seen so far which is unfortunately they only work with functions that have one perimeter so you know because I have to have this connecting inputs and Albus so that's a shame the good news is that every function is a one parameter function so all these patterns actually work for every single function which is kind of nice so in functional program you don't really have two parameter functions and three parameter functions in one plane every function is a one parameter function let me give you an example so here's ad that you might define it in a normal way it's got two parameters but you can also define ad in another way which is an ad it's just a value it's just a thing that returns a lambda all right so the ad itself now has no parameters but it returns a little bit of railway track that has exactly the same behavior as the function that has two parameters so this ad defined as a 0 parameter function in a sense and of course if you can do a 2 parameter 1 and a 1 parameter 0 parameter 1 why can't you do a 1 parameter 1 and in this case I take one parameter and I return the lambda that has that first primitive baked-in so it's a function that takes a parameter spits out a new function that has that parameter baked into it and then I get another function so it's a function that generates functions so in a true functional language every function every multi argument function is actually a function that generates other functions all the way down until you've passed the law pass the log last argument in so here's a concrete example here's 3 equals 1 plus 2 that's pretty obvious in F sharp you can actually take that plus and move it front and it becomes a little function like that so it's a two parameter function but then what I'm going to do is I'm going to take the plus one I'm going to pull it out I'm going to copy and paste it and give it a name I'm going to add one and at this point you say yeah but now it's missing a parameter and I reply to you that it's actually not missing a parameter that ad is a one parameter function ok you might think that addition is a two parameter function but no it's a one parameter function you can try this at home and see for yourself so once I have my add one I can then pass the two to it and I can get my three as I did the first time so this is true for any any fun can be broken down this way into one parameter functions and you can always pass in an argument and bake in the argument so that leads to a really powerful technique called partial application probably one of the most important hand in functional languages so let me give you another example here's a printing my name and I have a function here print has two parameters the first parameter is a format string and the second parameter is my name and what I'm going to do is I'm going to put the parentheses around the first two bits this is one of the reasons why function languages tend not to have parentheses they use spaces between the parameters and the reason is you do exactly this thing you can put parentheses around the front bit okay you can't do that in c-sharp or Java so you can actually take those front bits and turn it into a one-parameter function which I'm going to call hello so hello is now one parameter function that's just missing the name part and then I can call it with my name in the usual way but it's a one parameter function and now I can actually use this hello function I defined all over the place so originally I had a kind of hard coded version that only worked in my context but by partially applying something I've now got a kind of reusable function that I can pass around and other people in use as well so that you know it's very common for example when you're using lists the use partial application so there's my partially applied hello function and there's a list of names and for each name in the list I'm going to iterate over it and call this hello function so the missing parameter that hello needed is going to be supplied each time I loop through the list here's another example I'm going to partially apply one to get add one function and I'm going to partially apply two to get an equals two function okay so both of these add one the add one and the equals to a missing a parameter but when I apply them to a list then the extra parameter is provided by the list iteration routine so one to 100 list map add one that adds one to each element in the list filter equals two it filters on that quality function so you can see this it's really nice to build up little kind of utilities little helper functions just one-liners and then your code looks quite nice second if this code is very reasonable you know add one to everything in the list and then filter it we're equals two very very readable so the dot is kind of self-documenting code so a partial application for dependency injection this is a really important one people say how do you do dependency injection because I know how to do that in our and I need to do it in function I don't understand how to do in functions so let me show you let's say you have a repository and this is the repository interface where you give it a customer ID again it loads a customer from the database now this is not really a repository interface because it's just a type and in fact I don't even need to define this and everything would still work but this is the equivalent of having a get customer repository for example so it's there's nothing in this type that says it comes from a database right it's ignorant of the persistence mechanism so let's say I have a wheeeeel function that gets a customer from database now this particular real function needs a connection okay it's a sequel database I pass a connection and I also pass it a customer ID and then it does a select on that customer ID so unfortunately that cost that function requires a connection which means that that function as it stands does not meet that interface right there's a problem I can't use this get customer from database function where I want to however if I take the connection and I partially apply it I get a new function which I'm going to call get customer one and now if I look at what get customer one is get customer one now has the type of give me an ID and I'll give you back customer so this new customer this new customer get customer one does conform to the interface it conforms to the type that I need so that's really nice so now I have AB strata doubt the fact this is a database function I can take this function I can pass it anybody who needs a repository so let me show you another example which isn't a database one so here's the type let's say it's an in-memory database so instead of having a physical database we're gonna have a dictionary and again I have a particular method that works with a dictionary but the dictionary is now the first parameter and I want to get rid of that dictionary so what I do is I partially apply it and I get a new function get customer two and get customer to the dictionaries already baked in and all it needs now is the missing element missing parameter is now just the customer ID and again it conforms to the type that I need the interface that I need and so the get customer one is a database fashion get customer two is an in-memory function they both have exactly the same type they both kind of conform to the same interface I can pass them around they complete it interchangeable that's how you do dependency injection so the Hollywood principle don't call us we'll call you otherwise known as continuations in the functional world so let's look at this divided function obviously if it's zero it's going to throw an exception right so the problem is that I don't want it to throw an exception okay the problem is the method has decided to throw an exception without asking me all right who put the method in charge the university knows like I don't want you to throw an exception but you're going to throw an exception anyway I want to be in charge right so the way to make me in charge is for me to pass in functions that do what I want on each case so if it's zero I'm going to call this zero function and if it's a success I'm going to call the success function and that way I have complete control over what this object is not throwing an exception that I immediately have to catch again you might be they want to know I might be doing this all the time after like it's going to throw an exception I have to catch it it's going to throw when it's close like if I do this it's never going to throw an exception I don't have to catch it it's great I know exactly what it's going to do so the continuation is just a fancy word for what happens next I'm passing in a function that tells the called function what to do next the very last thing you need to do there's the F sharp equivalent again as for parameters and the there's zero and success so for parameters is a lot right I mean that's you're pushing it and it'd be really annoying if I have to pass them it's nice and flexible right you can see it's good but I would only be passing four parameters every time I call the divide that's just ridiculous right so it'd be really nice if there was some way of kind of baking in the two parameters that do the behavior all right and then I would just have a normal divide function after that so that's exactly why we're the partial application comes in because I've already shown you how to do that so if we take this function f sharp what I can do is define two behaviors if it's bad and you know if it's do I'm going to print bad if it's not zero I'm going to print good all right that's one sort of behavior and then I'm going to partially apply just those two parameters leaving the other two parameters alone and now I have a divide function which has two parameters it's a two parameter divide fashion it looks just like the original divide function so I can use everywhere that I was using divide except I can completely control what happens let's say I don't want to print something let's say I want to say you know if it's zero do nothing return none and if it's successful turn some so there's how I do that I bake those in and then I get again I get a divide function that was like normal for anybody else and let's say once a we produce the original behavior so I want to throw an exception if it's zero and if it's successful I just leave it alone so there's my setup again I bake the parameters in with partial application and again I've got a new divide function that looks just like any other divide function so this kind of passing in continuations is a really really powerful technique gives you complete control and if you have a nice function library it will allow you to do that all right it'll tend not to hard-code things like you I'm going to throw in exceptions like no you tell me what to do when something bad happens and then you know you have control over what happens so one one way you see continuation is used a lot in the sense is when you're doing callbacks so I'll give you an example here this is you know a null testing example you know if it's not null do something if it's not now then do something else it was still not null do a third thing these kind of nested null checks are very annoying and people call this the period of doom because it can end up with a super deep nested code you couldn't you can do early returns in some in F sharp you actually can't do in early time but even if you could just bear with me for a second because it's not always applicable because you can't do early returns for this kind of thing like tasks finishing so this is the same kind of thing when this task is finished call this other thing and when that one's finished call this other thing when that one's finished call this other thing again you get this nest of callbacks you get this level of indentation creeping up and you get the Pyramid of doom so you see that in all languages where there's some kind of callback mechanism especially for async or promises or those kind of thing you end up getting this a lot so it's really ugly so let's see what we can do about it so we look at this code and we look at it interesting you know what null nulls are really bad code smell we're going to replace null with option okay that's much better there you go that much nicer code now of course it's still really ugly code it's a terrible way of doing things so turning option doesn't love anything what we need to do is look at this pattern there's a pattern here we can exploit and we can use that pattern to make our code simpler so this is the pattern if it's something do something otherwise skip it if it's something do something otherwise skip it if it's something do something otherwise skip it right that's the pattern so let me zoom in on that little piece and if you look at that it's like that's just calling out to be prioritised right prioritize all the things so I'm going to write a little helper function called if something do and if it's if the you know the value is valid then I'm going to call the function and if the value is not valid for some reason I'm not going to call the function so that's parameterizing all the things and there's my little function that I'm going to be passing in and that's a continuation right there that means keep going if the value is valid otherwise barson so with that developer function I can we might my code like this if something do something and if it's still something do the next thing and if it's still something do the next thing so the code is much much nicer when you use this kind of continuation based design much cleaner and that takes us on to monads so monad is one of those really scary words that you hear a lot of in functional programming for the purposes of this talk I'm just going to say that monads is really just chaining continuations together so it's not really what a monad is it's a bit more complicated in there but for the you know I'm not going to get into too much but you can think of it's just chaining continuations so let's look at how we just did what we did for kind of another point of view so I liked analogy I like is points in a railway track we've been talking about little functions as well we track so this is a function which is that it has one thing coming in but two things coming out so it's either points or in if you Americanists switch so in this case input and then if it works on the green track and if it doesn't work on the on the red track the problem is we have a lot of these functions where each one comes something comes in and it might or might not work so the way we connect them is if the if the first thing works we connect it to the second thing and if the first thing doesn't work we just bypass the whole thing right I think that makes sense it's obvious how you connect them together and when you have a bunch of them like this you end up with something like that okay so you just convert to oops yeah there's little things into that I think that's pretty obvious that's how you would do it if you got a toy train set so here's the problem if you have one track functions with one input and one output they're really easy to glue together and if I have to track functions with two inputs and two outputs they're also easy to glue together I just connect them track up but what we've got here is we've got one track input and to track output okay that cannot be connected together so what we need is a way to combine these mismatched functions okay so if you talk to a functional programmer and you say how do you do this they say bind bind as the answer bind all the things it's like it's like a secret handshake if you go up some and say bind they'll say yeah that's nudge wink wink you know ffp people get excited by Bynes you can read into that what you will right so bind is the answer to everything and what does bind mean so here's our function that doesn't work if we can turn it into to track function it does work so bind is just a kind of an adapter block okay I want to I don't have it I have a function which doesn't fit and I want to turn it or something does fit this like a little kind of thing that fits on top of something I slot my points on my switch in and it turns into a to drop function so that's all the bind is okay if it's a successful input it calls the continuation and if it's unsuccessful input it just keeps going so that's all the bind is not mysterious thing is just a way of gluing these switches or points together so let's look at bind for changing options together so we saw this before his option bind so if it's something you call the function otherwise you see nothing so here's the pyramid of Doom version and then this is the same version after using bind much nicer know pyramids linear code and monadic bind that's the buzzword you can just say to someone I understand the netic bind and you'll get into the you know the secret society tasks the same kind of thing so a task you know you wait for something and if it completes then you call the next thing and if it doesn't complete or something goes wrong you bypass it and so you can chain tasks together the same way so we can create a task bind in this case it's like when finished call this continuation promises futures or variants the same thing so here's the primitive doom version then here's the same version using task bind or whatever you want to call it and in F sharp there's a thing called a sync which is a really nice version of this it has all sorts of other nice features like cancellation tokens and all sorts of cool stuff but this is like the one-liner you can write this yourself right this is this will work like the dotnet standard C shot style tasks and then finally you can use bind to chain air handlers together so let's say you have a function that's going to receive a request and you know update database and then send out some email to somebody a very simple function the problem is as soon as you start dealing with real world you start getting all these areas you have to track database exceptions and what if the customer is not found and what if the server's not available and blah blah blah he ended up with your code having thousands of error handling routines in it which you're not really part of the main code your code starts getting really ugly really fast I'm sure you've all seen this and in this case we've got six clean lines has turned to 18 ugly lines 200 percent extra code just for error handling so it'd be nice if you didn't have to do that so again monads to the rescue we define something that's a success or failure there's a little switch there's an example if the name is blank is a failure flea mails blank is a failure otherwise they're successful you take all the little things and you glue them together into a single two-track Lane like that and that's what I call the two-track model of error handling otherwise known as a railway oriented programming and I'm going to be doing a talk on this this Friday content and second so let's look at what the before code was before we had kind of a linear set of in doing something then do something else then do something else than do something else but it didn't do any error handling right if something like well names just like crash so let's look at the code after error handling has been added so the literary handling this is what the code looks like okay it looks exactly the same right so the code looks like it's doing the same thing but in fact behind the scenes it's doing the error handling but it's doing the error handling in such a way that it's nice it doesn't it doesn't interfere with what you think that you know it doesn't it doesn't complicate your code it's still quite easy to understand so I'm talking about this on Friday or you can go to my website a top left shop with a non-profit Maps okay so I'm sorry I'm going really fast like I said this is just a super super fast tour and I thought I just like do a brain dump so I just want to talk about everything really quickly maps now okay so we have a world of normal things integers and strings and billions and all this stuff so there's a parallel universe out there in this case it's the world of options so everything in there in the world down here and into like 42 there's a corresponding value in the universe of options so some 42 and as a string hello and in the universe up there it's some hello right so there's a parallel universe and what you find you do as a functional programmer is you end up kind of visiting this universe like you have something in it comes a sum it comes an option int option and then you now need to like do something like add 42 to it or something and you have to come back down to the world of normal values and then you go back up to the world options again and then you come back down to the world of normal values and then R and down and so on so you you know it's just kind of annoying if the right log ugly code with this and you might think well how else can you do it well if you're doing it this way you're doing it wrong this is actually the wrong way to do it okay what you really want to be doing is going up once you go up to the world of this alternative universe up there you want to stay up there okay you want to live in the world of options as long as you can and maybe you have to come down very at the very end right but you really try to avoid coming down back down to the the lower world if you can no once you've up there it's nice to stay up there that's the white waving that's the idiomatic way of doing it in functional programming so let me give an example here's a function that adds 40 to my favorite number and this works on normal values and here's kind of the ugly code right if it's something then I'm going to add 42 to it and if it's and then I'm going to wrap it back up again so I'm wrapping the thing I'm going to apply the add 42 function I'm going to wrap it back up again and stick it back into the world of options and like I say that's the wrong way to do it and here's the diagrammatic way I unwrap it I do my thing and I wrap it back up okay so don't do it that way how should you do it what you want to do is you want to have your ad 42 somehow teleported into the universe of options and you can just use it up there without him to come down how do you do that the answer is something called map so let's say you have a function that takes something to something else in that in the world of normal things you do with map is it will take your function and it will turn it into something that works options so you know you have an interest ring down here it will turn it into an option into an option string or you have a customer to customer ID it will turn it into a option customer to an option customer ID so that's what map does that's all it does but it allows you just once you understand what map does it allows you to stay in the world of options so if I have ad 42 and I one map on it I get a new function called add 42 two options so if I pass in one to route 42 and I get 43 if I pass in someone an optional one I get some 43 out I get an optional 43 so here's how it looks in code I have my ad 42 function I do option map and I get my new ad for the tutor option and so on in practice that's definitely the right way to do but in practice you don't even bother create an intermediate functional that you just call that option wrap and put it to straightaway it's like you don't normally go to the extra effort so that's how you live in the world of options and the same thing applies to the world of lists so you have a function that works in the normal things and there's a whole parallel universe of Lists and you use list map any function that works on normal things can be turned into function that works on lists and here's an example I do add 42 in this day and using list map so I'm turning it into a function that works you know that adds 42 to every single item in the list and you might have a world you know async functions or any other you know you name it any kind of generic wrapped function should have a map type that you can use so most wrapped generic types lists and options and and all the stuff they always have a map and you can you should really use it and if you do create your own type do create a map for it so that other people and use it and if you hear the word funked or a func tool is just a fancy name for a type that has a map it's a map herbal type that's all the factories all right mono AIDS so we're getting a bit mathy now but hopefully you can see these are even those in sort of mathematical words and matter but the mathematicians have got their first unfortunately so all of the jargon is kind of mathematical jargon monads and and whatnot but the concepts are actually quite useful to programmers so this last concept sounds very mathematical but I hope you'll see that it's actually quite useful so let's talk about them so yes there is some nasty mathematics ahead I hope you're not scared of mathematics you know if anyone faints I can call you know medical people so ready for some serious maths here we go one plus two equals three okay that too scary you can handle that all right how about the next one one plus two plus 3 is the same as one plus three plus three oh I know that's pretty intense how about one plus zero is the same as zero plus one and they're both equal to one all right can you handle that you pulse rates not too high right okay so what a matter what do you say oh it's not true in JavaScript yes fair enough okay so thinking like a mathematician so mathematicians what they like to do is they like to do patterns generation so map mathematicians will look at that and say hmm there's some interesting patterns here let me see what I can come up with so mathematician would look at 1 plus 2 equals 10 see hmm there's a bunch of things there's two things and we've got some way of combining them together and we make a new thing which is the same kind of thing as the two things I combined that's interesting I wonder if that works for other things too let me try multiplication does that work for multiplication two things a way of combining them and I get a new thing at the same time well that's very cool what about strings if I could take two strings and I can catenate them I get a new string awesome and if I take two lists and I can catenate them I get another list so that's actually really a more generic pattern and I thought when I just thought about using integers so why is that a useful pattern so if I look at 1+2 1+2 is another thing it's three other integer right because it's another integer I can do another pairwise addition on it and that's another integer so I can do another pairwise addition on it and I can keep going and going and going as long as I like so what I've really done is I have taken pairwise operation and transformed it into an operation that works on lists so that's very cool if you have this property you get this property for free that you've started with something it just works and two things and now you've extended it into something works on infinite lists okay what about the next one what this really says is the order of combining doesn't matter I can add two and three first or I can add one or two first it doesn't really matter right get the same thing so if I have 1 plus 2 Plus 3 plus 4 I can do 1 plus 2 and then I can do 3 plus 4 and I can add the answers or I can do 1 plus 2 and then I can add 3 in the neck and add 4 whichever way I do it I get the same answer right well that's kind of obvious it's not always true subtraction it doesn't work for so it works for dition it works for multiplication and it works for yes list could count and string and captain okay last one so mathematician would say that's very interesting there's some things very special thing that when I add it when I use the combination thing to any norm then get the original thing back as if nothing happened right zero means that like nothing happened it's like it almost like it doesn't exist right it's a null OP to use a programming jargon and of course you know if I'm using multiplication there's another thing which does nothing which in this case is 1 if I'm doing string concatenation there's a special thing that it does nothing which is the empty string and for this incantation it's the empty list and so on so that's zero concept is also quite extendable so let's look at all these generalizations we made we started off with a couple of very simple arithmetic things but we can make a generalization you start off a bunch of things that someway combine them two at a time we have a couple of rules if you combine two things you always get another one of those things if you combine more than two things which order you do it in doesn't make a difference and finally there's some sort of identity element that doesn't do anything so if you have these rules you have a mono age okay so Mon it's very simple Ramond is anything that just satisfies these three rules so okay that's the mathematical thing but why is that useful to a programmer okay it's kind of theoretical well let's look at closure for example as I said you can take any pair wise operation and turn it into a an operation that works on lists and that is normally called reduce so let's produce with plus collapse as a whole list of integers if I do it with multiplication again I can do list reduce multiplication and it collapses the list using multiplication and a string concatenation the same thing there's my pairwise operator and if I use it with list reduce and collapse all the strings onto a single string very powerful what about associativity so because it doesn't matter which order I do things I can use also some cool algorithms like divide and conquer algorithms parallelization incremental accumulation and so on so let's talk about so that parallelization for example so if I got one force to plus T plus four I can do one plus two on one core and I can do three plus four on another core and then combine the result right so anything where you have this associativity property you can actually get power lies that parallelization for free okay you can split the tasks among multiple CPUs or multiple cores do all the work in multiple things then and then combine the results because it doesn't matter which order you do the calculations in so that's a very powerful thing you get that for free if you have a mole annoyed the other nice thing you get is incremental accumulation so even if you're not doing parallel stuff this incremental stuff is quite useful so let's say you tell me to calculate 1 plus 2 Plus 3 and okay that's six and then tomorrow you say you know I got a new requirement I need you to add four as well and you say oh now I have to start all the way from beginning how to do one plus two plus two plus four no you don't have to do that right you've already calculated six you can just add four what you did yesterday right you don't have to start from scratch every single time a new number comes in so this incremental accumulation is a really nice feature of MA notes and we'll have a look at that a second so and then finally the entity elements really nice because if I don't if I have an empty list I can't do reduce so I need something if I have a divide and conquer algorithm there's nothing to divide I need something and if there's an incremental algorithm I've got no data I need something so that's where the zero comes in so that's where the identity element is useful some sort of initial value for empty or missing data and you don't always have to have an identity element if you don't have an identity element is called a semigroup another bit of mathematical jargon there is a way of turning a semigroup into mono age but I'm not going to go into that right now all right so here's a real useful pattern for something you might actually need so let's say I have an e-commerce site and I have a bunch of order lines with a quantity and a total and I want to add them all up so you might say well let me just loop over all the order lines and add up all the what is inaudible the total so what yeah that would work but I'm going to say well you know I'm clever I know this is a monoid how do I know it's an on line because every combination of MA lines is another model because engines on one item because floats and one ides then my order line is also going to be a monoid so all I need to do is define a pairwise action I'm going to add two lines together and all I do those add the two components together and create new one that's easy once I've got a pairwise operation I can use the distro do so and I get my totalizing function for free okay it's very nice I get free functionality I'm always a big fan of free functionality plus if I have a very large number of order lines I can do it in parallel not hopefully I don't have an e-commerce site which has like a million items in your basket but if you did try something like that you could paralyze the addition process so here's a common pattern you have a non mod and you want to turn into my line so you have a bunch of customers free say and test data about each customer how many times they visited your site how much money they spent all that kind of stuff you want to add all that stuff up but you can't add customers together because customers aren't a monoid so what you need to do is you need to turn them into something that is inner is a monoid in this case something like customer stats where everything in a customer stat is a integer or some sort of numeric field right and then you can add them up really nicely so that's a mod ID you know that's going to work so what you need to do is map each customer into a customer stats and once you've mapped them into the custom stats you can then reduce them into a total stats okay so there's a map for the very reduce okay so you might have heard that so this is a very simplified version of like Map Reduce that Google has obviously the Devils and the details but this is this kind of same principle but the simplified version and someone posted a nice tweet a while ago called the Hadoop or make me a sandwich and in this example you know a loaf of bread cannot and an onion cannot be combined into a sandwich directly they're not ma nodes but if you slice the loaf bread and you slice the onion and you slice the letters wherever the slices can be combined into a sandwich so the first thing you do is you map everything into the various slices and then once you've got the slices you can aggregate them or reduce them into the sandwich so I think that's in a nice model of how MapReduce works now here's another thing you might see frequently which is expensive models and too cheap monoids so let's I have a log file and I'm you know I've got a website and I my statistics I want to get the statistics for the whole week so I say oh our strings you know the log file is just a string and the strings are mono so I can combine all my log files into one ginormous log file and then run my statistics program on that ginormous log file but you know that that's really obviously a stupid idea right what would be much more sensible is to take a summary of each day get the statistics for each day and add those up you have to create a giant log file with gigabytes data and money the way to do is incrementally do the day's statistics and add those up so what we have is on monoid which is really hard to work with another mod ID which is much easier to work if you map from one mA node to another mono age which is much more efficient and that is called a monoid homomorphism alright so that's another buzzword that you might see so just a few more things I'm sorry I'm going to run a little bit late if anyone needs to leave feel free once you start using mods you start seeing them everywhere so if you do any kind of DevOps and you have to have metrics you've probably heard this dive and use counters rather than rates because counters are much easy to accumulate you can actually rephrase that is make sure your metrics and MA nodes okay because they aggregate they handle incremental stuff they can handle missing data so Mahanoy Tarr really useful concept we've been talk about Molly's with data but ma nodes actually work with functions as well so let's look at some functions here's two functions and I'm going to glue them together to make a function the problem is this new function is not the same type as the original function so it's not them it doesn't even satisfy the closure requirement right so it's not a mullet which is a shame however if I have a function that takes apples-to-apples and I combine it with another function that takes apples tackles I get a new function that takes Apple status right so that is closed right it's a new kind of function it's the same type as all the other functions and the soceity you get from function decomposition it turns out that functions like this are MA nodes all right so this is a special kind of function where the input type is the same as the output type all right so functions were the input type and the output type are the same I'll call our Mahanoy do what should we call these kinds of functions how about calling them functions with the same type as input now purpose no we're not going to call that we're going to call them endomorphisms and the reason we call them anymore fences because again the mathematicians got there first and they already gave them a name we probably should use the same name they use so all endomorphisms arm on roids so here's some simple endomorphisms plus one is an emotional int times too intense subtract 42 is int they're all endomorphisms means I can reduce them and I get a new function called plus 1 then x 2 then subtract 42 obviously it's kind of useless function but it just goes to show that I can actually create new functions from other functions let me show you a more practical example with the vent sourcing so if you're doing event sorting how many people do here the event sourcing a lot of people yeah so the vent sourcing you have this thing an event application function that you start with an event and you have an old state and after you've applied this event to it you've got a new state right so that's what the function looks like that state to state isn't endomorphism so any function that contains an endomorphism in its signature can also be converted into a monoid so let me give you an example of that so I have a bunch of events apply event 1 and partially applying the first event because I want to get rid of event and I'm left with a state 2 state function then choosing a morphism and I partially apply the second event and I partially apply the third event and now I have a bunch of sakes two states endomorphisms I can run reduce and I get one giant function which I'm going to call apply all events at once all right so there's something practical I can actually combine my event applications to make new event application and new functions that do stuff and of course this is parallel so I can do if I have you know there's something where you may well have a million events and you want to aggregate them nicely this will allow you to do paralyzation of them and it can handle incremental updates and can handle missing events so finally a monad versus mana leads okay two very bizarre sounding things hopefully they're not quite as scary as they might have been at the beginning of the talk is there any relation they both have Mon at the beginning okay is any relation between them there is so here's our monads railway tracks and if you combine two of them together you get another one so they're closed and the order you combine them in is not that important so they're actually associative and they're actually turns out there is an identity from monads as well so monads are actually mono eights and some monads can also be added together in parallel and again you get a new one and the order is not important and these are my notes as well so they're something called the Monad laws which you might have heard of so the Monad laws are really is the monoid laws in disguise so you have closure associativity identity and so on and people say well what happens if you break the Monad laws you know that's a common question the answer is supposed to go to jail but in addition to that you lose the Monod benefits such as aggregation so I'm just going to give you this I'm not going to tell you what it means but a monad is just a monoid in the colibri of end of factors okay people hear this all the time hopefully your head would explode too much I'll leave you that thanks for you
Info
Channel: Ivan Plyusnin
Views: 168,770
Rating: 4.9648504 out of 5
Keywords: Software Design Pattern (Field Of Study), Functional Programming (Programming Language Paradigm)
Id: E8I19uA-wGY
Channel Id: undefined
Length: 65min 44sec (3944 seconds)
Published: Sun Aug 30 2015
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.