Devreal

Comparing Functional Error Handling in Scalaz and Scalactic

Event: Scala at Sungevity: SF Scala goes to Oakland!

Bill Venners, Scalactic, SuperSafe, and Functional Error Handling, SF Scala @Sungevity 20150224

Recording: Bill Venners, Scalactic, SuperSafe, and Functional Error Handling, SF Scala @Sungevity 20150224

just a quick question how many people here have know anything about Scala z just a quick show hands okay since there's been a lot it's going to been along that already i was going to shorten my talk I did this talk two and a half three weeks ago in Boston so if you the parts that I'm not going to cover tonight you could go there and that's more comparing with Scala Z and scoloc comparing scoloc take with Scala Z what I thought I'd do tonight just off the cuff I wrote in a little paper plate whoops was just get a couple ideas across and then we can talk about it so how many people here are from eastbay out of curiosity just okay more than half that's good I'm from the east bay two so anyway what I would I just wanted to get one idea across about how to deal with errors like how like if you write a method and that method something could go wrong what do you do about it system dot heck is it I'm not sure if that's technically a side effect but anyway that's one possibility another possibility is throw an exception not mean anybody I shouldn't I just should let you guess that one but that's like the job answer was to throw an exception pretty much so I have another answer called or which I'd like to kind of introduce and then compare that with exceptions and and and suggest how to figure out whether or not to throw an exception that's what I thought I'd start with first I thought that would be somewhat practical so this thing called or is in this library called sky lactic which grew out of scala test basically there's been lots of user requests over the years and one of them was for a way to accumulate errors essentially people wanted a way to find out all the assertion failures in a test that was really the use case that was the the user request so i had to figure out how to accumulate errors to solve that problem and so what what i came up with something called checkpoints which is a imperative way of doing it because scala test throws when an assertion fails it throws an exception and the reason it does that is to fail fast because of two reasons one is a lot of times when something goes wrong up here in the test if the test is got a bunch more things going on and more assertions down below the ones after that may not usually don't actually matter to people and they they may even be nonsense errors at that point and the old days compilers I remember that you'd like get an error at the top and then a bunch of errors that really don't matter and nowadays they're better they just like kind of give you the important errors so that's what Scala test tries to do is just get out quickly don't spend time executing the rest of the code and don't waste your time with giving you much errors that don't matter to you right but I wanted to see well what would the functional way be of accumulating errors and because in in production code the other thing that's happened over the years is when people ask for something in Scala tests they want something in their tests they also wanted the same kind of thing to work in their production code so that's where scholastic came from is is I didn't want people to put like to put Scala test into their production code because it throws exceptions all the time usually when it's not happy it complains by throwing an exception and you really don't want to do that in your production code so we carved out bits and pieces little by little and put them in this other library called sky lactic that's used by Scala test that's it's only Scala dependency it's used by Scala test but you can also use that piece in your production code and so anyway that's where or came from is sort of out of that process and what it is is it's a type that has to type parameters the first type is the happy path so if everything goes right if a method returns in or it's going to return an int I mean basically you might have a method that that is you know if things go well it will return an int if they don't go well it will return the other one right so it's going to either return an aunt or an error message so that's like essentially instead of throwing exception you put the error value in a return value and then in Scala you can actually write it this way so any type in Scala that has to type parameters you can use infix notation most people have I mean that's pretty rare that people write it that way right types that way like you could do that with map yep if you have a map from ant to string you could say int space map space string that's a way to write it so Scott allows you do that with any type and so I use that with or just because when you show when you have a method that that returns it so here's a parse name method that takes a string and just checks if it's after trimming if it's empty that's not a valid name so that's either going to return a string valid string a good one or an error message right and then this other method down here is going to take a string and try to parse an int out of it so it's going to return this parse age methods he's going to return an int if everything goes well or it'll return an error message and that's if that's like if something goes wrong and the two things that could go wrong is one is when you call that to int that might blow up with a number format exception and in that case we return a error message which is off the screen here called input is not a valid integer otherwise if it's negative I decide that that's not a valid age either I give you a different error message which says that negative 3 is not a valid H and so what this good and bad is is that or has two subtypes I'm going to scroll to the quick top to the top here so there's two subtypes good oh now I need help holding my mic anybody want to volunteer to hold by microphone LXE alright thank you just its directional so I think you have to point it right at me or I'll point me at it okay so okay thank you all right so good and bad so here's a very teeny tiny good it would be better if it was big and so it's just there's a one subtype of or called good that takes one value of the you know the first type the good type and there's another one called bad which is also going to be teeny-tiny here for a second that X that's or where did bad go I'll click on bad again it'll go there okay there's bad so bad extends it takes up one of the bad types and extends or right so it's either a good or a bad so that's why I went in this this method here I returned either good or bad so let me can I find that again right here here's let's use make a little bit smaller this parts age method all right I'll hang on for a second this parts parse age method if basically the age is greater than equal to 0 and it's a valid in that I return good age otherwise we return bad some string because my bad type is error message so that's basically how you can make a method return an error instead of throwing exception with or then if you have multiple methods that do that and you want to combine the outputs then what you can do is use in a for expression because an oar is monadic so you can use it in for it has a map and a flat map and so I call parse name with some input string that's passed into parse person and then I call parse age with some input age that's passed into parse person right and then I yield the person named come of age and this is a case class that takes a string name and an int age and if both the name of the age are good then what you get out of that is a good person so what what parts person returns is a person or error message right so it'll be the good person or an error message and what it's going to be is the first one that you hit so it will short circuit in the monadic way if the name is invalid you'll get the error message about the name even if the nth was invalid it doesn't look at that if the ants invalid but the name is okay you'll hear an error message about the you know the age being invalid otherwise you get a good person so what I think that actually what's going on is that way back when when probably when Java was still called oak there was some discussion inside this very tiny group in Sun that created oak about exceptions and I think the idea of exceptions first came about because way back even before that I'm going to go way back to see days the way you actually dealt with errors is by returning values right so you return I can't I know zero meant okay and I can't remember if we return negative or positive numbers for errors but it was like one meant something to meant something else three meant something else and the problem with that is people were you know programmers were humans and so they would just not check the result you know the air the return value makes you know it is say if this was one then do this if it was a two than do that so what happened in C programs is that when an era did happen it wasn't caught there it was caught but you know it kind of percolated way downstream and then later it blew something blew up and you couldn't figure out why right because at the place where it happened it wasn't checked right so that's why the exception was actually supposed to solve because it fails fast it does two things one is it feels right away blows up right there where the error first happens which is better and it also has a this thing called a stack trace you can see how you got there you have a little bit information about how you got there and then there's even sometimes a little message in there in the exception that says what happened what went wrong so that was all better than what had come before and the this fellow name is a herd of Jim Waldo he he was at Sun way back when and he had something to do with something called Genie know if you remember that but he told the story that that he was actually the guy who said you know if we're going to say this is a type-safe language we should you know we should be checking the types of these exceptions because you got the same problem without checking them you have the same problem of when when someone throws an exception and it doesn't get handled then you're not going to basically the type checker is not going to say anything about that so it's the same kind of problem of like unhandled exceptions it's like unhandled return types in C ok so there was debate internally and I don't think Gosling actually liked it might the story I heard is he did not like this checked exceptions idea but when he was away for the weekend somebody put it in so it went in and it it just I think some people liked it most people complained about it and I found my opinion was that it's the the right idea but the wrong technique so what this does is it it's like checked exceptions except it's not an exception it's back to the return type like the old old days of C but it is actually something that's comfortable to manipulate and work with because now you have functional things like these four expressions that are really like monadic transformations so that's what's different so it's it's like checked exceptions except you're returning it and it I think it works much much better because because of the the syntax for the functional transformations that's my opinion so so the other thing that you can do with or is accumulate that's how actually I started out so this doesn't accumulate air is it just short circuits at the first one you'll get the first error and by the way the other the other way this is different from exceptions is this this error message here is a type alias for string but it doesn't have to be a string it could be any type so you so there's a type called try in Scala which is like this except it's very much like this actually except that the the air type has to be a throwable and I think that's an important type to have in in Scala because anything you do could blow up with an exception so even if I hell if I have like something that returns a person our error message the other thing that could happen it because of a bug or I run out of memory is this thing could blow up with an exception so if I'm doing it async like in a future or you know some other thread hey I'm not there to actually catch an exception or see it even so the only way to get it back to me is in something like this but that it forces the air type to be at my throat well yes the guy in the yellow in the back their conceptions so that called code might blow up right so let you play for excellent so yeah when I try to repeat the question time before we're not you really should just set or four times which is good advertising so uh yeah well I'm gonna have to repeat your question which I may not remember the whole thing but basically what he's saying is a like one of the ways you can handle a exception is letting it blow up all the way the call stack to some global handler that does something common like right into a log file that's common or in the case of play which you mentioned it might return well you said four or four but it could return some error status or something yeah four or something right so so I think well that I haven't got yet to like what to use exceptions for but that's I mean one of the things that exceptions do that this does not which was actually one of the big pain points of checked exceptions is it goes all it can go all the way back up the call stack and and so if you really want to not handle something in the 15 levels of method calls below that top level it's really kind of convenient be able to throw it all the way up and these guys have clean interfaces so it depends on the situation so i'll come back to like when to throw exceptions because there are times when you should i think in my opinion and that's kind of one of the the benefits but the try thing what I was just talking about it is a different thread that when you go back to the top of it it actually doesn't hit that global thing so that's for like you want to get it back across to your thread where you maybe you want to throw it and then hit that global thing possibly so that's what try I think achieve so all these things are tools for that fit different jobs I think so what try does is good for is a very specific thing of I'm doing something a sink and I need to get the exception back to this thread right so try does that and you need something like try that the air type is throwable this one's more just general where I want to return the I actually want to handle the air might it's not like something that I want to log or return some global thing but I want the caller to actually handle it that's what this is good for because it and that's really what checked exceptions we're supposed to be for is that so so anyway that the other thing that I wanted to show you was in or you can accumulate errors which is sort of where I came from what what I did prevent was made a bad type called every well I'll show you there's one called chain so what a chain is is a non-empty list right essentially a chain is like a list it actually wraps a list but it can never be empty so that's that's called chain and scholastic and every is a non empty vector so what what it is is a it's got two possible subtypes one or many so on every is you can create in every like that with one two or three things you can't make one that's empty but if you create it with one then it's actually an instance of subclass one if you create it with more than one that it's an instance of subclass many so that's what the two possibilities are and that what that allows you to do is make methods that return if I can like what part of click aren't you getting there we go good let's go back to or somewhere ah there we go I go back one more there we go I scroll down to accumulating so what you can say is I can change my parse name in my purse age methods to say they return one error message which is in every so no it's actually a one-term you know this says in the type that it's only ever going to return one but if you have the bad type being in every in an organ its accumulated so there's a there's an API to allow you to keep track of every error which might be useful like if you're validating form input or something you want to return all the different errors in at once so here I say if this parts age now is going to return int or one error message and then my parse person method I'm have to move this over a little bit parce person is i use it i don't use a for expression because for expressions always short circuit so there's this other API called with good so one of the things I do is I actually invoke both parts name and parse age no matter what they all both get invoked and then you call with good with those two values those are both oars if they're both goods you'll get back a good person using this function it'll pass in the name the good name the good age and you'll get back a good person otherwise you get every error message so you'll see and that's actually an out the type says the type says that parse first ten returns a person or every error message so if they if they're only one of them is bad you get back a one if both of our bad go get back on many that has two in it right so that's how it that's the API for accumulating errors and so you can see down here if I call this version of parse person with both of these are bad you get back both of them right so again this is I think an example of how the functional features of Scala make it comfortable and convenient and simple to deal with error returns it's like checked not exceptions but check error values so the good thing about checked error values is if somebody doesn't handle it then it doesn't compile so that that was the goal of checked exceptions and I think that that's useful because you you this kind of error I mean the kind of errors that you would use this for is the kind of errors you would want people to handle you would want to handle and you want the compiler to remind you to do it right so what I then my next topic was just simply when to use exceptions and my guideline for that was throw exceptions only at people never at code so like give in in scala in idiomatic scala that the time would you want to throw an exception is when your program can't deal with it except maybe that global way so there's a bit of a gray area but certainly if you want the if the program can recover and move on or if if this is like user input error and you're going to tell this information to the user definitely you should use a a functional return type like or or option or try or any of these source ecology has this disjunction type or validation type there's all these different kinds of options you can use but I think if if your program can handle it in other words if there's code in your program that's going to handle this kind of error put it in a functional error return otherwise it's better to throw an exception because that's what they're for because they fail fast you get a stack trace it goes into either a log file or it is it actually when you return it to the user you might also log it so that a developer can look at that stack trace and make some sense out of what went wrong that sort of thing so that was that was my my half my talk that was one concept Sony before I move on to the second topic do you want to anybody have a comment about that criticism yes I'm gonna find the right person to send it to it a lot of time your user is you know the the cashier with a long fingernails is drawing accepted heard you can got to smoke break you don't have anything you oh i should say yeah i should say throw exceptions only at developers never at code or other human non developer humans because yeah they won't know but yeah what I meant by that was if your program is supposed to recover from an error than in Scala you would not use an exception yep it's one of the 500 specifically to avoid doing that yeah so what I have found is that that there was gray area I mean you know three exceptions only could never people if we're logging something but then X and we actually killed that let's say job that an app is doing but the app continues do you throw an exception or do return so sometimes it's like you could go either way and so we've gone both ways before in the past and what I found is I've actually wasted time because of not getting the type checking so I would lean towards the the functional error return usually but what his point well I think was a good one where if there's like 15 stack like method calls that really aren't going to handle that thing then that sounds like a job for an exception James did you have yep well Oh five failures and we rented form with yes okay what he said just to repeat he said basically you use something like a functional error handle like something accumulates errors to capture all of them maybe throw an exception up to the the global handler which sends something down to the client like a 4-12 the 412 some message that it knows how to pull out this information and put up on the form to help the user so yeah so anyway I just I guess I kind of wanted I didn't wanna give the impression that I don't that exceptions are bad they're just there's a their tool for particular kind of job which i think is different in Scala than it was in Java just because Scala has these functional features okay so that was that let me move on the other one so the only other thing I want to talk about was the role of test versus types for quality and I'm going to show one slide which is that one as very proud of that slide it's got circles and rectangles so what and it's got that word monad that everybody freaks out by but what this is is a picture of something that actually ended up in scholastic because again it was a testing use case that I was trying to solve which was laws testing so one of the user requests that that has happened replete repeatedly over the years was how do i test that an object passes obeys the equality equals contract and hashcode you know just seems like there should be an easy way to say this should pass the equal contract now if you look at the equal contract its expressed in terms of mathematical laws of symmetry I mean you can write an equation and the funny thing is in the Java country in the java.lang.object Scott the Javadoc it they don't actually write equations they write them out in English but they're actually mathematical it's a mathematical contract symmetry and transitivity and reflexivity of the main three there's one called non nullity which isn't very mathematical it's not in the math but and there's another one called consistency which is because it's mutable because objects can be mutable but anyway those are the 55 points of that contract and what I want to draw here was that to me this is the the idea of 0 0 is always that there's this thing called an interface that's what this rectangle is and then back behind that is an implementation and this is an instance these are three instances objects in memory and so they have the interface they have the implementation part and the idea was that you abstract away detail with the interface so there's a lot of detail in here about how this thing is working that we don't let through here and then we connect the parts of our program by talking from interface to interface I mean basically talked to interfaces not implementations and that allows us to make changes to the implementation without breaking the code that just relies on the interface right that's the idea and the FP folks they come from the perspective that from mathematics I mean like if you look at the Haskell way of doing things they kind of are very guided by math by algebra and the way that can be fit it can be can be brought to object-oriented programming is that the this is just an object a monad here is just an object it's just an instance it's got an implementation and it's got a interface but the interface if you look at its contract it's like the equals contract it's just expressed in terms of mathematical laws so I think that's actually useful because it's very clear what the abstraction is if it passes that equation then it's valid yeah but in other words your implementation is valid and so it's a clear way to communicate the contract which is it doesn't have the ambiguities of just writing your contract in English but it's also easy to test you can use a property-based test like with Scott check or quick check to just write that equation in your test and boom it'll come up with a bunch of data to try to falsify it right so I think it has a lot of benefits but it's essentially there's two parts to this interface no matter whether it's algebraic or human language whether you describe the interface in terms of algebra like equations or human language one part is just the signatures of the the members the fields and methods and that is checked by the compiler so that's type checking the rest of it is is called i call it the contract which is if you look at the Javadoc or the scala doc you've got a human language description or maybe occasionally it's equations but that's the contract and that as we caught by tests right so that's sort of the role of tests is to test those contracts and what what I think FP has to offer ooo is that basically what Scala is is a object-oriented reform movement that's what object oriented programming originally was a lot about stateful or mutable state objects had mutable state in them and you encapsulate it and you put the methods that work with that state in the object so that those are the only things that can access that state what Scala says is that you know you now that we have modern garbage collectors it's actually practical to make objects immutable which is actually very different idea and that's what what it does is it brings sort of all those benefits of FP that doesn't is not an object-oriented programming object-oriented programming can actually enjoy those benefits so so anyway that's a that's what I wanted to say about that and then the the other thing though that I I wanted to show you was that I think there's a limit of what you can do with types so sure those are actually pointers or references I meet so this line here you mean so this is essentially there's a monad which is a it's actually a type class so I didn't show that it's square brackets type constructors so there'd be a monad of list or mourn out of option or moneda or all these things that are monads you can you can make an instance of this for it and then just use it in a method that just works with any kind of monad so that's sort of the way you can abstract and what what I used it for was for testing so the other kind of testing that I wanted to do myself was when I created his or type it's supposed to be a valid monad and I supposed to be a valid functor and I wanted to say in Scala test this should pass the Monad laws somehow and I couldn't so the that's what I've been working on for six months or something and it requires that I actually create the same kind of type classes that you see in Scala Z which is a monad and functor and applicative and that sort of thing to do laws testing and what this is is this is an adapter class for an actual instance of the object that is got a monad instance so like or is just an or so or is got an interface here and it's got an implementation behind it but it's valid if it implements what it says it does in its contract so if you look at its Scala dock it doesn't talk about monads or anything but does happen to have a map and a flat map method that passed the Monad laws I mean actually what I minute I wanted it to do that but I didn't have a good way to test it right so luckily when I finally I was able to test it it did pass the laws already because that's what I was supposed to do so what you can do is if you create one of these guys you can ask this to create an adapter that sort of when you call map on this it calls map on that when you call flat map on the it calls flat map on that but you don't when you know if you are using this thing you don't need to know what which monad is behind it you're just using that same interface so these are just this has a reference to the the actual motive instance in a reference to the thing could be an order list an optional feature a try you know whatever so that's what that is and then the other thing I wanted to show you was just that I tried actually let me kill some of these windows this one this one this one this one yeah what I tried to do was was actually make get type safety on contains checks I know if you guys are familiar but she can Alexi you want to hold my mic again since you had so much fun last time thank you appreciate it just cuz I have to type in I'm not I don't have a lot of practice typing with one hand to it oh yeah that's right you were sitting right he was sitting right there heckling so uh oh I need to make a different one because this one actually has this all right this is this is good mood lighting I'm gonna make a different thing and I'll say Scala so if i say list 1 2 3 dot well 12 30 that's fine that contains well capital letters hello what are you going to get yeah i get false so the fact is that this is a list event list 12 30 is a list of end if I just say list 12 30 and get rid of this you'll see it's a list event that could not possibly contain a string in it right but so this is kind of a silly thing that passes the type checker and so what I tried to do was find a way to get a type error for that and I did I found a way to do it but the trouble is that it actually relies on a implementation detail of type inference so it's actually if you type in any into this thing it will compile and so it's a kind of a long story but what scholars II did to deal with this is they actually make a different list basically they don't like the folks coming who've seen a school once you've seen Haskell you don't like that kind of type error so they actually made a their own list type called invariant list or I list it doesn't have that problem and so what one of the things that I have tried to do was figure out how to work with the standard library because because it's the standard essentially and we all have to kind of use it and so what I ended up doing is is deciding it it needs to be stated that you need to use static analysis to to do it so what if I were doing a green field design I mean I'm never going to i would never spend this my life this way but if i were designing a programming language and i'm going to spend 15 years doing that and building libraries i would try to make this a type error but there are trade-offs because there are actually benefits to making things covariant and if you actually make that a type error it's going to it makes it possible that someone could write an unsound contains method so it's not that necessarily an easy problem to solve yes unless you get rid of oh right so what what I came up with was this this compiler plug-in called super safe which I want to demo and it uses types but not the type system so you get a compiler error but not a type error so another example is is if you look at regular Scala because well not necessarily this is a design decision of Martin order ski of people who design Scala but I think it actually makes sense if you if you say one in a string equals the number one it just tells you false and that's because the equals method in java.lang.object takes an object so the double equals method in scala thought any takes in any just to be compatible and simple and it's it's really easy for everybody to understand but then you get all these I mean it's what's really easy to do sometimes it's a option of 1 equals 1 I mean like comparing options with non options just gives you false and if you don't so this kind of thing has to be caught in a test and if you're writing tests you'll usually catch it but this is where I think you can use static analysis to to find little problems like this and there's a lot of things that can be used for some sure oh I gotcha yeah so option 1 equals 1 compiles right and and I've done this myself a lot of times in tests that's where you do most equality comparisons which is where this all came from originally so in the if you use the plug-in the compiler plug-in and you say one equals one it doesn't compile and it's it's a you know it has to look if you make a set of list of one and that equals a so I say a set of vector of one you'll get a type a compiler error it's not a type error actually wait a minute I forgot one of my parentheses here that was a syntax error there you go so that's the super safe plug-in that is giving you a compiler error by looking at the types but it wouldn't be a type error because if you and it's it does things like if you say big end here so now I've got a big int deep down on one side and an int on the other side it actually compiles because that's true so there's uh oh sorry you know what i'll do is i'll move this I can't see it either because there's this big microphone in front of me so we all have obstacles let me move this up like this Oh Mac Apple makes things so simple that I can't actually move my let me do this- and it's minus minus but i'll do it this way essentially if you have bigint compared with an int deep down inside that actually companies to compile because it can be true because begins and ants cooperate so there's all kinds of like you notice it allows a list to be compared with a vector because those guys can be true also so anyway that the point I wanted to make is I have come to the conclusion that that there's really three prongs that that you know the that if you can use types and it's practical use types then that's the best way to do it so like chain and every having the type system that it's never empty so that's an example if I can put something in the type and then my method takes that then I don't have to compare I don't have to say in my my documentation never pass in an empty list you can't because it wouldn't compile if you tried right that's the best thing so try to get rid of requires and put it in the types and then if you if you can't then you're going to have to catch it in tests right so that's what soska lactic is really quality through types scala test is quality through tests and then the other thing that I think is a useful tool is this is using a static analysis and that's something I just released a couple weeks ago called super safe and it is a product and I want to give away a free copy tonight for one year and I had to kind of figure out how to do this and so Alexi didn't have any like standard way to give away things so I I one time in the old old days used to give design seminars with brew cycle and we would we want people to interact and then some people never want to interact right they don't want to talk and so I had I somehow I learned from somebody that if you throw something in the audience and then the person who catches has to talk then that's how you get everybody to talk right so I was a back home in Indiana and told my stepmother had he's something to throw into the the class and so we went down to the toy box in the basement and she said well once you use this this duck here because when you throw it at people you can yell duck which was pretty funny for my stepmother considering so what I'm gonna do is I my face out here and then you have to throw it to three more you have so much two more times so I I don't want to like pick somebody and the third person wins the the raffle alright so this is actually a good thing if you catch it the third time you win but you have to stay seated you can't like step up and fight each other all right so I'm gonna throw a way to the back and then that person those that's a second time and the third time that's the winner okay agreed all right I'm gonna exit sign ok I'm going to try to throw it over that let's see right here here we go yes oh that's one nobody caught it yeah okay throw out somebody else that's number two alright third person who ever you throw two wins all right there you go all right forgot to yell duck anyway so that's my that's all I had I just didn't want to take too long since it was a long night already but anybody have any questions or comments about any of these subjects yes wondering how you managed to achieve those funky return types we don't learn yeah that's actually a good question you can do that with any type that has to type grammar so I'm going to dim what with map so i can say Val my map colon I'm gonna say string map int I've never I've never tried this before so I'm at we'll see if I'm true if I'm correct I'll just say map of high 21 thank you I was actually how to to let's see if it works and then I'll move it move it up yep that does work so basically map is a type that takes to type parameters you can always stick in the middle don't do that but I mean if you think about it function one takes to type parameters can I can I can you hold it for me because you're getting very good at that yeah so if I say Val fun colon function one int comma int let's say equals I call an int i'll move this up to again rock at i plus 1 so this is an increment function we don't we don't usually write it that way we have this in text in this is actually built into the scala language but we usually write it like this so it's kind of like that right and so i think just every now and then there are types where it's nicer to do the in fix thing yes somebody else had a question somewhere yeah James one of the Jameses the laws testing is that part of its not yet it's in master so it'll probably two dot which ones that we decide to dot five so we're going to have a bunch of actually had a bunch of things like the last year that nothing got finished so we're starting to pump them out into little releases but yeah and it's it's not just there's a monad type class there but you'll be able to use any monad type class because there's there's one is called Z there's one in there's some new ones coming out because scalzi had kind of a meltdown and some people off shoot there's some offshoots and so there's one called cats that's being worked on another one structures so I will test it with all those to make sure you can use any anyone you want yeah anything else okay well thanks for coming at the guy that yeah come up oh it's hey aren't you from typesafe all right perfect let's get this into type safe all right sure okay it types this again at Titus is gonna get all right here comes look out oh alright alright thanks cool thanks you