Devreal

Understanding Scala's Type System

Event: A Tour of Caliban: FP GraphQL in Scala & Understanding Scala's Type System

SF Scala–A Tour of Caliban: FP GraphQL in Scala & Understanding Scala's Type System

Recording: SF Scala–A Tour of Caliban: FP GraphQL in Scala & Understanding Scala's Type System

in column it up and we are again hosted by the Monday's our host Erik thank you guys for hosting us and Michael Kaiser Salar is gonna run the show tonight Sal are put this together Thank You Sal are I just want to say a few words about the theme tonight we have the graph QL talk by Pierre and the type systems of by Bill we at SF skyline scale by the by thing the pioneering scholar community to share the graph QL ideas we had I think an invited talk about graph QL was just kind of hit the market it was always positioned as typed and performant a system which is obviously better FIFA scholar than JavaScript and we've been promoting it since then I think it took hold as I pretty much accepted middleware in the backend at Twitter and at medium and there is a huge interest now intuitive everybody is using it so it's a full stack technology super excited to see the talk about the Thank You seller for organizing than Pierre for speaking peers coming from Seoul so really amazing and will co-author of the scholar book has an update in the talk about scholars it's always great to have bill so I think we have a fantastic meet up tonight hope everybody enjoys it I know it's fried it's unusual so let's see how this goes already 40 participants exciting and with that I think demand base and hand it off to salaam arkansas organizer hi everyone thank you for joining us this one says that I meet at me scholar beta to start the ball rolling here's a the agenda for the evening demand response and resume for this event so big we're gonna start off the day I'm just telling you a bit about what they do and please everyone thank them for hosting us then after that peer like an exercise live live from South Korea will do his fabulous library and Caliban SP graphically in Scala and then of course there so that bill vendors the author of the programming in Scala book with odd s key he's doing a talk on there with on the Stanislas type system he is actually based in San Francisco so he will be coming live from the Bay Area so without any further delay or with your Eric to tell us all about the man base hello thank you yeah basically would you know what we're doing is we're just we're just hosting this on zoom or using our enterprise license would zoom to be able to handle all this traffic and to record it and to provide it for you afterwards in a different world we'd be we'd be offering you beer and pizza and I've seen you on site so thanks everyone for attending just a few words about demand base you know we're a late stage startup basically what we do is we process the world's business data to help marketing and sales organizations with their account based marketing needs and then a large fraction of our customers or fortune 500 companies and basically we you know we process massive amounts of data up to five petabytes a day 10 billion events per day we have over 50 machine learning models in production we use Scala we use we use ml Lea we use tensorflow bigquery and we really have an unbelievable data engineering and data science team and unlike other companies you know we don't we don't put our teams into buckets you know we believe that that the best organizations you know the data scientist product data engineering all work together so we have we have data scientists with PhDs that you know get trained by by engineers and we have engineers that get trained on data science and I think not many companies can say this but you know our VP of Product has a PhD and machine learning from Stanford you know so that just sort of gives you a sense of where we're at and we believe that really to build the next generation of AI driven data-driven you know account based marketing and sales products we you know we need engineers the proclivity for for data science and machine learning and so if you want to learn more about demand base please reach out to me or the organizers this Meetup and we can you know we can chat but we're always looking for experienced talent so this time we don't have any speakers like last time but we hope in the future to be able to feel some other speakers just to give you a sense of what we're doing with Scala what we're doing with you know big data machine learning at scale and that's pretty much all I wanted to say about demand base Thank You Salar and Alexi for you know for organizing this meet out then and thanks everybody for joining thank you thank you thank you Rick really appreciate everything helping us with the running the zoom and it will help to facilitate this event thank you so much and like Eric said please reach out to me if you want to if you need an introduction to Eric acting on bass for information and he's also on the slack community that we have great so without any further delay if I can introduce you to clarify that who's kind enough to do this talk now it's library Caliban all the way from South Korea over to Pierre thank you hey so let me share my screen first all right can everybody see my screen and can you only hear me yeah okay good so so today I'm going to talk about a library called Caliban that I created about six months ago so this is a library for creating graphical backends and front ends in SCARA the fronton bit was added quite recently so I'm gonna I'm gonna cover a bit all the features that are in Caliban I'm not going to cover too deeply some of the topics but if you're interested I wrote some blog posts about everything that I'm gonna talk about in this presentation so if you wanna if you wanna have more examples and so on you can refer to the blog post that I will link at the end of the talk here is more like a more like a tour an introduction of what you can do okay so Who am I my name is Pierre maybe you've seen my avatar or my my github handle somewhere I'm I'm French but I am I live in Korea so I'm I'm calling from Seoul it's 10:00 a.m. here I have been contributed to zero and a bunch of zero sub projects in the ecosystem and I created Caliban last year so first let's start with graph Korean maybe not all of you know exactly what it is so I'm just gonna briefly introduce it so that everybody can follow so the graphical is a query language api's it was created by Facebook furious back and it's getting more and more traction so a query language what it means is that it doesn't enforce you to use some technology on the on the back end or in the front end this only defines how the client and the server are gonna communicate together so in a way it's more similar to rest for example but then you can develop your your application in any programming language so what's what's special about graph Korea is that the server exposes a type schema which is actually a graph so what this game schema is is that it lists it it lists operations that are available are free types of operations queries there are just forgetting data mutations for modifying data and subscription to be notified of of data from the server so a schema lists operations and then for each operation it returns the type and then each type is clearly defined with some fields and each field returns other types and so on so it builds a whole tree like that with everything that's available and then the client when they do a query in graphical query they request only what they so they can they can ask for several root fields and then for each field is they say which field in the response they expect and so on so the advantage compared to rest is that if you have a web page and when the web page is open you need to do multiple rest API calls to get profile get preferences get whatever we've graph curl you can get everything at once you can just do one Korean see I want the profile the Preferences and this and another another advantage is that you don't need weave rest you you cannot really decide what you want right the the end point will return everything that it it has so it means that you end up some time gathering from the DBE or so sterilizing to JSON and then downloading on the client-side potentially a lot of data that you don't need so with craft trail you can say specifically what you need and the server will only return that I have a I have a short example a small video example to show you the experience doing a graphical query just one thing that is quite nice is that because graph QL exposes a type schema so we know all the types in advance you get some documentation for free tools like this one graphical and also insomnia postman Alta here they are able to introspect the API and show documentation with all the types and so on and it's also able to give you some Auto completions and and so on so that's something pretty nice compared to rest as well so here is a little example okay so you can see that when you start typing a field name it shows you could autocomplete because it knows the fields that are available thanks to the schema if you type a field that doesn't exist to tell you like here okay and then you send your request and you seen the response that all the fields that you get on the fields that you asked title and opening crawl and you can see also the auto-generated documentation from the schema so it makes the experience pretty nice especially on the client side when working with graphical alright so why did I decide to create a graphical library in scanner there was a there is another library in sky that exists at school sangria it's a pretty good library it was there for a long time from the early days of craft feel so the reason I decided to do to do another a new library was that I had this I had this REST API with a lot of endpoints over 100 different endpoints and I wanted to port that to graph QL to get some of the advantages that I mentioned before and the the problem with the existing library and this is not specific to sangria this is actually pretty common in other languages as well that is that when you want to expose a graphical API you need to define your schema kind of with a lot of boilerplate you need to say this is my root query type and these are the fields that I have and this field returns this type and this type add has these fields and so on and I had I had hundreds of case classes and scene traits and so on ADT's in my in my restaurant points and I found that was a lot of boilerplate if I had to redefine everything there are some macros in sangria that can help you for some cases but they don't support every type of every kind of type so it's it's not that useful so yeah one of my first motivation was to cut down the boilerplate so that I would be able to turn my existing REST API into graphical quickly another thing that I wanted was to have a purely functional API so I wanted everything to be typed I didn't want to have some type any that you have to cast around I want see the errors to be explicitly returned and not not have API that for exceptions I wanted the library to be user friendly that was also a strong motivation so that you could get started very easily that's maybe because I country I'm a contributor to zero and that's kind of the philosophy of the of the zero system of the zero ecosystem to have to be very approachable and so that you don't need to understand high highly advanced concepts of functional programming in order to use it and then the last thing I wanted was that I wanted to separate the schema so the definition of all the types from the resolver what we call a resolver is for each field how do we resolve that will how which function do we need to call to get the response for that field this is usually defined together so when you build your schema you say the resolver is that the type is that the name is that and the resolver is that what I want you to be able to have a schema that I we don't touch and then you can pass one or another resolver depending on the situation okay so I'm gonna show you an example of usage of how to create a small small API with with Caliban so here what what you have here is a is a definition of a of a schema in the graph QL schema definition language so what does it mean it means we have a type which is just an object bug with three fields a name list of nicknames and a picture URL so the the brackets means that it's list and the exclamation mark means that the field is so you will always have a value for the name for example on the other hand the picture URL because there is no exclamation mark it could return now so it's a bit like an option in SCARA and the the root query type that defined a list of queries that are available so you have bugs that returns a list of bug and then you have pub that takes an argument name which is not optional and returns maybe a bug so this is the API that we want to that we want to expose so how do we do that so with Caliban you actually define your schema using regular scalar case classes and and that's it there is no special API or to define your schema I just use case classes so we only need to turn our graph QL type into a skullet ID so the translation is pretty seamless here I use an option for the for the picture URL and that's it for the query it is also similar the only difference here is there was an argument in the field bug a name so to handle an argument we make our case class parameter take a function instead of just the value a function from a case class to the result ID why why did I use a case class here bug arcs and why not a function from string to option of park it's just to give a name to that argument because if it was a function from just string to option of bug there will be no name to that that string but by wrapping it into a case class you can give it a name I think it works if you don't wrap it in a case class but the name will be picked automatically I think it will be valuable ok so that's how you define your query schema what if what if your together the list of bugs you need to written an effect because you need to maybe gather the data from a database or stuff like that well it's just the same I just you can wrap your resolve will result in a task here it's tasks from zero but it could be Ebonics tasks it could be a future it could be a cat's eye or it could be whatever this is all supporting ok so now the resolver so we have a we will define our schema that was very simple we just created some case classes now the resolver well the resolver is just a value of that case class because that case class contains basically some functions by creating a value of that case class you give the implementation of each function so here let's say we have a perk service that we can we can query to get the data we are interested in so I just create a query value and I pass a function that will gather the data so for example for Feinberg query was expecting a function so I provide remarks and calling my park service with the name from the arcs so this is actually a resolver so how do we turn that into a graph QL API that's where finally we will start using Caliban so first we create a root resolver so this type is from Caliban this root resolver takes possibly three things a query root type a mutation root type and a subscription your prototype they are not all mandatory you can have only queries and new mutation and no subscription so you just wrap your own type into the Caliban root type and then you call the function graph QL on that resolver and this function graph QL from Caliban will analyze all the types that are in your root resolver so query everything that's that's included and see if it knows how to handle that type if it knows how to handle that type then it compiles all good you have an API and then you can just serve it I will show you a bit later however if there is a type that Caliban doesn't know how to handle there is a little more work to do so Caliban knows how to handle a bunch of types so obviously all the the basic types from the Scala library are supported so in strings boolean's list options tuples of course it supports as I showed before that's how we support arguments in graphical arguments it supports future 0 this stream is used for subscription how about your own types like you must have probably your own business case classes and so on so those are derived automatically at compile time using a library called Magnolia so what that means is that any case class from your code if its own if it's using types that Caliban knows how to handle it's going to be able to know how to handle that case pass it that works also if your case Christ uses some other of your case class like it can recursively know how to how to handle that time what if there is some type which is not a case class and not a stilt rate and not listed here then you have to provide you have to basically tell Caliban how to handle that type how to turn that unknown type into a graphical valid type so you do that by providing your instance of the schema trait so I have a little example here let's say we turn the picture URL now instead of a string it's java.net dot URL so that's not a case class and it's not already supported by Caliban so we need to provide the schema for java.net URL so there are two ways to do that you can just do news fimA of java.net URL and you have two methods to implement one of them is to turn the java.net that you are into a graphical type so what is the name what is the description and of that type what other fields and so on and that the second method you have to implement is how to resolve that type right if you receive java.net dot URL how do you turn that into a graphical response type so that's one way another simpler way is that if your type is a bit similar to an existing type you can reuse the schema for this existing type to create your your new schema so for example for the URL we just wanna we are going to receive the URL as a string and if you if we return the URL we just return a return a string right so you can reuse the string schema which is provided by Caliban and then use contra map and provide a function from your type to the type that you reused here a string and that's it so here if you know how to convert a URL to a string then you can just reuse the schema for string to make a schema for URL and that's it okay so there are a lot of example of you can see in the in the Caliban code how I created the schema for all the types that are already supported so it's pretty simple to create your own schema if you need to okay so that's how you handle unknown types if all the types are known then the previous code compiles you could graph QL and you have a graphical API object what can you do with this API object first you can render it so by calling API dot render you can see the schema definition in the graph QL language so you can compare with the one that you want hidden and make sure that it's is alright especially the most important thing is you can execute queries so to do that the first thing you need to do is to transform your API into an interpreter this will perform additional checks that cannot be done at compile time so it will verify that for example you don't have two case classes with the same name in different packages and that would clash because in in graph QL each type name should be unique cannot have two type two types with the same name so it will if we do some additional checks like that and then give you an interpreter and the interpreter can then be used by calling execute and passing a graphical query and it will return an error or a result so that's super simple very typically you will not call execute yourself you just want to expose your graph QL API by HTTP using an HTTP library so Caliban comes with a number of adapters that take care of exposing the execute method using the graphical commonly adopted format so it's busy post request with a query operation name and the list of variables so it takes care of that for you and just exposes an easy to use method to do that work so there are adapters for HTTP for s-http finch and newest newest kid on the block you see HTTP which is a minimal zero-based HTTP server library so there's an example here for HTTP for s so we just call make HTTP service you pass an interpreter and it gives you an HTTP route and then you can serve that route we've actually before us on the port that you want and and you can add middleware around it and so on there is also make WebSocket service that returns a different route for if you have less if you have subscriptions okay so mentioned before so Livan is using zero internally but there are additional modules if you prefer using hats IO or monix that expose that that add the support so you just need to add one import and it will add the support for those two the effect types it also supports Circe and play JSON so you if you use you can have a JSON directly in your API and it will know how to handle it if it's or plagiarism okay so now let me let me talk about a few more advanced features one is called Z query the other one is called wrappers so it's time to is aquarii there is a common problem that that happens especially with graph QL API is that is that you could end up doing a lot of requests to your back-end when there is a query so here's an example this is a graphical query you request an order even ID you want to return the names and you want to read the name and you want to return the list of products and for each product you want to return the name so typically a way to implement that using zero here would be that you first do a get order request to get the order information from your database and then for each Product ID that you had in your order you would get the product from its ID and then you bundle that into something that you return the problem with that is that you will end up doing one request for the other and then n requests for the product and being the number of products in the other and with craft trail because you can have a deeply nested schema you can have an object in an object an object you can end up doing exponent an exponential amount of requests to your backends if you have a lot of cases like that are nested together and you could also end doing multiple requests to follow the same finish in one part of your graph you are asking for something and in an other part of your graph you're asking for the same thing it will request requested multiple times so how how can we deal with that so you know in Caliban we introduced a type called Z query which is quite similar to 0 it has the same type parameters but it will behave differently so I'm just going to change the code here I just replaced zo by Zi query and instead of n plus 1 requests this will actually execute two requests how is it possible in order to create your user query you actually need to provide a data source and with that data source you have to define a function that well it's optionally you can define a function that defines how to query multiple requests at the same time and what the query will do is that before executing it will look at all the nested Z query inside what the query that don't depend on each other it will group them so that first you won't request the same one not full-time so it did you placate the requests and then it will run the function from your data source to group them together if you provided that function instead of executing them one by one I've have a small example here just the important part is is that you see the run function that takes a list of requests a list of get product requests and returns a map containing the result for each of the of the product so that's basically what you have to implement and then you can switch your 0 type with a Z query type and it's gonna run with those optimisation so this data type was was actually implemented by Adam Fraser who is on the call hi and so if you have question maybe you might imagine chiming this is actually not specific to graph QL and to Caliban so it fits pretty well with with graph QL but you might be able to use it in other use cases if you if you had the n plus one problem basically so at some point is going to maybe be extracted into its own library so that everybody could use it in their own in their own project ok so that's how we handle query optimizations another thing that Caliban offers is a feature called wrappers and what what it is for is for customizing how your API behaves in a very flexible way so with a wrapper you can wrap some parts of the computation of a graphical query so you can wrap the parsing you can wrap the validation you can wrap the execution of the whole of the query you can wrap each field execution or the whole thing and by wrapping I mean that you can you can modify the input data you can modify the output data you can do something before do something after it's it's quite flexible a few examples of of the things you can do so there is this operator that you can use to to add a wrapper on an API there is also function with wrappers wheel with wrapper if you don't like the operator so here I added on my own my graphical API max depth that will limit the number of the depth of the fields that you can query so this is this is I think a validation wrapper so after the query is parsed it will check the depth of the query and if the day is over the number that you specified it will reject the query it will fail it will not execute it that can be nice to protect your your system against malicious queries so there is a similar one max fields you can limit the number of fields that are requested there is a timeout so you can add a timeout on the whole query processing or you can even add the timeout on just the execution for example Roy even fill some field execution you can use it to print slow queries so again that's a wrapper around the whole thing it will measure the time that it takes and print something if if the the processing is too slow so those are examples of writers that are built-in but you can make your own I implemented the number of of extensions like tracing and for caching persist queries those are extensions from the Apollo JavaScript library which is quite heavily used so I was able to implement those plugins just using wrappers pretty easily just a few lines of code so this is a very flexible way to add something to your to your API like if you wanna report metrics to your own your own system you can do that okay there are more features that I will not talk about today but I just briefly mentioned them you can you don't have to have an API with all of your fields because you might have a lot of them and you're gonna have a gigantic case class and this is limited to 22 field so you can have smaller case classes and then you combine API together together there are annotations so you can customize some parts it's like if you don't want to use the name of your k2 class but you want to use another name for your graph gel-type you can use it you can use an annotation for that you can add a description with an annotation you can duplicate some fields with annotations caliban supports introspection so too we'll be able to introspect your schema and generate the documentation for you there is a cogeneration tool so issue already if you don't have a Scala code yet Caliban is very convenient if already of your Scala code and you want to expose it because you can reuse your existing types well if you start a new project and you just have a graphical schema in the graphical language and no Scala code you can use that code generation tool to create the case classes from the graphical types that's a nice good strap tool and more more features we are we are adding still adding some features quite quite often but the the last one I'm gonna I'm going to talk about for this talk is something that was added at the beginning of this year which is a Caliban client so there was so there wasn't any graphical client library in Scala actually there was just something that gives you some some helper to copy-paste your your graphical query string and run it and then and then get JSON back and that was it there was nothing more so I decided to create another module for of Caliban using the same principles as the the server library which are a limited amount of boilerplate I want you to be able to use a client very quickly on any given schema and then to be strongly typed so I wanted to avoid what most most client developers who work with graphical have to do and usually do which is they create their queries in their tools and then the copy-paste the query queries to their code it just has strings and then you just use that but if the if the schema changes and you need to change all your queries you you just have to go through all of them because the other strings the compiler will not help you so I wanted something different I wanted to have queries that are typed so that if the server changes you can regenerate the schema and you would find would find immediately if something breaks and then since I want you to use care for creating queries some concepts of graph QL such as aliases of fragments became unnecessary because the library will take care of it for you so if you for example we've graph Creole if you request multiple fields but the same field multiple times for example with different arguments you need to use aliases so that they don't have the same name in the response so that's something you don't need to care about here it's done for you so I will show you a quick example how to use Caliban client in in three steps so the first step is the code generation step you have a graphical schema and you run you run a tool and it will generate some helpers for you you technically don't have to use the code generation tool you could write the helpers yourself but that's possible but that's they'll be more boilerplate actually the the tool is an SBT plug-in but it's also exposed as as a simple library so you can use it with something else than SBT or your own code possibly so you you give to that tool the path to your schema so the graphical schema you can also give a URL now the URL to a live graphical API and it will get the schema by introspection that's also supported and then you run that tool and it's going to generate as I say a bunch of helpers so for example if you had that graphical type location which has two fields latitude and longitude that return a float that would generate this color code so it would create a type location with an object and in that object location two functions one for each field and this function return selection builder from a location to a double so that means that you are working on the location object and you want to extract the field a field that returns a double okay so that's for the code generation now that you have your your helper is generated you can write queries so writing queries is just combining selection builders together you can only combine selection builder that are on the same type so I can combine here two locations to two selection winders on location but I cannot combine a location with something else it would not make sense so here I combined my two selection builders on location and it gives me another selection builder that returns a couple of the result of of the two fields that I combined of course you can you can map a selection builder to a case class there is a map function and map n function so don't need to carry those big tuples around you can just map it to a case class so the way the way it would work typically is that if you want to write a query you would first find your what is the root query type because you have to start from the from the top very usually it's named query mutation or subscription so you type query dot and then you would your idea would show you all the helpers in the query object so let's say you pick search it will require an argument which is a name a station name in this example so you put the station name and then it will ask you for a selection builder of searchable okay you type searchable dot it will show you all the fields available unsearchable you pick stations and then it's gonna ask you a section builder of station and so on station that name doesn't require anything then you add a station that location it requires a selection builder of location and you can use the one that we we created just before because the selection builder is just a simple scalar value you can reuse one in multiple places so here I use location and if somewhere else in my query I was needing a location I could reuse it as well so we can understand that that's why you don't need graphical fragments graphical fragments are therefore because graph QL is not powerful enough to have values that you can use here and there here you don't need that you can just reuse the scalar value multiple places so this is how you write a query so it reads in a way which is not so far from the graphical language actually it feels pretty similar and then how do you run that query so caliban client depends on a library called HTTP which is a HTTP client library in scarra stata p is really flexible it has a core library that is used to define requests and responses and then you can use it with a lot of different backends so you can use it with like here I use the I think HTTP 0 back-end but there is a future back-end there is a Monique's back-end there are a lot of different back Akashi GP back-end you can pick the one that you want Caliban client only depend on the HTTP core then you can use much one so from the query that we created in the previous slide you just need to call two requests and pass a URL and this will turn it into a HTTP request object and then you can use send to execute the query and what's important to realize is that as a response you don't get a JSON JSON like type you get the type that is exactly what you had in your selection builder so here we had a selection window of list of string and a couple of double and that's what you get from executing your query so caliban client takes care of creating the graphical query from your selection builder but it also takes care of parsing the response back into the type that you that you expected so so everything is strongly-typed that's that's the point so yeah Taliban client is available for Scylla yes as well as Escarra all right a few a few closing yeah ask a question what do you want oh yeah I almost finished so give me two minutes and then add the questions so yeah just a few mention of the things on my backlog the thing I'm working on or I would like to work on in the future I would like to generate a graph QL API from tap here so tap here is a library for defining HTTP endpoints and then also generating documentation and so on so it's really good if you use rest but I'm working on experimental module to turn a REST API into graph QL instantly basically it would take all the all the rest endpoint and put them in a graphical schema so I have a proof-of-concept that's pretty cool I'd like to have an adapter for the Play Framework I've never used play myself so if there is anyone among you who want to become a contributor help be welcome there is not much work to do because plagiarism is already supported so it's just about exposing the endpoint the caliban client doesn't support subscriptions yet because they use WebSocket a WebSocket protocol that's a bit more complicated I would like to add that and at some point I'd like to look into supporting Scala free all right so everything I talked about here is covered in more detail on in the documentation encourage you to look at the resources page that has a link to blog post and I mentioned before we've detailed examples of the query of wrappers of caliban client as well there is an examples folder that has a lot of examples as well so you can see all the adapters and so on you can if you have questions you can come to the zero discord there is a Caliban channel where I'm pretty often and there are some other contributors who can help and you can find me on Twitter as well alright that's it for me now take any questions you have you can be slightly feel free to ask questions on slack as well I've got it open that I can read it out I've got a couple questions about five flights back yeah this one or okay one one third one forward okay yeah that's where you have the selection builder in the query in the client query yeah okay that's alright so so can you explain what the innermost thing is they're like what is location in this context here so location is what I created just above like here yeah which is I combined I combined the selection builder on on to two different loop selection builders on his latitude one is luggage longitude so I combined them into one selection builder so that that basically means that I want those two fields I see I see I see so so the station name combined the station dot location oh I see because you're saying a single selection builder cannot be on one type yeah I can combine types I can combine sorry I can combine selection builders that are on the same on the same type right so let's say on station I have a lot of available fields so I have a field name that returns a string then I have a field location that returns a location but location is an object so I need to define what fields I want in location right so you're saying that in this particular example you just define that Val but you didn't have to you could have just a location that latitude exactly exactly yeah I could have it done in nine I just wanted to use to reuse one just to show that these are just simple values and you can write if you need to repeat some section you can just use a value like that otherwise you can just do it in line of course correct correct and then the searchable is a case object or something that you generate Auto generate from the schema or what is it yes yeah it's it's if I go back it's like location here so location dot latitude so latitude is just a function on the on the object location so so trouble is it's also an object and there's a def stations in there okay okay and then on the next slide so I'm assuming all the way till the map this is lazy is absolve lazy or also so here actually you have a task wheel just this code it's not running it's run not running it actually you have to run it at some point yeah all right okay now that I into your HTTP client then yeah the absolve here is just because I think HTTP returns an either error or response and absolve move the either into Geo type so instead of being an IO of either it moves the error to the error channel of zero and then you just get the value that you want well you don't have to either floating around right chance to say it upwards thank you for writing the first craft cue well client life totally totally awesome days thanks for doing it yeah I think I think that's that's pretty nice I was a the only equivalent that I found is in in Elma so I found that there is a library that have a similar approach that is pretty cool but yeah I think well I was I was able to generate a client for a complex graphical schema like github they have a gigantic schema and you just run the tool and then you have everything in to start querying very very quickly so presumably the server and the client of this case will share all the case classes you can you can well initially I thought about reusing the server for implementing the client but I ended up not having any dependencies between between them because usually the client only wants a subset of what the server has to offer so it ended up being different case classes even though for the basic types like if you have item a user ID you can reuse it of course between both of them but the bigger types usually are not the same because the client only wants a subset but you can share types between of course you can map for example when you have a section builder here you can map it to a type which is the one that you had on the server side as well it's no problem with that right right like for ya and case ecology as most of the if all the times we shared then the DC which is remove most junk from the final JavaScript file anyway so I guess you're thinking more likely scenario is that the client implementer is going to write a smaller subset of case classes that are is going to use a smaller set of smaller subset of classes and what's defined on the server I guess that's what that's their laterally opposite is more common where people don't want to mess with that they just want the whole thing and that's it yeah well you you lose something if it's a you should get the whole thing you lose some of the benefits that you can ask only what you want but in some cases you you want in everything no I guess maybe I guess that proves that I'm misunderstanding so I mean I think the point of Caliban on the server side is that correct me if I'm wrong is that you define your entire scheme off in case classes such that it could be compiled down to the graph QL IDL and distributed oh but also that you could then have your you know your server-side code be using the same case classes that we'll use to generate the idea right so there you don't you're not duplicating the types in any way right oh so you mean like like here to generate the client right so generate the client right you're gonna get all the case classes in the client are going to be from the original schema file right the question is so the the scheme app have here is a graphical schema is not the SCADA one is the in the graphical language or a URL which returns breath kill so yeah it's it's it's not going to reuse the the server case classes because actually it's not it's not creating case classes here it's just creating some helper functions I saw yeah so it's up to you then to map it to your own case classes ah okay okay so you need to do it yeah but not necessarily the you're not kind of automating that yeah each each field returns its own type and then if you combine fields you get tuples that you have to map to case classes if you want because as I said quite often Ewan is not going to be the same case classes as the server it might be but it will probably be smaller case classes or ass on the on the server side you your case classes might have arguments so they might be functions that on a client you don't want the arguments pher got on the results yeah thank you okay so if it's okay if there's any more questions if we could move it to slack that'd be great because we're running a little bit behind schedule Thank You Pierre for a fantastic talk really appreciate it really appreciate it I would say big round of applause for Pierre before just a quick announcement just so I don't forget except a still meet up who share the same kind of people people were interested in functional programming have got a meet up on April 30th and it's also an online if anyone's interested in attending I'll post it in the slack channel for those interested and without further delay if I can introduce our next speaker bill winners bill as everyone knows he's the book programming in Scala with marginal risky he's had a that is probably the most popular book most of us learned scholar from so it's not a great foolish to be able to have a man at this media really super happy that it was happy to do this me to the top tonight so big round of applause for bill you Oh can you hear me uh actually these headphones help me okay I can hear you yeah uh anyway uh just should we do a five-minute break for people or where they gonna hold it during my whole talk I don't know if you did that unzoom meetings or we we didn't we didn't last time 20 people yeah okay so what I I have prepared I can just tell you give you a little background in case people take a quick bathroom break was I was gonna give a talk on the type system at Scala days and I was gonna practice it at Northeast Scala and of course all these got cancelled so I did it online at Northeast Scala and then I gave it again a little bit slightly different it fell in love last week I think it was so this one I have a little more time so I added a few slides so I cover most of the type system except for higher are kinda types tonight and what I did is I took I have a little Q and a slide I usually have at the end and I just stuck in like several places so what I'll do is I'll go for a little while and then once I get before I change subjects I'll just say it see if I have questions we can talk about like that subject that's what I think and I do make a little more conversational a little more structured so what looks it with the let me just share my screen here the talks about is just Stella's type system I can't then here we go okay there we go and so I'm gonna actually start also with this slide which I should put at the end just to let you know what our tiba does that's my company we be consulting and training for Scala and we actually do you have positions for us people if anybody is looking for a job right now I feel free to contact me we are even more available now a couple months ago when people started pulling back so if you need any help that think about us and the other thing I am is I do a I'm one of the community representatives on the Scala Center Advisory Board so I am a supposed to represent you all to the Scala center but I sometimes don't get a lot of complaints or you know concerns expressed so what I started doing is these little for free listing brown-bag lunches if your company has brown bag lunches you know and you want me to come and just join remotely like this and ask you questions about Scala like what you like what you don't like you know that kind of stuff what your concerns are then that would really help me so that's a freebie I do anyway so with no further ado hopefully everybody got back from their break so there's about types so like the basic most simplest type I can think of is a class when we define us a basic class we created type so when I say treat fruit and treat I'm considering a kind of class a special kind of class that you can multiple inherit from when I create fruit I get type fruit and I want to create a plum I get tight plum and then at the heart of Stella's type system is subtyping so when I you know say trait extent top plum extends fruit that defines plum is a subtype of fruit and fruit as a super type of plum so maybe draw that in a UML diagram over the left is we draw an arrow from the subject of the super-tight so what the little simple hierarchy I created here is there's two kinds of fruit plum and apricot and then there's a plot below plum and apricot and plot is a real thing it's a hybrid that you know someone crossed a plum and apricot and they got us you know something that has both plum DNA and African DNA sort of a Frankenstein fruit called pluot so in Scala I can't actually see cuz my galleries over here anyway I will imagine what I brought over there trait poetics ends plum with apricot that means plot has two super types plummet Africa alright so that's how we draw that and everybody's familiar with that that's sort of like the simplest thing types you can create in Scala and so when I you know my kind of path to scholar was I did see programming I guess I did some things before that but I did a lot of C programming in industry that was the sort of the first thing I used said a job after college then C++ and C++ is when I first entered an optional programming and that's when I subclass superclass space class what we call a base class and yeah we called it but anyway in the they had diagram to with arrows going between types but the arrows pointed down like from super tech the sub type in C++ and when I switch to job where the arrow went the other way it went up from subtype to super type and I thought wow this is so different but I really had no idea of what you know what a kind of why it would matter which direction the arrow went but when I came to Scala actually had an insight because if you turn it to the side like this and say Blum is a subtype of fruit that looks a little bit like a function type like this function goes from plum to fruit and it turns out you get that for free you get that implicit conversion of that type so for example this is a method that takes a plum and returns a fruit right if I have a method that takes a fruit and I have a plum in my hand one way I could pass my plum into the the eat method is to convert it explicitly from lumba fruit right and then I could now I have a fruit and I can pass that right in well I don't have to because I get that implicit that conversion implicitly right it's an implicit conversion from plumper fruit that's but the you know the arrow in the diagram I think it's a good way to sort of a good intuition for that arrow and and the other thing I think it I've observed that it means is that you don't have to change memory so like the fruit might create a new fruit I get an image on the heap for that fruit if I create a new plum I get an image on the heap that maybe a little bit bigger it plum may extend the fruit image that's what extends means but it includes the fruit image so I you know to look at this as a fruit I don't have to change memory I can just say the pointer is now type fruit and you know it's fruitless was there in the same spot is if it was just a plain old food so that's one thing about this is a subtype of implicit conversion as you'd never have to change memory which is not true of general implicit conversions and then either thing is it's reflexive and transitive so what reflexive means is that a type is a subtype of self and and do only a super type is a super type of itself so fruit is too something for free that's how it's defined you can kind of think of it as I get this implicit conversion from fruit the fruit or at the fact apricot which you know you don't really have to call because you're already at Africa but if you look in the diagram the UML diagram that's actually what's really the truth is that there's four more arrows there and there's always an arrow from from a type to itself in the UML diagram we just never draw those because they flutter up the diagram and then transitive means that given that pluot is a subtype of plum for example and plum is a subtype of fruit that means that pluot is a subtype of fruit that is to me that's what transitive means so a little curb air I do in the middle is also true usually don't draw that in you in all diagrams but those are all there also so that's that's transitive so I thought I'd just pop this so there's my tongue no that's this is the first QA slide I thought I'd just pause and see if anybody has a as something to discuss anymore I forgot to start slide anybody have a question on you can put it on slap a chip and inform the church at the Tech Center so Chad oh well here it is chef that would be here okay nope nothing in shot and where would you put where would they put questions in the a slight group sale are maybe random or the lobby is a power I think is the I have to join the channel that's my problem okay yeah let's use slack instead so you're an apricot okay that's good alright well I can move on if nobody has it that's not a question that's a statement it's probably a true circle well you can add a new tune it isn't a question or they're like a rather an absolute if you go back to a slide where you had the reflexive arrows like this yeah yes the next one where you had the arrow from kuat to fruit yes sir so doesn't this so I've seen like enough category theory diagrams right now to say that you know this almost looks like you know each of this type actually represents that category with the reflexive type actually being the ID and the address is being the functions or the yes it is it is a category okay Starla's type system is a category I'll talk about that in a little few more slides down but that's a good good I mean because with category you have to have an identity error if they say it's objects and arrows and here let's not call it object let's call it the dots and arrow thingy thingies and arrows so the thingies are types and the arrows they have to be identity and that's true for everyone and then you have to be able to compose write this one composes with that one then did you get that and that that's that's it really for a category thing so sure enough it is a category it's gone this type system the subtyping relation forms of category thank you okay so let's we can go a little farther then there's nobody else at event among clearly not a fruit okay so then the other thing that I think is pretty handy is to think of types of sets so kind of like that they represent sets of values which we call inhabitants of the type so a couple examples I've drawn here one is first of all this is kind of like visualizing is set the one in the top left corner is called labeled the unit that's the set unit and it has one value which is the unit value which we write as empty friends or empty curly braces early with my fingers or boolean is an example it's a it's a type boolean that has two inhabitants two and false well this set for fun too that you know that i blable boolean has two values in it the elements of this set of values instances of type boolean answers to open true or false right traffic light over here I create a sealed trait traffic light and I made object red yellow and green that extend practically so there's only three possible sub well there's only three possible instances of traffic light because it's sealed so this type has three inhabitants or the set that sort of corresponds to has three elements which are values red yellow blue green or int has two to the 32 inhabitants because it's you know minion oh sorry in time in value to infant max value and there's two to thirty two of those they couldn't alcohol fit on this diagram but you get the idea that's a finite number of elements in the set that corresponds to end so that's I think very I use that threw that out this hole is sort of metaphor throughout the whole talk so when you let me look at them as sets of values then this inheritance becomes you can really a diagram it with a Venn diagram so when a Venn diagram is just a graphical way to draw sets so what I have is this big yellow circle which is my fruit set and inside I have some purple dark purple ones on the left which are plums there's a sort of orange circle which is the plum well I've actually got my colors wrong I just noticed some so sweet dark purple but anyway the orange one this this guy on the Left here circling with my Luckies words my mouse the plum and the apricot circle has ever consented pluots belong both to plum and apricot so that's kind of like a you know an intersection of the sex fruit is the union of all those sets so that's basically is a subtype of that relationship corresponds to is a subset of when you sort of look at it as sets and and the thing the elements of these sets are values the possible values and usually it's an infinite number of elements but things like unit and boolean they're finite or even it when I said trait fruit actually that was an infinite number of potential elements because it was it sealed so anyway so that's one one one way to correspond and then another thing is what widening means I think an insight for widening a type which is the what Martin or dare ski said he wanted to call when we get that implicit conversion from a subject to super type that's widening the type and the intuition I have for that is is if you look at the plum if I have a plum in my hand I want to pass it to a function that expects a fruit it's gonna convert plum to fruit that's a implicit conversion I get if you look at the the circle around plums it's kind of smaller and the circular route fruit is bigger but every plum is a fruit so you know every element of plum is an element of fruit because plum is a subset of fruit but the fence is if you think of it as like a fence around the inhabitants then the fruit fence is wider than the plum fence so that's how you you're widening the type so this little arrow I drew between the the plum fence and the fruit fence is is I'm widening that that fence so anyway that's that's an insult I think an intuition for whitening and and now let's put any and nothing on there so any is the top type in fellows type system and that one represents the set of all possible values so that's the set of everything or anything every single possible instance of any class in any type in Scala is a is included in any right whereas nothing is in like an empty set has no unhappy at all so it turns out if you go look it up on a wiki pedia that a subset I'm sorry an empty set is a subset of any other set and correspondingly nothing is a subtype of any other type right so that's that's you can kind of see the again the correspondence between the you know subtyping and sets is T being a subtype of any means that T values the elements of type T's set are by definition a sub set of any because the set of any has everything so as for course is going to have every team instance whereas nothing's an empty set and just no matter what what T is it's gonna be a subset of is that's how it's define the set theory so that's that's an E and nothing but top and bottom types and then lastly before our next Q&A point what I wanted to do is say another way to think about these is to count the inhabitants so I made them all are contrived to be finite so nothing has zero inhabitants I has no elements in that set to art I just where's the blue I flew it over here you can kind of see it looks like a boat that's got three inhabitants plum has one two three four five plus three so it has eight is it the Pulitzer also plums apricot has four and three that's seven as the pillows are also at the pots a durian I can't see it's behind there so there's has some number of like maybe six dish looks like chocolate chip chocolate chips over there but they go smell like chocolate and then fruit is like you know mom's post post what's that that's what Sirians all those guys together unit I just stuck it up there as an example it only has one inhabited um and everything and he has everything so I just replaced that the overhand elected diagram I place which the account's I just did right I just put the number of inhabitants in there what you'll notice is that anytime type is a subtype of another type it's in its count of inhabits is less than or equal to the count of events at the super so pod is a subtype of plum and the m3 is less than or equal to eight right so that's another way you know if you keep your counting moving in accounting the subtype is a subtype of relationship to maps to is less than or equal to 4 the interpals okay so that's that's another good stopping point anybody have a switch over to slack see if there's any other question about that stuff so far traffic like is a fourth type yes but it's it's it's apps it's yeah that's a good questions let me go back to that so try to fight is a fourth type source port types okay so that's this guy there are four types here traffic like red yellow green but this is not a set of types this is a set of values and there's only three values red red is a value yellows of value Green is value traffic light is a tight but it's not a value and actually Red's not a value red dot type is the value which I'll talk about when I get to singleton thanks I read to type yellow dot type green dot type of the three types there so that's one and hey good another question sure if you could the slide there you had the arrows for starting from unit all right say nothing yes and you talked about widening right so so so I think before this thing I forgive it's like was it you said that I get from pluot you can go to Africa yeah it was yeah okay so from plum you're going to the upper type yep so okay so but then when you could the next slide everything above clue what makes sense but I do not understand how you go from nothing to pure yeah it's it's it's a little bit of a stretch for you know your brain but you can think of the fence around nothing because nothing has zero inhabitants right as being infinitesimal it's just like a point and it's it's sort of inside its defined to be inside every other set and I actually have to look that up on Wikipedia to make sure that was true and it then it was it just its defined that way that the empty said it you know is a subset of any other set so the only way you could think of it is there's like a infinitesimal point that's got like the fence around nothing and so you know if I wide net to plumb I'm lightening that little infinitesimally small point to something bigger I think it's later I was talking about in terms of sick right okay yeah okay you said then I agree okay thanks yep I mean coming to Scala I hadn't had a bottom flight like this before where there was like a type it's a subtype of everything like actually with nothing we sometimes you'll see like little arrows down here but just got imply it's a subtype of everything but there's an arrow here here here here you know and that's sort of maps to set theory very nicely also so okay infinite sets can be subtypes yes correct yeah Mike right now like you might I use a sub like sorry can't see what's behind this let me move this I know how I can read your comments hey there we go um I just drew my carnelli comment well does infinity and there's different sizes of infinity so I not quite sure how that works you're not but you can have like an infinity that's twice as big as the other infinity and like the set of positive integers is infinite the set of integers is also infinite but it's a bigger infinity more for some first set point one of you but I was interested yeah but the real numbers I have a different cardinality than the integers but I was just curious about whether infinite sets could have corresponding type in Scala and yes oh yeah freak like when I said trait fruit that's an infinite set of possible inhabitants it's you know the set has every possible inhabitants so like string you know it's an infinite set so if they are if positive integers integers have the same number of inhabitants excuse me it still worked this unless that are equal there's those aren't subtypes but you know it's you know the going to be this guy it's less than or equal to so if two things are equal it's still your Phyllis yeah I mean we have an example right here it's it's this one llamas infinite fruit is infinite but there's more there's more fruits than plums because applicants aren't plums and we think that robots right so this is a bigger infinity than this one somehow I think but you're stretching my math anyway yeah that's good yeah okay so so so getting back to category one of the things that scholars I prefer are three is is a pre-order for your is is like a total order is like integers where every integer is less than their every other integer like the equivalence class that has one thing in it and so there's like for any two integers there's a relationship less than or equal to let's say if you want if I do it that way because then you can have the same energy in the relationship and and and it's it's when you switch it it always is like two and falls right it's consistent so there's one total order across a partial order that you could be like a few things that aren't for which that's not true like a float that's primitive type in Java because of 0 and minus 0 being in the same equivalence class and not a number not sorting correctly that's a partial order and then a pre order is is there can be things that don't have a relationship like plum and apricot actually don't have a sub type or super type relationship at all so that's that's a that's a pre-order and a pre door defines a category so anytime we have a pre here you have a category in category theory and then in another thing this is very close to you when spell two is a lattice and the lattice it actually isn't a lattice in Scala two but it is a lattice in Scala three so I want to talk about like lattice would and what the problem was in spell it to and what what one big change in Scala threes type system that came out because of this together we get lattice achieve a lattice would what a lattice requires is that for any two types there's a least upper bound which they call a join and there's a there is a greater like a unique least upper bound and the unique greatest lower bound it's for the meet so here like for example plum and apricot you know free could be its least upper bound that's fine it has one and that's important in scala because Scala has subtyping and type inference right so Java has some timing but it didn't have to type inference so was it quite so important that it was a lattice what's fella has to do is to test it like compute least upper bounds a lot when it's inferring types for example that the code on the bottom right hand corner I've got an if else would be then side is is like plum and the outside is safe apricot but I didn't give a type myself I didn't explicitly annotate F with the type so the compiler is gonna have to figure it out and what does is it looks the hip side and the inside sort of and the L side and it finds the nearest super type that both of these are a subtype of and in this case it's going to find fruit and the type of f is fruit so that's all fine and good except when you throw in type parameters so when you see like square brackets on the type that's called a parameterised type so T there is a type parameter and she'll of T is a parameterised type that's what that's called and so what I'm gonna do is like by making that when I'm a trait fruit I got one type right you know Anna cake plum I got one type one but when I say trait show of T that itself just one trait generates a pin for the number of types so what I get is show of any show of fruit shall flunk show that Oh of nothing but also gets show of show of any show of show of freak to show show plumb the other than enough and I have to got to get three shows of all those and then four shows of all those all the way to infinity right an infant number of shows of any infant number of shows of free but you never get to and each one of those is a super type of nothing in a subtype of any but they're not related to each other because show the type T and show is invariant so that's that's like Scala has declaration psyche variants so if you put a plus sign there it's going to be covariant they put a minus ID confer grant but this one's invariant and so you know these guys are just kind of all siblings but there's an infinite number so far so good as far as lattice goes the problem comes with programs in thunder it's because it's more interesting the plot thickens if I make a trade basket of plus T that means ASCII the program and it's like grammar T again I get an infinite number of types I get basket of fruit that's gonna plumb well basket of any basket food basket basket basket basket nothing I get basket of basket of any that's it a basket of fruit basket best upon right all the way to infinity except what's interesting about these guys is that because it's covariant the relationship like an inherence relationship between the type parameters of two different parameters types two different baskets implies an inherence relationship between the brown rice type so that's what core rates means so for example because plum is a subtype of fruit here in the left-hand side a basket of plum is also a subtype of basket of fruit kind of in de right over there to the right the inherent turkey kind of maps in the same direction system will take parameters in turkey and a basket of any is an end so you can see kind of basket then he goes down below any there um then I did another one where it's basket of basket any that's actually a basket of any because a basket of any is in any and it's pro variant so therefore a basket of basket of any is a basket of any weight asking a basket of free is a basket of best friend you can see each time I go down to those type parameters that it sort of maps that way not just going to infinity ynx and smaller and and that's that's how various looks contrivance is even more interesting color wise because hunter variance is about what you can consume so this is trait eater of T and I got a minus sign and that means that the there is an inherent relationship of parameterize types implied by an inherence relationship of type parameters but it's the opposite so here because plum is a subtype of fruit an eater of plum is actually a super type of eater of fruit you can see the yellow ones down below that's this time and the reason is is because it's about what it can beat for example what a what something can consume if there's a method that says I want you to pass me an ether of plums well what that methods can do is speed bumps to the whatever you pass in there well an eater of fruit can eat plums because upon its fruit so it's actually okay to pass it here as proof or an eater of plum is asked for and that is that means he interprets a subtype of either plum so it turns out that eater of nothing if somebody wants to eat or nothing that means I can't pass anything to it well I can take any kind of eater at all all right so you can even pass an eater of any that's part of the top type of this so an eater nothing is any so in kind of what was blue is on top now and what was Green eight Arrhenius the lowest one but then if you if you put another eater in there it flips it an intervener of any which is like like an eater eater fruit it would be like a shark right something that eats something that eats fruit but it flips and so you now you see greens on top again and so this goes to infinity where goes green blue greens with green blue green and that's the kind of hopefully can give you a little bit of our intuition about contravariance but anyway back to lattice here's the problem and this is in mostella to spec he actually has only paragraph about this it says the least upper bound a greatest lower bound do not always exist and in scala too and the problem is that if is kind of a contrived example but you can do it I say treat basket of rusty like that or to slide skill and I make two subtypes Ruth basket and end basket and fruit basket extends basket of fruit basket that's well f bound polymorphism by the way when you use like a class that you're not finished defining yet as a type parameter for the super type so an example of that is ordered you know if I say class person extends ordered a person I'm putting the class I'm actually in the process of defining using it in take forever that's called F bound polymorphism so I can do that fruit basket extends basket basket it's bouncy since basket basket I mean if I do this if at Bell F equals and on one side of the you know the inside of my if-else I have a basket and the outside its gotta find the least upper bound between basket well they're both baskets of something they're both baskets of something mental what's since we're an acquittance upper bounded that guy well you know they're both baskets of any was a basket of fruit basket is a basket already and a basket big baskets about city so you could think well maybe it's basket of eighty right well it turns out there are also baskets of baskets already but they're also baskets baskets baskets Betty and they're also baskets basket basket basket and it turns out that the least upper bound is the farthest down one the one that has an infant on four baskets of any which really doesn't exist right that's the least upper bound so what be really early days Scala can probably would do in this case is explode because it would run out of memory but what it does now it just is our basket of it but it's not really the least upper bound right so what they added in Scala three and Dottie is called a union type and the ID of the do also an intersection type the Union type is just stuck it in between fruit and the sort of plum apricot siblings and it's plum or Africa use little plate there that means it's the union of the inhabitants of the two types plum and apricot so if you look over here on the right hand side I've got three arrows kinda pointing to plum throughout Africa all those sections plum or apricot is the union of those two sets it happens to have the same number of inhabitants right because fruit there's only two kinds in this diagram it has the same actual number that happen it's it's fruit but it doesn't have food and then the dual is the is called the intersection type that's an ampersand this is also in spell a three plum and apricot and that's the intersection so at the bottom I just saved from you know the upside-down use like intersect apricot it's the boat shape thing it's just pluots in this diagram that's what's plum intercept but it means that like if I were to go back here back and smell a3f would have type fruit basket or investment that's what it's type of being for it to it's it's the Union type and that means it's gotta love it's gotta be super bad so that means install a free the type system videos about us okay so I thought that'd be a good point to stop anybody have a question about that stuff yeah I do is there a difference between Scott - and Scott a three with respect to the relatively common and obscure usage of extending a trade with sterilizable and product so that it could it for properly for containers this talk is to to extract that's actually practical what so I don't know the answer but was that that's a good question I can like to find out and I'm not sure how to get the answer to you but go oh I'll try to find out about that because that's been a pain for a long time okay I will I'll try to find out so anybody else have a question yeah I had a question so if you go back to this slide where you had the any of the holes we're trying to find the eluvian yeah this one yeah yeah so this is the case right now in this color - compiler yeah and this looks very much like a fixed point problem right like you have a continued of a container for continued you're trying to find what denote a pinch me yeah how does the compiler resolve it right now I guess is it yeah I you can destroy it you can just like this 14 I think it says basket of any I've seen it actually go a couple levels sometimes on it's not I'm not sure how perfectly if it picks the top one but what it does is it doesn't go into an infinite loop and blow up because it runs out of memory anymore it just picks one but it's not the least upper bound but it is an actual but it is one of the super types so I think when I pasted this code and write this code here just the big basket of any and I think it just notices it it's like that's this problem that's an optimization in the compiler thing yes yeah Myron told the story wants where he was in an audience and someone showed how they could get both the Java compiler in the spell okay way to blow up on stage so anyway it's a very corner case but it's just annoying that you know that it's there and so that's one of the things they wanted to fix things fella three rework just with your variants examples there you've got covariant and contravariant examples what happens if you have one that's parameters by say covariant and an invariant you mean more than one type for Amal yeah you know it would look like this except for each one of these so the covariant one would make it kick it into this shape but the invariant one would mean that for each one of these you'd have an infinite number of types that are unrelated to each other other than this relationship I think that would work because when I say show of T see how I get on infant umber of these so that would be a second you basket of busty come at you for every one of these little basket of some things I would actually have basket of fruit , any basket of fruit , fruit basket of fruit coming from basket and those are all you know although all the basket of like better food comma plummets a basket of apricot come a plum is going to be a subtype of basket of fruit from a plum because because they have they have the identical you type but you're not going to get any other structure it'll look like this you'll just get a lot more types another infinity that makes sense what happens if you had a covariant and contravariant but functional right at the same time yeah okay can I take that as a homework assignment you have to merge this one in this one okay that's a real good question I think it kind of hard to draw after a while but oh if I could be yeah they might make a beautiful fractal or something I don't know that's a good question so I'm gonna lay these down because I don't want to forget so do not forget he's already forgot the first one what was the first one there is going to find out the SP this ya serializable alright that'll be enough to remind me okay anyone else before I venture forth yes yes go ahead yeah sure in the case of the basket of nothing yeah does it have any inhabitants or is it equal to its basket I'm not thinking that yeah like an empty basket is a basket of nothing like an empty list is a list of nothing okay the basket can't have anything in it but it can the basket of nothing type has the inhabitant empty basket but maybe that's an infant number you know you can maybe make an infinite number of those hmm the reason you couldn't yeah thanks sir okay she's gone we can get another one yeah that's fine list of empty value yeah hi yes I think what you mean is nil is a list of nothing so if I say let's not empty that's list of nothing okay sorry I think I've got one too many things going well this this whole shutdown thing is the time to pause and reflect there we go see think about things yeah so basket of nothing's kind of like this you could not put anything in that basket but you can certainly type list of nothing has it inhabitant cuz nil is one of them actually it's the only one this is singleton and list is sealed alright anybody else once yes thank you okay all right let's move on and we'll stop again so the next subject is about parameter city really it's what this term does is permit tricity because that came from haskell there was a paper by phil waddler called theorems for free which showed that you know if you just have a type parameter and don't say anything else about that type you can actually prove a bunch of things about it without knowing anything about what the what the method does that was called videos for free and what it means in practice is it you know if we have if we use type parameters it's actually can be it really limits our ability to get something to compile which means that it limits our ability to get it wrong look like there's fewer things to your mistakes that can compile and scholar because we have type system I think of it as any as I'm sorry subtyping I kind of think of it any a city or think of it as well it's really about any because any is the most abstract type we have and as you go down the hierarchy you get less abstract and more specific and there's more information than where I go down like if I had a plum in my hand I know a lot more about it I could be a lot of things plum like things with it because I know it's a plum whereas if I have a nanny I don't know where it is and type parameters by default if you don't put any bounds on them or type any that's all I know about them so nothing is a weird kind of exception to that rule because it's not an extend subtype so like as I go down the hierarchy here any ref extends fruit I'm sorry to since any rep plum extends fruit you add more stuff right it becomes more there's more information there I want to get to nothing because there's no inhabitants you don't need you know that's that special thing I've an empty set it could be a subset of anything else and actually doesn't mean to have any of those methods because you can't ever have an instance of nothing to call any of those methods on so that's why it's a special case which is sort of like has them no information again at the bottom kind of loops around but an example of it is simply this where if I have a basket of you know I want to put a map method on my basket and I said you know a actually my best I can just have one one thing in it currently like a cell that could continue another wrap another object I call that a and it's type a big a if I want to put a map method just kind of like the map method on lists or some actually this is just like some so the be in the in the type prim would be there on the map method means that anytime anybody calls map there'll be a be there shall be a B that will be a you're explicitly given but you say it's just inferred and then I got a pass in a function from A to B to my map method and I'll get back a basket of B so inside this class there's very few ways I can non evil ways I can get this to compile without it being they aren't correct so like one of them you're staring at there's a stripper question mark which is thrown exception right because the type of throw is nothing as it doesn't actually return the value it was it on some other channel and so that's one way I can implement this but it's kind of obviously wrong the other way is basically I have to do this I have an a and have a function from A to B so I'm gonna have to pass the ADA the function f so I say f of a now I have a B and I have a constructor here where I can create a new Vascular but that be and that's my best idea that's really the only way I can do it because I don't know anything about it except this identity right it's any a city so I get abstraction on the inside like that that helps me to reduce errors but at the call site like every call site is different but this call side I happen to put a clue out in my gasket I know it's about to the court and that's exactly what I wanted to do because when I take that out I want to know it's a clue out so I can do cool things with it right so we you know subtype supertype is how scala goes this abstraction where we want it where we get there we get the benefit of like no not knowing anything about it and then concreteness or the opposite of abstraction where we want it which we also want that you know like when we put so what's in a basket or a list and then later we take them out we want them so baby blue lights we want to keep remembering that so anyway that's I think pretty fundamental the Scala and then another reason it's it's kind of good not to call it a parametric city is because we also have type members instead of take parameter so we're talking little bit about site members along these lines Spurs are very similar and the motivating example is is I went back to my C programming book as I could remember the syntax and I found this thing where it had a file in it this is a you know opening a file when I open a file in see I get a pointer to a file big f big I know capital F I led which was a type alias and then I get that back and then when I want to get a character or get a string I call F gets I need to pass the file and say get it from this file and then the limit try to remember to close the file I'll just pass that F close right so if you look on the documentation for this type which is like a type alias one of the things it says is the content of a file object is not meant to be accessed from outside the function you know the standard library functions right and that is always a bad smell to be where you you know you're telling somebody that here here's a bunch of really interesting things don't touch them right it's like it's like a sign that why did you why did you design that such that I could touch them it should be not something I can touch wait so what you can do in Scala to prevent that is is make a abstract type so an abstract type is what we call a type member that has no definition right so when I say trait like trait standard IO I can have type file and my F open can return that my F gets can take one and my F close can take one right so similar kind of structure but I I've made it abstract and what that means is that the caller can't do anything with it because if they don't know what it is it's just kind of like when I couldn't do anything with an A because I didn't know what a was or because I didn't know if he was and they did we lose bail I was learning my own computer but I'm glad you asked that I think so Billa can hear us you know wasn't taking my strings as well maybe he's a mosquito the family got his way because he's poor just to redialing he's dropped off so I assume he's going to rejoin well you'd have to do some editing in the video no it's real real-time 3d whilst we're waiting for bill to come if anyone wants to do a talk at a future SF's column it up please do get in touch with me and also let's talk more between meetups on slack good to keep in touch with everyone mark it out there how's the job market out there are the pool hanging out of the job what's going on you rent your back you out about your dinger bill you wanted to draw a factory yeah sorry about that I had noticed my my part after was had to become unplugged so I ran out of juice but I will continue oops Oh somebody's ever q42 making Chromebooks again or whoever can can make me who you should be yeah oh yeah I see Yoko's now they're all set built co-presenter yeah that's perfect you know the birds chirping or the moment wasn't my keynote for that so I can share it here it is SF's dollar all right there sure my screen okay let's see if I have there it is okay now we're back so can you hear me can somebody unmute and just make sure that you can hear me before I you're good yes we can yep we can hear you and when we see your position slides now oh good anybody hear me yep perfect mm-hmm oh I don't know the problem is I can't hear you all right yeah probably okay that's it my volume got turned down - all right well that was a reset yeah okay I'm telling you about them yeah so essentially when I took a break I was talking about this kind of type here which is called a type member if it's just sitting there it's an abstract type it doesn't have any balance or it's not to find anything and so with that this is where I was essentially the you know inside standard i/o it's kind of like the a inside basket where there's a type that exists but I don't know anything about it other that it's an Emmy so right up here like F open you know when I implement F open well I can't import open here cuz I don't know what that type is I'm down in this subtype I can fix it to something like I created a file handle case last year and I have fixed it to file handle so now I know exactly what it is so it's this kind of like you know when I created a basket of Cluett I knew that the best it contain exactly what's right so where I wanted abstract I have an abstract where I want it concrete I have a concrete but what's nice about this is that if someone calls my get a standard i/o class it just returns standard i/o and at the level of abstraction of standard i/o you don't know anything about file except that it's an any right so we can't do anything with it so that's why we don't need that that kind of documentation like this where you know it's saying please don't mess with the file object you can't mess with the file object this one because you know it's an existential type we know at the standard i/o level we're inside the trader outside of it you know that there is a file that you know type that exists but we don't know what it is so you can do the same kind of thing basically you get the same thing this way so there's kind of two way to do the same thing in this respect in Scala I could instead of using a type member just use a type parameter and now in the subclass I just say you know down here private class actually this way so I can point to a private class sub studio standard i/o extends the Enduro and here's where I fix it right so again inside here I know what it is it's a concrete type just like before to get the same kind of existential type of the client I'd have to use a wild card which in Scala 2 is that you an underscore so currently you would write that in Scala but install them 3 they want to change that to a question mark which it was kind of prettier so I'm gonna use that one here this is what it is in Java Java's wild card is a question mark and they want in Scala 3 to make the underscore kind of mean the same thing at the type level that it does at the value level which is a placeholder notation person's so anyway they're gonna change it to question mark and so that that's sort of the corresponding kind of parameterize type to the to the to the abstract it's a standard i/o which contains an abstract so did you get the same thing so the other thing I could do with course a parameterize type is I can say well I don't just return any old standard i/o here right here I've changed this I return to standard i/o of file handle so now the client knows exactly what it is and maybe I need to make a comment saying hey don't touch this but really if I really you know in this case if I'm doing this I'd probably want them to be able to touch it or something otherwise you wouldn't give it to them so the question then is how do you do this with type members that is called a refinement type so I made it pink here what I can do with it with a you know the standard i/o that has typed file as a member is I can this whole pink thing right here this guy is called a refinement type because standard i/o is sort of a type I refine it with what's in these curly braces which is more information about it something that narrows it to make its you know the set of inhabitants smaller here it's not just any old standard i/o it's a standard i/o whose file type has been set to well that's called a refinement type and that gives you the same thing as the previous slide with type parameter so in summary for these guys you know the the the you know standard i/o with a type file member is the file is an existential type at that level in the sense that it it has a you know there's some type there inside there we don't know what it is it's known by the subtype and I don't know if there's some type of standard i/o is you can do the same meaning with standard i/o underscore currently its fellow 2 or standard i/o question mark it's fellow 3 if you want to fix it you use a parameterised type in on the left-hand side and a refinement type on the right-hand side and then I can actually even make you know some like concrete types below that that are you know the the ones I made on my previous slides where I said class pregnant class substitute standard i/o extends standard i/o or file handle that was the left-hand one and then on the right hand side I just extended standard i/o but inside my body I made type file handle final equals file handle so I think that's that one so does anybody have a question about yeah I'll take members and abstract types and refinement types I guess one other thing I would add is that I wasn't going to talk about what we call structural types in this talk structural types are refinement types on any so right here I'm you know this is a refinement type on standard i/o if that were in any you could just leave it off and that's it that's all the structural type it's refined which I want anything just means it could be anything with a you know method or to be put in there between the curly braces so anybody have a question about okay well if not I can kick in you can go back and ask about it later if you like so the next thing I want to do is talk about bounds bounds really was difficult in the sense of lower bounds I guess especially upper bounds there's a there's a lambda calculus variant that when system f sub that sort of as a soundness proof and everything but Scala has lower bounds also and so lower bounds really throws a wrench in their works because people can make the lower bound above the upper bound which is in makes it an empty set so it's like bad bounds whereas I can't really do that with when I make it is extends the compiler will check to make sure it makes sense I can't have you know fruit extend plum and then find plum makes sense fruit it won't comply all right but I could actually make bad bounds so that that's part of the Scala 3 project was to figure out how to make a sound us proof with lower bounds and that was I think the kind of a intellectual achievement of that because of that work because that they I think they figured that out for the first time for anybody but anyway so if I have my trade show of T and I I'm gonna start using the wild-card one here where I say show of question mark what show question mark means it's pretty make space that kind of means the same thing as show of any it has the same inhabitants because that question mark can be filled up with anything it's just I don't know what it is whereas show up any I know it's in any but of course since any type is any I do know is in any so it sort of means the same thing and it also means subtype of Benny so anytime you don't have a and anytime you don't have what can I get rid of my go-to here so I can use them at house when you don't have an upper bound on your wild card type it means it's a subtype of any that's what it means so if you see show a question mark that means show question mark except type of any and show of question mark subtype of any sure fruit is actually one of them show of plum is is one of these guys so you can see these these are the sets this is a set of show of fruit this is a set of show of plum so inhabitants and they're inside the set show of question mark because as you know there's a plum on any yes so that means that you know it is one of those but show a question mark subtype of fruit that means anything that's a subtype of fruit you know is a member of that type so show a plum again is a show of question mark subtype of fruit because plum is a subtype of fruit you know you plug in plum for the question mark and it it is true so therefore it's part of this set so you can see everything inside this yellow circle is a show of question marks up there for food but show a fruit is just in this circle because a show up plum is not a short fruit remember these are you know show is invariant so there's no root just because plum is a subtype of fruit that does not imply any inherence relationship between show of plum and Shortridge they're invariant so that's sort of how it looks and you go down here this one is the show of nothing's which they do exist right you can create them and then over here this kind of the hair is argued bitmap sitteth at Venn diagram so that's invariance so what covariance looks like when you use upper bounds this is just showing upper bounds is what happens is basket of any now there's an inheritance relationship or basket or fruit is a basket of any because of covariance so you see these little circles right here like this one this one this one this one they go away and now basically basket of any means the same thing as basket of question marks subtype of any so that's actually how you can relate variance to bounds and in Scala 3 that's what basically the type parameters are redefined in terms of type members they'll rewrite a type parameter at some point to a type member with a fictitious name or they make up a name synthetic name and so that's how they you know when they rewrite something at I parameters covariant they're actually gonna put a bound like this on it so anyway that's that's covariance one and then in it's kind of cool it's inside out right because remember how an eater of fruit is a subtype of eater of plum so you can see it kind of goes this way and that one at the top is either nothing but sort of symmetrical is like the inverse or the dual of the other one so that's this is or except I did make one difference here is these are now lower balance right this is eater of anything that's a super type of nothing which means like if something is nothing you can't guess if something requires an eat or nothing that function cannot pass anything in there so it's okay to pass an eater if P Watson here two phones either fruits no so that's why an eater of anything that's a super type of nothing is on the outside here so again when when Scala three rewrites type members to type parameters this time parameters type members this is the sort of what they do with it they'll put a lower bound on it okay so so this is kind of the same thing that's just kind of shows that you know types with the square brackets your parameters types type with question marks are called wild part parameters and that's this is a scholar through syntax to smell to syntax is the same thing with an underscore but it's kind of like subtype relationships between these kind of bounded types with upper bound lower bound you can think of it as interval exclusion you can just sort of think them as sets right so what it's a fruit goes from here to here right that includes plums and apricots this one goes from pluots just to plums this one goes from plums just fruits right so this guy includes a smaller well it's like a subset of this because this goes from pluots to fruits it's going to include the just the plums two fruits right so that's why this is a subtype of that interval inclusion if you include you know if this interval is included in this one then this is a subtype of that one that's essentially how that works and if you again try to map I just took the same thing the same hierarchy I just put it on a Venn diagram so it looks this actually looks like the one the first one I had with the little circles you know inside here the reason I want to show this is I want to show you that for everything you can do with these wild card types and bounds you can do with refinement types so here I just the you know sort of map the wild card to I put into a refinement type of bounds and the intervals are the same the subtype soup type relationships are the same and even this diagram looks the same except I had to make them wider because they're longer horizontally is the exact same relationship when you use bounce so bounds if you know like subtypes super type relationships are implied between bounds Wendy you know the subtype like set of inhabitants is included in the super-tight set of in cabinets so that that's a big one does anybody have any questions about that one upper bounds and lower bounds you mentioned that intersection types in Scala tree yes do the intersection intersection type it's a bounded the intersection type can well let me scroll back to that one slide I'll just think it's easier to say we've had in front of me so like this is an intersection type this is a union type either one is that it's like any two types can be any two types can be intersected any two types can be Union so I I could take a like epic you know question mark subtype of fruits could be over here or plum something like that right I mean I can I can union a two types I can intersect any two types and I get a new type but but there's nothing special you can't like put a bound on a purse and of any other questions balance so and this is just one question that you know more like like dealing with legacy tower libraries and how like they expose the API so is it like in your experience is it better to use type the member type the apps like types or like oh well make this go with type classes it's like what that parameters yeah typewriters versus type vampers is still a good question like design question one thing you can like a couple differences when you can thing you can do with type members is Pat the pinna types dependent types which you can't do with type parameters because they're kind of like private and then the other one is Peyer kinda types are about site parameters so if you're gonna do any things like you know listed looking at pop monad type classes you're gonna use a parameter ya parameter so there are some differences but that's what I would say the difference is like just like with looking at like what I showed you they're isomorphic everything I could do with a wild-card type I can do with a type temper and and in fact in Scala 3 they just rewrite type parameters to type members internally in the compiler is they could pile along but there are some differences in fit what like depending on what you're trying to do certainly if you want to do a dependent type you would use a type member and if you wanted to do something like that like with our guided types like you can say my monad takes an F open square bracket underscore close square bracket that you can't do with type members excuse me so so both of those are useful any other questions ok good little further I've got two more q and a's and we're done but there are only two slides each so we're wrapping up here the next one is just one concept with just singleton types sorry so going back to my traffic light example where I have three objects red yellow green the dark red circle like this this dark red circle this dark yellow circle this dark green circle it's not a bright green those are the inhabitants right that's a value and there's just three of them but these like circles that are faded are the type so there's four types traffic light is one type yellow type is the type we want instance of well it contains out the yellow essentially red duck type is the type it's the set of all which is only one of them red objects and so what dot type here means is if you have a singleton object that's actually a term I can say red and it's actually you know I can print red and I can pass to something that takes a traffic light it's a value if I say dot type after this term it turns it into a type it means the one and only one object that that guy points to which is a singleton there's only one of them because this is never going to change right the compiler ensures that there's only one singleton Fred so that actually maps to a singleton set so here you can see this set named red dot type as one element in it that's called a singleton set that's why we call it a single to type in Scala and you can also do it with the bowels so if I said Val x equals high and then y equals x both x and y point to the same object so there's really just one and as far as singleton is concerned there they should you can think of them as the same type right but compiler can't tell that at compile time so what it does it says well I know X will always refer to the same string because it's about and the compiler ensures that it forces it Y will always point to the same string I don't know what your string it is because it's a vowel right so X dot type and Y dot type is a subtype of string and there are two different types in Scala Texas and even though they actually happen at runtime they point to the same object so here's X dot type and here's the string hi that's a subtype of you know it's a subset of the string set which is infinite so that's called those we want singleton types any questions about that single types check slack and there's subtypes of the type of it the other thing like this this guy this this type was a sub red dot type of subtype of traffic like and X dot type is a subtype of string yeah go ahead I'm curious what use case that this would mean well no one use case I've seen it uses dsls but the main use case I think is dependent X which is my last one which I'll show next yeah so any other questions about Singleton's yeah so okay so last one last two slides is this so first of all there's so many types of things one of the things Scala did is it got rid of statics right so in Java for example you have static methods which are different from instance methods on a class so I can have a class outer and it could have static methods and instance methods but in Scala you class outer you know I can create instances of and then where I would put my static methods as I would put him in object outer so object outer you know this outer here is actually a term it's the name of a it's almost like a vowel like a reference it points to the one only one instance of this object outer class outer is a class it's a type right because the class defines a type outer that type is a type with this guy but this is just outer because that's a singleton give me a single to type out about type this class gives me like so those are two different things but they have the same name and they can both have nested types inside of them so here I've got an inner class well the inner inside this outer is a type and here I've got a type member well the inside this out is a faith right so how do you differentiate them well turns out that if I use a dot that means that the thing to the left is a term which means it's a name that refers to one and only one object it has to be either a vowel or a singleton object Wow for this to work out where you'd be able to use this and that's called the path so this is like a path dependent type because I have a I have a path to get to this enter and everything leading up to the last thing the last thing is always a type everything leading up to it is a term so it's either a vowel or a seems an object like it's a tie beat ICG outer inner and even the package names you could think of patching these packages as singleton object so they're also stable so those are part of the path really whereas this guy they call this a tie projection so one of the reason they need to have this pound sign keyword is well I just used the dot and this in Java would be a dot which is select the type inside to type so what the pound sign means is this is both of these are selecting a type inside something but the dot you're selecting the type inside of term and the pound sign I'm cycling type inside another type so this one is the you know the inner type inside any outer instance is what that means and that's that would be outer dot inner in Java so that's called the type projection because projection just means selection I'm selecting something inside something else so here I'm selecting a type inside a type so that's a type projection this would be a term projection I guess but anyway with this class here's what I can do I can create two new outers I'll name that outer one it out or two and then I can with those two references I can create two new inners this is a new inner inside outer one this is a new inner an outside outer two and the type of this guide remember this this type of inner one is outer one inner the type of inner two is outer to inner and those are some types of the tie protection so that's I mean this one when I came to Scala is just like one to many symbols it was really hard to kind of like oh my god what's this one type rejection it just means I'm selecting a type inside a type and it's kind of you needed this other character here because we ate this one you know we ate the dot so it couldn't use it for this and this is useful still to have but this is a path dependent type this is a path the Bennet type you know here remember every the dot means the thing over here is a term in this case of term is a singleton object in this case the term is a vowel oops sorry well outer one here's the other one Bell so anyway that's tie projections and that the data types so what is actually useful about fat dependent types is that you can actually refer to them and this is like like puts all this stuff together about subtyping so what Pat the pen types and smell do is use subtyping to actually get sort of dependent types sort of but without in a different way so what what I have here is I can have an example method that takes an outer that's an instance where this is actually the type I get with class outer right because if this were this if I were trying to say I got it you got to pass me to singleton object it would have to be outer dot type so anyway there's this you know I'm taking an instance about her and I'm saying you're going to return the inner inside that thing and of course at this point I don't know what that is right but you know maybe there's some methods on here that I haven't shown that if it called it will give me well right whereas here I've made a loop so I forgot to say extends sorry I made a mistake here extends outer important piece so this guy extends out or he's a specific outer right and he fixes it to string so where I pass in specific outer the compiler looks and says Oh at this call site the outer is a subtype of is the subtype of outerwear inner is fix the string therefore outer that inner of the string so it knows like in each call site it will figure out a new what this type is it depends on the specific subtype that's passed in out the call side that's out tight like that's like to use in Scala and so what I what I would say is that it's a it's a nice feature but it's actually not necessarily needed because you can actually do the similar thing with this if I were to say every call said I could define my example method this way where I take a T and I say well T is a is is going to be inferred at every call site and it has to be a subtype of outer right that's kind of saying the same thing as this because you can pass any subtype of outer here and then I'm gonna say it's whatever that subtype is the inner protection on it it's like the type inside that subtype that's actually means the exact same thing as this that's what that's meant thanks meat and Scala is tie projections on though the subtype and and really it's the it's sort of where single types come in is because this specific subtype is the singleton type of the whatever you're passing in at the call site so here this is another way to write this guy is I could say I take an outer and then it's a type rejection on the single to the type of whatever this guy was at the call site so it's sort of maybe a thinker but that's another way to write you know this and this is just almost like syntax sugar for it and then spell it to we still can't do this kind of thing with constructors I believe you can only do it with methods and small three they fix that but it's really just almost like syntax sugar for for doing this you know it's the steeple type type of jail so that is my whole spiel the only thing you actually went every type of type I think I guess I didn't do big take some thought ID well I went for every scholar three with too tight except for a higher kind of types so that's all I got does anybody have any final questions back once like sure just a fifty-five oh sorry right so in the last def example without the type annotation there so I'm confused by auto type yeah that so the other type is is the type of the singleton though why is it why is it hash inner then because if the hash means that the thing to the left is it tight right so all right whenever it yeah and so really what like this is another way to do it but it doesn't look the same because I have to have a type parameter right but it actually would give me the same benefit I sort of inner depends on what T is what subtype about her it is but this guy here he doesn't have a type parameter and it actually means the same thing it's how I can turn a I got into a pile and side as I I use the singleton type of this and in the compiler I think they switch it to this they just use the signal plane with a pound sign because that means the same thing okay now in the previous 554 yeah so the outer one got inner in the diagram yes it is the story auto wonder inner so I'm sorry yes right so that's a subtype of outer pound inner outer pound inner is the nested class inner right correct yeah but the outer one dot inner is the singleton oh no no because other one was a new instance of this class right all right okay so he's more so writing okay yes thanks yeah so anybody else I'm puzzled why is that a sub class isn't it the same class well because we are using the object outer where the inner is defined to be a specific string in the outer class the inner the class inner is still all so isn't outer one that inner the same classes pound inner it's more specific so the reason it's a sub class is this one only has one so outer one is a vowel so it if we first said this guy so that's like you can think of it as yeah I guess I could I could rewrite it let's make it this I'll show you the other way you could think of this one is our one type that's a type now pounce on dinner so you can say it's you know there's only one singleton instance of this this instance here that I've created is referred to that by this valve though only this will only refer to that one so it's a singleton type outer one duck type the type projection insight bad well yeah it's a same class but it you know there's only one here there's one here but this guy has both of them because this is this any instance of inner inside class outer so this is one and that's another one so that's why the reasons the subtype is this is a singleton this is a singleton jet and this is not this is more general anyway anyone else you will learn from you on how to do Q&A on a virtual Meetup thank you so much for them yeah you know what I just kind of thought of it we're all figuring this out as we go but yeah yeah you know so I know really super super super talk from both yourself and here so thanks thanks so much sure both of you for taking the time to do this yeah yeah those conversations can continue on slack and I didn't make the mistake of last time I did bring wine to the ending of this for happy hour even though my wine look it disappears yes it does if anyone else wants to do a scholar meter or knows anyone who wants to please get in touch with me but of course I'm on slack otherwise thanks for everyone who attended also thank you for taking the time to attend one of our events anyone wants to talk about yes before we sign up zoom of course the conversations on slang continue indefinitely just a comment I'm consulting with a company called HPE right now we've got some openings for Scala hackers the team this particular team is deep into Scala so they look try to get into functional programming and effects based programming and so on they're looking for careers as well as in architecture Thanks ear phone if you get a chance advertise the role on the job sounds like we actually created a jobs channel to facilitate the hallway jobs thing of a real media yeah doesn't Robert isn't there either thank you anyone else anything the man base Erica and Leo thank you so much for hosting us and really appreciate my guys all the time and provides for the Xoom facility and running it so a pleasure will yeah well we recorded we'll make the recording online available to you to pose thank you looking forward to more in the future and hopefully more speakers - thank you thank you - appreciate it thanks really appreciate it yeah thanks thanks Bill thanks - thanks everyone into their signature all right everybody