Secret Haskell Composition Technique

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
today I wanted to talk about composition of functions I use composition of functions quite often and every time I use it I need to explain people what the hell it is and I decided you know why not just record the video and every time I need to explain what is a composition of functions I can just point people at that yeah and here this is the video you're you're watching it to understand what is the composition of factors we need to understand what is a functor and a factor is anything that is anything that can be f map a key penetrated so I'd like to call this operation a penetration because it kind of makes sense because imagine that you have a functor just five which is essentially and maybe that contains a which is a number and you use f map operation that takes with a function that takes an x and increases that x by one and you just apply it to just five and you get a just six you see we don't unwrap just we inject a function into maybe increment the number there and yeah and just do nothing with it like and this is what separates roz developers from haskell developers right so r as developers like to unwrap everything they constantly unwrap anything they cannot work with values unless they and rabbiting it on wrap every second every day in haskell world we don't unwrap things we inject functions into things and modify them from within this is how we work and this is what factories and as a matter of fact like f map has an areas a very convenient areas that looks like dollar sign with the some special brackets and it's absolutely the same semantically absolutely the same and furthermore you can even simplify this expression further by using partial location for operators just using plus one and plus one is basically a function it takes any value in incremented by one so this is how you can do that so I just took this function and injected it into the maybe I just been attracted and maybe okay but the management that you have not just a single functor but several function because there can be several kinds of factors for example list is also a functor right and if you try to penetrate this factor it will have an interesting effect it will increment each individual element so basically F map on lists acts like map and map is basically a special case of a map that only works with lists simple as that so and imagine that you have two layers of these factors and you want to penetrate all of the layers and increment each an individual element of that list by one but yeah you have least first of all and you have adjust so by taking this entire thing and just penetrating it with +1 this is not really gonna work because you're essentially applying +1 to at least and yeah so what you have to do you have to penetrate it yet again and only then is going to work which is kind of tedious right so I would like to treat this composition of functions as a single factor which I can penetrate once and achieve what I want here basically what you find the the most like low-level elements of the of this composition right so and this is where we use composition of functions and it's a part of the standard level of Haskell you can find those things in data functor composed and here they are compose it's a special type I would say was actually see if I can find it quick enough probably not I probably have to scroll it up very inconvenient so it takes three parameters my gut a first functor second functor and the will but these are tab parameters you usually don't have to worry about them to construct a value of composure you have to have a composition of functions first this one and you just wrap it with the data constructor compose and you get your composition so with this composition what you can do you can just penetrate it once and there you go you achieved what you wanted so compose merge these two functors into a single filter and expose the interface of a single factor but it will act like a double penetration of these two factors so this is what it is but after that you still have a compose right so to access the actual value you have to you know unwrap it back but this particular thing enables you with actually chaining several modifications for example on top of adding one I can multiply by two and you can have more in more of these modifications that keep penetrating both of the layers of the of the founders and then once you're done penetrating both of the layers you can just get compose and wrap it back into you know pure compositional founders so yeah this is basically what this this is basically what it is very convenient technique very convenient trick that function programmers came up with and I use it every time but okay so this is how you use that but the question is how would you implement something like compose because yeah that's the most interesting thing because right now we treat it as like a magic box like we just apply compose and magically it just just works let's demystify that magic a little bit let's try to implement our own compose I think it's going to be interesting and all right so what's gonna be the compose it's gonna be a type a generic type then is parametrized by three arguments my god this is a very complex type three three type arguments can you imagine that first functor second time a functor and values that is contained within the composition of the of functors right and what's the definition of that type it's going to be composed it can be a record that has only one field get composed the type of which is a wrapped in G rotten F and it's usually a good idea to automatically implement a show interface for these particular types so if F G and a are show both the whole thing is going to be shoulder as well and we will be able to see it down here in the report and so usually pretty convene to do something that listen I think about and why this record has a field called get compose I actually explained that in my Jason parson video it's sort of like a trick that Haskell developers came up with it basically this entire definition generates you two functions or at least things that act like functions because one of them is going to be data constructor which is not incidentally function but it acts like a function so if you take a look at the compose I'm not sure if I can use T and compose I think you should be able to no you cannot but I'm pretty sure you should be able to use get compose no you cannot as well probably because I screwed up something we have ambiguous occurrences oh this is because I already created I already imported the compose from the standard library and now I have my own compose and we compile and everything doesn't help so the only option I have right now is to kill my entire session and restart the session yet again hoping that everything going to be okay okay and now I can say that I have a compose that takes a composition of functions and returns my compose this is the first function and it also generates a function get compose that basically performs an opposite operation you see you can wrap compose and you can easily unwrap compose this is sort of a like a trick that has the developers came up with to generate two functions that do opposite operations and it relies on the specific on how on the specific use all the records of Haskell so yeah if you want to know a little bit more details and look my Jason parson video it's it's really strange but it's really interesting at the same time yeah the most important part here is that we can compose and we can come compose simply that so now what we need to do we need to implement a functor interface for compose let's go ahead and do that so in creating an instance and what do we have we have F which is a function and G which is also a factor and what we need to prove we need to prove that composition of F and G is also a function so you see if you do use compose FG without a it's going to be a type that takes one type parameter making it effectively a factor which actually fits perfectly into this particular place anyway so let's actually define it like that and see what kind of methods we have to implement we have to implement F map so and F map if I remember correctly has this signature so is the first thing it takes a function that we need to inject into the functor then the functor itself and we need to return something there we don't know what we get in return I'm gonna return the whole just to see what's gonna be there so whole is supposed to be composed okay let's actually unwrap it by wrapping the hole in compose but that will actually unwrap the type of a because it's supposed to fit into this particular place and at the type of a is going to be the composition of these two founders so what things we have in the context we have C which is composed which probably needs to be you know Al wrapped as as well so it's actually a patter magic which effectively will unwrap it in turn have internal C into composition of F and G and here's the interesting thing the whole a where's the error the time the whole egg has a type F G B and whole and C from the context has the type F G a so you see we have F G a and we need to turn it into F G B and on top of that we have a function that turns F a into B so that's pretty much it that's the whole idea so what we need to do here I suppose we need to take C and try to penetrate it with something so what we're going to penetrate it with we need to penetrate it with the function that takes G a and returns G B so basically we unwrap the first layer of things which means that I think we can achieve it like so yes yeah in it compiles okay so we successfully implemented the functor instance for compose and it should act like the one from the standard library let's actually check it out so I already have my compose it only has two interfaces the show and function interface let's generate at least from one to five let's wrap that list into maybe and let's compose it and let's take a look at it so here it is and I should be able to just simply penetrate it and it should work after the penetration should be able to get composed and extract my internal type everything seems to be okay so this is how we implement that so and what's fun is that we still perform double penetration as we did at the beginning of the video but we sort of hidden that double penetration under the separate type and this is pretty much the point of this composition so you still perform double penetration but you hide it from the user you still hide it but what's funny is that factor is not the only thing you can compose you can compose also something that is called applicative and applicative is a very interesting interface and we use it a lot in my JSON parsing video again I really recommend to watch it it's it's a long video but it's an interesting one it's packed with interesting concept and interesting tricks for Haskell programming so that's that's why I keep recommending it so and applicative it has a very interesting workflow it has an operation that looks like that I don't even know how the separation called so I'm gonna call it the separation applicative emerge because it basically merges two applicatives and you supposed to use it alone with F map right so if you have applicative you have to use it along with this operation so the reason why I have to do that is because the left argument of this appear ever takes applicative that contains a function from A to B and right one contains a and what basically does it applies internal function into the internal value and then returns you the result wrapped in applicatives but it basically merges these two applicative together right and let's let's take a look at example four example you may have two maybes right and you wanna sum them up without unwrapping the maybe I think I even already moved through this example in my Jason person video but I'm gonna do that again just just for the context so the first thing you have to do with the first maybe you have to apply plus operation to it and that will create a very interesting time it will create a maybe that contains a function from A to A so we already got an applicative that contains a function so after that you use this merge operation to merge this thing with six and there you go you just summed up two values without actually unwrapping the applicative and what's funny is that this particular approach actually scales to as many arguments as you want you just need to have appropriate function for example let's take a look at the function that takes three arguments right so for example this particular function construct a triple and accepts three three arguments so what we can do here is apply to just five then merge it with just six then merge it again with just seven and you got a triple within the applicative without actually unwrapping any applicative you just merge them together so and so this is the basic workflow with the applicative and you may have a similar situation as with a functor for example you may have a composition of applicatives right and you wanna merge them together for example by I don't know summon up some the numbers in the internal in the internal lists but in case of applicative it's not going to be you know like pair by pair sum up because merging least as an applicative actually used a Cartesian product yeah but I mean it's it's besides the point you still need to penetrate like additional layer of applicative and you can do that but if you implement an applicative interface for your composition you will be able to do that let's actually see how it can be done imagine that you have F which is applicative and G which is also applicative and you need to prove that the composition of F and G is applicative as well let's go ahead and do that let's go ahead and do that so what we need to do here is first apparition that you need to implement is of course a pure operation pure operation takes just a William and wraps that well you into the applicative so let's see what we will have to return so we already have to return compose let's unwrap call a and now we have a composition of F and G both of which or applicatives which means that I can just keep applying pure until they achieved the right composition and furthermore here I can use at a reduction by removing X and replacing of applications with compositions and now I have a very nice and neat definition so first pure rubs applicative G second pure Grubbs applicative F and then we'll wrap the whole result in to compose this is how we can implement pure operation for for compose the next operation we have to implement is this merge separation I don't know if it's called mercenary I really apologize if I call it in incorrect way so we have two compositions and we have to produce something else here so of course let's unwrap everything just in case mm-hmm wrap everything just in case and let's take a look at the context that we have C 1 and C 2 both are compositions of the same applicatives so what I want to do first I think I one emerge the first layer of applicatives this one EPS so to do that as usual I'm gonna use this separation c1 c2 but to properly multiplicative again you need to use this F map operation but I have no idea what kind of function I have to apply here so I'm gonna just put a hole here to see of what the comparable suggest me so the hole has to have this particular type which looks kind of familiar don't you recognize this type so it takes G that contains function from M to B then G that contains n a and returns to G that contains B this signature looks exactly that like the merge operation itself like it looks exactly like it would do that yes so essentially to implement this separation I just have to pass merge here and it compiles it in fact compiles so this is how we do that and you see we had to perform this double merge yet again we still perform double merge but we hand it behind this compose type so we don't have to do that directly anymore so imagine that we have two compositions of two applicatives all right as usual they are composed together and let's try to alert them what's going to be the operation that we're going to merge them with what's the Blas and as you can see everything works as expected yeah we successfully implemented the composition of applicatives you can actually go even further I think like there is a very interesting example you can make a composition of functions that contain semigroup and may improve that entire composition is also going to be same a group so what is a semigroup by the way Semih group is a very interesting interface that has just one operation just one operation this one and it takes a one simha group element of a one element of semi-group another element of semigroup and returns another element of semigroup so basically it merges two elements together simple as that what could be example of same a group well it could be a string and for a string this merging is going to be simply concatenation so yeah and if a inside of composition is a semi group you can actually demonstrate that the whole composition is going to be a semi group but you can only do that if F and G are applicatives let's actually go ahead and try to do that it's actually a very interesting thing so imagine that you have F which is applicative then you have G which is applicative and you have a which is a similar and what you need to prove in the prove that composition of a of G and a is going to be a semi group as well okay so you just need to implement oh my god Emacs come on you need to implement only this you know append operations I think it's called depends if I'm not mistaken so what we need to have here let's let's take a look what's deca underscore a has to be a composition and C 1 and C 2 are composition so what's interesting is that I know that composition of F and G where F of G and F and G or applicatives is applicative itself so to merge these things together I don't have to unwrap them anymore right I don't have to unwrap them I have to just you know use the merge operation but what kind of function I have to use here to actually merge them so it's like let's take a look at it well it's a very familiar signature very familiar one it's basically the operation of the semi group and there we go we just proved that if the internal a is this in group and F and G are applicative the entire thing is a semigroup we actually prove that maybe not because there is also some some laws that cannot be expressed in the type system of Haskell and if it is possible to implement in instance of some interface it is not necessary it does not necessarily means that we proved that that thing is a sever group so but I don't remember laws of the semi group I think it's associativity or something like that so if I'm if I'm wrong on that please correct me in the comments of course yes but I just want you to implement that because I think it's an interesting example nonetheless if it's incorrect well I'm I really apologize to that so let's actually check out how it's going to work let's imagine that we have a string hello wrapped in the least wrapped in a maybe and let's compose these things together so and then we're gonna append it to another string wrapped in at least two wrapped in may be composed and we should be able to concatenate these two internal strings together and we managed to do that and we managed to do that with the help of this particular instance whether it's correct or not I have no idea if it's correct or not maybe it's not and you can actually implement as many interfaces for your composition as possible for example if you want you can try to implement an instance where you have F which is a Monnett G which is also a Monnett and you can try to prove that composition of these two things is going to be monitor's well so yeah the only thing you will have to implement is this vine depression which accepts I think first it accepts the moments itself but I don't remember I think it accepts function first yes let me see mc1 yeah so the second one is a function and you just need to implement this thing and a underscore a is supposed to be composition but I'm going to leave the implementation of this intense instance as the whole work for the viewers good luck [Music]
Info
Channel: Tsoding
Views: 14,846
Rating: 4.9566002 out of 5
Keywords: Programming, Coding, Functional Programming, Haskell, Emacs, Linux, Debian, Rust, Tutorial, Monad, Functor, Applicative, Composition
Id: bT3wsZgrZto
Channel Id: undefined
Length: 26min 44sec (1604 seconds)
Published: Mon Mar 02 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.