funconf 2013, Bill Venners: Implicit Conversions rocket Implicit Parameters in ScalaTest 2.0
so uh i'm really actually going to talk about two things triple equals and shift so i wanted to uh uh give you a little bit of history of what triple equals was before and talk about what we're doing with it now and um so i most of my talk is just uh demos find the slide there okay so this is um scholarship 1.9.1 that i'm going to show you as this guy and uh all that triple equals did in the past in 1.0 was it was used to get a good error message so if you uh if you have a is equal to 1 and b equals equal to two if you say a equals b and get false right double equals um if you say assert a equals b double equals b you get this exception but it doesn't tell you anything about what caused the exception right so the idea of triple equals was if you if you use triple equals in the current scalar test 1.9.1 um it actually gives you an option of string and if it is if a did equal b then you get a nun back right which means everything was cool if a did not equal b you'll actually get a string that is the error message that's kind of more useful right that's all it was so then if you say assert a triple equals b you would get an exception if you turn there i get an exception and it says that uh you know the test failed because one did not equal two okay very exciting and that's all it was uh uh from the beginning right that was just to get you a good error message so as of 2.10 scala has macros in well they're experimental right now but it's a better way to get good error messages so i was thinking that i wouldn't actually need triple equals anymore i could deprecate it so i'll just give you a quick demo of macros which we're working on let me grab that one so here is uh what it looks like with macros instead this doesn't use implicit parameters yet nothing you've seen does um so again i have a is one b is two um if i say a double equals b it says false again but if i say assert a double equals b it says one did not equal two so it can just analyze the macro assert is now a macro or will be a macro and it analyzes this expression and figures out what a good error message would be if it were to actually be false right so um but it it can also do things like notice a is less than b you can say a was one was not greater than two you could if you do this one whereas a less than b and b greater than three you could do things like uh one was less than two but two was not greater than three right so that's a better way to do it and what i was thinking is that we don't really need triple equals anymore but then um several requirements came along and so triple equals is now doing a lot of other things and mostly it's using implicit grammar so um so let me just give you some demos on that one um the main like camel that broke or the straw that broke the camel's back was this one client who is using scala test and um had a situation where in the past they were not um boxing things and and then they refactored uh they did a big refactor and now they were boxing those things right so they had a bunch of existing code where things weren't being boxed this kind of thing and i can't say exactly what it is but uh and a bunch of tests where you didn't need to box and unbox them and now suddenly all that stuff was broken because now you have to actually box it up okay so it looked kind of like this um you can find the top here so i just have a class box and it can have a value inside of any type t so box has a type of t right and then i've got i can make little subclasses i hear of a name which is a string and a uses an it right so that's what they have that kind of thing and they have hundreds of them and then then you can put them together into something you store in the database which i'll call person entity has a name and an age right so that's the sort of thing they were doing and so they have tests all over the place doing things like a certain nice that name is equal to alicia right like if i if you look inside uh alicia the name of alicia the niece um person entity has the alicia name but actually what's inside of there is the boxed name right so this now failed with name alicia did not equal alicia right and they i mean it fails with it except it fails and you can go fix it but this was all over the place and they were just taking this caused them a lot of pain to try to do that and what they wanted was that did not compile right they wanted a type error if the types were not consistent right and um this is the same thing with uh you know this kind of thing where before the age was just an int now it's a box tint a box event and so this also would fail with page 19 to not equal 19. so what they have to do now is say nice.name.value to get the value out to unbox it or just box the other side right either one of those would work wait i missed something why is it before and why is it different um before this was at a client and they changed how they were doing something to do with their their stuff which i can't really say what it is so after they changed it all these things had to be boxed before they did not so all the existing code they had was not working and so they had to find all the places where they needed to box and unbox and it was causing this assertion this triple equals thing was causing them pain because they really wanted to have this vehicle pilot here okay um so another thing that uh like would happen is if you just say nice.name in the past that would be string now it's a name of it's actually a type name so this type entrance had changed and they would have to do this to actually get a type error right a lot of times they did not right so that was also causing the pain and um so because of that they said well why don't we make this convenience boxing and unboxing implicits that people can decide to actually import if they want to have like things like that uh this type of right here on top fixed automatically so this this one right up there if you say name call and string equals nice dot name that would actually implicitly convert the string to a name right because because of this implicit conversion but you'd still even when you do that so now this thing works because it implicitly converts the name that's boxed it implicitly on it just unboxes it essentially but this still failed because triple equals was working on any so it compares any to any so it's not really looking for a string so it doesn't know to unbox it right so they also wanted the option to use those implicit conversions right the convenience ones that if they did that that it would actually apply that implicit conversion and implicitly convert this side oh sorry uh this side and unbox it so that it would would uh succeed right so would you say was too smart very smart just was doing looking too deep with one structural equivalence i would say it was too dumb it was really simple all it did was compare anything with double equals it actually did one other thing which was if both sides were raised it would call that deep right okay so uh so anyway that was sort of the uh the requirement let me go back to my my page and there was another that so that was one requirement um and there was another one which is uh they had they're also these guys same same client a lot of these came from that one but they had stuff that was calling into c programs and doing number crunching and getting results back and for some reason sometimes they wouldn't get exactly the same result right so uh let me go to the top of this guy actually let me just make sure i don't have anything that i don't want in there okay so for example if uh they were you usually getting 12 12.0 back as a result of a calculation every now and then they'd get 12.0001 which notice this actually gets turned into a two here for some reason but they would get something that isn't exactly expected right most times they would get the 12.0 but every now and then it was kind of weird they would get something exactly 12 months ago but they actually didn't care it was close enough right so what they wanted was to do uh they basically wanted to do this with a little tolerance it says close to 12 and there's a way in um matchers to do that you could uh say occasional results should be 12. plus or minus 0.001 right and it will be okay if it's within that that tolerance of 12.00 right there's no way to do it with assertions so they really wanted to do with triple equals but they really want to be able to say like plus or minus 12.1 here or 0.1 right so that was another requirement and then moreover sometimes that was deep deep down inside um if you look at this one i'm going to put out make sure i'm just using what i'm getting like this 12.0 i'm just comparing it for 12.00 but what a lot of times these these numbers were very deep inside other objects so like this is that box again but this time i'm making a coefficient that's a double so coefficient is a box double and then i have a computed result that contains a coefficient maybe that could be used in an entity or something so there's a double but it's wrapped inside two objects and if the expected is that there's 12 inside there and the actual swell that'll work fine but the occasionally would be this so now just having plus or minus isn't going to help because plus or minus doesn't work on something called computer result that i've never heard right so what i really want is to be able to customize what equality means for a type right so if i say uh usual actual equals expected that's going to work but occasional actual equals expected it'll just say that blah blah blah 12.001 did not equal blah blah blah 12. right and what they really wanted to do was to be able to customize what equality means for computed results so one way to do this is just override the equals method but actually in this case a lot of times it made sense that that equals method was just you know looking precisely for 12.00 so they wanted to be able to make extra equal methods and another way you can think of doing that is to normalize it so one in a lot of cases people want to normalize things before they compare them for equality and tests at least for example here it may be that they the coefficients should only ever be whole numbers 12.0 is okay 13.0 is okay but 13.5 would never be valid right so one way to normalize it would be just to truncate off any extra stuff and if you just truncated both sides and then compared that with equality then then it would work right it would solve the problem also so normalization was kind of another thing that was thrown in there so that was sort of most of the requirements and i'll go back to my slides and i'll show you because to summarize what triple eagles really needed to do in the future was a tunable type check so because sometimes it's overprotective when you start like giving type errors um there should be a way to not have a type check and then also make sure that existing all the existing uses of triple equals would continue to work as before right compile and use work as before so it had to actually not have any type check or you could select the subtype super type type check um that would make sure that the left is a subtype or super type of right or if they have the you know if you have a implicit conversion in there you may want to be able to require that it's a subtype or super type or be implicitly convertible from one to the other right so that's sort of what's there direct tolerance check is like putting plus or minus to use with triple equals and custom equality is just basically they want to be able to customize quality on the outside and they also need to do these things in production code too so there were a few things showing up in scala test that they kind of wanted to put in production code too right and then the last piece is normalization so um okay so let me show you a few more demos so here's shallow tolerance this one's real simple and this all again this one doesn't use an implicit parameter but now i'm going to go to the latest stuff like this is the latest snap of 2.0 and um snap snap release that's out okay so here first of all there's something called spelling utils which is okay to use in your production code so it's a little it's a very small it's just one package and it's just a handful of things where you could use in your tests but you could also use it in your production code that way you don't have to include a scala test in your production code which is a bad idea right so i import scala utils and something called triple equals and i create the 12 and 12.201 if you say use usual actual integral equals 12 i get true if i say the occasional action equals 12 it's false right so what i can then do is i can just say plus or minus let me go like this if i import tolerance then i can do that so that's a way to directly say i want to check something with the tolerance you can use this in production so then plus or minus spelled out like deprecated and replace it with this symbol uh the other one will work for a good while but uh that's the new symbol and then so that's simple that's direct uh tolerance so then there's something called normalization and this will be my first demo of a way that i used implicit parameters so um get that to come up all right so i have my old box and i have the coefficient same thing computer results same thing i've got my expected is 12.00 um and i have my usual actual and my occasional actual right same old stuff and if i say triple equals uh between usual actual unexpected that's always true and when i say occasional actual that should be false right so what i'm going to do is i'm going to create a normalization i'm going to define a way to normalize this type and that is a type class and i'll show you the syntax of it here or the structure of it it's just simple it says i can define a normalization of a by implementing this one method called normalize that takes an a and returns an a so you might imagine one called lowercase that takes the string and returns it lowercase as a way to normalize strings or one called i don't know normalize xml that takes an xml node gets rid of all the spaces between the elements and returns an x and it's the same type it's just transforming it in some way where it makes sense to compare great quality after that so i did that for this uh this guy and all i did was call dot floor which is over here that's how you track it off that's how you try to get off all that there was no scholar documentation for that one but it sounded like it did seem to truncate off 0.0001 so that's all i do is i say the way to normalize a computed result is to for the uh the double that's inside the coefficient that's inside the computer right that's how i normalize it so then what i can do is if i import norm methods then i can just say dot norm and that's how i know so i say occasional dot norm is equal to expected and that's fine and i could actually just normalize both sides right and um if i don't know what the right side is normally so the way that works let's see if i have a uh this is an implicit conversion um on any type t for which there's a normalization of t available right so this is the implicit parameter and it's type class so basically i can call the norm method this adds a norm method to anything that any type t for which it can find an implicit normalization does that make sense so that's the only reason i can call about norm on anything if you if you make a lower case and make that implicit then i could call dot norm on the string all right okay so that's how it's implemented and um so over here what's really going on is there's an implicit conversion ending norm but that requires a plus parameter which i'm providing up here this implicit uh def computed result normal normalization that guy is being used by the implicit conversion that adds more and it also so it enables me to call it around and also tells me how to normalize something so it does sort of two roles okay so that's normalization go back to here so that last thing up there oops that i moved this guy this is kind of a general thing you might want to do i mean let's say you got 100 of these and you want to normalize both sides your hands are going to hurt typing.normal all the time right so why not tell it to just always do that and what that really is is a a custom equality for computed results right so what you want to really do is customize equality for computer result type and that's what this one is i'm going to just check a bit put out and make sure that i don't have anything above and i'm in hearing basically when you put these implicits in scope if you don't exit they'll still be in school all right i just wanna make sure i'm demoing what i think i'm doing okay so this time again i have my box and my coefficient my computer is all the same thing the same expected user actual occasional actual and i have this thing again this is the same computed uh result normalization that i had before um and i imported norm methods again so that's why i can say this right so this succeeded because it normalized both sides before comparing it for equality but i want to get rid of the norms i want to really actually be able to do this where i say you know when you see triple equals used with a tight computed result normalize it the left and right side before you compare it with equality right the default equality okay so what you can use there is an equality type class and i'll show you what that looks like first that one's also pretty simple and really what it is is it's the it's really the equals method in java lang object moved outside of the class you're comparing with equality so in in java langton object there's a known type and an unknown type right the equals method takes any and it so in your um the known type is the type of class you're in right if you have in class rational and you make equal equals method there then it's uh the type of this is rational and the type passed in is any so you have to do a type test in java and um so that's really the same thing here you implement this in the same way so here's an example go back to this guy this is an equality of computed result and so you see b match i mean the thing that's coming in is b is any just like in an equals method so i have a pattern match just like in an equals method and if it is what i think it is which is the a type then what i'm going to do in this case is i want to normalize both sides so i make a norm by calling because i imported my normalization stuff i've just called that norm one a because it already is a computed result and b norm i call b compress which is my pattern match to actually cast down to the actual type right so i can hold that norm of that and normalize that side and now i just compare the two for quality and that's the result otherwise it's false so it's pretty much exactly like just writing an equals method outside the class and now i made an implicit so when you do this it actually worked like that's what i wanted to do i didn't have i didn't want to say that yes you could probably convert this whole thing into a guard to the computer you can define it yes you could yes you would you can compress it into a garden um so it also works if you import mattress so uh like right here you see occasional actual sheets will expect it because that implicit equality is available it will pick it up and use it right so equality is works the same with triple equals and assertions or in your production code just building expressions or matchers and there's a new one called triple equals here you can say occasional actual should triple equals expected and that also picks up equality but b does not b is actually just uses default equality and the reason is is that every time you have to do an implicit lookup it's um there's actually a compile time hit a slight button so if you're doing code jan and you're generating 10 million assertions quality checks if you're probably better off using b yes so what's the difference between these three should we should triple equals uh this one also does the type checking which i haven't shown yet the triple equals is the one where you can do requiring a subtype super type both these two take custom equality this one doesn't take customer quality so you can pile fastest so those are the differences and so when i hit return it still isn't using the implicit quality um okay all right so let me go back to my list here so really that's also done again with equality is another type class and these uh these expressions here all these expressions are taking that type class too it actually isn't enabling in this case because there's a default equality always available so in java on the java platform there's a sensible default for equality which is calling double equals but install a test because it was doing that deep on arrays the default equality in stall test 1.0 it only did it if they were both arrays and 2.0 would actually if either side is an array it will do it right so it's enabled for everything already so you can always compare things with triple equals you can always say should equal and if you want to customize it then you can give a specific equality like we did here for computer result and we'll use this one instead of the default one because this is more specific so it doesn't enable it it just allows you to customize what equality means okay so let me click this and i think i copied that yeah okay so um because sometimes you may want to customize quality you may want to customize quality just one time and not like in your whole file it's kind of a pain bring something in implicit just for that so you can just of course pass anytime you have an implicit parameter is required you always pass in something explicitly right so because i figured that would be pretty common in tests that you just want to have one-off customizations i made a little dsl for it so an example is string normalizations there's there's a string normalizations trait uh here in in in scholar utils that has things like lowercase and trim that'll do normalizations like that and so if i actually don't care about case in some circumstance um like i want to be able to say hi equals capital h high and have that actually work and not fail um i can i can use that explicitly bsl and the way it looks is decided by default quality of string that's that's the default equality of string is that default equality that checks to see if either side is an array um otherwise it will just use double equals right um after being lowercase so first lowercase both the left to the right and then we'll use default that's what that means so now i brought that in scope implicitly like if i'm going to do it a lot then um then then i might bring this in in as an implicit now there's an implicit equality of string the type of that is uh well normalizing equality is a kind of a quality that normalizes first and then but that's what it is it's quality of string so therefore be picked up here here and here and that's why i can compare without caring about case right i mean another use case i think that could be common is xml if you want to write it like a literal xml it often won't have the same structure exactly won't equal the xml that you care about because you have a few extra white space right so you could put an implicit xml uh equality that normalizes them by getting rid of them right or just compares them without looking at the white space this is beautiful oh well thanks well it gets well i think it should have stopped by there it gets really complicated okay let me quit and come back so um if you're only doing it once though it's nice to just basically you can use that dsl uh right where the implicit parameter is needed so here i think i have the same thing let me just go back to see what i start high should equal high with a big h course doesn't work by default you can just say high should equal high after being lowercased right so lowercase in that case is a normalization of string i say after being lower case it gives me an equality of strength that normalizes both sides first with that one with low case and then that's what's used now i'm just providing an implicit parameter explicitly right so the same thing is you can use it with the same like these other syntaxes like high should equal high of course fails without you know by default but you can say high should equal high after being lowercased and tripped oh wait a minute i stuck a space in there there's also a space so you can say so there's also trimmed which just trims the string and that's how it normalizes it so you can say uh after being rotation trimmed and that's that's what that works and it also works with assertions it works in your production code which is just building expressions right it's really all the same thing okay so that's explicitly okay so let's look at type checking so one of those requirements was they wanted things to not compile right and um here's an example i'll go to the top of this guy um i've got my box again and a name and an age again and uh person entity against eight one and i make an alicia and a niece and a nephew these are my niece and nephews and um this thing works right if i say dot value and um equals alicia that's fine because i've actually unboxed it by hand if i box the age then that also works because this is they're both bots right um but this one of course gives me the the air that was frustrating these guys so what you can do is uh instead of using triple equals you use type check triple equals and it means the same thing except it may not go wrong right so it does all the same thing it is plus or minus it does its custom equality and everything you saw in normalizations but it may not compile if it doesn't like the type constraint it actually adds a type instrument so i'll show you how to say it is yet another implicit parameter but this one isn't a type class so what you'll get now is a type error so let's say types name and string do not adhere to the type constraint selected for triple equals and not equals right instead of compiling it at runtime something later it gives you an exception right same thing for this one get the same similar kind of type error and but now uh when i when i do the thing i it fixes it why that does come back right because now that in fact these guys are exactly the same type and both types they're well the top one is a box of string on both sides the bottom one is a box of hint on both sides but the requirement is that the left is either a subtype or a super type in the right and a type is a subtype and a super type of itself installed right so the proof of that here is i can actually add a type description you can actually add these type descriptions to things and so now the type of this expression is actually any so because any is on the right and box of string is on the left there's actually any as a sub super type of box of string right so that actually passes this constraint um and it can be on the other side too so here i've converted the left side to any the right side is a string uh so yes this is actually unboxed so then it's a string but i make it in any and now that's a super type of this one so so that's kind of an example of it can be overprotective because sometimes you may actually have it not compiling and you want it to compile you can always get it to compile by saying it's an any or some common supervision good yeah there's one i wasn't sure i was going to make so i put it at the back but i'll put it here so that was um basically enabled by this constraint which i said isn't a type class because it doesn't just have one ground but the type check triple equals like regular triple equals takes inequality of t for the left hand side type type triple equals actually takes a time constraint of a comma b and a is the left side and b is the right side right so i and so if you don't pass the type constraint then you can't compile because i'm requiring an implicit parameter of this type and so how do you get one and type tech triple equals it actually provides one if the left side is the subtype of the right or the right is the subtype of the length right and that guy the guy that provides that takes in a quality that's used to implement this re and so it's one of the things that that you do a lot when you provide an implicit parameter you may actually require this from parameter in that step uh so this is the implicit parameters needed is type constraint and it requires an equality right okay so um so what i want to show you since i think i have enough time is conversion checked uh close this and open it again and wait for things to get going here there's a lot of stuff here so okay got my usual stuff i'm going to skip down to where the new stuff starts um okay so here's type check triple equals again and it doesn't allow nissan name to equal alicia right as it did before because i need to unbox um so what i might do is try importing this convenience unboxing implicit conversion and it still doesn't work because type check it has to be a subtype or a super type and in this case this is a string and this is box of string it's not a subtype for super type so it won't defile and that's actually what type check tripolis means it's supposed to do that right but if you wanted to actually uh let implicit conversions be applied um you can use a different one and here's here's another example of where it can be kind of overprotective actually this is a better example if you compare one an int and one along it actually doesn't compile other types of triple equals because ant and long are not subtypes of supervisor but actually let that compile it with six six six seed um but there isn't plus a conversion from hand to long it's a widening conversion that's created by predict so if you actually allowed that implicit conversion to be applied to int then they would both be longs and it would combine right so that's what conversion check triple equals does so if you import um actually before i get to that i could get into a file by doing this little trick of widening making one of them a super type like picking a and now antival is a super type of ins and anybody's protective long either way it will work right okay but if i import this guy you see i'm bringing in conversion check triple equals that one loosens the type check triple equals constraint right if it's a subtype of subtype it'll compile but if there's an implicit conversion from a to b it will also compile and it will compile and it will actually apply the implicit um so in this case where i say niece.name equals alicia alicia is a string least.name is a box of string and that one implicit conversion takes a box of string and gives me back a string right so i have a i actually have an implicit conversion from the left side to the right side or a to b so it will compile before it checks this for equality it will actually convert you'll apply to the complete implicit conversion from box of string to string and now you have string on both sides right and then similarly for like uh on the bottom here where i say assert one l equals one um there's an implicit conversion from n to long now this is actually going from b to a right it's going from right uh right to left that's my implicit on this one so it will compile because there's some this conversion between these types but before it checks it for equal it actually converts again to long by by uh applying that implicit and now i have two lines so whether you're using type technical equals or conversion check digital equals b at the end of the day you actually have the same type on both sides right and even when it's a subtype super type it will actually convert the subtype to the super type and you'll have two super types okay so that's what's going on behind the scenes but then of course collections don't work like you want them yet because if you say list of one two three or vector of one two equals vector one two three that doesn't compile even other conversion checks because list and vector are not a subtype of super duper each other and they uh there's no implicit conversion between list and vector and you shouldn't add one right so what you can do is uh basically the way this works is all triple equals needs is a type constraint of left type right type so what really needs is a type and string list vector list and vector end right so you can just give it one and if you import this guy it will give you right so you import traversible equality constraints um then it will this will not work and and what it does is it makes things compile that actually makes sense for scala and with what equality works in uh collections is if they're both sikhs then they're equal if they have the same elements if they're both sets they're equal they have the same elements well seeks has to be the same order and if they're both maps they're equal if they have the same elements it doesn't matter if they're immutable or immutable or what kind as long as they're both seeks people just look at the elements so this one compiles and actually succeeds this one shouldn't compile and it doesn't so if you try to compare a list with a set it actually gives you a compiler error because that would always be false at random so what you can do is actually make your own equality constraints for your own types if you need to i think most times you will need to but you can right and the way you do it is you provide implicit equality constraints of a comma b for your your terms okay so that's um conversion chip trigger and okay great so the last bit so let me actually go forward on my slide a little bit um the other thing i want to talk about yes oh wait i forgot that's all right i like real breakers i was just seeing who would actually do that do you have like a macro or if you thought about a macro i have thought about that and the concern i have is i really hate to use macros to change semantics of scala especially double eagles but that's definitely something that should be discussed but i my intuition has been the macros i'll use to do things like get better error messages and give type areas where i couldn't otherwise give them for things they don't want to compile but not change what things mean out from other people because they'd have to really know i mean if they look at the code you have no idea what anything means if you change things the other problem with it is that inside a cert it would mean one thing somewhere else would mean something else and now it's inconsistent i think that's usable usability problem but uh what happens in practice is people forget to say civil equals they'll say double numbers and then they won't get the typer and it's painful so i am aware of that but anyway um so i should it's the last thing i want to talk about this is shorter so the way this worked in 1.00 was implicit conversions and so when i when i first encountered implicits in scala implicit conversions made sense to me but implicit parameters i wasn't quite sure what i would use them for i wasn't sure what they were intended for and um over the years i found that they were very useful and in fact maybe the preferred way to to do things a lot of times and so a good example is how matches were implemented 1.0 versus how they're implemented now so in 1.0 the way it worked was there were implicit conversions on different types that would enable different syntax so it makes sense to say list of one two three should contain one i'll just type that into the thing here to show you this is the 1.0 minded this is going back to 1.0 if i say list of one two three should contain uh two or something that makes sense i'm not sure what i have imported should matches okay so that compiles but if you have like two should contain two that doesn't make sense and this just wouldn't compile because there's an implicit conversion on any that adds things like equal right you can ask anything if it equals something else but the implicit conversion there's an implicit conversion on gender reversible that adds the contains effects right it has it in there and it inherits the stuff from the any uh should refer right so so they were like about well 30 some implicits on different types there are implicit conversions that enable syntax and implement and what i switched it to was there's right now there's two but there will ultimately be one specific conversion that adds should right so instead of having some odd 20 odd composite conversions that should and label different syntax there's one so every anytime you call on anything it uses the same one implicit conversion that should and then the syntax is enabled by implicit parameters so if you are if you want to say contain that'll work for any type for which there's a containing of t right so if there isn't this is an ant there's no containing int provided so this would still not compile but there is a containing for gen traverse pulse that's the difference so i'll show you uh some examples here this is back to blue blue is new um so the other thing about contain is that people wanted to actually customize the quality for how both a custom way to determine how container ship is determined to decide how container shape uh what containership means so these guys actually use equality so if i say list of high hopes should equal high that works if i say high or capitalize it doesn't but if i if i bring in an equality like i did before where it doesn't care about case when i say list of a high hose you contain high with a big h it actually works so contain also uses the equality type class and you can use it with uh the explicitly dsl too same thing um and then it's also i thought it made sense to enable this syntax on options now that i can make containing of t it's easier for me to make it available for more things it was simpler it's also simple for you to make it available for your types right so so you can say some high you know an option should contain high and that means what you think it means it works it also notice there's a capital h so it's using the equality of string in this case just like everybody else um and there's uh one of and a nun of right so i could say list hi-ho she contained one of these guys well you could say that about option two right you know it contains one of these things um none of these guys you could say that for lister option but it doesn't really make sense to say all of right so it makes sense in the list i'll say a list high host you can name all of hi ho but this would make sense to really say because it would always be false because a list an option can only contain at most one thing and i'm saying it has to pay all of two things so it doesn't compile and the reason is that all love requires an aggregating of team type class and i don't provide one for option right so you you basically turn on and off the you enable the syntax with an implicit parameter is the presence of it okay so that's my last demo is just an example of the end um that is i'm gonna quit and enter again make sure i have refresh stuff um i just want to show you how you would enable audio syntax so there's this box thing i've been using um boxes contain things we enable the contain syntax on box right uh the way that looks i go up here uh okay here's my box name age same thing alicia if i say name should contain alicia right there up on top it doesn't compile because there's no containing of name right and what i made it containing because sometimes it was easy to name a type class like length the length of of bridge or something but containing is is like a type class that defines the containing nature of something so this is the containing nature of name and name contains strings right so um so what i'm going to do is actually make an implicit uh where are you containing a box and this is starting to look kind of hairy but what it's really doing is it's capturing both is capturing the type parameter as e so you say there's a type e there's also a type big box that is a subtype of our box and then type um let me skip that for a second the type i'm getting back is a containing a box of e so if i want a containing a box of string then e is string right and um now i need to actually implement these three methods so let me just show you real quick type the scala dock for it i think it's this one yes um so here's the containing class there's there's a bunch of enablers here you'll see over here i can't say aggregating collecting containing definition emptiness uh existence key mapping length messaging readability sequencing size sortable value mapping credibility those are all the enablers for the mattress index that we have so far there's going to be one or two more but it just has these three methods contains contains none of and contains one of um and then in the companion object which is where they went and that's important i'm going to skip over the companion that's where i actually provide the implicits because once one of the nice things about implicit parameters is you can actually create a new type like containing and the compiler who doesn't find it in space like inherited or in scope it will look in companion objects of things including the name of the type class so you can actually provide your ones there and it makes the compiles fast most of the time because if you have something in scope then every time you do anything that requires an implicit it has to look there to make sure that one won't work right so it's good to get most of them out and the type of the implicit parameters actually allow you to put these implicits there's a lot more implicit it's actually installed as 2.0 but they're all often these companion objects so it should actually go up faster than scala tests so uh it if if you just compare like finding something in scope versus finding something object finding it in scope will actually compile faster because because it finds it sooner in general but just as far as like getting overall faster compilation you want to have most your stuff in companion objects um okay so anyway this is the same kind of thing like it's actually looks a lot like this one oh no not that one optional there it is containing nature of option and what it what it does is um it takes inequality so there's another case where this guy's supporting a type class it's providing a um this type as an implicit parameter and it's requiring its own implicit vector which is an equality of that type grammar and that's why i needed to capture the typewriter so i know which type of equality you have and so then i then it actually uses the equality to determine dictatorship so um now to go down here and say name should contain alicia it actually works right the one on top there if i say alicia with capital letters it doesn't work because his name has lowercase alicia in it but if i uh i can use the explicit dsl with that now because because the implicit the provider the containing of name actually requires an equality of string in this case and uh so you can actually explicitly deprive it or implicitly bring in the scope and now it works so that is all myself so this would be a good time for questions although i wanted to ask well actually to summarize this is how these are kind of the use cases i found for implicit parameters configuring which i didn't mention that's in 1.0 like eventually takes an explicit parameter that determines the patience how long to uh keep drawing how often to retry and before you give up and vote so that's one use for implicit parameters configuring but customizing constraining enabling it to do stuff so um i want to mention we do have this workshop coming up in san jose which is near this town in end of september and uh just questions yes yeah so the object that had nested co-efficient yeah that you wanted to enable customer quality dependence would be how did you do that um let me look at the code here and i'll show you like the easiest way not that one much there it is just make it really big what was it was uh the quality of uh well i'll look for that this is it you know for it was what um it called it was an equality of uh coefficient that's right i'll look for coefficient there it is quality of computer is all this is the code right here so so triple equals and should equal all these things are now looking for an equality of t and there's a default equality for everything so for me to customize it i just need to make a specific one for computer results so this vowel makes it a quality of computer result and now this will be picked up instead of the default basically the the rules and plastic resolution are kind of similar to overloaded method resolution where if you have two overload methods one that takes an object and one takes a string if you pass in a string it will pick the string one using the more specific one so all i had to do was place this in scope and it would pick this up instead of default and what it does is it just is an r equal method that's written very much the same way as you would write an equals method in java right no i was thinking there was another field inside um the computer result contained a coefficient which contained a double right like a c um oh you know what i normalized this one so if you look up at the normalized i'm actually using the marbles here which is just grabbing out this coefficient from the one passed to it flooring it and then re-wrapping it and that's it we haven't had another question yes five minutes yes so you mentioned that from earlier versions and i think it changes from the digital version yes so of course the method uh um so he's basically asking about the differences like what is the main difference between them and what um i think what i what i learned over time was that implicit conversions are good to add methods onto things so i had triple equals with an implicit conversion and that normally conversion but to enable syntax and to define things like what a normalization is for a type or to enable the contained syntax things i actually used to use implicit conversions for i now use in physical directories and um if you if you but you invite your efficiency yeah i guess the difference is that where what do you use differently that's my question what do you think is differently between 1.012.00 the main thing is the main way to see it is in how matches are implemented in uh 1.0 matches are implemented with about 20 20 to 30 implicit conversions on different types and that those implicit conversions enable the syntax that makes sense for those types if you look at 2.0 it's it's right now two but it will be one implicit conversion so if i had to hold those conversions and change it to one and but then i have a bunch of close-up rounders but often companion like this so i should compile faster right uh anybody else yes is 2.0 ready is it stable enough at this point the music oh yeah it's very stable okay so i ran we released something almost every week it's called snap it's not a snapshot so it's a stable i mean it won't change out from under if you use it so a lot of people are just following along that way but um what uh a actual release of skull just means is i i promise not to break your code until the next 2. 3.0 to a great extent so um so the next main release will be milestone six and really the problem is i could release a milestone 6 today if i could get my documentation done so yeah i need to get it out it's been a long time so let's see one more maybe going once all right well i didn't say going twice going twice come on all right well thank you for coming