Scale By The Bay 2018: Julie Laver, Getting started with EitherT
Recording: Scale By The Bay 2018: Julie Laver, Getting started with EitherT
all right before we get started fair warning I'm gonna say either a lot in this talk if you've ever tried to say either a hundred times it starts to get really hard real fast so if I trip up a bunch bear with me anyways I'm Julie I'm a software engineer on the messaging team at the messaging channels team at Twilio basically we make it easy for you to send your SMS or in the case of channels Facebook whatsapp or vine messages from your apps I've been working in Scala since I joined Twilio about four years ago and just when I was starting to think that Scala wasn't so bad after all I start to come across code that heavily used either T's that brings us to this talk we'll start with looking at either's Before we jump into either T's you can't really understand you know T's about understanding either's many of the examples in these slides are based on using either's for error handling you are in no way limited to do it using them for just that however it's a common cavies case and i like to use them for that so what is it either here are some properties of it either and either it can be a left or right it will wrap another value you can get context from the value depending on if it's a left or right they are right biased and we'll talk more about what that means in a couple of slides they are monads so you can apply functions such as map flatmap and fold to them in this case I have in either my either which can be either a string or an int the string will be our left and it will be our right we will if we want to create an either with a value that is an int such as totally right and if we want to create one with a that's one we simply wrap that in right if we wanted to do the same thing for a string we would take our string and we are wrapped by unless and this is sort of what is meant by a vest or right given context to the value if my either is a right we know it will be an int and if my either is a left we know it will be a string so let's go back to write back the right bias that I mentioned a few slides before this means that map and any other function such as flat mat fold etcetera only get applied if the either contains values that are right as opposed to left occasionally this is referred to as the happy side I have here a function it's doing something very important you can tell because it's called do something important we're passing in and into it and we're getting back and either of a string or an int basically if our integer that we pass in is not zero we will just wrap that value in a right and we will return that is are either otherwise we will return a string of you chose wrong cup a couple examples here in both of these examples our map function is simply adding one to the value if the value is right that is our first example we're passing one in to do something important which will give us back in either containing a right of one so we end up with in that first example either containing or right up to the second example we are passing zero and to do something important this gives us back our string wrapped in the left in this case the map function will not run and we will simply have our left often we have a situation where you may want to do multiple operations on this value here's an example of that using maps this first example will evaluate first of all we have a handful of variables first right second right and a left I bet you can guess which ones return rights and less in this first example we are using just the first right and the second right so this will evaluate to a right of three in the second example we've introduced the left nothing past this point we'll evaluate and we'll just be left with a left or we'll be left with what a left was which is you chose wrong when doing multiple calls you can chain them in four comprehensions like this as well if a left pops up you're going to fail fast and stop evaluating on the value of that either this makes sense if you think about it because if you were to go to the left say in this example you win it and we're trying to add a bunch of integers together you wouldn't have an integer to add together in this case you'd be unable to carry out that yields you may have already noticed that either lend themselves well to error handling we've already seen how you you're able to compose multiple either's together and evaluate them only when you have a right to use either for error handling we'll treat left as our error side and right as any successful value any time we encounter a left we can short-circuit our processing and instead handle the error if we choose let's take a look at a slightly more substantial example which uses either for head handling we have a trait processing error which we'll use on our left side basically this tray is just going to be any error that we want to bubble up to the end-user maybe someone's using this library and these are the errors they're going to see the method valid a person simply takes in a string and returns in either of this processing error or a string if they pass in null or empty string sorry we will return a system error wrapped in a left that's an invalid state so you get error State or a error back if they pass in a name as John Doe we will also treat this as an error a person does not exist they're also wrapped in a left and lastly anything else that they that they pass in for name we will treat as valid and return this as a right here so this is an example of it actually being used in this case for passing in two valid names so we're just going to end up with our array of a list containing both of these names this is very similar to what we saw a couple slides ago if we now will pass in invalid name and empty string this will return the left so we'll just we won't we'll stop processing and we'll end up with our left of system error but realistically it's not that simple nothing's that simple real life has micro-services and networks real life has network issues it will core database issues whatever it might be so you knew futures we're gonna show up somewhere you're gonna end up with these I'm sorry there's really no way around it let's all take a moment and accept this okay back to the slides so here we have our future real life it's a future of either of processing air events if we try to if if we wanted to use the int value in this we have to do a double unpack the first map gets us are either and then we map on that to get our right value it oops and we get our right value it already isn't very nice but don't worry it gets worse so in this case we again have a future of are either of our error type and we have this example here we're gonna do a check on a number and then use the result of that check to do a check on another number ignoring the fact that I'm checking the same number twice this is pretty realistic situation you might end up in where you're using the result of one check to do and some other check let's take a look at the return type this would give you yeah this example isn't even nearly as ugly as the first example I had up here but that one I couldn't leave that one up it just looked too bad so there has to be a better way and there is we have either T's so these what you combine two wrappers for example a future and either the either is always present because it's an either T but the other wrapper can be anything else you could use lists I'm using futures it's part of the cats library and it's also part of the skeleton library so here we have my either T it's an either T where the wrappers of future are left of a string and our rent is an int looks fairly similar to what we've been seeing before and we can unpack this so if we were to do my either T value we actually get back that same type we'd been seeing before future by either of a string of an int this also shows how you could create that it's really just you take your future your right and wrap that at either T so the example from a few slides ago that was a future of either of a ray of another future of another ray or whatever it was that would have been really not that useful for us this example is probably what we were trying to achieve there we're using we're doing a check we're using the result of that check to do another check and we're yielding the value however this gives us something that is much easier to read we just certain and with an either T of a future of all the errors event and it gives us something that's actually kind of useful to use alright now we know what an e30 is and why we may want to use it so let's take a look at some more practical examples the next few slides will go over some of these and some different functions that may come in handy if you're using either T's so first I'm gonna be referring to this with a little bit so let's talk about our error hierarchy now that you're writing complex programs and you have more air types that you have to convey you might have Network errors or system errors or user errors this is what we're gonna base it on here we have a couple of different sealed traits internal error and processing error are two separate traits and then these have some other case classes or objects extending them internal error we're going to use for things such as like Network error database errors anything that we don't want to expose to the end-user processing error or errors that we don't mind if this is a library we would pass up to the user and allow them to act on them as needed in many cases you might be using some Java libraries or other libraries which throw exceptions in order to keep your cut those out of my code I like pushing the either creation as far as I can to the edge or they mean by this so say I had a function it's get person from database and say it was querying a database this is very likely returning a future of just a future dot successful of say a string so what I'll do here is once you get your query result back I'll map over that if it's a right I create my either of that value as it right otherwise you can see there is a few errors I'm choose just to handle one and then everything else becomes a general exception but depending on the air type the two exceptions for example I say is a database error like I said this allows me to keep the rest of my code fairly clean and I don't need to worry about handling exceptions that other people might be throwing anywhere else so now some functions the other map aka the less map just like you converted an exception into an either sometimes you have to convert an either from one type to another so for example we have here and either T that's it has a left of an internal error maybe I want that left to be a processing error you know about map already but you can use less map to change the left side this might be if you're moving from one part of your program to another part of your program which uses a different error scheme basically this just lets you map over that left side and process it or change it from one type to another ensuring sometimes you may want to verify your right value meet the specific condition an example of this is if you want to fail fast if someone did not have any hobbies we did a look-up on a person we got that person back but maybe there's just they just don't have any hobbies listed you can use an insure function to check that the hobbies is an empty if for example it was empty in this case we would change our air type this would have been we were we would have had another processing error or we wouldn't have had a processing error we would have had a right sorry so we would now have either that with a left and a left of everyone has a hobby error and then lastly we have folding the only way we all know the only way to get rid of your future is to block on it you don't really want to do that but that's another discussion you can however get rid of your either tea by handling both cases and consolidating into one type in this example maybe I'm okay that if we had an error that we just returned and count of zero for how many hobbies a person had so that's what this is doing if there's an error if we had a left sorry or an error I'll just return zero a future that contains zero otherwise we'll count how many hobbies they had so either teas aren't the only mana monad transformer that exists there are other there's also option teas right your teas and some other ones which once you understand one these all sort of become a lot easier to use you're also not limited to using either's for error handling however it's a great way to express errors in functional programming either teas are simply a way to make working with either's and other structures such as futures a little bit easier alright that's it for the talk if you have any questions I'll be somewhere around you