 All right. Can everybody hear me? I hope you can. I can hear myself. Yeah. Haskell is the best, right? You got the type system. You got the laziness. And you've got everything you need, essentially. So welcome to Advent of Code. Again, I did this last year and I thought it was a lot of fun. So I'm doing it again and I hope you enjoy it. So a little bit about me. I am doing my PhD in in programming languages at Chalmers in Sweden. And it's mostly because I like Haskell. And then, you know, if you're doing a PhD, you can just do a lot of Haskell if you want to. But all right, let's get to it. So I think this stream will be not too long, right? Because the first day is usually pretty easy. But yeah, we'll see. And also, like, let me know if the, you know, Christmas music is too loud or or anything, really. All right. So let's look at today's problem. This is the Advent of Code website. And we're opening it up. All right. I wonder what we're going to get. So last year we had like, yeah, thanks. I have my Hindi thing on. Let me actually disallow it. Okay. It's nice. It's like switches words out. So you can learn a language if you want. Like an alert vocabulary, right? Otherwise, you just learn a bunch of words about cows. But then you, oh, wow. Thanks for the following. All right. Wow. Okay, let's go. So day one, sooner sweep. You're mining your own business on a ship at sea when the overboard alarm goes off. You rush to see if you can help. Apparently, one of the L strip and accidentally sent off the slaggy slang, one of the slaggy slang into the ocean. Okay. Before you know it, you're inside a submarine. The elves keep ready for a stitch. Why would they have a submarine for these? I mean, does it happen often? I don't know. It's covered in Christmas lights because of course it is. And it even has an experimental antenna that you should be able to track the keys if you can boost the signal strength high enough. There's a little meter that indicates the antenna signal strength, but it's playing zero to 50 stars. Okay. So I guess like all the challenges this year will be about boosting the signal. All right. Gotta get all 50 stars by December 25th. Christmas. Okay. We saw puzzles. Yes. Two puzzles available each day. Yeah. And each puzzle gives one star. Makes sense. Okay. As the submarine drops below the surface of the ocean, it automatically performs the sonar sweep of the nearby sea floor. On a small screen, the sonar sweep report your puzzle input appears. Each line is read as a measurement of the sea floor depth, the sea floor depth. As the sweep looks further and further away from the submarine. Okay. For example, suppose you had the following report. Okay. So what we're gonna do is we are going to say this as example. Okay. And then we just say example and we paste and we got our example. Okay. This report indicates that the scanning out from the submarine, the sonar sweep found as of one nine nine two hundred. Okay. The first order of business is to figure out how quickly the depth increases just so you can know what you're dealing with. You never know if your keys will get carried into deep water by an ocean current or fish or something. Okay. To do this count the number of times a depth measurement increases from the previous measurement. There's no measurement before the first measurement. Okay. So there are seven measurements that are larger than the previous measurements. Okay. How many measurements are larger than the previous measurement? Okay. So well seems good. So we're just so we're finding I think this is like a subsequence to this problem, right? There's like super efficient algorithms for this. But you know, we're not gonna we're not gonna do that too much. Okay. So let's just see what we can do here. Okay. Let's we have the example input and let's make this a bit like this. You can see my messy desktop. What's not to like? Okay. Let's see day one. So an example is going to be a list of ints. Example equals. Okay. So I think we can do read file. Right. I never remember like any API. I always have to look it up. Yeah. So read file takes in a file path and gives us an IO string. So we're gonna read an example. Okay. And then we are going to turn it into a list of yeah. Okay. So we read the file, then we do I think online some of the lines, right? Yeah. So we could do get lines and that gives us like all the lines in the file. And then we are going to map read at int over the lines. I like this right. So we need to actually add type applications here. I think maybe good type applications. I think we have like I think type applications aren't gc 2021. So I think that's like the version of Haskell we're using like the compiler is 8.10. I might switch to 9. I don't have it now, but I think that one works okay so far. And I think like in that one you have this GAT 2021 extension. That is just a collection of kind of extensions that everyone uses all the time. And you know it works out. So we'll probably end up using that but in the meantime, I think we go do like this. So now we do load day one. A read file is applied to too many arguments. Oh yeah, we did the dots. Okay, let's just get so yet. Let's just write read input. Try to fix in file name, file path, and it returns a list of ints, io here, read input equals. And then we take all these and paste it. So as kind of this thing grows, we will we need like more sophisticated parsers eventually. Yeah, I mean, this is how you do it, right? You read it, map, yeah. That's exactly how you do these things, right? So this is going to be read input example. Let's say you load a write. So this is going to be an io page. And it doesn't like yes, because we have to fmap. This is this is how I program, right? It's all a it's all a conversation with the compiler, right? You instead of like trying to get it right right away, you just wait a minute. So pretty much type io string with char, okay? What is the type of lines over read file? Need file? That gives us a string, right? And then maybe what is going on here? So this is fmap, right? That should give us we should be able to say, you know, something fmapped over read file. What? What am I missing here? fmap. All right, got the file makes sense. Okay, now it works. And example is a list of numbers. Okay. I think I know what we do here. So there's a function called group by group. Isn't it called group import data dot list group by which takes in a function. And it kind of goes over the list and it groups them. So what I want to do is I want to do group by less than or equal to to group the ints. Okay, so we're going to do this. And then we're going to say this over the example. Right. So here it's like, I guess we have to group by it doesn't really say what happens if it's the same. But okay, so we have the first measurement and then yeah, and then it increases and then increases. But then these in these three. Oh, yeah, yeah, yeah, this is the part where because it doesn't it doesn't like so it doesn't actually because it kind of groups by the the first one, right? And then it doesn't stop until it yeah. Yeah. Okay, let's just write it, you know, it was probably a nice kind of group by thing we could do here. But I think it's just easier to just write the function that says count ink, which takes in a list of ints and returns on it. Count ink is equal to count ink prime of zero. Where uh count ink prime. So this is like the classic recursive programming, right? You kind of you write the function that is your base case. And then you invoke it with a base case. But like yeah, so now we have our initial value. So we're definitely we're kind of just defining a fold in the sense of yeah, so now we're just kind of defining like how are you going to start, right? And then like, we know what we want to do when we start. So we so we want to start with this zero, right? So this is going to be an int to a list of ints to an int. Yeah, like a recursion scheme. Yeah, so recursion schemes are kind of uh a way to tell like how you want to consume the structure, right? Like how are you going to recur? Is this a recursion scheme? Is that what it's? I don't know. I always think about like very complex recursion schemes. I didn't remember. Yeah, I want to learn more about what you meant. Okay, so we have the curve. Okay, and if we have the empty list, we just return the curve. We'll go return the curve. So essentially, right, if we're going to count the number of increases, and we reach the end, we were done, right? So we return the current one. Okay. Ah, yes. Right. So here we're actually going to say first, and then rest. And we're going to say zero and then first, and then rest. And we're going to say a last L, right? And we don't actually care about in this case. So count. So what are we trying to do here, right? We're going to do curve. And we have the kind of the first element. This is a trick, right? That's why they say here, right? No previous measurement. Okay, so we can actually call this crevmes. Okay. And then if we have cremes and then rest equals, we actually do a guard, right? So if the previous measurement is smaller than the, I'm just going to say that less than or equals is it can be. Now we're counting the increases, right? So if it stays the same, that's not an increase. So the previous measurement is smaller than the current measurement. Then we want to recurse, but we want to, okay, we actually can actually join these cases. This is going to be counting currprime, cremes, rest, where currprime equals. So currprime is if crevmes is less than currmes equals curr plus one currprime, otherwise equals curr. I think you can do this with guards. I'm not entirely sure. I did that last year. Okay. Yeah, no, okay. This is not okay. I think we need to do like this. And we say otherwise equals curr. And it doesn't like it because we give it a type and then we change it. And then there was a good hello. Lucky urn wolf. Sorry. I have to zoom in my chat a bit. It's on my like, so I have like a, I have like a teleprompter, right? So I can look at chat when I'm looking at chat. So I'm looking into the camera when I'm talking to you. But it's like a tiny screen, right? It's not, it's cheap. So I had to, and it's also like, it's a dark mode. So and I can't put into non dark mode. Yeah, 2020. It's like a necessity drives innovation, right? Like if you want to, yeah, I just, I just went kind of all into my video setup, right? So it's so nice. If you're a zoom, you can just look people in the eye while you're talking to them. Problem is that like they don't have a teleprompter. So they're not looking back. They're looking, you know, always talking to you, looking somewhere else, but I can look into your eye. So everyone likes the chat. Okay, let's say run our count ink over the example. Seven. Yes. No, because I was made fun of last advent of code, right? Because I was always looking over here to talk to chat. And then yeah, that wasn't popular, apparently. So now I can look into at you when I'm talking to you. And now I'm looking at the code, looking at you. It all works out. All right, we got the right answer for the example. So we are going to get our puzzle input, control A, control C. Yeah. I am coding the first advent of code problem. So there's like a collection of 25 problems. And there's a new one every day until December 25th. And I'm going to be doing them every day. I mean, not every day, because like, yeah, like Friday, mom's like coming to visit. So I have to go away then. And then, you know, I'll be traveling back home for Christmas. So but then I'll do like the day after I'll do a double feature or something like that. So all right, now we have the input. And let's just run it. We're going to go count ink over read input input 1527. And see, this is also nice about yeah, so most things exactly. Yeah, unless I have a good reason not. That's what's nice about this, like you just stream a bunch for a couple of days, or like for like a month. And then, and then last year I tried to do something else. But I don't know, it's a it's more fun with a Christmas mood, you play Christmas music, it's all happening. By the way, I want to ask you, is the Christmas music too loud or no, because I because I can tune it. Just let me know if you if you don't like the audio. And yeah, okay, see now we ran it and it was this is what I I tried to do is that I tried to not over optimize right until it actually. Yeah, because it's pretty fast, at least in the beginning, like if you don't, if you like approach it in a sensible way, it's usually not too bad. So but then I mean, yeah, at like day 15 or like, or maybe earlier, like day 11, like then you really have to think about like, how can I optimize this so that it runs very fast. But now it's, yeah, I mean, if it runs, instantaneously, like there's nowhere I mean, there's a lot of competition with that bit of code, actually, where, you know, the the rust people, they're always like, Oh, I finished in two microseconds. And you're like, Oh, well, it took me shorter time to write. All right. That was a clip. Okay. Let's see 1527. Yes. Also, what's the advent of code? So yeah, so you go to admin of code.com. And it's like this Christmas calendar that a every day until the 25th, so until Christmas, they publish a new programming challenge. And like the first few days are quite nice. Like, yeah, it's just the something you might get on like computer science 101 exam. But then it really you know, they really pump up the difficulty, like, especially like around day 10, it gets it can get very hard, right? So yeah, but it's fun, right? And then yeah, then you really have to like go into especially in Haskell, right? You have to really pump out the performance. All right. Considering every single measurement isn't as useful as you expected, there's just too much noise in the data. Instead, consider sums of three measurements lighting window again. Okay. Yeah, exactly. So this is the first programming. Oh, thanks. I'm guessing that's Stainfield. He's a friend of mine. He's cool. Okay. Let's see. All right. So, hey, okay. The sum of measurements is larger than the sum. The first this first comparison. Okay. So, okay. So we just, okay. We just slide the window. Okay. Let's do that then. So count ink. Okay, this is let's mark it first one. So count ink. Second one. Easy. Count ink. Two. Now we're going to get to do something. It's just coffee Stainfield in a Moomin cup. So lucky, this is just VS code. It's actually quite nice. I'm using like the colorblind color scheme from GitHub. It's quite nice. Yeah, it just works. Okay. So now we're going to have a three sliding window thing, right? So instead of just looking at the one, we just say A, B, and C. And then the rest. Okay. And then we count the increases. No, that's actually throwing an exception here. Because like you can assume a list is not empty, but I'm assuming it has three elements. That's a bit much, right? Count ink, otherwise, exception, too few elements. Now, A, B, C, rest. Okay. Yes. So this is going to be count ink. This is actually going to be A plus B plus C. So what we're going to do is that we're going to, and then we actually going to throw it. Yeah, I like it. It feels, it's just easier to see, right? That's why it's like for colorblinds because it does just the colors are farther away from each other. So you know, even if you're not colorblind, it's not, it's better. Okay. So what we're going to do here is that we're going to say A plus B plus C, and then the rest in the B and C of the rest, right? And then what we are going to do is we are going to say, okay, so this is the prep sum. Okay. And then we're going to return it in case, in this case, if it's, if we're done, we're going to return it. So I think we should pass in A here as well. Okay. So just call that first. Now let's say another inch here. So what we're going to do is that we have like the current sum, right? And then we add the next value. And then we kind of, yeah, so we kind of add the next value and then we remove the A, right? So then we only have to keep track of one value at a time. So this is going to be the next and the rest. Okay. And what's the recursion here? I think the curve prime is fine. But the new sum, let's just define it right there. Yeah, yeah. I mean, coding is also like, it's, it's mostly about practice, right? So I mean, you learn computer science and that makes you, you get like a gut feeling for what's good, or like, what's a nice approach, right? Like what's going to be complex or not. But it's mostly just about, you know, you play around, you program and then you get some experience. And yeah, that's, that's kind of all you, yeah. And then the more practice you get, the kind of quicker you get. But of course, like now I'm not trying to speed code this. I'm just, I like talking about it as well. That's what I like about the stream, right? Yeah. Right, like, what's your question? Sum is equal to a first crown sum plus next minus first, like this. Okay. Okay. Yeah, you can pattern match against anything, Jonathan. But it's, I guess it's, it's, it's a bit much, right? Because you can't assume that a list is not empty. That's like reasonable, but at the same wing, it has three elements. That's, that's risky stuff. Okay. So with the next sum is going to be, so now we have, oh yeah. So now we got to kind of, we got to kind of pass the, be here. Ah, let's, let's pass all of them. A, B, C, cur, this is going to be A, B, C, C, prep sum, data.list, at least three lists. Yeah, yeah, that would be good. All right, let's see. What did, let me see. How did it get the start package thingy to start? Because I watch, when I watch videos, I don't know how to get the pre-made starting thingy. And I don't quite know what you mean. Can you rephrase it? Just, just so I can get another understanding of it. I'll just finish day one in C sharp and bigger than and bigger than equal. Yeah, yeah, exactly. Yeah, when I start the code, yeah, that is exactly what you want. We don't actually need the sum here because we have the element. Let's just sum them up again. Let's say this is D. Okay, now this is going to be, the curve prime is just a check. Is A plus, A plus, B plus, C, less than B plus, C plus, D. And then we increase and then we say the new list is going to be B, C, D. I think this works. So when you start, lucky, we want to figure it out. So, yeah, so to start this, exactly. So one trick you can do in VS code is that you have these dev containers. And so, yeah, after I after I've done with this, I'll show you how you can you can add a directory that's like called dev containers. And then in that you have something called dev container.json. And then you can kind of load up an entire environment into a VS code, which is pre-installed and everything, which is pretty nice. Okay, let's see if this actually does something. There is supposed to be an exception function, right? Any reason why you aren't streaming in software and game dev? Well, yeah, so there's no generic programming, right? I'm not really developing software. Okay, I guess I would be a better category. I'll change it. I will change it. I don't think it is a software and game development. Okay, yeah, I guess maybe people have coalesced around that now for having the code. Yes. So I've changed it. It'll be correct next time. Okay, let's see. Does this... Oh yeah, no, it's error. Sorry. Error. Error. Okay. Yeah, now I added too many types. This is a list of things, actually. No, let's do it all. This is what happens when you... Yeah, I think it's correct now. Okay, it's a good point. We have to categorize things. It's the categorical imperative. Okay, now let's check if counting works on our example. We get seven again. Is that correct? I don't think it is, right? No, there's supposed to be five. Five. Let's actually see what goes on. Import debug.trace. Now, let's just look at our... Let's look at the running sums. Okay, so this is our s hat and then we do trace show s dollar. This is a nice trick you can use in Haskell where you kind of... It's the Haskell way of printing out, but you can't have a side effect. But trace show... What trace show does is that whenever it's evaluated, it prints this first argument, right? And it's a debug print of Haskell. Okay, counting two of, for example. So, $199, $200, $208, $200. Yeah, there's something going on here, right? $209, $109. So, where did it to $10 go? Let me see. Yeah, yeah. So, it's the element of code, exactly. A, A, B, C, and then B, C, rest. Okay, let's say... Is there like a scope error? Let's print the list and it's some A plus B plus C. $607, $608. Okay, so it's supposed to be $199, $200, $200. That's correct. Then it's $200, $208, $200 again. A, B, C, cur. I think there's like a scope issue. Now, let me see. A1, B1, C1. A1, B1, C1, B1, C1. $199, $200, $208, $200, $200, $200, $200. So, it's just a... It's not updating the list correctly. So, what is the D here? So, it's A, B, and C. Okay, let's actually not do it like this, right? Okay, come on, B1, C1. Okay, yeah, exactly. Sorry, now I'm like sinking into the code and then it started a bit harder for me to answer. Okay, the first sliding window is correct. We have $200, $109, $200, $208. Okay, and then we have D. Why is D here? Oh, okay. Right. So, we shouldn't add them back. I think that's the problem that we were adding them back. And we were doing it differently now. Yeah, exactly. So now, yeah, yeah, yeah. Okay, we fixed it. Yeah, because I added them back and then it was kind of... It wasn't actually doing the thing. Okay, but now we get five for this. Okay, so let's throw this out. Yeah, Haskell is a very... It's like a functional programming language, which means that you always write functions. And it's all about writing a function, right? So, if you have a problem, you write a function and then if you want to fix it, if you get another problem, you just write another function, right? And then you... It's all about kind of gluing all the functions together so that you... So, it becomes like a data transformation pipeline, right? So, here, what this function does is that it transforms a list of ints into one int. And then you kind of define this whole data flow pipeline where all your input data goes in and it gets processed and you get the answer or the side effects that you want. Yeah, exactly. Janatin and me are the same. It's also the... It's the best programming language. That's my opinion, but I am a qualified professional. Okay, so it worked. Let's reload it without the thing and let's run it on our input. It's always... You always have to do it on the input. Same input, actually. So now we have the sliding window and then no change. Yeah. Five sums. Okay. Let's go. That can't be. Really. Oh, 1570. Okay, yeah. It's slightly different. Okay. I thought we were getting the same... Let's check it. Might be wrong. Might be not. We completed day one. It was pretty good. Yeah. We got a bit set back by the... We did it wrong in the start, but it turned out okay. That's my favorite color. I think it is yellow. Look at this. Such a nice color, huh? Now orange is also good. So this is a good theme. And a good combination. Okay, so yeah. Let's go over what we did, right? First, we were always just kind of keeping track of the first one. And then we were going to switch to a sliding window. So we just switched to a sliding window. And because it's Haskell, right, we can just pattern match on all the values, right? And then we just carry them with us everywhere. And then we construct a new list. So this is not the most optimal way, right? It's going to... Because it takes this list and then it has to construct this list. And it's an entirely new list, right? So this is not the best way to do it. And you also notice here that like this sum is equal to... Yeah, so we really just have to check is if b is bigger than d, right? Let me check. We even need... Oh, okay. Yeah, exactly. We don't... We don't even need... I use take three with the tail recursion function in my implementation. Yeah. I mean, this is tail recursive, right? Count, ink, pry. It all works down. Okay, but notice what we saw here, right? We don't actually need... We don't actually need b and c in the output. Yeah, so I think that's what Jenkins is trying to tell us, right? So instead of checking like if this one is bigger than the next one, you're really just checking is this one bigger than this one, right? So like four steps ahead. Yeah. I don't know. Let's define a main list into print. Okay, so we're going to compile it with O3. How fast is it going to go? Save it, compile it, day one. Oh no. Okay, it takes 0.2 seconds, which is not bad, yeah. Right, so if we had an array, right, we would... Okay, that makes sense. Yeah, so no. What is happening? I am sorry. This is all a big mistake. Okay, there we go. Okay, yeah, it doesn't take long, right? It takes... In fact, it takes shorter time to run our program than for Bash to try and figure out if this is a command or not. That's not bad. So 21 milliseconds. And I would like to point out that if we do like this and we don't even do our computation. Okay, so like that's the boot up time is quite long. And then int is read input input. Let's just time it, right? How long? Oh my god. Now, I think this will actually be optimized the way. Or, okay, let's actually print the length of the input. No, oh yeah. Do, okay, print the length of the input that sort of takes us out. It's... No. I keep like not reading what I'm running. Okay, so that takes 10 real seconds. Whereas... So we run it and yeah, so it takes us 24. Yeah, 21 milliseconds. It's not bad. We can dump the core. How do I dump it again? Let's see. Now we're getting into advanced house code. Dump show generated core gg. D dump splices. D dump core stats. D dump ds. D dump ds. I think that's D dump ds. Where does it dump it? It doesn't actually dump it. Watch me do advanced house code. Exactly. Why is it not dumping the core? Maybe I need to tell it where to dump it. D dump file dump. Dump to file. Okay, so let's see. D dump simple. D dump to file. Maybe it's going to some... No. D dump file prefix equals... It's just not dumping it. What if I do... What if I turn off O3? Oh, now it actually did something. Yes. Okay, so this is the core. So what was happening is that it was essentially not dumping it. Why? Well, it already compiled the file. So it was like, I don't need to compile it again. So now we get the actual thing. Okay. So the main is just... Yeah, so the example... Yeah, that's not interesting. So this is our count in prime function, right? And you can kind of say... See that? Okay, this is a very kind of primitive, right? But it really just goes down into a case statement. And you can say that it checks whether the... Yeah, I mean, it really just defaults into like checking the... Sorry. Yeah, it just text it and then it calls itself again, right? Let me see. What does this mean? Okay, so case current mass. That's a lot. That was our current measurement. So we kind of pattern match on the current measurement. And it takes the y82gq, okay? And then it... What is the other case actually? Okay, there is no other case. Okay, so it just kind of unwraps the integer. Yeah, yeah. Okay, that's what it's doing, right? Because it's an int, right? It's a wrapped int. So it has to unwrap the... It has to unbox the int. That's what it's doing, right? So this is an unboxed int. And then we compare the unboxed int to the one we had before. So this is the prev-mes, right? And this is the new mes, right? So it unvoxes the int. And then it compares the two. And I think this is false. So if it's false, then we just continue with res and sc2eq. Otherwise, it does the same, but we add one to the sc2eq, right? So you can see that the way we wrote it, I mean, it's really just a loop with some case statements, right? And there's no kind of fancy optimization. I mean, the only thing I can see we could have fixed here is probably we can use like unboxed integers because we know they are integers. So it doesn't really matter. Okay. So yeah, so this is what's called core, right? So put Haskell compiles into core. And then core is compiled into C minus minus, I think. And that's what we run, right? But this is kind of... This is where my expertise ends. It's at core because you can write a core to core plugin to... And you can see here, right? The actual, like the previous measurement, it knows that it's always going to be an integer. So it actually optimizes it to be an unboxed integer, right? But what it can't know is that the current mes, like the head of the list, right? It doesn't know that it's got a list of unboxed integers. So it has to kind of make sure that it's an unboxed integer, right? But it doesn't have another... So yeah, it's basically saying, you know, if it's an unboxed then, like, and then I think there's a... I think it could have gone deeper into this, right? It probably could have said, okay, there is no other case, right? It's always going to be an integer. So maybe we can turn this into a list of unboxed integers. But anyway, you can see that, like, this function here, right? With all our... No, it was nothing. It was this one, right? With all our ware clauses and blah, blah, blah, blah, right? It's really compiled into a very small core, right? So there's no funny business going on here. However, countink2... No, this is countink prime. Oh, right. Okay, this is countink, sorry. So we were looking at this code, which makes sense. Yeah, okay, so it calls... Okay, so it initially kind of does the initial loop, kind of. And then countink prime... Wait, so this is countink... Countink prime. And this is countink prime. Okay, so this function here got lifted. No, wait. Okay, yeah, this was the original function. But what is this? No. So I wrote this code, but now we finished. We finished quite fast. So now we're kind of... We're digging into the code that was generated by the compiler to try and figure out... Yeah, like, could we have done something better? Okay, so this is counting dollar counting, right? Okay, so it either... So this one is just calling itself. But what is this one? Where do we refer? Okay. Yeah, okay, so it generates a bunch of functions and it kind of lifts it. And then they all become kind of, I don't know. I don't quite know what I'm doing or looking at. But what I'm... This is the actual counting. But you can see that all of them are kind of... So this one is... Okay, this is countink. Okay, that one is invoked with the initial one with the unboxed zero. Okay. And then that is countink. Okay, and then that one invokes... Oh, okay, all right. That one invokes the dot dollar w countink prime, which is our helper, which is defined here. The dollar dot counting prime. But when is this one... Where is this one defined? So this one is in dot dollar counting prime. Okay, so our global counting... Yeah, there's probably something we can do about code size here. So this one invokes... This one, which invokes... Yeah, I think this is like... Oh, wow. We are getting arrayed. That's cool. So what we're doing now is that we wrote this code, right? And now we're looking at the compiler output because I write compilers. So we're trying to figure out what's going on here. Because I mean, I write some of them, but I don't know what's going on here. So I think like some of these here are kind of the inlinings. I'm not entirely sure. So this one... This is the main one. It calls this one. And this one calls... Where does this one call? That is my question. Like why is there one main dot countink and another countink? I don't like that. Okay, let's see. Read input, blah, blah, blah. Read input, read input. Example... Yeah, and here we can see like a lot of the terms. And this is like the string, and it's all kind of lifted. And this is fail because we have... In case we don't match the pattern... Well, here's a counting two. Yeah, and you can see that it kind of does the same except it takes in three arguments, which are the like the three numbers. Yeah. Yeah, I have... I sometimes... I work on GC a bit. I have... If you used type holes, you want to find something that's showable? Eh, no, wait. So that doesn't work. Anyway, you can say like, hey, I want to find everything that's boolean scope. So this part is mine. Wow. But if you set f refinement level whole fits equals two. This is a cool part. It actually looks for things that given something returns a boolean. So now you can find every function that takes in two things and returns a boolean, which is like and and or stuff like that. Yeah, it's nice. The valid whole fits are nice, right? And if you write here, like you can say underscore and... Oh, wait. I don't have a fast school language server, I think. Do I? G-H-G. No, yeah. So I have to install the language server. I don't think I have it here. So we have 8.10.6. Oh, and it's not HLS power. Okay, that is our problem. Why isn't it... Okay, let's install this one. And let's just switch to nine. Now what's the type? I really like... So I added typos because... Oh, I didn't. I added that valid whole fits suggestions. Because they enable you to do very cool type dependent autocompletes. But yeah, I'll show it next time. But if you have it installed and then you have a Haskell language... Okay, I have it installed. I think it's just because I don't have the Haskell language server for the right version. All right, I will install this one and we'll see if it works. But... Yeah. Okay. All right. Anyway, I think we covered this well. And yeah, I don't think we should dig too much into this. But you kind of see that it just compiles to a loop. And it's always just calling itself. And then it's all tail color is cursive. So even if you're kind of pattern matching on a lot of list things, then you can do that. HLS power. Oh, okay. This one should work. And then that's the one we want, right? Let's see. All right. And yeah, like, there's a lot of output here. But like, this is... I mean, this is like actual runnable code, right? You know, this is like, it's a case statement, right? So case open file of like, if it exists, then you get the context. Otherwise, you... Oh, no. Yeah, now it's installing GAC. Okay. That might take a while. But I read input isn't actually that useful. But I think, what word did we have the counting to? I see. There. Yeah. So you can see here, let me grab this one and put it here. Okay, so this is counting two. Okay. So this is counting two. And it's calling counting two prime, right? Okay. So counting two doesn't really do anything, right? It just calls the... These are the... These three, right? And then you have the... But I think it's like the... What is it? No, this is... Okay. This is not the counting function, sorry. This is counting two, exactly. So that one calls the list. And then, you know, it checks what is the list. Is it... Like, does it have the first element? And then we check. The second, does it have the second element? And if it has the third element, A, B, and C, then we invoke counting two. Counting, right? Which is this function, which takes in these three, right? So it's in opposite order, right? So this is going to be the de-rest, right? This one. And then it has the A, B, and C. So it doesn't... It's not like wrapped as a... It's not wrapped as a list anymore, right? It's just... It compiles to, like, just a three-argument function, right? So this is the A, B, and C. And then we check for the SC, SC38 here. Case of, if it's empty, then we fail. No, then we return this one, right? All right. So this... These two compiles into one case statement. And if it's empty, then we just return the prime value, which is what we want. Otherwise, we check the A, and if that's the thing, and then if... Oh, yeah. And then we check with the D. And if that's the thing, then we kind of primitively compare the two. This was the A and the D, and now... And they're called X and Y for some reason, but okay. And if they are less, then we simply kind of keep going forward. So if they are... If this returns false... And this was curve, right, when we compiled. Then we... Then we just keep looping, right, with the curve, otherwise we keep looping the other one. And you can see that these are just turned into new arguments, right? Okay, so that is nice. So here, we're not actually passing it a list. It just turns into calling it with the new arguments. That is quite nice, actually. So now, remember when I talked about... Oh, it might be not good enough, but it actually seems to be quite good. Let me see. Let's set this one. Okay, now let's quit. Now GSC version. Okay, now we should be able to use Haskell language server. Let's open it up again. Now where is our language server? This used to work as my comment here. This extended has reported one uncut error. Let's disable it. And this might take a few minutes, actually. Oh, and it forgot all my settings. Okay. Let me see Haskell language server again. I think I might have... Now it's enabled. And did it... No, it didn't complain. Now it actually works. Right. So we can... Now it's just redone in brackets. And you see this? It says underscore and it's looking for an int, right? And we can replace it with cur. And it lists all the other ints in scope, right? So it's like a superpower with typetones, right? Because you can kind of... You know from the type what you can put there, right? And we're actually using this for code synthesis. So we can create entire programs by kind of recursively... You know, so we can like replace it with something like this, right? And then we can recursively replace this whole with something else. Now, it is a bit slow in 8.10. But we fixed that in 9.2. I think you have to have 9.2, actually. I patched it before 9, but it was... It didn't make it in time. So then it's much faster. So... Anyway, so you get a lot of nice things with these typetone completions, which is... Which is nice, right? Okay. Yeah. Yeah, that's in G8C itself. So if we look at... Let's just look at it. GitLab. G8C. I never remember it. Look at G8C. Let's just look for me. Tritlo. Damn it. Okay, I think I might have to sign in. And then we look at... Yeah, there are some things that are a bit weird. This one. This merger quest. Two months ago. This is fresh off the press. So there was a bug. That was just a... It's slow. And then we fixed it. And it's not that complex. It was mostly... So I added a new function that allows you to do type checking, but it fails immediately. So, yeah. RunTCSS derives early abort, which is basically... What it does is that it fails fast. So, okay, this was like another fit. Another small fix to make it a slightly faster. But where do I actually... Yeah. RunTCSS derived early abort. So the thing is that you try and find the things that fit, but you're doing it by invoking the type checker. And what happens is that the type checker will... If it fails, it can't solve the constraints, it will really, really try to keep solving them to figure out why to generate good error messages. But when we're checking for whole fits, we're not actually using the error at all. We're just need to know. Does it match or not? I don't care why. So I added this early abort function to kind of make it... As soon as you know that it won't work, just quit. I don't need the error. So it makes it a lot faster. But that, I think, it was merged two months ago. And so it's available in 9.2, the fast one. I mean, it's not super slow. It's just like if you have a lot of stuff in scope and they are like hard to type check, then it was a bit slow. But now it's a lot faster. All right. I am going to call it a day for today. I'll see you hopefully tomorrow for some more advert of code in Haskell. But I think... Yeah, maybe you probably won't dig into the dump again tomorrow. I was just, you know, because the day was a bit short, right? But yeah. So tune in again tomorrow. And probably I won't be on... Won't be on Friday, I think, because I'm going to some Christmas market or something. But there'll be a double feature on Saturday. No, no. It's nice, right? I'm also just talking about why we do things and why we do it this way. And yeah. And that's the main reason here. Why did we do it this way is because we can see that it just compiles to a loop with the case statement. So I think it's a very nice way to do it. But yeah. Thanks for today. And yeah. Tune in tomorrow. It's nicer when we have a bit of a conversation going. All right. Bye.