 position. I tend to write my talks last minute. Usually that works out really well because I'm an expert in the area that I'm talking about. And this is a talk about something that I'm not an expert at. In fact, there's at least four people in this audience who will probably be rolling their eyes and putting their hands on their faces. I talk about this because I'm fairly new to Scholar's Ed. And it turns out it took me longer to get all my thoughts together and get things right than I liked. So the majority of this is there on slides. I might drop into some live coding. And some of it is really legitimately it's okay to be unfinished because I want to talk about the things that I understand or at least think that I understand and give you guys enough to go on to say, hey, this is pretty interesting. So how many of you have used Scholar's Ed before? What is that? About a third maybe? How many of you have heard of Scholar's Ed? How many of you were afraid of Scholar's Ed? Good. Including several people who said they used Scholar's Ed. So this is a fairly reasonable thing and that was part of it for me. A big part of where I saw things is that I spent a long time saying that we are not using the Z word. We're just not because, first of all, I failed most of the math classes I took. I think the last math class I did well in was like Algebra and past that I probably had some bad math teachers because I wish that I had found someone who inspired in me what I'm finding now which is this stuff is cool. So I avoided this as, oh, I don't need these things. This is people being far too serious about their data structures and what I have works fine. Until it didn't, until I found the situations where it wasn't working and I went exploring down this road, I think there's also to be fair some reputations in the Scholar's Ed community of them being difficult to work with, of it being obscure and what I found is that's really not true. There's some really helpful people, Eric Oshheim, Rob Naras, the bunch of other people who have just been incredibly patient and helpful as I go through trying to understand things because the other problem that I've had is, okay, I understand it. Now, how do I understand it so I can explain it to other people? And so, of course, I'm now at this point where I'm fairly happily using it and talking about Scholar's Ed on a regular basis. My coworkers don't look murderous as much when I talk about it and suggest it and I've got at least two other people on my team of four that are using it, that have written code with it and been like, okay, I've convinced. There's two pieces I'm using and I'm only convinced them of one of them so I still have some work to do. And here is the important part. As I said, I've been playing with it a lot lately and there's a lot that's in there. I don't understand all of it. I don't understand most of it but I've started to understand the tools I need and what I've found is that as long as I understand what I'm working with enough to be useful, that works. There's just so many things that are in there that you could spend years probably learning and mastering but I'm making it valuable. So one of the situation that actually just started with for me was finding ways because my team builds REST APIs and we work with a UI team that builds Angular on top of that and for me it was finding better ways to collect and return errors when things went wrong with my system and I was having a hard time with the tools that I had and I'll show some of those examples where using these Scholar's Ed tools was a huge, huge improvement. Can you guys see the slides with this color in the back? Okay, good. Okay, is it possible to turn the lights back down? That'll help. I'm just realizing like, hey, can people see this? I think it's just the angle that I'm at is a little harder. So the first thing that we came across and the first thing I looked at because I do a lot of things like collecting errors with a lot of the work that I did early on and my team was working with either because I was dealing with a Jira API. So it was important, did this succeed and give me a successful thing or did it fail and give me a throwable? And so Scholar has this built-in object called either. It's pretty commonly used. It's got a left and a right projection. Now convention, which means you don't have to do it this way but most people do and if you want people to not hit you when they look at your code, you should follow these rules. Convention says that left is an error and right is some kind of success value. And it's a good concept but it's actually pretty mediocre interaction. It's got some issues. So here is part of the problem with either and I'm really tempted to switch my color scheme again. So I've instantiated an instance of right. I've just said right, success, okay? And that gives me an instance of scholarly till right. I haven't specified a type for the left so that's just left is nothing. And I can test conditions. I can say success is right, success is left. One of the things that I want to do is use it in a for comprehension. Use it as a monad because I probably have done a couple things like fetch from an option, the value of the ticket number that I need to look up in JIRA and then I want to iterate over the result. So right here I've already hit a limitation where I have to write hacky code to get around this instead of writing something that's elegant and somewhat idiomatic. So because it's not a monad it's kind of a pain in the ass to work with. There is no flat map or map implementations here and so we kind of have to force the right projection to do anything. And so you end up writing things like is right and then extracting it or whatever else. Which makes me want to build nuclear bombs and set them off. So there is an alternative that is offered by Scala Z, which is backslash, forward slash, which I had a hard time knowing what to call this. In Scala Z it's actually either dot Scala. But it turns out when you refer to either then people aren't sure which either you're talking about. So I've been informed that the right name is disjunction. Also I would love for someone to compile an awesome dictionary of the terms that people use because there's some really great terms for all the symbols in Scala Z that people have come up with. Disjunction looks a lot like I said it's either dot Scala. It actually looks a lot like either. It follows some of the same ideas. But it assumes that we want the right side, the success most of the time. It has a right hand bias so that if we do things like treat it like a monad, it's going to assume that you're looking for the right side and therefore let us progress in that way. So this is a rough sort of console session. I've already had Lars yell at me for doing import Scala Z dot underscore. I haven't figured out all of the clean imports yet. So apparently there are better imports that you can be more specific and I haven't quite gotten there yet. There are some cool implicit that come into play. So you can have any value, any Scala value and call dot write on it. And you will get back an instance of a right disjunction representing that value. And this comes out here. You'll also notice all of the sudden that we've got this really confusing backslash forward slash dash. Easy way to remember it. The backslash forward slash that the dash is on indicates that it's left or it's right. You're already remembering why you're not using Scala Z, aren't you? I had some confusion with this early on but kind of got there. But this is my success type and obviously because I haven't provided information about nothing, there's some implied information that I still have to work with. And I can do the same thing with failure. Failure not left. I get a left back, right? I can also say dash backslash forward slash failure. I think it was Lars who specifically told me it was some, it was either Lars or Rob Nars who probably said, don't do that, do this. So don't instantiate it with dash backslash forward slash, instantiate it with backslash forward slash dot left. Unfortunately, I haven't found an analog for doing matches so you still have to kind of use the dash backslash forward slash. But there are tools there. You can get the instance you need. And so I can say the same backslash forward slash success, backslash forward slash dot right. Still get these things in. So I've got something that looks a whole lot like either. I can return a disjunction and get back a left or a right. Something I forgot to put on here is you can also, I forget what the exact term is for doing it but instead of saying like backslash forward slash throwable comma string, you can actually describe the type and your return type as throwable space backslash forward slash string. What's the term for that kind of description? Infix, okay. So that seems to be the best way to describe things. I think my colleagues have found that more readable. And it works very nicely. So now you're sort of saying the backslash forward slash is in the middle. You've got your left type and your right type and there's no sort of question about how that's described. So I want to make a quick digression around Scala's option. Scala option, it's pretty commonly used as a container. It has a none and a sum. None has nothing in it. Some has something in it. That part is really well named because I actually can remember what's in it. There are some downsides. There are some interesting issues, including the fact that the base trait option defines methods like get that you can attempt to get on the none and other things. But it has a bias towards a value. I can treat it like a monad and get things out of it. And so it will assume that I'm looking for some. But this is actually the problem that led me to start to use Scala's Z is that when you comprehend over a set of options, what you end up with is a failure if there's anything that's none and no idea where it failed. And so we have database objects. We sort of have our own homegrown database layer. So I might call get by ID. Here's the ID. And I get back an option of database object. And then that database object may have other case classes in it that represent joins or something else, which are options. And so if I comprehend over that stack and I fail at some point in that, I get none back. Now, how do I communicate to my API team? Well, the user ID you gave me didn't exist. It's actually a malformed record. And the join to the address table doesn't exist. Or any other number of things. We have these partnerships that are actually in an amalgamation of several different companies who may, there may be a partnership with the same companies, but this company is responsible for this part of building something. And this company is part of building another thing. And so there's another one. Well, if it's this type of project, there has to be this type of company in that partnership. And that's a common one as well. And if I'm comprehending over this stack, I can't adequately describe to somebody on the UI side, well, this was the problem. It wasn't your fault. What you sent me was perfectly fine. What happened was that we have a malformed database record. Instead, we return none, which then becomes, oh, a 400 bad request or a 500 internal server error. And it really makes UI people happy because they love digging through Scala code. I mean, they write JavaScript. And that's fine. They're building stuff in Angular. It looks really cool. But they're not Scala programmers. So they don't want to have to dig through the code to figure out what went wrong, which means that now you're pair programming, one person who doesn't understand the language and other who does, digging through logs and trying to figure out what went wrong. That looks a lot like this. So I've defined a couple quick things to example. I've got a case class user with a first name and a last name. I've got a case class DB object. Gee, I wonder where that came from after all the years I spent doing MongoDB. I just realized that's a confusing name. So DB object has an ID of long and then has a user, which is an option of user. It's a terrible example record because why would I only have an ID and no user record? But, you know, it's good enough for an example. So I've defined Brendan here, which is a sum of DB object with an ID and a user inside of it. This is pretty representative of the type of object that I work with fetching for my database. There's going to be probably an option hanging off of that that represents whatever it is that I'm looking for. And then there's some other guy who for some reason has a basic entry, but there's no user. So think about that. Brendan is an option of user, I'm sorry, an option of DB object, which is sum with an option of user that's sum. Whereas other guy is a sum and a none. And so I wrote two quick methods, getB gives me Brendan, getOther, gives me some other guy. I probably could have made that more elegant when you consider it. And here is a kind of bog standard comprehension. This is a lot like what we do. So early on, I insisted on making the terribly looking nested match after match after match, because at least with a case none I could say what went wrong. And it's not, it looks ugly. It doesn't read well. It's hard to maintain. So for comprehension is great, but only if I can find out what went wrong. So for getB is a DAO. We know that's sum, so that's going to be sum of a user. And DAO.user, which again breaks out from Scala into user. Sum is the bias, so we assume if there's a value that's what we're extracting. And yield user, and I get back an option of user, which is actually sum. I get back what I'm looking for. Great. But if I do this with the other guy, well this is a sum of db object, but it's got no user in it. And so when I extract the user, what happens? So what's that? I get none, because when you do a for comprehension over something like this, at any point, if any of your statements return none, the for comprehension short circuits it basically aborts and returns back none to us. So imagine that there's five or six or seven or 10 or 15 levels deep of these abstractions. Well what went wrong? Was it the first, the second, the 10th, the 25th item that didn't have a value? And that's all I get back. Okay, well I've got an option of user which is none. And now I'm returning information to the front end that basically says, sorry I don't know what went wrong. Why don't we spend 20 minutes digging through the logs? Which actually is a good error message. Is there an HDB code for that? So I mean we talked about what went wrong here, which is that ultimately yes, this is somewhat useful, but it doesn't return the information that I need to understand why it failed. And so we do have a solution. I'm going to actually combine two things here to give the example. One is converting an option to a disjunction because that's kind of useful. That's kind of cool. You can convert an option right to a disjunction. That was well the first thing that I found. And it was great because I didn't have to rewrite all of the get methods on the database layer that return option. I can just take what I already have and convert it to a disjunction in line. As well as comprehending over disjunctions. I really should probably just refer to them as disjunctions here. So we remember the get be and the get other methods that I wrote a few slides ago, right? Is anybody just asleep and not with me so far? Okay. So here I've used, and actually to be fair, I started out using this because I went, nobody's going to want to see these extra symbols. So you can, on an option, you can call to write disjunction and provide an argument. So what you need to think of this like is get or else argument. When I say get or else argument and it's some, so I would say I have a user, a user get or else no user found. What's returned? Okay. You're right. This is a separate issue with the fact that I'm using options. Another place where disjunction comes in mind. But if it's with get or else that argument is only if the value isn't there. And so it's the same thing here. When you say to write disjunction, what you're saying is please try to convert this to a disjunction of the right. And this argument is in case you can't do that. This is what I want you to return. So that works fairly well. You could also say to lift left disjunction if you want to flip them around and confuse people. So there's this operator. I was not the one who introduced this operator. One of my co-workers introduced this and then I went, what the hell is this? Which is backslash forward slash greater than. And I'm guessing that less than backslash forward slash is probably too left disjunction, but I haven't looked to be honest. So this obviously reads a little cleaner when you write a for comprehension because there's less letters running you off the line. So getB returns an option of DB object. And I'm saying to write disjunction, no user by that ID. So what I can do is now if the user is none, I get whatever the disjunction, I'm sorry, if the DB object is none, I get no user by that ID. And if the DAO is there but the user wasn't, well hey, join fail, no user object. Great. Now of course, this short circuits, the first item that isn't there is going to exit. But I get back a disjunction. So in this case, I got a right of a user, but here where we don't have a user object, I got a left. And this really helpful message that I can return to the front end. So I might still send a 400, but it's going to come with the message, the join fail, there's no user object. And my UI team is probably going to go, oh, I should talk to the right person about the fact that there's a database problem rather than, hey, that call failed. Do you know what happened? So it's communication through code, which means I have to interact with other people even less. It's a win-win. Wait, that's on camera, I probably shouldn't say that. No, I mean the goal for me really is to make that interaction easier because when you think about things, the UI and the back end are part of one product. And if they're separated out, then you're making interaction for everyone harder and I like things to go well. So as you know, I can just say none to write disjunction symbol no object found or none to write disjunction no object found. Everybody with me so far. Any questions about disjunctions? Yes, so the first thing that failed is going to exit and that's what you're going to yield. So if I had six of them and the third one failed, then I will get back the disjunction for whatever that one is with the error message for that section that exited. Does that make sense? Does that answer the question? And coming back to remember that I'm using this because it's useful not because I want to hit the perfection of computing. I'm a hack. I dropped out of college. I have no idea what I'm doing half the time and if my code compiles, I'm happy. And this stuff makes sense and I'm starting to understand that better. But I think I almost go with that direction of okay it's useful but this is working for what I need. I get back an error message if it fails or I get back to success if it doesn't and that for me is good enough. So I want to talk about validation. And this is the part where I probably have to jump into a little bit of live code to make it make sense. Validation looks similar to disjunction and there are methods to implicitly convert. You can say dot disjunction on a validation and dot validation on a disjunction. The subtypes of validation are success and failure. Validation is not a monad though and this was a part where I was really confused and anyone who was hanging out on Scala's ed will probably remember the two days when I was trying to figure out why this was happening. There were a bunch of examples out there for Scala's ed six that showed validation being used as a monad and I think the short answer I got was that was a mistake that we fixed in seven. It was accidental. So validation is not a monad. You shouldn't be able to comprehend over it. It's an applicative functor and so we validate all of the events with validation. Everything that we feed into it is validated instead of short circuiting. So we say, hey, this is the stuff that I want back. And any failures in the chain win. So ultimately if there's any failures then we lean towards failure and all the errors get mashed together. So this uses M append so by default all your error messages are going to get smushed together into one string if it's, you know, if your failure is string which not terribly useful we'll look at a solution for that. Well that's good. Hold on. This is the downside of doing everything in markdown or the upside. So this is actually a snippet of code that I grabbed from my code. It keeps doing that to me. I know X. I keep forgetting that it's throwing it up in the other direction. So we've got a bunch of validation and in this case I validated something called a model group. This is actually doing a non-empty list which we'll talk about next and combining it with a firmware version. Now this is I think the home alone operator. I think we, before we knew it was the home alone operator we argued about whether it was the Cinnabon stand or the tie fighter. I still think tie fighter is a better name but, the which? Yes the scream operator. See this is the wonderful part about symbols. Nobody knows what they are and so you can talk about the same operator and no one will be confused. This is one of the parts where I really do want like an English to scholar's ed dictionary or better a dwarf fortress to scholar's ed symbol dictionary since I understand dwarf fortress better than I do scholar's ed symbols. In this case this is combined all of them and what this case statement is. This case so if there's a failure they're amapended together where you'll just get one string all together. If there's success well I have two separate objects that were returned here. I got a model group and a firmware version. So I say case and then the tuple because I'm extracting these out and I can do what I need to do with this because ultimately what I was looking for is was the model group valid was the firmware version valid and if they were then I want to actually create something out of these and so you extract this out of the success and I can return my result. Now I read a bunch of articles that suggested that validation should be for your internal APIs and you should focus on returning disjunctions externally. I think part of it is because the disjunction is more concrete and that you've finally you've said this is success or this is failure instead of having something that you can continue to apply other items to. So typically I will return it as a disjunction because I'm easily swayed by blogs that may or may not actually be authoritative apparently but it worked for me. It was a useful piece of information from my point of view. Now non-empty list is a separate thing. Did I paste the other one? Yeah I put the other one in the wrong place and again I got a real quick, see I wish this had some kind of auto wrap on its own but there we go much better. I actually in this case this was part of what I was doing so there's another set of steps that comes back to improving my interaction with my UI team which is before I start doing any work, before I start actually trying to process the request object in the database, I want to do a bunch of validations. This one was we had an issue where there was a sequence that was sent with a request that it turned out we weren't checking whether there were any items in it. It was causing other issues so this one just says are there model items in here and then this one is hey validate the names. Are they unique in our database? And this one is validate the other thing, the names being unique. Oh validate something, sorry these validate some other conditions on there. This one does unique and then there's a serial number that I have to check as well. Now each of these independently returns a success or a failure object but I want to combine them together. I actually don't care about the success in this case and I forget who recommended the star greater than operator and I don't know what the hell to call it so it's the star greater than operator. But what this actually does is it sees at least the way that I'm using it, it drops my right hand side because I think I just returned unit from these. I'm not trying to accrue the success because it's the same thing being fed into all of them. But what I get out of this is an appended set of failures. So if I use a regular string then it's going to be an M append but if I use this other thing which is non-empty list then it's something else. So non-empty list is one of those bits that I didn't get a chance to finish the slides. So a list, a regular list in Scala can have how many elements? We'll say that again? Zero to N. Right, zero to N. Now of course the problem with that is what if I want to say there needs to be at least one item and I want to authoritatively tell someone else I'm going to return you at least one item. So this is where non-empty list comes in and it's I have a note here on it so I don't sound like an idiot. It's a single link list, it's guaranteed to have at least one element. So that also is known as it's not going to be empty if you return it. And there are, it's very commonly used with validation because as I said if I just have a bunch of validations that return string failures they're just going to get smushed together. But if I return a non-empty list it's going to accrue each of those failures in elements of my non-empty list. And that's a lot more useful because now I can return an array of errors. Now with that there are a couple different things. Let's see if I can get a terminal window up. Not the window I want. That's the window I want. Bear with me here. How am I doing on time by the way? Five? Okay. So real quick I probably will screw this up. That's okay. Like I said I'm not an expert yet. Let's actually make this one Baz. So you notice as I suggested previously the problem here of course is that everything gets appended together into one jumbled up error message which might be useful in some cases. Or I might want to return this list. So instead I can return, I can say failure NEL which implies that I want a non-empty list. And bar can be bar and Baz can be Baz. Did that just run off the screen? Yeah. I got them all correct. It worked. I just had my terminal longer. So now I've got a failure of non-empty list of foo and bar and Baz and my terminal is still hanging off the screen. So the last bit on this because this is just a quick taste is it turns out the validation and non-empty lists go together quite often. And so there's a shortcut type called validation NEL sorry which is going to be like AB. Now when you say validation NEL what you're actually saying is that the left hand side, the failure will be a non-empty list. And so it's an implied type to make it easy to say instead of having to say validation non-empty list AB. So you can say validation NEL. Cool? All right. You might be right. Either way I think as long as I got the basic information out there monad transformers are something that I struggled with maybe describing. I'm missing a slide here. Dammit. There's a cat picture that really describes. I'm serious man. So real quick because monad transformers are one of those things you all should look at. Essentially you're inverting. So when I work with I've started to play with them. When I work with JIRA for example there are three conditions really. I can have a failure in which case JIRA gave me an exception and I can have a success but a success may not be a success. I might say get user from JIRA and it's okay if there's no user it's just going to give me an option. And so imagine you've got a disjunction of option and then you've got to do these nested four comprehensions to pull them apart. So what monad transformers would give me in this case is like an option T where it's inside out. A cat in a box and a cat in a box in a box is a box roughly. So that's something you all should go look at because it's actually pretty damn cool. And somehow I forgot to put that on my slide. So the last thing I want to say before I close out I hope that no one is surprised by this but tests matter. Tests are really important. I sometimes forget to write tests and then I wonder why nothing works. I've been building some cool tools for myself for doing ScalaZ testing with ScalaTest. So taking advantage of things like bias. How many of you have used ScalaTest? How many of you use the option tools in ScalaTest? Cool. So only a few of you. But in ScalaTest if you import this special import you get an option back. You can say blah, blah, blah dot value. And that implies in ScalaTest unpack this if it's some or fail the test if it's none. It's really useful. And so given that something like disjunction is right biased I've built similar tools like that. We use ScalaTest and Netflix. Specs 2 I also think is pretty awesome. And there's already helpers for ScalaZ at typelevel.org for that. I am building slowly but surely a series of test helpers which I'm looking to release in the next week or two. And then slowly a crew of hey, here's all these really cool tools that I built to make it easier to test my ScalaZ code. And I know my teammates have not found this helpful which means that it's not just me. And everybody needs a little buck. So a couple of quick bits because I cheated off of this one especially putting the talk together. Eugene Yucata has an awesome learning ScalaZ tutorial. He sort of linked it up with learn you a Haskell for great good. So if you've read learn you a Haskell for great good or you have a copy of it you can kind of read a chapter of that and then Eugene has linked articles that tell you more about how this applies in ScalaZ. Freedown on ScalaZ really really really helpful as long as you're willing to like completely be blown away by conversations that you don't understand. And a couple of people have been incredibly helpful to me like Rob, Colt Fredrickson, Adalbert and Miles all of whom have like really those are the people you should bother incessantly to get all of your answers and not leave them alone because they will help you. Questions? Okay. Well hopefully that was helpful to people and thank you.