 Today, I'm going to talk to you about typed holes. So what's a typed hole? So often when you're writing a program, there's a part of the program where you know what the type of the thing that you want, but you don't actually know what's supposed to go there. So in that case, you just put a placeholder there, like a hole, an incomplete hole. So why would you want this anyway? Well, if your programming language has support for it, it can actually help your programming language help you, let your programming language help you write programs. So why do holes need to be typed anyway though? To demonstrate, let's start a simple program in Python. The program will take a function and a list, and it'll apply the function to each element of the list. So I think it's a pretty simple program because I explained what it does to you in one sentence. Is this a correct definition of this program? No, no it's not. It returns an empty list. So I know that this is wrong, you know that this is wrong, but does Python know that this is wrong? No, it doesn't. It'll just happily accept this program. So I go off and I read up on list comprehensions, which are apparently the way that you work with lists in Python. So I do my list comprehension up on my function to each element in my list, but I forget to return it. So I'm noticing that I know that this is wrong, you know that this is wrong, but again, does Python know that this is wrong? No, it doesn't. It'll happily accept this program. So I'm getting really frustrated at this stage. I read up on how the built-in map is implemented, and it works on iterators, and it returns a generator, not just a list. So what that means is that I swap out my square brackets with parentheses, and I put my run statement in this time, and I run it, and instead of getting the list that I want, I get a location memory, and this is really useless to me. I don't think this is useful at all. So I think this is wrong. Hopefully you think this is wrong, but again, Python will happily accept this program. So I've been making mistakes like this in Python for over ten years at this stage. It's really frustrating. And I constantly wonder, how do I write a program that actually works? So I've asked a lot of people, I've gotten a lot of advice, but the one bit of advice that's actually been useful is you need to write a test. I'm like, okay, fair enough. Let's write a function, and a test to go with the function. My test classes and everything is great, right? The problem is that a test is only as useful in so far as it specifies how the program is supposed to behave. There's no way for me to take a failing test and let the program language tell me where in my code I'm wrong. Language doesn't really understand tests. However, the test aren't the only specification that exists. There's also types, and the language does understand types. It can look at a type and a program that don't match and tell me where in my code I'm going wrong. So what does this look like in practice? Enter Haskell. Haskell is a programming language that's statically typed. Now, this is nothing special. Lots of languages are statically typed, but what is special about Haskell is that it has type inference, which means I don't need to provide the types up front. The compiler is usually smart enough to figure it out. So what does this look like in practice? Type tools. So what's a type tool? This is a type tool, so this is quite a lot of output. This is an error message, and this is a program. And don't focus on the middle of the error message. Try to avoid it. Just look at the top and the bottom. So here's my program, and my program is a map function as before. It takes a function that takes a value from type A and returns a value of type B. It takes a list of values of type A and returns a list of values of type B. And this underscores my type tool. So what is it telling me? It's telling me that I have to provide a value of list of type B. And that's fair enough. I already knew that. That's what I said up front. But let's proceed. So the only thing that I can do with a list is pattern match on the list. So a list in Haskell can be either an empty list. So an empty list. That's hole number one. Or it can be a head and a tail. And that's hole number two. So do that. Oh, no. What have I done? I have forgotten how to write Haskell. Great, so now I have two type holes. So both of them are of list value of type B. So not so useful yet. But I know that if I have an empty list, the only reasonable thing I can do in this case is give back another empty list. So I'm back down to one type hole. And I know that if I tear a list apart into its head and its tail using pattern matching, the only thing I can do is to put something back together. So again, two type holes. Now again, errors. But I know that I find that I have a hole of type B, which is different from what I had before. And looking at this output, I can see that I can get a value of type B by applying my f to my x. So I go ahead and do that. And looking at this output, I know how to recur. So I take my map, and I take my f, and I take my x's. So I go ahead and do that. Great, it's all good. So it compiles, but does it work? It does work. So everything's good, except this is really, really easy to break this program. Let me show you my favorite way. So instead of having this stuff here, what if I just return an empty list in all cases? So I'm commenting that out, empty list. It's still all good. So what's going on here? An empty list is a valid list of any type. Is an empty list a list of strings? Sure. Is an empty list a list of integers? Yeah, why not? So this isn't good enough. And I actually have to look at the output and squint and think about it for a bit, and then go back and change my program. So I'd like to do better, and especially in cases like this, where there's only one obvious result. I would like the compiler to just figure it out for me. Like, why can't I do that? So can we do better? We can. Enter Idris. So Idris is a programming orange that has a more sophisticated type system than Haskell's. Unfortunately, because of its more sophisticated type system, it also has weaker type inference. It has really good edit integration, though, better than what I've shown you before. And all of this means that it has fancier type holes. So what does this look like in practice? Here's another program. The difference between this program and the Haskell program I showed you is that instead of using lists, it uses a more interesting type called a Vect. And a Vect can be either a nilVect, so like, yeah, an emptyVect, or it can be a head attached to a tail of some length length, giving me a new Vect of length length plus one. So I've implemented equality on these because I use it in my example. And I have a map which looks pretty much the same as I did before. I'm not gonna show you the editor window like I did last time, sorry, the error messages like I did last time because there aren't any, and you don't really, yeah, it's not important. I'll show you in a bit. So this is cool, so this is, so I can get Idris to do things like fill in a skeleton definition for me. So I'm gonna show you my key strokes so you can see what follows going on. So I can do a define, so a default define, so it'll fill in the skeleton definition for me. Great. I can ask it to show me the type of this whole with a leaderD, different type. So this is useful. I could progress on this path as before, but I could just go ahead and ask Idris to do a case split for me. So it splits it out into the different cases. As before, I'm gonna split it, meet either an empty list or a head attached to a tail. So I think there's only one thing that can go here and maybe Idris thinks so too. So I can ask Idris to do what's called a proof search where it searches the space of all possible programs and picks the first one that fits. So I'm gonna go ahead and do that. There's an O for obvious. Great. So that works for the first case, but does that work for the more complicated case? I'm gonna try it. Great. So it compiles, but does it run? Reload. Great, it does work. So what happens if I try to break this program the way that I broke my previous one? So I'll bring it up and try to make that mistake again. Computers. So reload. I'll turn off my keystrokes because they're distracting. Oh no, that's not what I wanted. Oh, no, it's not right. So sorry, just a second. Um. Okay, great. So to show you that again, reload. And so what it's telling me now is instead of giving it a list of success or some other of some length, I've given it an empty list. So I've failed to like pull the wool over Idris's eyes and everything's great. So just undo what I did with the reload so you can, yep, do that thing again just so you can see that it does actually work. I'm not just. So we did it. The most important thing that I want you to take away from this is that typos exist. You can download these languages and you can use them today. And if you used to work with other statically type programming languages you used to basically feeding the compiler a whole bunch of types in order to get it to accept your program. That's not all the types can be. Types can help you design your program, debug your program, design your program and write your program. And programming doesn't have to be a sequence of writing subtly incorrect programs until you get something that finally works. It can be fun and interesting. It can be an exploration with your compiler and an interactive process. So here's some resources. There's a tutorial. This is Conor McGride. So Conor McGride is a lecturer, researcher and computer scientist who spent more time than most people thinking about what types are and what we can use them for. So thank you. But before that you go and tell you about untyped holes. So what if you like the idea of holes but you don't like the idea of types? What do you do? What you could do is you could write a program with gaps in it called a sketch because it's a rough program. You could write some test cases that you expect to pass. You can feed both these things to an SET or SMT solver which is a clever program with a bag of tricks that will look through all the possible programs that could fit, churn, churn, think for a while and finally give you a working program. This sounds amazing, right? Why isn't everyone doing this already? Oh, as you probably guessed, this is a research topic for now. But if you're interested, you can read the thesis or use the, look at these research prototypes that make use of these things. And I'm actually done now. So thank you. Thank you.