Devreal

SF Scala at Twitter: Travis Brown, Some possible futures for Finch

SF Scala at Twitter: Travis Brown, Some possible futures for Finch

Recording: SF Scala at Twitter: Travis Brown, Some possible futures for Finch

okay so i'm travis browne i'm going to be talking about so vladimir just gave us a history of finch i'm going to be talking about the some a couple of the directions that Finch is going specifically in terms of integration with these two third-party libraries shapeless and cats the cats integration is still something that's on the table it's not definite but the shapeless integration is already in the master branch on github and it will be available in the Finch 07 release so first of all how many people could I just see a show of hands how many people have used shapeless before or okay wow so so almost probably a third to half of the room has that that's that's more people than I expected so I will give a kind of introduction to shapeless first and talk and some motivation for why we would why we want to use it in Finch okay so shapeless is a library for generic programming in Scala and what that means is that it provides us a bunch of abstractions and and generic operations for things like like tuples so how many people have at some point really wish that Scala gave you a way to take two tuples and combine them into a bigger tuple okay so a lot of people this is something that that's it's it feels like a piece that's possibly missing from the Scala standard library another another issue is shapeless gives you abstraction over functionality so basically anytime you have these these like 21 22 23 24 or function one function to function three function for in the standard library the standard library isn't going to help you abstract over that tuple in part but shapeless does okay another thing this is the this is mostly new in the boilerplate freeway in shapeless too but shapeless gives you facilities for abstracting over case classes so I'll show an example of what that looks like in just a minute in the same way it gives you a way of mapping really cleanly between case classes and tuples okay and it also has a lot of other really useful things so you can kind of think about it as like the opposite of juice so in shapeless we're trying to take everything we can and encode it in the type system so that the Scala compiler is helping us make sure that our program is correct before we ever run our program okay so things like statically size collections and type level natural numbers okay so here's this is all you need to do if you have a shapeless dependency to add it to two pulls together it's that big enough to see okay okay so what we've done here is and we've got a tuple of a symbol in a string and then a tuple of some numbers we use this + + operator that shapeless provides and we get a tuple of five things and you'll see that in the repple hear the static type of the result is exactly what we want this is entirely typesafe we're not going to ever get any kind of runtime error working with these operators okay so that's a very simple example that's that's just one nice operator that shapeless provides this is a more complex example where I'm trying to do something that at first it might seem like you would just take an enormous amount of of boilerplate but so I've got these two case classes right here and they have they have members that have the same types in the same names but they're in different orders and so I'd like to write a generic method for taking any two case classes that have the same member names and say member types in different orders and convert them between each other and this is all the code that I need to do that so it looks kind of messy like it's intimidating and there's a bunch of type class instances there but that's all the code that you need to convert any to quase classes that share these properties between each other so it's really powerful operation that we're able to do very concisely because we've got these these powerful type classes okay so this is the kind of thing that you could do with a macro so I could write a macro pretty easily it would be maybe 40 lines of code or so that would take any 2 k's classes that share these properties and can provide converters between them but it's really nice if you can to to avoid writing these kinds of one-off macros so the idea behind these operations and shapeless is that it's let somebody else write the macros for you and let them make sure that they're minimal that they're going to be well-maintained and that they're well tested but it's not something that you have to have in many cases in your own code base and shapeless gives you away to use the power of macros but not have them in your own code base okay so also i've been using tables for a few years and there's just a lot of really fun stuff that you can do with it so here i've got links to a solution of the Tower of Hanoi towers of Hanoi problem at the type level where when you compile your program you specify the problem instance and the compiler will actually solve the problem and print it out while it's compiling your program so it's it's frivolous it doesn't mean anything but it's kind of cool that you can make the Scala compiler actually solve this kind of problem at compile time ok so but shapeless isn't just a toy so there are lots and lots of of really important uses of shapeless so the specs library for example inspects to is using it in the given and win Combinator's spray is using it for its routers and then s codec is anybody used s codec before ok so s codec is by far in my opinion the best library and Scala for doing binary serialization it's just it's really amazing really beautiful encourage you to take a look ok and then parboiled is a parsing parlor Combinator library that is it's much it's much more oriented towards performance than the parser Combinator's in the standard library ok so before I move on to how we're using shapeless in Finch I want to give a really quick introduction to cats so who has heard about the cats project in Scala Wow again a lot more people than I would have expected um so cats is only three months old so it started at the very end of january or the very beginning of februari but the idea behind cats is that it's a it's a library for functional programming abstractions in Scala what other library does this sound like ok yeah if it sounds a lot like Scala Zed and cats is in a lot of ways a direct descendant of Scala said there are a few differences in terms of emphasis so cats is built on a couple of different compiler and build system plugins like simulacrum and machinist and another one called kind projector that allow you to make the code base a lot cleaner so the cats codebase the goal is as little boilerplate as possible through the use of these compiler and build system plugins I mean it's also there's more of a focus on performance in cats so it's still very young but this is something that is more explicitly a goal of the cat's project and it's ever been for Scala said it's it's more willing to so it's not trying to be Haskell in Scala it's trying to provide functional functional abstractions in Scala and it's more willing at least to make compromises when necessary to provide these this as a scholar library not as an attempt to turn Scala into something else okay so yeah and it's still very very young okay so because it is very very young it's still this is still so the shapeless stuff is already in Finch the cat stuff is it's possibly on the table for Finch one point oh but it might appear in Finch after one point oh I'm depending on what how how quickly cats development moves along but the idea is that there are lots and lots of functional programming abstractions that we're using in Finch unlike the reader monad like the validation type which is like either accept it allows you to accumulate errors on the left side and then things like monoid like the it's it's nice to have representations of these things so the scholars standard library doesn't give you representations of monads or applicative functors or functors even though it kind of has them built into its syntactic sugar and cats provide you with explicit representations of all those things so it's nice to have these things it would be nice not to have to rewrite them from scratch in Finch which is more or less what we're currently doing okay so for both of these libraries shapeless and cats the kind of big picture motivation is let's clean up Finch by instead of rebuilding these abstractions inside a Finch for ourselves let's bring them in bring that functionality in through these these well tested well maintained third-party libraries also let's let's do away with all of the era debased boilerplate so every time we've got some kind of function that we have to write 22 times because we need to cover all 22 function ends or tuple ends let's get rid of all of that also let's provide more type safety where we can and actually instead of using integration with these libraries letting it be something that makes our a plea is more complex and let's let's take it as an opportunity to make our API is more elegant ok so the links are here is pretty easy if you google shapeless scholar cat skull as well you'll come across across these projects but I'd encourage you to take a look at them ok so I'm going to focus on this this request reader app type in in bench because it's it's pretty easy to wrap your head around what it does so it takes a an HTTP request coming in and it parses some information out of that request like query parameters or what are the body or whatever you need and gives you some some new type so the request and that new type is returned in a future so you can't potentially fail and it might it might take a while all that's modeled in the type system so it's a when we have something that is a request reader user here what that actually is is a wrapper around the function from an HTTP request to a user inside of a future and this is so in Finch 06 this is what it looks like to write a request reader for a forecast class so it's actually it's really elegant it's it's a nice very simple API where what we're doing is saying we want to take a quit an ID query parameter parse it as a long and then compose it with a name parameter and then pipe those both into our user type so it's it's very nice but it does have a few drawbacks so one of the drawbacks is that this this Tildy here is actually a case class and that's something that that it's it's a very generic thing but it's something that we have to maintain and there are a lot of operations that are a handful of operations that go along with it that are part of the Finch codebase that are super generic that there's no particular reason that they need to live inside a Finch it's got I'm going to take a risk and click a link here this is an example of what the air d the era d boilerplate looks like we have to if we want that nice little till the arrow operator we've got to write all of this boilerplate code it's just a mess you can actually have the we kind of have this done inside of like as something that's run at the compile time by the build system but it either way it's a it's a pain to have to maintain this kind of boilerplate okay and the case class support is fairly limited so in that example we're seeing the till the arrow go into the user although is happening there is we were piping it into the user dot apply method okay so this is the new I think this landed two days ago in master a couple of days ago so this is the new shapeless style way of doing exactly the same thing so here again we've got that user case class and where we have a parameter ID in exactly the same way we pars it into a long and then we compose it not using a Tildy but using this this colon colon and then we instead of piping it with the with until the arrow we just say we want to use this as a user so it's very very similar in terms of the syntax but we've done away with a lot of the specific but a lot of the the types and Finch that don't need to actually live in Finch so instead of our Tildy type hour till decays class we're using shapeless as H list all of that era t boilerplate just goes away we can we can write those those till the operators using shape Lissa's abstraction over function arity and we get much nicer case class support so this is an example of what that much nicer case class support looks like so what's happening here is that we don't even have to specify so in those previous examples we had to say we want to read a parameter named with the key ID out of our query string in this case we're going to let the compiler figure out that this case class has two members named ID and name and actually find those those keys in the query string so it's just we don't we have to write basically nothing and the nice thing too is that if we change our user case class we don't have to worry about updating it here as well so this is actually it looks very very simple but what's happening behind the scenes is pretty complicated because so first the macro has to analyze the case class and say ok the case class has members with these field names and these field types and then we have to create pram readers for each of those those name type pairs and then we have to be sure that for each of those types we have decode result instances in scope so that we actually know how to parse that query parameter into whatever type we need for our case class and then we compose all of these pieces into a request reader so without writing a single new macro we're doing all of that at compile time in this one line of code so it's completely typesafe if for some reason like our user has some kind of has some kind of member of a type that we don't know how to parse out of a query string parameter and we'll get a failure at compile time not at runtime okay and this is not quite in in shapeless yet we're trying to figure out so i don't really like this API it's kind of necessary to this this dot-to-dot from params it's necessary to work around the fact that we can't partially apply type parameters in Scala but it's not too bad and it gives us a way to say like a request reader to user from body or from some other piece of the HTTP request okay so we went through this already okay any questions about shape about shapeless and Finch before we move on to cats if we have time we can look in a little bit more detail at how that's actually implemented but the nice thing is it's very very little code so we've taken a lot of code out of finch and we put in we've added a new dependency but it's a dependency that we trust and we've we've basically its net deletion of a ton of code okay so I'm going to again focus on the request reader because it is this nice simple type and in the same way that we provided nicer ways of composing and building up request readers using shapeless here I'm going to look at how we can actually throw out our request reader type entirely so there is no more request reader in Finch after this change which is much much further in the future will just be a type alias it won't even there won't be a request reader class and Finch so as Vladimir mentioned this so the the pee in front of here this is a slightly more generic version of the of the request reader where it can take any kind of input not just an HTTP request and in this form this is basically a function from some fixed type a to some type inside of a future and then when we take off the p that's a type alias in the current version of finch for the same thing but we fix that first we fix that input type to HTTP request and this is called this is called in the kind of functional programming literature a reader monad and there's a good discussion on the on the finch website by vladimir of what that means with some some links to other resources so if this is a term that you've never seen before I'd encourage you to take a look at follow this link and take a look at the resources there okay yeah so this is just a wrapper for a function a to some some future type yes so this is actually a very specific kind of monad the so like list is a monad for example and list doesn't really have that shape at all so what this means is that this this so vladimir showed earlier the kind of nice for comprehensions for building up your request readers where you have four and then you pull out like one Pete one of the query parameters by name and then you pull out the body by name and then you you compose it using this for comprehension and that for comprehension we can do because request reader is a monad so that's basically all it means it's going to do gurtu calls to flat map and map behind the scenes yeah so so this this specific shape that is it's an example of a monad it's not what makes a monad yeah good question other questions before we go on okay so this is a little bit confusing and I wish that the terminology was standardized here but so a reader monad where you have this kind of type constructor in the return type so reader monad is just a wrapper for a function but a reader monad where you have a type constructor around the return type so we've got like a into future mb or a into list be that's also called a cly's Lee arrow and so what we can say is that our reader our request reader and Finch is just a clys Lee arrow over future just being kind of hand wavy but the thing is that there's a really nice implementation of cly's Lee arrows in cats so you can see here it's a little small that this is just a case class that wraps a function from A to F of B so this this class looks very very very similar to the definition of requests reader in in Finch so what we've done is we fix that F to be future but otherwise this class looks very similar the map method is almost exactly the same the flat maps almost exactly the same the there are some other Combinator's that have different names and Finch but they have almost exact equivalents in the cat's implementation so that's an opportunity that's a place where we can make Finch smaller by bringing in this functionality from this library okay so this is a brand new experiment and this is something that there's no guarantee that will it will ever actually make it into cats but it's something that we're very interested in and that we think has a lot of promise where I've got a branch in my fork of cats where I've torn out request reader and P request reader entirely and replace them with the yeah so here-here's request reader just going away so there's no more request reader class in Finch instead request reader is just a type alias for fork lies Lee in cats so this is pretty cool we can get rid of a lot of code we don't have to implement our own map on flat map around in bed flat map all of these Combinator's that are really useful we can let somebody else test somebody else implement somebody else maintain okay so yeah I already mentioned these parts in some places the the API and Finch when this happens eventually we'll have to change or we could provide aliases but this is actually I think a really good thing because it standardizes the terminology in the community so anybody who's using Finch who also is using cats or seen cats before will know oh I've got this function that I want to use on my request reader that takes an a and maps it into a future instead of into another request reader that function is going to be called flat map k it's not going to be called regular flat map so it's nice that we have an embed flat map and pinch right now but if we can use the standard terminology that's going to be familiar to the community it's even nicer okay some other stuff this is some of this is more minor but I'm so right now there's a there's a custom to future method that is enriched onto any any type you want we threw an implicit conversion in in Finch and that goes away we've already got that in in cats we also have these things like so so is our people familiar with the idea of applicative applicative validation for error accumulation how many people have seen this before this okay okay um so basically what this means is we've got a bunch of operations that can fail and we want to run those operations in parallel and collect the failures instead of just having the entire computation fail with a single failure we're doing that in Finch in a way that works and it's nice but it's it's ad hoc compared to if we were using validation or validated from cats okay there's lots of this stuff so this this is another this is a brand new project that I started one night last week because i was i was playing around with this with using cats and finch and i realized that a lot of the stuff i was writing was not specific to finch so i factored out like the like we really need a monad in for future why does I need to live in Finch so that's moved into this project that's currently in my own github repository but it'll probably move to the finagle organization or somewhere else at some point called catbird so this provides things like like bye Jek shins between finagle services and clys lee arrows provides monad instances and other things for future and other types so eventually none of this is sudden stone yet but the idea is that this this or some something like this this is very experimental at this point would provide these kind of fundamental instances for Twitter you till four finagle and then Finch would build on top of that ok so the advantages of both of these the current integration was shapeless and the integration with cats is less code we shared types and names with the community so if somebody else has written written some kind of operation that works on class lee arrows they can just plug a request reader into it and will do exactly what they expect and when they're reading the finch code if they see if they see these operator names they'll know exactly what they do because they're the same library so those are two of the advantages and one of the really nice things is that if you do the API design right the changes are pretty minimal so we no longer have the Tildy Tildy arrow stuff but the semicolon is almost identical it's basically a mechanical transformation and in the case of request reader the the actual changes to user code will be even smaller so for the most part that we're not we're using these libraries that are built on complex ideas and complex implementations and complex macros in some cases but we're not forcing that complexity on the user of Finch ok so I'm offered time so there's some things that we want to wrap up for the current shapeless pizzas and Finch like that that kind of full derivation of request readers from case classes without any input from the user in terms of naming parameter stuff like that that needs to be more generic where we can't actually pull things in from the body we can make things optional and that's going to happen in that pull request that I linked earlier this is still something that we're working out exactly what it should look like but the the idea that Vladimir mentioned of heterogeneous routers where you have a router that's composed of differently typed routers and then you use shapeless to prove things about the types for each of those components that's something that I'm hoping to have some time to get a good draft for review done this weekend and then so Argonaut shapeless is a so argonaut is the currently suggested like default JSON library and Finch you can definitely use it it's with Jackson as well but when you just fire up the finch console from scratch you're going to get Argonaut included there and there's a nice argonaut shapeless library that let us show off even more the power of shapeless here so those are a few of the next steps and then we need to continue thinking about whether it makes sense given the development of cats to to bring in cats integration as well and that's something that will be will be probably i'll be i'll continue development in a separate cats branch and try to keep it as closely in sync with with Finch master as I can over the next few months possibly okay so can anybody guess what some of the concerns would be yes the heirs you get when things don't compile yeah that's a good one so I shapeless is likely to be a little better at this because shapeless is on it on a two point O version at this point and a lot of attention has been put into trying to make the errors intelligible but yeah that's definitely a concern other stuff yeah right right there are no longer Yeah right I think that this is a this is a really good point that the idea is that if I'm just sitting down in writing a set of services and routers for the services I have an API that looks like the API is before shapeless or it's very very similar but as soon as I need to go in and actually look at what the code looks like it's going to be potentially really intimidating and so yeah I think that that's definitely the fact that we're using like the code base underneath the API is going to stay as consistent as we can as we add shapeless integration as we at some point we possibly bringing cats types but and the code underneath that is going to shrink because we can pull out a lot of this stuff but it's also going to become potentially less readable so I think yeah the it's our job and it's definitely our responsibility to make sure that that's being well documented if we keep moving in this direction yeah it's a good point other questions or i mean are other things that you would like if I was good if I if I was working for you and I said hey I'm going to do this to our library what would you say in response yeah or whether right right I am I am technically a cat's contributor so I have I have some say here but yeah I think they're a pretty reasonable group so yeah that's also a concern though so we are turning over some of our power / AP editor over the design of our library to a third party and we might not always get the things we want this is actually one of the reasons that Twitter hasn't ever used Scala Zed it's because Scala said team just we don't care about performance we care about correctness we care about functional purity we really needed performance changes and so in a couple of Twitter libraries we've implemented our own version of monad clickety functor things like that yeah but it's a good point yes right right yeah yeah so this is something that that I feel like the the community around shapeless which overlaps a lot with the community around cats is is converging on a so yeah the issue is that you're likely if you're using these kinds of libraries to pull in a shapeless dependency from somewhere else and then if you have to worry about keeping that in sync with with cat with Finch's shapeless dependency it can be really painful so yeah I think this in this case the responsibility is on the community to keep versions up to date and that sucks yeah the new one oh right right yeah when is this come in is that what that's shapeless three Irish call a three-pointer okay right right yeah um okay yes yeah this is another good point so this is something that that miles the the leader of the shapeless project has been he's been pushing for a more more modular shapeless three-point oh so it's it's not a huge dependency to start with and we are using quite a bit of it but yeah we're not using right now at least the this statically sized do you mind logging yourself back in sorry the statically sighs collections there are a lot of parts of shapeless that we're not currently using but yeah that will get better in so shapeless 2 point 0 is on it's one of its later release candidates now and I think that the next the the plan is to move on to shapeless three-point oh pretty quickly after that but yeah a more module that so cats is one this is another thing that I should actually put in the slides so one of the differences between cats and scholars ed is cats is much more modular so you have a core module that only includes the core type classes and a few data types and then and then all of the standard library instances are in a separate module all the other the pieces like the free monads stuff all of that is in in separate modules so that's the direction the cats has been going from the beginning in contrast to scholars head and that's the direction that shapeless is moving other questions yeah what are the things that any interested disease a separating router functionality has its own separate by 31 frustrating things about working and trying to choose to be different pace you eat right works right Robert psls are propagating like one every weekend yeah it would be great to have a standard way of defining or proud to say a service interface that's shared separate from an underlying education yeah I think what you're describing something like the probably the better route no I definitely so are you thinking of this as is even more generic than that it's not finagle specific or okay right yeah so so right now we've got this P request type in in the current version of a bench and also in whatever cats version of Finch there will be and the P request type is not fanatical specific but as soon as we fix it as soon as we fix that input type to HTTP requests then it becomes finagle specific yeah it also returns Twitter future so those are the two so yeah if you don't fix that first argument you still have a Twitter you till dependency I think that it gets really difficult to have something that's both generic and that if we throw yeah if we move away from the from the from the tonight I can imagine having a nice rather like generic router library that doesn't have the finagle dependency but you really need something like I guess you could do this the Scala standard library futures but then you're in a different a different set of interoperability problems yeah okay I guess I kind of got derailed in two questions there when I was still going through so most of these things we mentioned already except performance so this is something that didn't come up so what is the performance impact of these these kinds of operations anybody have any guesses yeah right Rach you concatenate tuples you create richness that you right yeah i did a little garnish yeah you you will you will do a lot more allocation when you're using shapeless that's not as much of a so the way that we're using shapeless is actually a pretty it's pretty much a drop-in replacement for that Tildy type which is basically like a kind of H list itself so there we didn't add at least we didn't massively add allocations when we switched from till d2h list I we haven't actually benchmarked this yet but it's a pretty small change so far and I think it will we should benchmark it sooner rather than later but yeah in that case it is just a drop in of H list for Tildy so you're not going to see massive differences but yeah one of the nice things about shapeless is that you do have these type class instances that do float around at runtime but all of the type class instance resolution happens at compile time so so most of the complex computation that shapeless is doing is happening at compile time because there's issues with only one fetus those instances just like scholars issues with functions out maybe yeah its colonies to talk to her about it right as soon as you have three different instances of function everything becomes terribly slow I don't really know I don't I don't know if I've seen a good good examination of that issue in shapeless but yeah it's a good point so just as one thing that we have benchmarked so there's a kind of sister project to Finch it's much less well-developed it's something that Vladimir not put together during hack week at Twitter in January the second link here finagle serial so finagle serial is basically trying to do what Finch does for HTTP services for binary services so instead of instead of IDL based binary services you have binary services that are built on top of the S codec binary serialization library which is a type class serialization library so and in Finch we have actually done benchmarks of I'm sorry infini go serial of finagle serial services versus thrift services on finagle and you get about half the throughput so you are paying a price but you're you're getting a massively simpler build process in API and I'd encourage you to take a look at the nagal cereal it is it's a as far as I know nobody's using it in production or anything like production but it is a really interesting little project that allows you to write finagle services that you can actually use in a real-world way in four or five lines of code okay so yeah that's the closest thing that we have to have in it and because it's built on s codec it's also built on shapeless so I would imagine that in the case of Finch you don't see so if you're taking just a pure finagle HTTP service and comparing it to a Finch service you're not going to see anywhere near that that like half the three puts slow down and because there's much less rapper going on but yeah there is a there is a runtime cost okay I guess we can go ahead and think that was my last slide yeah other questions I guess I could pass this around yes yeah that's a really good question so the reason is is because almost everything under the Twitter organization on github lives in our internal mono repo and is and is synced out to github and the things under the finagle organization live primarily on github and if they're used internally they're synced internally so it's it's just it's a matter of which direction things are going whether they're they're going from the mono repo out and then being synced back in or whether they primarily live on github and our occasionally synced internally does that yeah it's something that could be better articulated in seems tall oh just one okay so is this wait just what is this a vote of confidence should we continue in this direction with shapeless integration cats does anybody if you were going to use Finch before and you saw this presentation are you like no I'm not going to use Finch now or yes I'm sorry Oh awesome okay great thanks yes micros on its way out anyway yeah so the idea of so so what ya I'm sorry to the now we're actually treating request reader directly as a clot as a close Lee arrow and finagle services are closed Laros and this whole like micros wanted him to do this kind of unification we get that unification for free if we go the cats route it's further in the future and micro will go away before that I think Mike Rowe has already been deprecated right yeah but it but it's it's it's a it's an attempt along a different angle towards the same general goal is that right son right brother right I was trying to solve the problem all I was in the rolls or something from tires so you can confirm something to various pause so you can come home in a blizzard commercial flight with a lot of time and I believe hit your genius from tercis ockenden it's not your place right now yeah yeah so keep an eye open for the work that should be coming up in the next week on the heterogeneous routers yes talk to your doctors about people or actually weren't any patient production how they feel about categories something to their yes and so look most of these people right now are either in this room or on the getter channel or pretty consistently so yeah then all of this stuff is being run past the people who are currently using Finch and production I'm very positive as far as I've seen I don't live in the ghetto channel all the time but Vladimir does that seem yes I think as long I try to keep the API right just understand dinner's ready yeah you can use my office kiss there's no yeah cuz I'm even here with people were the sea scholars at Rome right yeah and again like you won't even have to unless you dig into the code base you will never see the word closely because we have this type alias which is P request reader and it behaves exactly the same as as our old p request reader it's just it's implemented in cats as a class Lee arrow so yeah the the actual things that people will see if they dig down it gets scary but you don't have to get that far and this is modeled so we're really inspired by the s codec API which is just really beautiful and built on on shapeless and you never have to see see shapeless unless you do dig down into the code lots of people are using it happily without being shapeless experts so yeah we want to stay pretty close to that I do okay okay I'm done sorry