Devreal

Scale By The Bay 2018 Unconference: Gabriel Volpe

Scale By The Bay 2018 Unconference: Gabriel Volpe

Recording: Scale By The Bay 2018 Unconference: Gabriel Volpe

everyone thank you for staying here I don't have anything really prepared for this talk so it's gonna be like everything more like life demo and showing some bunch of code so this is me I'm my name is Gabriel and I wrote a blog post a few months ago and about error handling in HTTP for us using this fancy library called me out MTL so if you don't understand much what I'm saying here because I only have 20 minutes you can always come back to this blog post check it out I think quality spoil okay I haven't reviewed by Ross here so I think as quality is a guarantee of quality sir so yeah I'm just like this is the library I'm gonna be showing it's called mio MTL it's basically next level MTL built on top of cuts MTL and cuts effects so it provides some a few bunch of instances and it makes it really easy to work with the MTL a material style and tactless finance color so I created this repository if you want to follow follow along with the code it's called classy optics so all the code that I'm gonna be showing now it's here I wrote it yesterday sure it's compiling so I think so yeah let's get started like let's get started with this I have him how this this code here and the idea you know like reading configuration something very basic I created this bunch of case classes here I'm using the pure conflict library to read the configurations like this application comes in the idea was scared we can applicative ask it's like the the MTL equivalent of like kind of like the mana tree derp but it's just like operates on the applicative side and the idea is just like it can carry some context it's like glossary or like reader tea but on the empty level so we can use it as an S&M TL as a type class here right so we we can define this bunch of programs here I define this type Alice's like to make the code more readable but it's you could just use applicative asked straightaway here but I think this is this makes the code like much more readable and much more easier to understand so I have these three different programs here this one has all of them had a parametric F type type constructor and he has these sync type licenses from cuts effects and then has up config in this case and I defined just say a method foo just to you know show you how how it works but basically we can we can implicitly ask for for this instance of an applicative ask of F in app config we call a scan which is flat map and access the configuration and just like printing print online of the configuration not doing much more and I have two more similar programs from to and program three which they look exactly the same the only difference is like the the configuration is is a different type so one has the up config the other one HTTP server config and and the other one has a service config so this makes it clear there you know we have really big configuration file in a case class data structure we don't want to share the whole conflict you know to every component in our application so this way we can just ask for whatever we need exactly what we need but there is an issue like whenever we want to instantiate this this type classes if you want to combine program one program to and program three you're gonna have issues like with the what is the instance well how can we provide an instance for applicative ask all these three different types and we're gonna have some kind of conflicts there and one way like to work with MTL type classes is just to use mana transformers which is the way that i use it here so in this case I'm kind of cheating because I'm I'm using crisi which is the aridity of the three different types and then my effect type which as IO and I should run the effect with the with the configuration that I already loaded so I'm kind of doing this manually but if I try to compile it combined all these problems you wouldn't compile because the instance was not much they did we have a three different instances of the same type class so we get we get in an error there so how can I think I think we just I can also run this just so you can see how it runs yeah similar one just try printing line of the configuration basically reading with pure config so yeah I was like kind of cheating in this case so is there any way we can kind of like have a single instance of this applicative ask and inhabit you know accessible to up config HTTP server conflict in service conflict look HTTP servant and in service config are just nested data structures of up config so it means that we can probably access that and and that's what lenses do or classy lenses like operate at the data structure layer are the type last level so this is what this nice library called meow MTL provides so just gonna comment this here that's that's an importer that's all the magic but basically in this case I'm just defining an instance of applicative ask for i/o job normally in Scala you just write all these things this manually for performance reasons you so you just want to have a single type at the end of the war which is either I or tasks or whatever is your effect type like normally this is preferable for performance reasons if you use mana transformers they are terrible in Scala is super slow so this is more recommendable to use so in this case our effect type it just it's just uh oh so we are not using class 3 anymore we don't have very dirty kind of like different instances and we have we instant initiate our three different programs with the same effect type but if you go back to the definition of program one program to and program three they require different instances of applicative ask right so this code here shouldn't compile because our f like only p1 will compile which has the right instance but the other two will complain and we can we can we can verify that and try to compile that hopefully it works yeah so p1 it was alright no problems at p2 and p3 its complaining because it doesn't have the right instance of applicative tasks in this this is what this library does so if we just go back here and uncomment this this is like kind of black magic like import this and what this library will do or we can try to compile it first call compile again and now it passes and we can even run this demo to go it works and then how does it work well by important this like calm or like or like this hierarchy underscore it actually derives all these lenses for you so we have this applicative ask of application config again go back to the definition right so we have app config which has HTTP server config and service config and if you create this case class on your own you say you have an app config in order to access the inner data structures like HTTP service in nature and you just like you know have to access that data structure and that's what is kind of like zooming in into the data structure or zooming out if you wanna go back and forth and this is what the concept of lenses are and miscalled classy lenses cause operates on at the type class level so what this library is gonna do with this magic import it's just going to derive all these lenses instances for you all you have to do is just like parameterize your your problems with the different constraints fabricate if asked and the library will magically will magically derive the instances so you can zoom in and into this data structures in the lenses update other type last level I think that's that's super amazing so now that we define this I'm gonna go back and show a different more interesting use case for this is like this is a very interesting use case another one it's something that I discover that we could do for HTTP for us it's like we have this algebra here so basically use your user interface parameter is an arbitrary F and we have some a bunch of user errors here I'll explain later why extends exception but ignore that for now and this is how you define and routes in HTTP for us right so that this is the normal way we have an instance we have we require our parameterize F to be a sink which is a type a cut effect type class which allow us to defer effects side effects so normally sink extends monitor or of F with the fixed type which is trouble so it means that if you want to have a mana another one at our instance here of our of our ADT type it's kind of getting conflict with these instances already in scope so we can't do that so but we can do this this kind of stuff we can just call or our services and handle the the errors manually one by one in in the cases where we needed to handle the errors right so this is a common way and it's like one of the ways that most people do it and that was the way that we were doing it before as well another interesting way of handling errors is trying to leverage these MTL type classes and come up with a different way of seeing these say okay how we can you know get around this constraint that we have this Mona terror of troll already in scope but we want to handle errors of our species specific ADT of errors so come up with this which is an alternative okay extract all this error handling in the different era so we defined this HTTP error handler of F in our user error which is represents an ADT of errors and we just handle errors at the roots level basically we define all the roots and we know that that we need to handle this specific type of errors in these roads and how does it look like this is how our handle is defined so you see the constraint and probable here this is a limitation because a cuts effects basically fixed the error type to preferable so in order to get around that we have to define the our error type has to that's why we extend exception there out trouble so yeah so this is just an util case I just - it's gonna be generic in using it every time but this is how the type class looks like and it's how the instance looks like so we define our instance for our a specific ADT error and in this case we require our F to be a monetary of our specific error type and so we don't have the constraint of sync here so we don't we don't have this conflict of instances which is super cool and we are liberating the MTL this library meow ntl to do the derivation of the instances for us so the same way with applicative asked we could derive like the lenses to access the inner the inner data type we could zoom in it does the same for the mana terror as well because user error extends exception which is a subtype of trouble so it can figure it out for you and that's amazing I think we can get back here if you add a new error to our ADT we're gonna get you know non-exhaustive pattern matching there so you're gonna get compiler or see if we if we like for example if I just comment this try to compile I believe I should get an error there right so much may not be exhaustive so we gain again this is type safety again once again I know there there's a few caveats with this this approach and it's like we don't win exactly but we don't have an association of affair as well our easier algebra can raise errors in the context of F and we we don't really know so it requires some discipline from the programmer to say okay we have to kind of like mentalize that this is the HTTP error handler interface handle is a user error which our user algebra can race but there is no guarantee by the type system of that so few other approaches for example using the by front row which has a channel for error but I think it was an interesting experiment and and we've been using this this in production as well so I think it pays off it's it's nice if you have discipline in Scala so just to wrap it up I think this is the server here how it start the Blazer will build there and my type my F type is IO that's that's amazing and I just define an implicit error handler as our user HTTP error handler and I believe the import here what you saw sitting right there yeah so this import here is what that's all the magic and arrives it figures out that you know the one that error instance that you need when you create this new user HTTP error handler we already have a user monitor here of F in trouble so it figures out that user error is a subtype and it derives that instance for you and it's magic and it works so then yeah we can try to compile this should compile against a defier probably what was that fun oops don't even know I shouldn't I kind of like a hug so I can start the HTTP server and I'm not gonna show you so much but that's what I have so yeah I can take any questions if you have one but I don't want to delay more this talk so the next talk and any questions why thank you then [Applause]