Railway oriented programming is a functional programming paradigm that treats functions as standalone entities (like railway tracks) that can be composed together using a pipeline model, where error handling is modeled using a result type (success or failure) instead of exceptions, allowing developers to build robust applications by connecting functions in a clean, composable way that handles errors gracefully without cluttering the main logic.
Railway Oriented Programming: Functional Error Handling Explained
Added:hello scott hello vagiev hello good morning uh how are you today i'm fine thank you great uh so as an introduction question for uh your talk scott i would like to ask you one simple question uh in the program which is accessible uh on our website techtrain uh there are several hashtags for your presentation and one of them is a hashtag cleancode i heard some rumors that nowadays the uh famously known book called clean code by martin fowler is not is sometimes people say that it's not the best book and even consider it a collection of [Music] practices which will not work today and tomorrow so uh how is your talk maybe connected to to that particular book or briefly this pictures some insights in that area so yeah i think the idea of clean code is a very good one but i think in that particular book he often has very very specific things to do and i think coding has changed a lot since then since he wrote that book and especially things like functional programming which i'm going to talk about today there are ways to get the same idea of clean code but not necessarily use exactly the same in special things that he wants people to do so i think that i can say i think everybody wants to have clean code and uh but i think the reason why people don't like that book so much is that i think we've learned a lot since then and like some of the techniques today i'm going to show you are i think also very clean but they have nothing to do with the the books the the things that he talks about in that book uh sounds promising so uh if you don't mind let us move on to the talk okay right so i think i'm ready to start thanks everybody um my name is scott veloson as they said i have the slides and also the code demos that i'm going to use are available on my github and there's a link down there at the bottom you can go and fetch them and i'll also put them into the chat later on we can we can make sure that everyone has those if you want them so okay railway oriented programming what does that have to do with uh regular programming why is that special so i'm going to tell you all about railways today so i'm going to cover quite a few things this is about functional programming mostly this talk so i'm going to talk about the principles of functional programming the three ones which i think are very important the most important principle of function programming is is composition and uh so i'll spend a lot of time talking about that and then i'll move on to error handling because the way that you do error handling in function programming uses this composition technique and so it's a very different way of doing error handling that you might be used to in an object-oriented language with with exceptions or things like that so um and then finally uh we'll actually build a complete pipeline and i'll show you how this whole thing works with a wheel program right now on the second sorry yes right so um let's start with the three core principles um the three principles are that functions are things um and what i mean by that is that functions are like little bit of uh railway track um then the next principle is this composition everywhere that we're gonna be using and and finally um the types are not the same thing as classes if you're coming from an object or into the world uh you think the types and classes are the same thing um but they're they're different so okay uh let's start off with functions as things so i'm going to use this railway analogy all the way through this talk and the idea is that functions are like little bits of railway track and there's a little tunnel on the track and something goes into the tunnel and it comes out something different so here we have an apple goes in and it comes out as a banana so an apple turns into a banana so this is a function that turns apples into bananas and we say this is an apple arrow banana function and the thing about functional programming is that functions are standalone things they're not attached to a class or anything it's just a thing just like in programming where a string is a thing or an integer is a thing you can pass them around right functions are exactly the same kind of thing and that means that it can be used as an input or an output for other functions they can be used as parameters and stuff now this standalone thing is also very important because standalone is another word for reusable right if if it's a standalone thing you can uh it's not connected to something you can just you know you can move it around without having to disconnect it from something else so here is a a function and it has a regular input but it could have a function as an output um here is another function and it has a function as an input and something else is an output like a string as an output or something uh here is a function which has a normal input and a normal output but there's an extra parameter which is another function so you have this extra function is controlling how the main function works and in object-oriented programming we would call this the strategy pattern but in functional programming we don't really have a special name for this this is just called passing in a function parameter it doesn't it's not a pattern it's just it's very very common way of doing things and then finally we could have a function where the input is a function and the output is also a function and i'm going to call this a function transformer this is a function that turns one kind of function into another kind of function and we will be using these a lot in this in this tool this is a very common pattern in functional programming so functions as outputs functions as inputs functions as controlling parameters and function transformers that is the basic idea of functional programming and if you uh can understand this then you basically understand how to do functional programming this is the basic idea now you can get very very complex systems from this uh you know a function that returns another function that has a function that's a parameter and the function is a function transformer but um the the basic idea is actually all on one page here right so that's what functions are now let's talk about composition so composition as you can see from this little picture is like lego so if you know how to use lego which i think everybody does then you know how to do composition so what is composition what do i mean by composition so i'm going to talk about lego first and then i'm going to apply everything we know from lego i'm going to apply it to the functional design so in lego pieces are designed to be connected and if you connect two pieces together you get another kind of piece that you can add things to and the pieces are reusable right so let's look at each one of these things in turn and apply them to functional philosophy so here's some lego pieces and notice that every single piece has a little bump on it right every single piece is designed to connect to other pieces so if we apply that to functional design we have the same thing every single function is designed to be connected to other functions we just that's part of the way we do our functional design okay now what about adding legos together right you can take legos and they'll make bigger bigger ones out of them right and when you do this you don't need any kind of adapter you don't need a special tool you can just literally take any pieces and and put them together and and of course because of that you can keep adding and adding and adding and adding and adding and making bigger and bigger pieces of lego so here is a really big piece of lego made from lots and lots of smaller pieces and um this is you know still a piece of lego i could actually take two of these things and put them on top of each other and make a really big a double sized piece so we're going to do the same thing with functions we're going to have the idea that you can connect any two functions together and get another function that can be connected together and finally of course lego pieces are reusable right i can build something and then i can take it apart and i can build something else and we want to do the same thing with our functions and the reason this works for lego is that these lego pieces are they do not have wires or strings or anything connected to them so i can you know if they were connected by wires or something it would be very hard to like disconnect them and plug them in somewhere else but because they don't have any wires they don't have any strings they are very easy to reuse and we want to do the same thing with functions so we want to make sure our functions are reusable in different contexts and that means they have to be completely standalone with no wires linking them up to anything else the power of composition is you can make really big things from lots of small things so let's actually look at a a kind of a real example or not i'll i'll do some real examples soon but this is the idea let's say we have we want to build a web application from a bunch of smaller functions how would we go about doing that well we start off with two small functions like this and we want to connect them together how would we connect two functions together well i think if you see the railway idea you can see you take the output of the first function and you feed it into the input of the second function right and that's if you do if you connect them together you get a new function and so this new function um is built from the two small functions but you cannot tell that it was built from the smaller functions once you've put it together this new function is another standalone function it turns apples into cherries and for example where did the banana go you do not know about bananas anymore you don't care about bananas at this level of the functions you don't care about bananas now this function is also a standalone function so it can be combined with another function to make an even bigger function and this is how composition works so you can actually build you can take these small functions and build big things from all these small functions so let's say we have a small function like this uppercasing a string right so this is a function there's an input and an output and it's a you know a regular string as an output now let's say you have a bunch of small operations like this you can combine them into what i'm going to call a service like an address validation service or something and you know this has an input and it has an output so this is a function and i like to use the word service because i'm an old guy i've been around if you're a young person you can call it a microservice just the same thing so service and microservice same thing for my point of view okay let's say we have these very different services and each thing does one little task and i want to combine them together well i combine them into a use case or a scenario or a story or a workflow whatever you want to call it but there's some sort of task that you want to accomplish and again you're going to model it as a function with an input and an output so this is very different from the object model the object model is a request and a response this is an input and an output it's a pipeline model and then you can take all these different use cases or stories or workflows and you can build a complete web application now if you think about it a web application is in fact a function because there is an input which is the request and there is an output which is the response so web applications are in fact big big big functions that's all they are so inside this web application you have to decide which one of these workflows or work stories or use cases you want to run and so of course you have a dispatcher or a router or a controller or something to decide which one of these things to run but the overall thing is just a big function and when you put it together your your web application is going to look something like this so you have your input and your output and inside there's all these little functions which have been connected together and there's obviously some branching and so on but the important thing is this is a pipeline it all goes in one direction you don't have loops and and you don't have backwards flowers everything kind of tends to flow in the same direction so this is very nice so that's composition uh of functions to make a web application now the third thing is i just want to quickly touch on types now i'm talking about statically typed functional programming languages like f sharp or o camel or haskell or even uh elm or reason ml things like that so things like closure and stuff don't really fit in but if you are using a statically tight functional language the types that we use are not the same thing as object oriented classes they're much more like um uh set set theory right with little intersections and stuff so what does this mean so if we have a function there is a set of inputs that you can use for this function and a set of outputs right and that is just a set of things so there's no behavior it's just it's just a set a collection and a type is just a name for a set of things that's all the type is so it's not the same thing as a class at all so if i say all the valid inputs for this function are integers we call the set of integers we call this type integer uh or if the set of outputs is all the possible strings we would call that type string right we'll just give it a name instead of those things will just give it a name we call that string if the set of all possible people as the input we'll call that type person so a person is not a class it's just the set of all possible people that's all it is here is the set of all possible fruits and we would call that type fruit and because it's just because these things are just sets you can have anything in a set in particular you can have a set of functions so this is all the set of this is all the functions that turn fruit into fruit so the fruit to fruit functions and we can give that to set of functions and we'll give it a name we'll call that type fruit arrow fruit right so then there's the the type is all the fruits of fruit functions so types of types are very different from classes because they don't have any uh behavior it's just a set of things now when we do composition in a static language it is type checked so uh you know it's very important that the set of outputs is the same set as the set of inputs so here the output is the set of all bananas and the input is the set of all cherries they're not the same set right they're different sets and the compiler will complain that you can't do that and this is very important it works even for something like something like float and int because the set of floats and the set of ins are different sets so in a functional language this is not allowed in an object-oriented language sometimes this is allowed but in a functional language this is definitely not allowed so we talked about composition of functions but we can compose types as well so how can we compose types the most functional languages have something called an algebraic type system algebraic is mathematical words um but it basically just means composable a composable type system and means you can build bigger types from smaller types just like bigger functions and smaller functions right so we can build bigger types and smaller types using the word and and using the word or right and this is possible because the the uh there's no behavior right these are just sets so you can do just like with sets you can do a union of sets an intersection of sets and the cartesian product of sets you can do the same thing with types so let's look about anding things together okay what do i mean by and well let's say i want to model a fruit salad i would say it's an apple and a banana and a cherry so this way of doing things is really common every every language every programming language has this a pair of things a tuple or tuple of things record a structs you know this is how you do it in f sharp we call this a record in f sharp uh it kind of looks a little like jason so this is a a data structure with three different fields an apple and an apple field and a banana field and a cherry field and all three fields have to be there right so it's an apple and a banana and a cherry and this extra thing here this is the set of all apples so i'm saying the apple field has to belong to all one of the setable apples that's all that means okay now composing with or is a different thing let's say i want to model a snack and i say it's an apple or a banana or a cherry so just one of these things not all three just one how would i model that so in a functional language you use something called a choice type which is literally a choice between these different things so i am saying it's an apple or banana or a cherry that's what the vertical bar means is ore uh in f sharp these are techn these are sometimes called discriminated unions and or sometimes they're called sum types s-u-m some types so this is how you model this in f-sharp uh and this is you can think of this for if you have an object-oriented background you can think of this as more like a um an enum maybe or as three different subclasses but it's it's it's not quite the same as those things but it's it's similar to that it's the way you want to model different um things like that right so let's look at a real world example of of building bigger things some types so let's say we have a requirement that you want to take some payments and we have cash or we have paypal or we have a credit card or something like that so for cash we don't need any information for paypal we need some sort of email address and um for credit cards we need a card type and a card number and a date and a security code and all the other things right so how would you model this in different styles well in an object oriented paradigm most people would implement this as three different subclasses right so let's look at how you do it in an object-oriented way you'd have some sort of base class or some sort of interface class and then you'd have a subclass for cache and a subclass for paypal and a subclass for credit cards and the paypal subclass you know has an email and the credit card class as uh the extra you know the card and the card number and so on now in functional programming we would do it uh by building up a bigger type from a bunch of smaller types right we build it up from the bottom so we start off some small types we start off with an email address and a card number for example they're just strings so these are just primitive types and then we would say okay well a card type is a visa or a mastercard or you know whatever else there would be and a credit card information is a card type and the card number and all the other stuff right so what we have is we have a choice where we say every time we say or visa or mastercard there's a choice and every save every time we say and that's a record type card nut type and card number right what else okay so now we can get to our payment method and we say payment method is cash or paypal or credit card so this is a choice we have a choice between three things and we model it with a choice type uh and we can keep going we can add just like with the lego we can add things to it we don't have to stop we can just build on top of it and make bigger and bigger things so i could define um some more primitives for example you know maybe a payment mount and a currency and then with those three things i can now build a bigger thing like a payment and a payment is a an amount and a currency and a payment method and i could take this and i could build something bigger on top of this so we're building assembling bigger and bigger things right and we're using record types we're using choice types um and we can build really really big things from these basically small starting points so this is why i like to use the lego analogy so the final type is built from lots of smaller types right so that's what composition is applied to types so that is the end that's everything you need to know about functional programming we talked about functions we talked about composition and we talked about types so you could actually go away and start functional programming with all that but let's actually let's actually keep going let's not stop there so let's look at actually uh some composition in practice before we start on the error handling i just want to show you what it looks like without any error handling with a regular kind of composition so here we have some functions and we have three different functions and in most program languages if i want to say i want to add one and then i want to double it and then i want to square it i have to start off with the um most the first thing is right in the middle right it's like it's nested so it sometimes that can get very confusing because you have to start in the middle and you kind of work your way out so in functional programming we tend not to do it this way what we're going to do is we use the composition technique so if i have two different functions and i treat them like little bits of railway track um i can literally just connect them together i take the first function and the second function i and i connect them together and now i have a new function which is add one and double it and that is a new function i can just call it right so that's uh one way of doing composition and if i have um so in f sharp by the way the composition operator is this little angle angle bracket angle bracket like that so that's one way of doing it and what's nice about this is that you can keep adding and adding and adding right if i want to have another function which is three things in a row i can just connect them all together right i don't have to do anything complicated that's one way now there's another way of doing composition which is the way i'm going to use in this talk which is more common in f sharp and so on and that is the method called piping so in piping it's very similar to if you've ever used a like a unix command line and you pipe things to each other it's exactly the same idea we start off with a number and we feed it into the first function and we take the output of that function and we feed it into the next function and we take the output of that and we feed it into the next function and we end up with this pipeline as the numbers go through each function in turn so i think this is actually easier to understand a lot of people so let's actually look at what this uh how this shows up in code so this is how you do it in fsharp this vertical bar is the pipeline symbol okay so what we say was take five and we feed it into add one and we take the output of that and we feed it into double and we take the output of that and we feed it into square so this is the pipeline model of building bigger functions and that symbol is the f sharp pipe simple now the vertical bar in unix we just use the vertical bar but in um in f sharp that's already taken so we have the vertical bar with a little uh thing like this and this is actually a very common symbol now alexa uses it and i think even javascript is going to be getting this at some point i think it's a really nice way of doing i think people appreciate this right so let me actually give you a demo of what piping looks like so i'm just going to switch to my visual studio here and f sharp by the way is a multi-um platform language it doesn't run on windows i mean it runs on windows linux mac it's a it's a you know cross-platform language it's open source so it's not it's not a microsoft specific language so here is our three different functions and f sharp also has an interactive mode i can actually highlight stuff and run it i can say uh execute in interactive and um it will show me the answers down here so you can see that this function if the int is an integer output uh coming in and it going out and they can all be connected together right so this is the the kind of standard way that we do it in most programming languages right so if i take the square i you know the problem is it reads backwards i start off by adding and then i double it and then i square it um which is not it reads it doesn't read that way now if in the f sharp version using the track the railway track model this is how i would build the bigger function and now i have a new function and i can literally just call it like that it works and if i want to have a three three uh things i can do that too and then i now this is a new function i've built a new function from a bunch of smaller functions and i can just call this a new function it works fine that's the that's the railway oriented composition and then here's the piping model and so again i take five and i feed it into add one and i take the output of that and feed it into double and take the alpha that and feed it into square and if i run it i get 144 again so one nice thing about this piping model is when it gets longer and longer you can just like put them on top of each other like this so you know you can actually have you know quite you can have 10 20 things in a row and it's really easy to read still and finally i want to make if i want to make a function out of this i think okay this is a nice reusable piece of code i can literally just take this whole thing and instead of putting 5 i just put an x because i don't know what it is and i can just give it a name so this is how you turn that into a function right so that is the end of that demo and um i'll do one more example of composition and uh let's talk about roman numerals now so roman numerals uh a roman numeral is a very it's very very simple thing to do and i'm going to show you the kind of functional way of doing this using composition and piping so we want to convert an integer into roman numerals so like 5 becomes v 10 becomes x and so on right and the way i'm going to use the way i'm going to design it is i'm going to use this tally system where you make marks and when you get to five you put a slash through it like this so that's our that's going to be our our design that we're going to use so what we're going to do is we'll start with however many copies of the are of the slash or the i and then every time you see five eyes we put a slash through it turn it into v and every time we see two v's we'll put an x for it right and so on and so on and so forth uh all the way up to thousands okay so this is the implementation uh let's let's look at a real world example let's say i have 27 so i start off with 27 and then i replace the five eyes with a v so it looks like v v v v one one and then i replace the two v's with an x and there we go that's it so from a pipeline point of view we're going to just have a little each step is going to be a little quite a little separate function and we're going to feed the value all the way through the pipeline so we're using the same piping model to implement something like this so let me do another demo i'm going to switch back to visual studio again and where are we okay here's visual studio right so uh this is our little helper method here right so here is the here's the code right i replicate the the number and then i replace five ones with a v and i replace two v's with the x and so on and so on so the code is very simple and you can see that the pipeline is uh you know it makes sense you can you can see how how the code works so let me actually test it if i put in this one now i notice there's like four c's okay so let's fix that in a minute if i can let me do all the ones from 1 to 30.
there you go you can see all the numbers down there and again it looks a bit weird with the x's with the four v so i will fix that so the nice thing about this model is it's really easy to add new steps into the pipeline so anywhere in the pipeline i can add new things without touching the other ones so afterwards after i've done the main one i'll just add some extra ones that do that fix it up so if i fix up this one if i do this new version um and i put this one in now this one looks a lot better and if i do the first 30 numbers uh you see this much i got a 9 here that looks much better that everything these just look much more like um this looks just nicer numbers there now one thing which is really nice about pipelines is you can easily add new codes without breaking existing code so let's say i want to add logging into this pipeline i can have a little logger function and then i can take my pipeline and i can put a logging here and i can put some logging here and i can put some logging here and you know without changing the rest of the code i can just add and remove new steps in the pipeline and if i want to test it with uh 14 see i've got some logging at the beginning and i've got some more logging and i got some more logging and i can just trace it all the way through and i mean i could easily put a logger anywhere in here right because it's the it just fits in with the pipeline very nicely pipelines are a great way of doing programming in general which is why i think people like them so much okay so i think i can see there's some questions coming in and i think what i'll do is i'll answer the questions later on after i've done a presentation uh so thank you for your questions i'll be very very happy to stay and answer them as long as you like right so we've covered all the core principles of functional programming um we've got functions we've got types and we're talking about composition everywhere so now let's talk about what happens when things go wrong what happens if things go wrong and this is where we're going to talk about error handling so how do you do error handling when you do this kind of pipeline approach because most errors are done through exceptions right and especially in traditional programming we use exceptions for error handling now one of the problems of using exceptions is we'd like to focus on the happy path right we always like to focus on on when things go right so here's an i'm just going to give you a little workflow and we're going to we're going to tweak it and i'm going to show you how we add error handling so let's say as a user i want to update my name and address in a web application or something so i get some sort of request and there it is it's got a name and an email um so the first thing i want to do is validate it like is the name blank is the email blank uh canonicalize what i mean by that is trimming all the blanks and and and locating the email just making it into a standard format maybe update the database and then if i've changed my email maybe i need to send you an email message saying you've changed your email please verify your new email or something like that so this is a very very simple workflow with only three steps in it but we always tend to focus on the happy path right what happens when things go wrong so you often would get unhandled exceptions now i'm going to show you a bunch of screenshots these are from desktop applications nowadays of course you don't see this but if you go into a javascript console in most web apps you will see a lot of errors they just don't show up in your face anymore but this is what it used to be like back in the day you get unhandled exception unhandle exception runtime error six uh unhandle exception additional information the developer needs to do his job um bad user you've been warned three times this far does not exist now you've made us catch this worthless exception do not do this again this is a true one keyboard not plugged in uh press f1 to retry uh how about this one the error has occurred while creating an error report how about an error has occurred but the error message cannot be retrieved due to another error and this is my favorite one error the operation completed successfully so you know what are you supposed to do these are very unhelpful these are useless messages you do not want to show these messages to your users right so what we should really say is every time we write a story we should say as a user i want to do something and see sensible error messages when something goes wrong right it should be every single story should have that added so what kinds of elements what error messages should we have well personal validation could fail the name is not is blank or something maybe you can't find the user in the database maybe there's a database connection error maybe you can't send the email there's an authorization error or there's a network timeout or something there's many many things that go wrong even something as simple as this so this is some c sharp code that implements that workflow um without any error handling right it's just the four five steps now let's put the error handling in so we need to check whether it's validated and then we need to check whether you could find the customer record and then you need to handle what happens to the database had an exception and then what happens if the email couldn't be sent and so on so what's happened here is the original code was just a few lines and we've added all this extra error handling and the code looks much much more ugly right in fact it's it's it's three times longer and it's much harder to understand because of all the error handling now you have to have the error handling because production quality code should have should always handle the errors you shouldn't just ignore them but it does make the code much more ugly so let's look at the functional version of this and see if we can fix that so we want to try and not have the nice clean code be clogged up with all these ugly errors so what we're going to do is we're going to use a result type for error handling and a result type is a way of modeling success or failure so let's say i do a validation right when when the output of the validation it could be success or failure it's a choice right how can i model a choice well i'm going to use one of these choice types it's okay or it's an error and this is very very common type that most functional programming languages have it's going to have two different choices either it worked or it didn't work right now this is actually not a generic type in f sharp would it would turn it into a generic type where it could be any kind of success type and any kind of error type and so in fsharp this is what it looks like it uses the angle brackets and the little ticks so this is actually a type that you could write in f-sharp and um it's completely generic it's completely reusable and what's nice about the algebraic type system is that you could build this yourself you don't you know you don't have to change the compiler to support it if you have a language which supports algebraic or composable types you can do a lot of these cool things yourself you don't need to you know we completely redesign the language oh let's look at uh some some code that validates the input so if the name is blank that's an error if the email is blank that's an error uh if the inputs otherwise everything's good so this is a good example of a visual validation okay and notice that we're keeping track of the data in both the error case and the success case we're keeping track of the data so in from a railway point of view i'm going to model this as um an input and a railway track with a branch in it right so in england we call these switches points in america they call switches i'm sure in russian they have a name for these things too anyway you know you know the kind of thing these kinds of railway tracks with a with a branch in them so what we're going to do is make all our functions look like this every time a function can have an error it's going to return one of these kinds of shapes and then when we can connect them together we're going to compose them into a two track so this is what they look before and after they've been composed together we have something that looks like this and this is what i call the two-track model of error handling or railway oriented programming so this is what our functional code would look like before we did error handling right it would look very similar to the c-sharp code it's just like you take thing and you pass it all the way through now without the error handling this is just like a one track thing and it could still throw exceptions and so on now let's look at it after we add error handling okay with the error handling this is what it's going to look like what's interesting is with the error handling it looks exactly the same and it does look the same i'm actually cheating a bit because these are not exactly the same functions um what's going on here is these are all two track functions and so this is a two-track model and the errors are being handled but it doesn't make the code look ugly the code is still looking nice and clean so i will show you this code in a minute so how do we compose these railway functions right um this is the the switch of the track with the branch in it right so that's fine now we want to connect two of these together um so what we say if if the first one works we pass it into the next one and if the first one doesn't work we don't we just skip bypass it right so that's how we want our composition to work and we end up with something that looks like this and if we have a whole bunch of these things again when we connect them together we'll have this two-track model so that's it's kind of easy to see how it should work how does it actually how can you write the code to make this happen how do you actually do this in practice so if you think about these um things we have uh these little tunnels and inside the tunnel is this you know uh switch here so this is a interesting way of thinking about it because if these if these tunnels had one input and one output they could be connected together no problem and if they had two inputs and two outputs they could also be connected together because that's also uh pretty easy but we don't have that we have one input and two outputs and they you can't connect them together right so that's that's the problem how do we connect these things together how do we combine these mismatch functions well so here's the function that doesn't work but we noticed before that if it did have two inputs and two outputs that would work so the bottom function would work the top function doesn't work so what we can do if we can find a way of turning the top function into the bottom function then we have solved our problem so what we're going to do is try and convert the top function into the bottom function and the way we're going to do that is with an adapter block right it's got a little slot on it and the function comes in right this is a function transformer a function comes in and it comes out like that so this is a function which has an input as a function and an output as a function just like i was talking about so um uh there you go that's that's once we have this um we can do stuff now this function is is often called bind it's also called flat map sometimes it's called and then in haskell it has the special symbol and if you do c sharp in link it's select many so it's lots of different names for this function but normally it's called bind it's really easy to implement it's only three lines of code it's much more complicated to explain it than it is to actually write it so the way it works is something comes in and if you're on the success track you basically handle that and call that function and if you're on the error track you just skip you just go right through so that's the implementations really easy to do so again if we can convert these things into two tracks using bind we can connect them together so let's look at an example here is our here is our um request say a very simple one and we want to validate it so we have a function here and another function here and another function here and all these functions uh have this switches points shape uh with either it's an error or it's a success right and we want to connect these together so to connect them together and you know again i can't just compose them together directly that won't work but if i convert the other ones into two tracks with binds and with bind then i can connect them together that's how we're going to do it we're going to write our code using bind and when we put it all together the actual final piece of code looks like this we take the input we feed it into the first function and then we need the next function but this is the bind version of the next function um and what we can do what's nice about this is we can take this whole thing and then wrap it in another function and this new function has the same shape right it's got one input and two outputs so this is just like the same kind of composition we've built a bigger function from a bunch of smaller functions so and then we can take this bigger function and connect it to other functions to make an even bigger function right so um i just want to point out that you can still transform the data as you go through right so you start off with an apple and turn it into banana and turn it into cherry and it does keep working right it's not that they're stuck okay and type checking still applies right the inputs and the outputs have to match so if the output is a banana and the input is a cherry that's no good right um let me do a quick demo i'm going to just switch to visual studio where are we here we go [Music] so there is our validation here's the little helper functions these little validation functions we want and sometimes you'll see people try to chain them together with these kind of ugly lambdas or you know things and it's like test each thing and if that works test the next thing and if that works test the next thing this really ugly code you often see this with async code as well or futures and stuff in javascript um don't do that use the result bind and it's so much easier and um again i can check what it works like if i have a bad name i can parse it in and i get the error name must not be blank so it's all working and again because i'm using um uh this pipeline thing i can add some new functions in if i want to add a new validation in let me add two new validations in i i can just without changing the existing codes i can just add some new ones in after the other ones so these this pipeline model is a really nice way of doing things right back to the slides so just to finish up i just want to talk about what can you do if you have different shapes of track because not everything uh has the same shape right not everything looks like these things so let's start off with one track functions so this is a what i call a one track function because it doesn't have any errors right just if i'm trimming the blanks and i'm lowercasing the email that's always going to work so this is a one track function it's not a it doesn't have a two outputs and the problem with that is it doesn't fit in our pipeline and so we have a problem how we're going to make it fit well the answer is we're going to do the same thing we did before we're going to put it through a function transformer which changes it into a two-track function and this is what it looks like so again same idea it comes in as a one-track function and it comes out as a two-track function and uh once we do that then it will fit so this is another function transformer type of thing you see these function transformers are really really common in functional programming right so uh this is typical map and this is its implementation again it's three lines of code it's really easy to write in if you're doing c sharp the select function in link is also a map type function and it's the same idea the implementation says something comes in and if it's on the success track you just call the function and you also have to um turn it back into the success track you have to put it in okay and then on the error track you just leave the error track alone and that's it very simple to write so once we've done that that works now we can fit it into our pipeline what about what i call a dead end function so a dead end function is a function that doesn't have any output like if you write to a database or you write to a file or you write to the network you don't normally get any useful output maybe you get the number of bytes written or something but it's not very useful so i'm going to call this a function with no output and um like i said it's very common when you're writing to something the problem is it doesn't fit into the pipeline so how do we fix this well we do the same thing we're going to transform it into a shape that does fit right and then we're going to do that by making an adapter block and calling the main calling that function and then we just return the original input out again and now now it works so we can fit it into our two track model and let's also talk about functions for exceptions because often you have a function that looks like a normal function but it actually can throw an exception and we don't want to do that so here's a function let's say i want to send an email and um it looks innocent but maybe it throws a timeout exception right and that causes our system to crash so what we're going to do is put it in an adapter block and this adapter block is going to put a try catch around it so it'll handle the timeouts or something and turn it into a nice error that we can work with right so we're turning it from a one track function with exceptions into a two-track function without exceptions now that's not strictly to certain exceptions you shouldn't catch you shouldn't catch out of memory you shouldn't catch null reference you shouldn't catch divide by zero so if it's a bug if it's a programmer problem or a system problem there's nothing you can do uh you should only catch the main models um you know errors which are part of your core domain model not not program errors right so um this thing of don't try and use exceptions for control flow if you expect something use a failure use an error right and if you're a star wars fan you all know this the star yoda actually said don't use exceptions for control flow you may have not known this but he actually said do or do not there is no try so yes don't use try for uh control flow right so here's here's what we had we had these functions that they wouldn't compose together and we're using these function transformers to change their shape so that they do fit together so the first one the the one with the two outputs we turned it into two track with bind then we the the other one with one track we turned it into two track with map and then the dead end one we kind of turned it into a normal one track and then we could use map of that and then the error throwing one the exception throwing one we could turn it into a points function and then we can use bind and that so we're using all these different transforming functions to make them all fit together and this is the really really common pattern in functional programming is to use these function transformers so this is what we had before where they none of them really fit together very well and after we've done the transformation they fit together really well so now um we can compose them together so let's put it all together into a pipeline we have our inputs our outputs um we get the output though we have a problem because it's two track outputs and your web browser probably doesn't understand new tracks so we need an extra little adapter thing to collapse the two tracks back into one so if you're doing a web application it'll probably be pretty simple if it's okay you're gonna say that's 200 and if there's an error that's going to be a 400 or something obviously it would be more complicated in real life but that's the basic idea it's pretty straightforward to handle both of them right so i'm going to do one more demo and i'll show you the complete pipeline as i promised whoops okay right so i'm going to load up some code here this is our request that we want to use and then here is our validation functions that we talked about before right you see this error or is it okay and then i can combine these three these two these three validations using result bind so i now have a new validation function which is a bigger one and that will fit into the big scheme of things and interactively i can like test things right i can test before i even build the rest of it i can just make sure that one's good the good requests yeah that's okay but i have a bad request and um that is uh not so good right uh and um finally i have an unsendable request uh and that it's unsendable it'll cause the email system to crash i'm running out of time so i'm just going to just show you the code i'm not really going to go through the code but i can highlight all this code this is the update the database one and then this is me transforming it into a two-track version using the result map here and and so on and so forth email that's the bad email and then i can turn it into the two track email by wrapping it with my catch thing so i'm not gonna go like i say you can look at the code later on um but finally and this i can put a logo in here because i can put logging in anywhere so you know i've got my validation i've got my email i've got my updated database i've got my sending i've got my logger and then finally i can return the response like i showed you before with the 200 or 400 and uh there's the overall piece of code right and i can put the whole thing into a function like this and there it is so as i promised this is doing error handling because if i put in a good request it says 200.
and if i put in a bad request it says you know 400 and they must not be blank and if i put in a an unsendable request it says you know it updates the database but it can't send the email so all that stuff is working fine and there's no the error handling is not obvious it's nice and clean right it doesn't look ugly at all scott yes thank you for talk it was brilliant okay i would like i would like to invite everyone to the discussion booth which starts in 5 seconds see you there have a nice time thank you
Up Next

Machine Learning with Python: A Beginner's Guide to AI Models
@CognitiveClass
35.2K views•2017-03-07

Building Real-Time ML Pipelines with Feature Stores and MLOps Frameworks
@ODSCAI
5.1K views•2022-02-20

Bypassing Tor Censorship: Bridges and Pluggable Transport Guide
@Coding_ForEveryone
397 views•2024-06-11

Neural Networks Explained: Math, Layers, and Learning Fundamentals
@3blue1brown
21.9M views•2017-10-05
Related Study Plans & Knowledge Roadmaps
Structured learning paths in Artificial Intelligence









![BJC Lecture 4: Functions [1080p HD]](https://i.ytimg.com/vi/_uKCBmQEf5w/maxresdefault.jpg)




























