 So you're at the talk, Programming and Math, and my name's Harold Carr. I work for Oracle by way of Sun. And I say that, and I think I mentioned this a couple of people at lunch. Before when I worked for Sun, people go, cool, well, far out. And then when Oracle acquired Sun, now I work for Oracle. Now I say, I work for Oracle, and people go, yeah. But Notice Oracle is one of the sponsors. So it's got some good people in it. Anyway, this talk is the credits, really, about a paper I read called Programming Design by Calculation by Jose Oliveira. How do you say that in Spanish? OK, actually Portuguese, excuse me, Portuguese. He teaches at the University of Minho in Portugal. And it's a great paper. I'll have a link to it later. And it really, because I was always trying to read papers, introduction to category theory and stuff. And I'd always get a little ways into it. And then I'd like, but what does this do with programming? Show me the meat, or the beef, or whatever that is. And so this paper actually got me there a lot quicker. And it motivated me to actually continue looking around. So that's what the idea of this is to kind of show you some patterns that occur in functional programming. And there's a lot, a lot more. Like if we could make it to the end of this presentation, it makes it up to page 30 of that paper, which is actually 235 pages. It's actually a book. It was meant to be a book. It never got finished, but it's still available. So here we go. So we start out with really basic stuff. How do you define a function? So in math, we've all seen that before. This is the factorial function. And it just says there's the two cases in Haskell. And I'm not going to assume you know any Haskells. So I'll explain a few things. It says that f is a function from integer to integer. In case f is given a 0, it's going to return 1. And for any other n, it's going to return a recursive call to f with n minus 1 times n. So it looks pretty much similar to the math definition. And in function application in math, you just see f of parentheses x. And in Haskell, the one nice thing about Haskell, the very most important thing in functional programming is applying a function, because that's how you get something done. And so Haskell made the decision to make that almost syntax-free. So you just name the function, and you give it the arguments. There's no parentheses. There's no commas. There's no curly braces. There's not anything. And I think that was a great decision, because it makes it really a compact notation. So let's go on. So the first thing you want to do with functions is compose them. And all this says is, given a function g that takes types a and returns types b, and given a function f that takes input as types from b to c, if you compose them together, then it's a function from a to c. Pretty simple. And in math, the notation is this f after g. And in a lot of people, that's a little weird to read, because you read left to right, so you think f and g. But it's really this way, and because it's because of the way math also does it, is you do g of x and then f of x. So the composition is that little dot in the middle. In Haskell, the operator for composition is this dot operator. And it says exactly what it says. Given a function f from b to c, and given a function g from a to b, then return a function, and you declare a function by saying backslash x, and that's the argument. And then this is the body, run g of x, and then on the result, run f. So that is function composition. And in Haskell, here's where I've composed. I've defined this function c, and it says, given any number a, I'm going to return a number. And what I've done here is first, there's the dot operator, and I'm going to call function times 99. This is another Haskell notation, it's called sections, and it's a partially applied function. So it's whatever you give at times 99. So the times operator takes two arguments, and it's already been given one here. So whatever you give it is going to be times by 99. And then that's gonna be followed by whatever the result of that is by plus 10. So that, once again, is pretty... So c of one, 109, no big deal. Okay, I wanna say something first about composition and purity. And I think that's best shown with an example. In Haskell, it's a pure language. So when you call a function with an argument, you're gonna get back the same result with the same arguments every single time. If you have something like Java, and here's these two functions again. Here's f, which takes an int and returns an int. And here's g, which takes an int and returns an int. And if I call them by first calling g on one and then calling f on the result, well, you think I could maybe get the same result. But look what they're really doing. They're actually calling, actually they're basically doing IO. And you can't tell that by the function definition. So if you run that, you run that, you get something different every time. So let's look at the same thing in Haskell. First of all, I'm gonna take a couple of things off. Because if we wanted to look at just like Java, we'll just say, okay, here's two functions. There's g function from int to int, and here's f from int to int. And let's try to compile that. ghci is the Haskell interpreter. So let's say load composition is purity. And oh, I didn't save it. That's why I made the change. Okay, notice a whole bunch of stuff rolled by. Those are all error messages, which we won't try to figure out what they mean. Because that's actually one of the not so great things about Haskell is deciphering error messages. What I do in Haskell is I just look at the line number it says and go look, sometimes I actually read the error messages, but mostly I just see what the line number is and go figure it out. So this is doing the same thing that the Java program did, but you have to say IO int. So actually when you do a IO operation, it shows up in the type signature. For some people hate that, I particularly like it. It means particularly if you're on a distributed team and you wake up in the morning and somebody in China has changed one of your interfaces overnight, you're gonna know about it. You're gonna know if they're doing side effects and that's like very critical. So now if I run this, if I run this, I can't do what we've been doing F of G of three. No, not in scope, I didn't reload it. So F after G of three. Notice again, it's complaining that it can't match IO event because it's a whole different structure and you can run that by way of this thing and it operates just like Java. We're not gonna get into that's like monads in bind but that's not what this talk is about. But the main point is everything we're talking about today depends on purity, depends on like when you call it with arguments, you're gonna get back the same results for the same argument every time. Okay, so the next thing we're gonna talk about is composition is associative and you probably already know this and it's very similar to like addition or multiplication is associative. So A plus B plus C doesn't matter which side you do first it's gonna give you the same result and it's the same thing with associativity. So with this diagram and there's gonna be a lot of diagrams this diagram showing that if let's try the left hand side first it says first run H. So H will get me from A to B and then run the composition F of G F after G so that will get me to here. So let's try the left hand side which says first run G after H which will get me to here and then run F which will get me to D again. So same thing and what they're all really doing is first running H, then running G, then running F which if you look at the composition the composition as just one thing without any parentheses it's just a function from A to D. So let's go on to identity functions and when I say identity functions because in a house gal identity can be as defined as ID of A to A and what that means given any type A I'm gonna return something of that type and the definition is just ID of given an X returns that X. The interesting thing about an identity function is that it doesn't lose any information and it's also the unit of composition and what that means is it's like in addition zero is the unit. So if you add N, zero to N you're gonna get N no matter which side you put it on and it's the same thing. If you compose ID with F on the left or the right it's the same thing as just running F and that's shown by this diagram. If you first run ID it just gives you back the same thing and then you run F and you get to B. If you run F first you get to B and then you run ID you get to the same place. So let's, but a lot of times you see identity think well that's a pretty stupid function it doesn't do anything why would you even use it? And the Haskell code I'm gonna show you is motivates what you would do with an identity function which I'm gonna probably have to reduce the font a little bit to make it readable, let's call it 24. Can you still read that with the lights down? Okay, so let's go back to top. So let's say in Haskell there's this thing called fold R meaning fold from the right and when you first learn the functional programming you'll do a lot of recursion. So you'll do things like length to define length you'll say if it's the empty list the length is zero and if it's X cons down to the rest of some list it's one plus the length of the rest of the list and that's like an explicit recursion. But after a while you stop kind of writing that stuff and you use like folds because folds are a way to actually map not to map to traverse a list and provide a summary value. So given this definition of fold which just says that given a function and that given an A and a B returns a B and some zero element which is the kind of whatever when there's nothing else left that's the zero element. If there is no, if there's no elements just returns zero if there is an X cons down to the rest of a list then run F with given an X and given the results of fold recursively calling fold R on the rest of the list. So if you have that you can define flatten of a list as just fold R and plus plus means append. So if you flattened this list of lists so you have a list of integers. So I have a list with just one element one and two and three that is the same thing as doing one plus plus two plus plus three and that concatenates them together and it looks like, so flatten zero. So it just flattens them down. Great, but the nice thing about that you didn't write explicit recursion. You didn't write flatten by calling itself. It just reused fold R which is a good idea to use fold R as much as possible because there's lots of compiler knows lots of tricks to do. So now let's say we have this thing called flat map. It's another thing which is given a function given an A returns a list of B and then given a list of A returns a list of B. So what this says is I given this X I run G of X on that and that's going to give me this list of B but then I'm going to append that list with whatever the accumulator is which is the results of traversing the rest of that. So like flat map what that looks like is if you called flat map with a function given an X returns X times two in a list it is just going to do basically this. So two, four, three. So the main point is if you have flat map already defined then you instead of just finding flatten up here like this you can define flatten with just say flat map of ID. So the point and this is the big point is a lot of times you'll have a lot of functions that are already doing some pretty interesting things for you and to use those in other places where you can use ID functions so they can do some work for you and here let's see how that works. So if I call flat map with ID of this one, two, three which is really going to be a flatten. So I replace and this one I'm doing here is basically equational reasoning and that just means you're replacing likes with likes in other words like you do in the algebra if you say anything in algebra when you replace something with another equality it's the same value. So the definition of flat map ID is fold R with this function but with the ID plugged in there and then the arguments. So now let's do the first step and that says it is this function given the first element of the list which is one and then the rest is just that same definition but now we've taken off and this is the tail of the list. So when you execute this function ID of X that is going to turn into just ID of this the X is now the one. So I've taken the one from here it was given as X in the function so now it becomes X and it says plus plus the accumulator and the accumulator is the result of the recursive call to fold R. So, okay so then I do the next call which just says ID of two and it does the same thing turns that into a two and then it's a recursive call and ID of three and we finally end up with just one plus plus two plus plus three plus plus the empty list which was the zero element we gave it. So the point of that little digression would say ID actually can turn out to be a useful function when used in combination with other higher order functions. Okay, constant functions the opposite and remember ID didn't lose any information a constant function loses all information and in Haskell a constant function there is a thing called const and it's a function of type A given an A and given a B it returns an A and what that definition is const of X and it doesn't matter what the second thing is you don't need to give it a name so that's what the underscore means just return the X. So what the constant function does is lose all information. So here's a constant function C and says given any A it's always gonna return a character so you can say const of the character C and if you apply that to anything the resulting function it's going to be a C. So let's take a look at that. This is kind of the same thing I'm about to get to is why is that another really dumb function? Doesn't do anything, why would you use it? Well it's the same idea as you can use it with higher order functions to get work done. So let's say you've defined length which I was mentioning earlier so you can define length with explicit recursion by saying length of the empty list is zero the length of X cons on the tail of the list is one plus the length of the tail of the list. So that's the standard way you do it when you're first learning functional programming but let's say you have fold left which is to find this which I'm not gonna drop down into the definition just, but it works similar to fold right in terms of what it's gonna do for you it just operates differently. So you can define length now as fold left of const compose with the successor function. So that's pretty cool. Const actually can do something for you. So let's see how that works. This is what it looks like. If you say length of a two element list then it turns into fold of this composition const compose with successor of zero and so that's the definition just replanting length. So then when you apply it once you say it is now the second call is fold of the same it's always gonna be this is the function that keeps getting passed on and on through every recursive call and then here's the first application it says apply this function which is the composition of constant successor to zero and a. So when you do the successor function which is the one that runs first it turns that zero into a one and then when you run the const on one and a it ignores the a and you have a one. So now when you go through for the next element you say the same thing const of one and it basically just does the same thing it applies successor to one turns that into a two ignores the b returns to. So same thing about constant functions they don't seem to do very much but when used in higher order functions they can make those higher order functions work for you and you can kind of look at constant and ID functions as limit points. One doesn't lose any information constant function loses all information and then all other functions are going to lose a little bit of information and the functional program can be viewed as the art of transformation transforming or losing information to fit a certain context. Okay so now we're gonna look at a bunch of laws that go along with this and the idea of this the rest of this talk is to get you used to thinking I've heard a million times programming and program math or category theory like what does that really mean? And the idea it means just looking at this as your functions mathematically and that's what the rest of this talk will do. So constant fusion the this law called constant fusion just says given a function f of a to b and given a constant function and then given excuse me given that and given an a is just going to return c in other words it just ignores the f. So let's look at that in constant fusion not constant confusion which I've when I've looked at these these after a while I get dizzy looking at these arrows because it's gonna be those diagrams but they actually do something. So constant fusion this is a slightly different definition because I wanted to pass in the constant function but what it says is if given constant fusion well here's a constant which c prime is this function up here which says always no matter what you give it always return the character c and I'm gonna compose that with some function f in this case the f is just plus one so given any number add one to it so when you run c zero it just returns c so what constant fusion is saying is that you can just ignore the application of f and just run constant directly same thing in other words here I've given it this plus one function which does some work and then gets ignored in this case it just gets ignored this is the same thing let's go on because I'm realizing I'm not gonna make it through this talk okay isomorphisms isomorphisms you probably already know about it just says that given a function f from a to b then it has an inverse function from b to a and the law is that if you compose run f the inverse first and then compose with f that's the same thing as id of b what that means is first you run this function so it takes a b to an a and then you run f and that takes an a to a b so you end up back with what you started with so that's id of b and if you do the other composition first run f and then the inverse you get id of b and what isomorphisms do and we do this as programmers all the time it converts between programs how many people write JSON on the wire based on some data that's you're writing some sort of isomorphism from one data structure to another and object relational mappings all those kind of things we matter of fact I always joke with people like most of the things that we do as programmers is transform formats somewhere somebody's piece of program is actually doing some calculation something actually useful but the rest of the time we're like oh well I'm taking it off the wire but now I gotta call this other service and it needs it in this format so I transform it to that and now I gotta call this other thing and it needs some other format so I transform it to that finally somebody does something and then I gotta transform it all the way back out to whatever I told the client I was gonna give it so it turns out doing transformations is pretty ubiquitous products okay so products this is, we've been looking so far at compositions of functions and composition is where the output of one function matches the input of another function and you can hook those together but what if not composable in other words the outputs are not the same well for products it's a case where let's look at this one first now let's look at the Haskell it says given an F which goes from C to A and given a G going from C to B in other words they share the same domain but they have different co-domains and then given a C what can you do with it well I'll give you a pair of outputs and this notation with the parentheses here actually means I'm going to give you a tuple and it's gonna have a result type of A and a result of B and what that looks like is here's pair definition given an F, given a G and given some C just execute call F with C call F a G with C and return that as a pair and we're gonna use this other notation here in the diagrams which is the same thing so these angle brackets means pair which is given a C return the product of A and B which in the definition looks pretty much the same so let's look at products so there's the definition of pair which was the one we just had there and sometimes products or pairs are called splits and transform where did we have transform? I think I went to the wrong file oh products oh I know I forgot something when I was talking I know I forgot that's why I'm not seeing this I forgot to show one thing for isomorphisms okay so here's isomorphism we said we were transforming data structures so we have this data structure called a weekday and it just names the weekday names and we have this thing called seven which just has one, two, three, four, five, six, seven and then I have this transform function which says given any sort of thing that's already an enum and it's an ordinal ordinal just means you can put it in some order define order and enum just means there's no arguments to any of the data constructures so as long as both the arguments are enums and ordinals given an A return of B so first I say from enum and then I compose it with to enum so I'm just changing it whatever enum it is so here's a transform I'm given a Tuesday and I want to turn it into a seven so so if I say I zero you see it does do that notice the next one I zero prime it says I'm given a weekday but I want to return a weekday even though the actual body says the same thing so if I say I zero prime it gives me a Tuesday the same thing and that's because you've told it what type you wanted it I want a seven in this case I want a weekday in that case even though I'm giving it a weekday and then if I want to turn a three into a weekday then I just actually give a something else to it so I won and let's get the rest of that so anyway it's just transforming data from one format to another so products oh yeah that's why I went there products so this one is saying given the show function and given the transform function and transform was the one we just looked at on the last slide on the last file and if I run that it's going to give me so they both have the same input and that is we don't know what it is it's a C but it's got to be an enum and an ordinal it's going to return in this case I'm saying it's going to be a seven and a string so show is Haskell's way to turn any data structure into a string and transformers what we just saw so if I say p zero prime is one on Sunday and I just wanted to point out one other thing because I've defined this pair thing but in Haskell there's this package called control dot arrow and it is a way to deal with different kinds of function applications you know with the most the function application we're typical used to is just call it and it returns a result but when you're working with products and co-products and another thing called exponentials which we won't talk about today you can use the arrows package so even though I've explicitly defined pair you can use the arrow package and it looks like this arrow transform ampersand ampersand ampersand arrow show and that does the exact same thing so if you see p of one prime it returns the same thing okay product cancellation so if you run that pair of functions so give it a C run F and G on it and you get back the pair product A and B and if you need to get just one piece of it you call first or second no big deal there you know it's like car and cat or in list or first and second there's another piece here called the product of two functions so this is what one you'd use when neither the domains nor the ranges coincide in other words you're given something that is a C and a D so it's a pair type C and D and it's going to return types A and B so what it does is when the function runs here's the definition F times G is first you take the first element which is C and that's what A takes and then you run F on it and then you take the second element you run second on it and run G on it and then because it is in a pair notice it has this pair notation it returns the product of that so you come up with an A times B so that is the product of two functions let's go to product so there's the definition of product and what this is saying is it's going to take an integer and a string and I'm returning a string and integer so I'm just reversing the arguments although I'm doing more than just swapping arguments I'm doing something too but at the types I'm swapping the types so what it says is for the one side I want to first add I mean append one to it because it's given a string so I want to append one to whatever string I give it and then I'm calling read read is the thing that will turn string representations of Haskell objects into Haskell objects and then on the other side I'm saying given this the uh... integer times it by two and then show it turn it into a string uh... and once again there's this control arrow dot arrow notation uh... so you actually wouldn't use my definition use the control dot arrow but if you load this and say product zero prime you see it's four and sixty one so I've timed two two by two but I turned it in then I've got said show so it's a string uh... four and then this one I've given the six I've appended one to it and then I've read it turning it into the integer sixty one so that is uh... the product of two functions okay next one is product fusion what this says is that pair is right distributive with respect to composition if I have the pair g of eight composed with f that's the same thing as the pair of first running at and then g and then first running at and then age so you look at that this diagram like this let's look at the left hand side first so here's the f so let's run it first so f takes us from d to c and then you're going to run both g and h on it because they both take c as input but they return a and b as different outputs so if you run g and h together it returns an a times b which you can tell because c g goes from c to a c and h goes from c to b so now you can then you can look at the right hand side okay so how does that work first you do it first in f and then in h which is this side so given that d you'll get a b and then left hand side you say first run f then g and you'll get an a and because it's in this pair it will turn it back into this product so let's look see what that looks like okay so there's the definition of uh... product fusion left and right which uh... it'd be easier if i could switch back and had them on the same screen but uh... product fusion left is the pair composed with f and the right side is the pair of the two compositions which you can see that here's the left the pair of g and h composed with f and the right hand side is the pair of the composition of those two here's some more equational reasoning which shows you if you look at all these things uh... product fusion left is really just the pair running this pair of times two and show and then the digit in so let's first you run digit in on this digit three it turns into three and then you say show three which gives you the strings three and then the times two of three and that gives you six that's the left hand side if you do a similar thing with the right hand side you see it's the same thing so if i actually look at and say product fusions they all return the exact same thing okay here's another thing uh... we're not going to go through this but there's a thing called times absorption and what this says we the last thing we showed that uh... that it was that top sums are are right distributive with respect to composition that's not true about left distributivity but it does hold when f is the product of two functions so f is the product of two functions then if you get that composed with g and h is the same thing as the pair i composed with g and g composed j composed with h one thing uh... if you really want your programs to be super correct you really want to know things like is that really true i can you know it's easy to type that out box is not that easy it's it's hard and look at it to mess but uh... you so what you can do is uh... is uh... some reasoning on it and that is given this definition if you look at the definition of the product of two functions and replace that it turns into this and then if you use that other law we looked at earlier time a product fusion it turns into that and then if you turn in a look you remember that uh... composition is associative you can move the parentheses around once they're moved around then you can use product cancellation and you end up with the right hand side don't expect anybody to look at that although if you go through this paper on your own there's a bunch of exercises you end up doing things like this which are pretty fun okay so the product fusion just arrived looks like this if i'm given a c and i run the pair g of h g and h it's going to run g which gives me a d and h which gives me an a and then you're gonna have a pair of those that's what that means and then i'm going to run the function uh... a time eight uh... i a product j and that is going to run both of these it's going to run i on d j on i and give me a and b so that's all that said and there's different ways to get about to this diagram keep moving product absorption i'm going to skip that file because i want to get to co-products here's something about uh... products and projections it says if you're given and first that's the same thing as first composed with product of two functions and what that means is you don't really need to even evaluate j because you're going to just take first on it so you can skip it and the same thing says the same thing about j i'm going to skip fast all the rest of these uh... this one's actually yeah let's go to this one reflection just says uh... product reflection that if you give a pair but the pair happened to be the functions first and second it's just like giving id uh... to it because you're going to take the a you're going to run first on it then you're going to take b and you're going to run second on this a times b and then it returns the pair so it's just uh... an identity and here's another one of those equational reasoning it says that uh... product is commutative uh... and once again you can go through the depper derivation of this by using the axioms in the theorems that we've already uh... looked at what this is really saying is that uh... uh... products uh... that when you swap the fields in a record it doesn't really mean anything about the information there's just in a different order but no information is lost or gained and i'm gonna skip this and get the co-products okay so products if you remember where when you have functions which take the same type as input but they give two different types as outputs so they both take an input c and one gives back an a and the other one gives back a b so instead you you can run them both and you get back the pair what co-products are you're given an a or a b and these are labeled so it'll say in haskell it's convenient to say left or right so it's either if it's an a it'll say it's a left a and if it's a right it'll say it's a right b and then depending on the definition says if it's a left a it's gonna run the f function if it's a right it's going to run the g function so and if you look at that it's similar right this one it's just that you've flipped these around so instead of a times b returning a c it is a or b returning a c so the main for that co-products look very similar to products so let's go back to that one too the diagram as you have to see it gives this and then there's a way to get the elements with first and second and if you go to this guy instead you're given and left or right of a and then you return a c so it's just kind of the opposite let's see that in haskell with either so either is a type and I'm defining it explicitly but it's actually in haskell ready and it says I'm given a function from a to c and I'm given a function from b to c and I'm given an either an a or b and I'm going to return a c so in the case I'm given a left a then I ignore g and just grab f and I run f of a and in the case that it's right then I'm going to ignore the f grab the g and then run g of b and once again there's arrow notation for this so if you load either and you look like an e zero and e one and e two they're all going to return to e two and return the same thing so what this is saying is if I'm given a left then I'm going to take this value that's in left and times it by eleven if I'm given a right I'm going to take the value and add one to it and the arrow notation is just the same thing we've seen before where it says arrow and then or or or it's kind of like in uh... reminiscent of or which because it either is or so okay so that's the either part so the thing about products yes okay five minutes products and cold products are are uh... dual meaning anything you say about one can be said to the other so I'm going to rush through this uh... I'm not going to actually drop anything but this has the same thing remember we saw a product of two functions so this says uh... it is the sum of two functions and what that says is if I'm given a a or a c then I'm going to run either f or g on it and when I'm done running it I'm going to label it the result with if I if it was enough it's going to be labeled within left and if it's a right it will be labeled with right so that's very similar to what we saw a moment ago where we said given a product of these things I'm going to run them actually it's going to run both of them and give me a different type okay cancellation uh... and that says given a left composed with the sum of two function the the sum of two functions it's the same thing of just doing g in other words you don't really even need to because you've already labeled it what that says is given some value a where's this i want that really should say left and this should say right uh... then it's going to be you run g or h and you'll come with with c so if you go look at the it looks like the same thing but in reverse and then we have the same thing with uh... some reflection that says if there if you give left and right uh... as the functions to uh... to the either then if it's an a then it's just going to turn back into a left of a if it's a left of b it's going to turn back into a left of b so it's the same thing as id of a or b looks like this in reverse that's that's the product reflection it there's the same fusion type of thing where it says on the left-hand side if i run the the either of g and h so if i'm given a left it an a or a b excuse me and run it through the either the sum of g h i'm going to get back a c and then i run it and i can also run it by saying no instead i'm going to just run if it's a b i'm going to run f of h and if it's a uh... a i'm going to run uh... f after g so that looks very similar to that diagram but the arrows end up in reverse uh... there's product uh... some absorption and there's functions sorry about this diagram but uh... i ran out of time turning it into a beautiful diagram so it's just the the uh... hand-drawn one uh... but it says the same thing i'm gonna end up here so there's this mixing products and co-products which says that if you have uh... pro-product a or b you can tune into a product a prime times b prime uh... so let's get the actual definition of that and because uh... we want to eat lunch and i'm out of time so some of the things that talked about is purity all the stuff works because there's no side effects and has cal's rate that way because if there is a heart side effects you can't even use the composition operator fact that their side effects is in the type signature so we talked about various ways to apply functions and compose them and not just compose them when their outputs match and with inputs products and co-products the products were the ones where they both take the same input but get different outputs and co-products are where they uh... that's co-products where they uh... where they take a left or right and then they're going to run one to the other and then give you that output we showed a little bit of equation of reasoning when you have this type of information you can actually reason about your programs by by saying here's what it looks like i replace it with the definition i run that function and replace it by the value and you end up with some very powerful ways to think about your program and then this basically showed you a lot of very interesting patterns and that's what kind of like you if you hear about category theory when i've looked at category theory it gets it stays so abstracts that it takes me a while to relate it to programming when i found this paper i went oh okay i can actually relate that to programming now but now i'm actually feeling more confident that i could go to category theory and actually dive in a little deeper there's lots more in the paper which is the full link to the paper and where we made it to was page thirty of two hundred and eighty-five pages so you've all got your work cut out for you because it's uh... pretty interesting reading and it's got lots of exercises and if you want the code and the slides it's right there at this uh... bitly link bitly is two thousand fifteen lambda dash comp dash herald dash car and it has all the house gal code and slides and uh... yeah that's it and but that that paper i really recommend going and getting that paper and running through it's a great paper thank you any questions