Functional programming design patterns differ fundamentally from object-oriented patterns by emphasizing functions as first-class citizens, composition over inheritance, and static types for domain modeling. Key principles include treating functions as standalone entities that can be composed like Lego pieces, using algebraic types (product types and sum types) to model data, applying partial application for dependency injection, leveraging monads for error handling and asynchronous operations, and utilizing monoids for aggregating data operations through associative operations with identity elements. These patterns enable cleaner, more maintainable code by focusing on pure functions, immutability, and declarative composition rather than mutable state and inheritance hierarchies.
Functional Programming Design Patterns Explained
Added:with can everyone hear me at the back there very good okay um so I'm going to this is going to be very fast and a very long uh 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 of everything I can think of that can squeeze into 60 minutes so my name is Scott ven I have a website F forun andrc and uh F works there's a group of people who do F Consulting so if you want F Consulting come and ask us um where's my slide thing here we go of course my thing is there we go so um I was a bit hesitant to use the word pattern because obviously there aot of uh overloaded connotations with patterns so I thought about using practices or approaches or tips or something but you know what um my my project my thing is not working um uh I'm going to luly stick with um patterns so these are not gang of four 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 uh a lot of people think that functional programmers are very anti- oo and they're very academic and they don't really understand oo and they just hate on no for no reason so I'm going to give you my background so as you can tell I've been around a long time uh this is a childhood photo that's uh me over there in the corner that was a vacation that ended badly so you know like most people I um I did the usual things I the boring languages like I con and modular 2 and prologue and stuff but eventually I discovered um Small Talk which I totally love and I still love 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 small talk for quite a while and so I was you know a very serious Small Talk Guy and um even though I love small talk even the small talk people hated Enterprise o right so CU that wasn't real o wheel o was 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 it's like shooting fish in a barrel or um shooting green vertebrates in an abstract Barrel proxy Factory so it's easy to say easy for you to say okay so and then I discovered uh functional programming a few years ago and I love functional programming too and you know it started off kind of innocent 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 H and that's what happens when you dable too much in fun you get assimilated into the functional programming community and they took me to this Ivory Tower um they didn't take me to the top floor the top floor is reserved for high school programmers uh I'm an F guy so they put me a bit further down with the old cam guys uh the Visual Basic people are down in the basement and of course the list people are like on another planet altogether 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 oo patterns yada yada y we've 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 con relity functional as functions open close principle is functions dependency inversion principles also functions um interface cations functions you know [Laughter] functions so I guess the point of this slide really is that functional patterns are not the same as oo patterns they're different okay so there's no point trying to transfer oo patterns to functional patterns I'll give you a couple examples but you really need to change the way you think about programming to be a good functional programmer so the kind of functional patterns that you're probably all familiar with you know apomorphy and zygomorphic pre morphisms 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 uh functions using them in a different way than you might do in objectoriented World functions as interfaces and as the sort of way of doing abstraction um partial application dependency injection continuations and the Pyramid of Doom mon ads uh especially for error handling and async and things like that and then Maps a little bit on maps and um finally monoids which is a very mathematical sounding word but it actually turns out to be very useful for aggregating data 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 in 5 minutes and you don't really get a chance to stop and and look at it properly that's what this talk is going to be like so it 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 because 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 a little bit so there's a lot of core principles of functional program but here's some of my favorites or or rather the ones I can fit into 60 minutes so I think it's very important to understand the core principles because um again you try to bring in your existing paradigms if you're an O programmer and 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 um so the core principles of functional programming or a couple of them are functions are things right they're not just methods on a class um I like to use the wellway analogy a lot so I like to think of functions as little bit of Railway track and there's a input and an 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 bigger piece that's composition and types are not classes so we think of types and classes in O as basically the same thing um they're more like set theory okay it's it's a a different way of thinking about types but it actually turns out to be quite powerful so let's start with the the functions as things so function is a standalone thing it's not attached to a class not attached to an object um 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 trans formed so in this particular case I have an apple turning into a banana and um to demonstrate the functions are things this is some F code here so I have a a an assignment to a number Z equals 1 so I put little one in a box and I give it a name Z now if I Define a function in f i define a little bit of wellway track and I go in a name ad what's interesting is in F and in most functional language the way you define a function and the way you define of 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 uh you're not I'm not expecting you to understand the code or read the code just can look at the pretty pictures um so here's a function takes an integer and it outputs a new function okay this is generating a 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 splits an integer out and it takes another integer uh it takes another function as a parameter so it'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 functional programming but once you get your head around it actually makes a lot of sense 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 I it's encapsulated how it was built it's just a function I don't really care how it work 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 from smaller functions so that's a very cool feature about composition and that leads to the first sort of uh design Paradigm which is functions all the way down um sometimes people say functions in the small um objects in the large I I would say functions in the small and functions in the large you can use functions everywhere and I'll give you an example so you start off with a lowlevel operation like know upper casing a string so it has an input and an output um and then you take these lowlevel operations and you combine them into a service say an address validation service and it has an input and an output and notice that this inputs and outputs is 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 who don't know what a service is um everyone knows what a microservice is right so microservice a service is just like a microservice but without the micro 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 uh some response comes out and then you take a bunch of use cases and you compose them into for example a web application in this case the input is is a HTTP request uh 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 bigger ones works at the low level and also works all the way up to an application at some point um you might you know when you have systems you you have to start using message cues or something to do asynchronous that's when you start getting rid of the functions but then that's where reactive functional comes in so composition is sort of fractal U fractal may be not the accurate word self similar might be a better word but fractal sounds cooler so I'm going to say that composition is fral it's the same at the small uh level as the high level both all right types are not classes so what do I mean by that so here's a uh a class diagram uh but these are not types these are classes so don't think about classes 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 uh you have a function which has 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 that function okay 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 for example int is a type okay I could have a set of integers any of those integers are valid input that's type but 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 outputs it's just a set of all the in to int functions that's a type as well and we'll be seeing integer uh function types in a minute so that's what types are it's just a set it's just a 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 Maps lists a lists um a list is just data right if I want to do something with it I need another function so I have functions that transform list to other list or transform list in integers or strings whatever those are completely different from the list themselves the lists have no Behavior so the behavior and the data are completely separate the thing about types is because they don't have any Behavior associated with just data they can be composed just like functions so um most functional languages have an algebraic type system which is not an O type system so an algebraic type system you start with perimeters and you create new types by gluing them together just like you compose functions and there's two basically two basic ways you can glue them together uh you can glue them together by multiplying them which sounds kind of strange but here for example I have a set of people a set of dates and I combine them together and I get a birthday okay so that's called a product type and uh the alternative way of doing them is to add them together so if I have a a cash method or a check method and a credit card method I combine 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 every input for a function there's a valid output all right sounds simple enough so let's look at an example so here's a very simple example 12 divided by a kind of toy example 12 ID 3 is 4 12 ID 2 is 6 12 ID 1 is 12 12 ID 0 is what okay there is no answer this is an undetermined and undefined result so this is not a total function as it stands so you might say um let me throw an invalid argument exception okay that might be the O way of doing it uh actually it's not the O way of doing it it's the C and Java way of doing it um I'm going to throw an exception here um but you know what happens is I look at the type and and this this function says it takes an integer and it splits out an integer and that type uh signature is a lie okay it's telling me that it will spit out an in and that is wrong because it doesn't always spit out an in sometimes it throws an exception so I don't like types that lie to me okay and and 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 intey say sorry I can't handle it what's up with that you know can't you you can write better code that's a really stupid way of writing code so what's the alternative well the first alternative yeah don't do that okay please don't throw exceptions the first alternative is to constrain the input so I'm going to say I'm going to define a new type called non-zero integer and zero is not that set all right Zero's missing now if zero 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 it says it takes a non-zero integer and gives me an INT and that is a true type signature that's not lying to me um and it act as documentation it tells me that you better not pass in a zero in fact a compile a static type uh language will not let you pass zero into that uh the function so you get compile eror if you're trying to puse zero in which is 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 is but then in all the other cases I have to change them to be something so in cases where I do know what the answer is I return some four some six some 12 so now what we do is we have an option of int right so sometimes it's something and sometimes it's nothing in which case now in 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 in I might give you an INT 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 is always going to give me an integer back so total functions are really nice and this is something that functional 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 the kind of things you end up 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 uh static types to embed business rules in which is hard to believe but um it's actually possible to create a situation where things which are illegal in the real world are not compilable in your code so the types act as a sort of uh compile 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 um 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 parameterize all the things it's the rallying Cry of functional programmers let me give you a little example so here we have a um something that prints a list of integers and you know typically as a program look at that and you say you know what you've hardcoded 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 parameterize the data structures we don't like seeing hardcoded constants in our code right there's just second nature to get rid of them and replace them with paramed things but if you're a functional program you say oh look you've hardcoded the behavior in there too let's parze that as well so a functional program would immediately create a parameter which is a a parameter to do the thing for each item so now what I do is I have two parameters one which is the list and one is 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 ins it could be a list of strings could be an action that works on strings or anything so it's infinitely more generic already and we've decouple 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 uh thing can be replaced with 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 a lot of trouble 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 in two lines of code so let's look at a real example this is a little bit of a c kind of snippet um obviously C has link when I show these examples people C people say well yeah I can do this with link in one line it's like yes you can it's called functional programming but I'm going to use traditional I'm going to use traditional style uh for 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 one the initial value is zero and then also the action that you take each time to the loop is different in both cases so we need to preserve the distinctions and get rid of the common boiler plate code and in F uh 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 it focuses it helps you focus much more on what you're actually trying to do with your code you're focusing why is a product different from a sum the two lines really help you understand the difference you're not bulged down with all this Loop code so actually link has the thing link aggregate is the same thing in C um it's not often used I think it's quite complicated to understand there's the common code there's the initial value and there's the parameterized action and of course any decent collection uh will have thousands of these kinds of things there's fold there's Map There's reduce there's collect there's select and 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 a lot of powerful stuff you can reduce a lot of your code ply down to one or two lines using these uh collection classes collection functions all right function types are interfaces so what does I what do I mean by that I mean that the function types provide the um abstraction layer so in in object programming you tend to use interfaces to to force you to program to the interface don't program to the implementation in uh functional programming you program to the function type right not to the implementation so let's see how that works so here's an interface an O style interface called a bunch of stuff it's got three different uh methods in it if we take the single responsibility principle it says you know only one reason to change the interface segregation principle you know don't contaminate interfaces with 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 I guarantee it's 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 interfaces have 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 as a a type called bunch of stuff it takes an INT and returns an INT so any function which has uh which takes and returns is compatible with this interface so add two is compatible and times three they're both compatible and I didn't have to say they inherit from this interface right they're automatically compatible by the very fact that they take an into matern and in so the strategy pattern in oo you have to pass in um you know a strategy object in the Constructor or something and 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 just a function that you call so I'll try and do it in pictures and 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 a slot there for it and the nice thing about the functional model again you don't have to predefine any interfaces at all I didn't really have to Define an i bunch of stuff type in F because in int is a sort of built-in type I don't need to Define it anything it's an in in works 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 uh interface and I can just plug it in I don't have to prea proactively Define all these interfaces all the time uh let's have a quick look at The Decorator pattern so here an is 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 uh print uh the input and it's going to print the output and 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 inable function it's it can substitute anywhere that I had the original function that's not a but but you know what in practice a functional uh programmer py wouldn't write it like that it's a little bit uh clunky a functional program I probably use function composition like this so I 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 bull this new function is also a decorated version of it even and again I can substitute it anywhere that I had the original function all right 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 parameter so you know cuz I have to have this connecting inputs and outputs 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 and one 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 uh it's got two parameters but you can also Define ad in another way which is an ad is 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 add defined as a zero parameter function in a sense and of course if you can do a two parameter one and a one parameter a zero parameter one why can't you do a a one parameter one and in this case I take one par and I return the Lambda that has that first parameter baked in so it's a function that takes a parameter spits out a new function that has that parameter baked into it and now I have another function so it's a function that generates functions so in 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 log up pass the log last argument in so here's a concrete example here's 3 = 1 + 2 two it's pretty obvious um in F you can actually take that plus and move it to 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 call 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 add is a one parameter function okay you might think that addition is a 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 um 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 function 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 patterns 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 prameters 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 can do exactly this thing you can put parentheses around the front bit okay you can't do that in C or Java so you can actually take those that front bit 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 um but it's a one parameter function and now I can actually use this hello function I've defined all over the place so originally I had a kind of hard-coded version that only worked in my context but by by partially applying something I've now got kind of reusable function that I can pass around and and other people can use it as well so that you know it's very common for example when you're using uh lists that you 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 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 equals 2 are missing a parameter but when I apply them to a list then the extra parameter is provided by the list iteration routine so 1 to 100 list map add one that adds one to each element in the list filter equals two it filters on on the the equality function so you can see that it's really nice to build up a little kind of utilities Little Helper functions just one liners and then your code looks quite nice I can this code is very reasonable you know add one to everything in the list and then filter it where it equals two very very readable so the doc it's kind of self-documenting code um so uh 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 O and I need to do it in function and I don't understand how to do it in functions so let me show you let's say you have a a repository and this is the repository interface where you give it a customer ID and 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 uh get customer repository for example so it's this there's nothing in this uh type that says it comes from a database right it's it's ignorant of the persistence mechanism so let's say have a real function that gets a customer from database now this particular real function needs a connection okay it's a SQL database I pass it a connection and I also pass it a custom ID and then it does a select on that custom ID so unfortunately that c 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 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 a 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've I've abstracted out the fact this is a database function I can take this function I can pass it to anybody who needs a repository so let me show you another example which isn't a database one so here's the type here let's say it's an in-memory database so instead of having a physical database I'm going to have a dictionary and again I have a particular method that works with the 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 2 and get customer 2 the dictionary is already baked in and all it needs now is the missing ele the 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 function get customer two is an in-memory function they both have exactly the same type they both can conform to the same interface I can pass them around they're completely interchangeable that's how you do dependency injection so the Hollywood principle uh don't call us we'll call you um otherwise known as continuations in the functional world so let's uh look at this divide function um 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 right who put the method in charge of the universe you know it's 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 function does it's not throwing uh uh an exception that I immediately have to catch again it might be that I want to you know I might be doing this all the time I have to like it's going to throw an exception I have to catch it it's going to throw one it's C 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 um so the continuation is just the fancy word for what happens next I'm passing in a function that tells the the the called function what to do next the very last thing you need to do so here's the F equivalent um again there's four parameters and and the zero and success so four parameters is a lot right I mean that's you're pushing it and it'd be really annoying if I have to pass I mean it's nice and flexible right you can see it's good but I really don't want to be passing four parameters every time I call the Divide it's just ridiculous right so it' be really nice if there was some way of kind of baking in the two parameters that do the behavior right and then I would just have a normal divide function after that so that's exactly why where the partial application comes in because I've already shown you how to do that so if we take this function f what I can do is Define two behaviors uh if it's bad and you know if it's zero I'm going to print bad if it's uh 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 function 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 return some so there's how I do that I bake those in and then I get again I get a divide function that works like normal for anybody else uh and let's say I want to reproduce 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 uh setup again I bake the uh 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 uh passing in continuations is a really really powerful technique gives you complete control and if you you have a nice functional Library it will allow you to do that all right it will tend not to hard code things like you I'm going to throw an exception it's like no you tell me what to do when something bad happens and and then you know you have control over what happens so one one way you see continuation is used a lot in this sense is when you're doing callbacks so um I'll give you an example here this is uh you know a null testing example uh you know if it's not null do something if it's not null then do something else if it's still not null do a third thing um these kind of n nested null checks are very annoying and um people call this the period of Doom because it can you end up with this super deep nested code um you can you can do early returns in some in in F sh you actually can't do an early turn but even if you could just bear with me for a second because it's not always applicable um 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 these nested callbacks you get this level of indentation creeping up and you get the PID of Doom so you see that in all languages where there's some kind of callback mechanism especially for um async or promises or those kind of things you end up getting us 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 and we say you know what null null's a really bad code smell we're going to replace null with option okay that's much better there you go isn't that much nicer code no of course it's still really ugly code it's a terrible way of doing things so turning option doesn't resolve 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 calling out to be paramed right parze all the things so I'm going to wrate 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 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 B it so with that help of function I can remite 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 uh design much cleaner and that takes us onto monads so monad is one of those really scary words that you hear a lot of in functional programming um 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 than that but for the you know I'm not going to get into too much but you can think of it as just chaining continuations so let's look at uh how we just did what we did from kind of point of view so I like to the good analogy I like is uh points in a railway track we've been talking about little functions as railway tracks so this is a function which is uh has one thing coming in but two things coming out so it's either points or if you're American it's a switch so in this case input and then if it works we're on the green track and if it doesn't work we're 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 uh convert uh oops Yeah those little things into that I think that's pretty obvious that's how you would do it if you had 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 two track functions with two inputs and two outputs they're also easy to glue together I just connect the track up but what we've got here is we've got one track input and two 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 is the answer bind all the things it's like it's like a secret handshake if you go up to someone and say bind they'll say yeah nudge nudge wink win you know F FPS people get excited by bind you can read into that what you will right so bind is the answer to everything um and what does bind mean so here's our function that doesn't work if we can turn it into two track function it does work so bind is just a kind of an adapter block okay I I want to I have a I have a uh a function which doesn't fit and I want to turn into something it does fit it's like a little kind of thing that fits on top of something and I slot my uh points or my switch in and it turns into a two function so that's all that bind is okay if it's a successful input it calls the continuation and if it's unsuccessful uh input it just keeps going so that's all the bind is not mysterious thing it's just a way of gluing these uh switches or points together so let's look at bind for chaining options together so we saw this before uh here's option bind so if it's something you call the function otherwise you you say nothing so here's uh the Pyramid of Doom version and then this is the same version after using bind much nicer no pyramids linear code and Mantic bind that's the buzz word and you can just say to someone I understand Mantic bind and you'll get into the you know the secret society um 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 um we can create a task bind in this case it's like when finished call this continuation uh promises Futures all variant of the same thing so here's the perimeter Doom version and here's the same version using task bind or whatever you want to call it and in F there's a thing called async 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 for like net standard C style tasks and then finally you can use Bine to chain a handlers together so let's say you have a um a function that's going to receive a request and uh you know update database and then send out some email to somebody you know very simple function the problem is as soon as you start dealing with real world you start getting all these errors you have to tr database exceptions and what if the customer's not found and what if the server not available and blah blah blah you end up with your code having thousands of error handling routines in it which are not really part of the main code you 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 um 18 ugly lines 200% extra code just for error handling so it' be nice if you didn't have to do that so again moan adds to the rescue we Define something that's a success or failure it's a little switch um there's an example if the name is blank it's a failure if the email is blank it's 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 uh otherwise known as Railway oriented programming and um I'm going to be doing a talk uh on this uh this Friday I'll come to that in a second so let's look at what the before code was before we had kind of a linear uh set of doing something then do something else then do something else then do something else but it didn't do any error handling right if something went wrong it would just like crash so let's look at the code after error handling has been added so with error 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 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 at r f for Fun and Profit Maps Okay so I'm sorry I'm going really really fast like I said this is just a super super fast tour and I thought I'd 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 uh integers and strings and booleans and all this other stuff there's a parallel universe out there uh in this case it's the world of options so everything in the in the world down here and in like 42 there's a corresponding uh value in the universe of options so some 42 there's a string hello and in the universe up there it's a 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 and becomes a sum it becomes an option in 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 of options again and then you come back down to the world of normal values and then up and down and so on so you've you know it's just kind of annoying if to write L ugly code for 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 once you've up there it's nice to stay up up there that's the right way of doing that's the idiomatic way of doing it in functional programming so let me give you an example here's a function that adds 42 my favorite number and this works on normal values and here's kind of the ugly code right uh if it's something uh 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 unwrapping the thing I'm going to apply the add 42 function and I'm going to wrap it back up again and stick it back into the world of options and um like I say that's the wrong way to do it and here's the kind of 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 ad42 somehow teleported into the universe of options and you can just use it up there without having to come down how do you do that the answer is something called map so let's say you have a function that takes uh something to something else in the in the world of normal things what you do with map is it will take your function and it will turn it into something that works in options so you know you have an inter string down here it will turn it into an option into an option string or you have a customer to a customer ID it will turn it into an option customer to an option customer ID so that's what map does that's all it does but it allows you to Once You' understand what map does it allows you to stay in the world of options so if I have ADD 42 and I run map on it I get a new function called add 42 to options say so if I pass in one to add 42 and I get 43 if I pass in some one an optional one I get some 43 out I get an optional 43 so here's how it looks in code I have my uh ad 42 function I do option map and I get my new ad 42 option and so on in in practice um that's definitely the right way to do but in practice you don't even bother creating an intermediate function like that you just call that option map on2 straightway it's like you don't normally go to the extra effort so that's how you live in the world of um 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 a function that works on lists and here's an example I do add 42 in this time I'm 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 of 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 uh Monas and all this 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 can use it and uh if you hear the word funtor a functor is just a fancy name for a type that has a a map it's a mappable type that's all the fun is all right monoids so we're getting a bit mathy now but hopefully you can see these are even though this are s of mathematical words and Ma the mathematicians sort of got their first unfortunately so all lot the jargon is kind of mathematical JG and monads and and whatnot but um the concepts are actually quite useful to a programmer so this last concept sounds very mathematical um 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 mess here we go 1 + 2 = 3 okay is that too scary you can handle that right how about the next one 1 + 2 + 3 is the same as 1 + 2 + 3 all right I know that's pretty intense how about 1 + 0 is the same as 0 + 1 and they're both equal one all right can you handle that you pulse rate's not too high right okay so what a ma what did he say oh yeah it's not true in JavaScript yes fair enough okay um so thinking like a mathematician so mathematicians what they like to do is they like to do uh patterns generation so mathematicians will look at that and say hm there's some interesting patterns here let me see what I can come up with so mathematician would look at 1 plus 2al and say hm there's a bunch of things there's two things and we 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 of the same type well that's very cool what about strings if I take two strings and I can catenate them I get 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 than I thought when I just thought about using integers so why is that a useful pattern so if I look at 1 plus 2 1 plus 2 is another thing it's three another integer right and because it's another integer um I can do another pairwise addition on it and that's another integer so I can do another pair wise 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've taken pairwise operation and transformed it into an operation that works on lists so that's very cool if you have this property you you get this property for free that you've started with something that just works on two things and now you've extended it into something works on infinite number of 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 and two first it doesn't really matter right get the same thing so if I have 1 plus 2 plus 3 + 4 I can do 1 + 2 and then I can do 3 + 4 and I can add the answers or I can do 1+ 2 and then I can add three and then I can add four whichever way I do it I get the same answer right well that's kind of obvious um it's not always true subtraction it doesn't work for so it works for addition it works for multiplication um and it works for um list concat and string conat and so okay last one so a mathematician would say that's very interesting there's something very special thing that when I add it when I use the combination thing to any normal thing I get the original thing back as if nothing happened right the zero means that like nothing happened it's like almost like it doesn't exist right it's a it's a 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 one if I'm doing string and catenation there's a special thing that does nothing which is the empty string and for list concatenation it's the empty list and so on so that zero concept is also quite extendable so let's look at all these generalizations we've made we started off with a couple of very simple uh arithmetic things but we can make a generalization you start with a bunch of things there's some way combining them uh two at a time we have a couple of rules if you combine two things you always get another one of those things um if you combine more than two things which order you do it in doesn't make any difference and finally there's some sort of identity element that doesn't do anything so if you have these uh rules you have a monoid okay so a monoid is very simple a monoid 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 pairwise operation and turn it into uh an operation that works on lists and that is normally called reduce so list reduce with Plus collapses a whole list of integers if I do it with multiplication again I can do list reduced with multiplication and it collapses the list using multiplication and string concatenation the same thing there's my pairwise operator and if I use it with list ruce I Collapse all the strings into a single string very powerful what about associativity so because it doesn't matter which order I do things I can use all sorts of cool algorithms like divide and conquer algorithms uh parallelization uh increment Al accumulation and so on so let's talk about the paration for second so if I got 1+ 2+ 3+ 4 um I can do 1 plus 2 on one core and I can do 3 + 4 on another core and then combine the result right so anything where you have this associativity property you can actually get paral parallelization for free okay you can split the task among multiple CPUs or multiple cores do all the work in multiple things then and then combine the results because it doesn't doesn't matter which order you do the result the calculations in so that's a very powerful thing you get that for free if you have a monoid 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 uh you tell me to calculate 1 plus 2 plus 3 and it's like okay that's six and then tomorrow you say you know what I've 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 the beginning I have to do 1 plus 2 plus 3 plus 4 no you don't have to do that right you've already calculated six you can just add four to 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 monoids and we'll have a look at that second so and then finally The Entity element is 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 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 it's called a semigroup another bit of mathematical jargon there is a way of turning a semigroup into monoid 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 quanties and add up all the totals 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 a monoid because every combination of monoids is another monoid because integ are monoids and because floats are monoids then my order line is also going to be a monoid so all I need to do is Def find a pairwise action I'm going to add two lines together and all I do that add the two components together and create a new one that's easy once I've got a pairwise operation I can use list reduce 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 have something like that you could parallelize the addition process so here's a common pattern you have a a non- monoid and you want to turn it into monoid so you have a bunch of customers for say and um there's data about each customer how many times theyve 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 in a 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 monoid 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 customer stats you can then reduce them into a total stats okay so there's a map followed by reduce okay so you might have heard of that so this is very simplified version of like map reduce that the Google has obviously the devils and the details but this is the kind of same principle but the simplified version and uh someone posted a nice tweet a while ago called Hado make me a sandwich and in this example you know a loaf of bread cannot and and an onion cannot be combined into a sandwich directly they're not monoids but if you slice the loaf of bread and you slice the onion and you slice the lettuce whatever the slices can be combined into a sandwich so the first thing you do is you map everything into the VAR slices and then once you've got the slices you can aggregate them or reduce them into the sandwich so I think that's uh you know a nice model of how map produce Works um here's another thing you might see uh frequently which is expensive monoids and to cheap monoids so let's say I have a log file um and I'm you know I've got a website and I do my statistics I want to get the statistics for the whole week so I say oh strings you know the log file is just a string and the strings are mon 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 don't have to create a giant log file with gigabytes of data and money all you have to do is incrementally do the days statistics and add those up so what we have is one monoid which is really hard to work with another monoid which is much easier to work with you map from one uh monoid to another monoid uh which is much more efficient that is called a monoid homomorphism right so that's another buzz word you might see um 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 um once you start using monoid you start seeing them everywhere um so if you do any kind of devops and you have to have metrics um you've probably heard this guideline use counters rather than rates because counters are much easier to accumulate you can actually rephrase that is make sure your metrics are monoids okay okay because they aggregate they handle incremental stuff they can handle Miss Missing data so monoids are really useful concept we've been talking about monoids with data but monoids 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 third function the problem is this new function is not the same type as the original functions so it's not a it doesn't even uh satisfy the closure requirement right so it's not a monoid 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 to Apples I get a new function that takes Apples to Apples right so that is closed right it's a new kind of function but it's the same type as all the other functions and the stivity you get from function composition it turns out that functions like this are monoids 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 where the input type and the output type are the same are are monoid so what should we call these kinds of functions how about calling them functions with the same type as input and outputs no we're not going to call that we're going to call them endomorphisms and the reason we call them endomorphisms is because again the mathematicians got their first and they already gave them a name we probably should use the same name that they use so all endomorphisms are monoids so here's some simple endomorphisms uh plus one is an endomorphism in int * 2 in in subtract 42 is in int they're all endomorphisms means I can reduce them and I get a new function called plus one then * 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 uh practical example with event sourcing so if you're doing event sourcing how many people do here do event sourcing a lot of people yeah so with event 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 is an endomorphism so any function that contains an endomorphism in its signature can also be converted into aoid so let me give you an example of that so I have a bunch of events uh apply event one I'm partially applying the first event because I want to get rid of that event and I'm left with a state to state function that is the morphism and I partially apply the second event and I partially apply the third event now I have a bunch of state to state 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 of events and you want to aggregate them nicely this will allow you to do paralyzation of that and it can handle incremental updates and it can handle missing events so finally uh monads versus monoids okay two very bizarre sounding things uh 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 there any relation between them there is so here's our monads our 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 there actually turns out there is an identity for monads as well so monads are actually monoids and some monads can also be uh added together in parallel and again you get a new one and the order is not important and these are monoids as well so there's something called the monad laws which you might have heard of so the monad law are really just the monoid laws in Disguise um so you have closure associativity identity and so on and people say well what happens if you break the monoid laws you know that's a common question the answer is of course you go to jail but in addition to that you lose the monoid benefits uh 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 category of endofunctors okay people hear this all the time uh hopefully uh your head would EXP Lo too much all right I'll leave you with that thanks very much [Applause]
Up Next

Haskell Monads Explained: A Comprehensive Guide for Programmers
@philipphagenlocher
75.5K views•2020-01-22

BitTorrent Protocol Explained: Piece Selection & Peer Choking
@StevenGordonAU
481 views•2013-02-22

HTTP Requests Explained: GET, POST, PUT, DELETE
@codecademy
103.1K views•2021-10-07

Enigma Machine Mechanics: WWII Encryption Explained
@JaredOwen
13.2M views•2021-12-11
Related Study Plans & Knowledge Roadmaps
Structured learning paths in Computer Science



































![[Scala Central] - Richard Ashworth - Functional Design Patterns with Scala](https://i.ytimg.com/vi_webp/6GA9cXgidBs/maxresdefault.webp)


