 Hello again. Hello. Thanks for having me back in Bangalore this year. It's always fun. Today I'm going to talk to you about zippers. Who's heard of zippers? Who heard of them like this week? Because you saw it on the schedule. It's a data structure. I'm going to try and give you an intuition for why you might use zippers. And we're also going to look at some of the fundamental arithmetic and mathematics that gives rise to zippers. So, I work for the Queensland Functional Programming Lab, located in the state of Queensland, Australia. It is funded by the CSIRO, Federal Government, Commonwealth Research Organisation, and Advanced Queensland, the Queensland State Government. We're a team of about eight or nine Haskell programmers. Some come and go. The Australian Government wants us to write Haskell. That's what I conclude from this. Maybe we need to talk to the Indian Government. They should be here. We should put them in the room somewhere. Okay, zippers. The term zipper describes an end-hole context into a data structure. Okay, so by that I mean think of a data structure of any kind. It could be a list. It could be anything. And we pull out some holes from that data structure. Usually it's just one hole. Okay, so for this talk I'm just going to say n equals one because it makes it easier to talk about. But zippers in general, it could be some number of n. Okay, so I'm going to talk about one-hole zippers, a hole. I'm going to tell you what I mean by a hole. Okay, so that is a data structure that has a hole or a pointer on a focused element. So I'm going to give you an example. Okay. But one of the most important properties of a zipper is that we can traverse, so we can move that hole through the data structure in an efficient amount of time. So for example, constant time. So the example I'm going to give you, this is like an informal way of thinking about a zipper. Take any data structure. Just think of one right now and walk along it. Stand wherever you are and look around. What do you see? The things that you see is the zipper. Okay, I'll give you an example. I'm going to use list as an example. Who thought of lists? Here's the list one to ten. I literally lay it out on the floor in front of me. There it is. It's made of cubes. What I'm going to do is I'm going to walk to the element seven. I walk along it and I stop and I look around. What do I see? Seven is the hole. That element is the one-hole. Or the focus we sometimes call it. I see this. I see six, five, four, three, two, one, eight, nine, ten, seven. So I see a list to my left, a list to my right, and the thing that I'm standing on. It's three things. A list, a list, and the thing I'm standing on. It's a triple. We often call the thing that we're standing on the focus. I'm currently focused on the number seven. And I can traverse to my neighbors quickly. I can move over to the number six. And if I looked around, I'd still see two lists and the thing that I'm standing on. I can move in constant time in this case. So moving on to the number six is just constant to my neighbor. So if we look at this triple here and I'm standing on the seven, I see this to my, the things that I walked along to get to it, and that's still the things I haven't yet walked along. And I move over to the number six. I can go from this structure to this structure in constant time. Okay, I could write a function to do that. It would just be move over one, put the thing that was over there, put the thing I was standing on back over here, take the thing that's on my immediate left and just stand on it. That's what the code would do. The zipper for a list of A is the triple of a list of A, a list of A and the thing that I'm standing on. Okay? That's for lists. We call this the list zipper. We could think of some useful operations, like for example, move left and right to my neighbors. That'll run in constant time. I don't always get a zipper back, by the way. Sure. Why is the zipper for a list of A? List of A and list of A. So here's the list and over there is a list of A. So that's this one here. Over there is a list of A. That's this one here. And the thing I'm standing on. That's this one. Okay? I could say move along the zipper until a predicate matches. Like move to the first even number or something like that in the list. I say do it left, do it right. I could say modify the thing I'm standing on, add one to it. Or I could delete. Actually I was going to say when you say move or left, I don't always get a zipper back. Because if I move all the way to the left and there's nothing on my left, I can't move left. So I'd get a maybe list zipper. And the same is delete. Delete the thing I'm standing on. That means I have to move on to something. But what if there's nothing to stand on? So I might not get a zipper back. It's maybe list zipper. What about a multi-way tree? So that is a node with zero and children. What is its zipper? So the data type for a tree is, yep, question? A list with zero, one or two elements. Yes, it can. I think I even have that example. So in this talk, I'm going to show you how to calculate the zipper. Like with a calculator. There's a way to do it. And I think I even have that. It might be three, actually. I'll see if I can find it. So a tree is either A, the root node, or a list of trees, my children. It's a multi-way tree. Here's a diagram of a multi-way tree. Let's go and stand on an element and look around. What are we going to see? We're going to see our left siblings, our right siblings. They're all lists of trees. There's a list of trees over there and all their children. The thing I'm standing on. The element that I'm standing on, the focus. My children. It's a list of tree, all the things underneath me. And what about my parents? So my parents will be my parent and all of their siblings. And a list of those. So here is the zipper for a multi-way tree. I can move around a tree in constant time using this data structure. So this is just an example of a zipper. There's an obvious question, which is why would I even need a zipper? So I'll get to that. So here are some operations I might do for a tree zipper. Move to my parent or child, like move up, move down, move left, move right. It could be like a tree could be a HTML document. Move around the HTML document, shifting your focus onto the different elements. Go down onto your children. Go back up to your parent. Whatever it is you need to do. Modify when you see whatever it is you see. I've written zippers for all of these before. A JSON data structure. Right, because JSON is recursive. You can have an array of JSON with objects and all the way down. Move down the JSON data structure. Do things when you're there. Move back up. Yes? Of calling modify. I don't, but I could write one real quick. If I get time, I will. Who came to the intro two days ago? Intro to Haskell. And when we were there, we talked about functors and monads. Do you remember that? Functor is anything that maps. Monads are anything that maps and also does bind and pure. A co-monad is anything that maps and also extracts. Okay, so from some f of a to a. And also duplicates. From f of a to f of f of a. This is what a co-monad is. Anything that maps then extracts and then duplicates. With some laws. Is a list zipper a co-monad? That is to say, can I write a function extract? List zipper a to a. Yes, that's the focus. Does it map? Yes. And does it duplicate? Yes. Given a list zipper, give me a list zipper of all the other list zippers. That is, move the focus around. This is a list zipper of list zippers. It duplicates. What about a tree zipper? Can I map across it? Can I extract? Can I make a tree zipper of tree zippers? Yes, I can. I can write these functions. I'll show you the code, but it won't fit. It can be done. List zippers, tree zippers are co-monads. Actually, all zippers are co-monads. Isn't that interesting? You could say, I'm thinking of a zipper. I already know that you can duplicate and extract it. It's a co-monad. So let's use the co-monad for the list zipper and do something. Do any adjacent foci in the list zipper satisfy a given predicate? This is the use case. If you're subscribed in your email, requirements.docx, we have to write this function for some reason. We write this function, and we're going to use this function, find all zippers with a focus adjacent to a given value. That is to say, give me all the zippers with a focus adjacent to a given value. I said, go and find all the numbers that are adjacent to a given value of that focus. I'm standing on three. Find all zippers that are adjacent to the number three. Immediate neighbors. We would duplicate. This is one way to write it. Call duplicate for the list zipper. Call two lists. Given a list zipper of list zippers, I can just take that triple and make it a list. Now I have a list of list zipper. Use the regular old filter function. You know the filter function. Just go through a list and keep all the things satisfying our predicate. We still now got a list of list zipper. Here's the code. We duplicate two lists, call that function that we just wrote earlier, and then filter that predicate. I've used the co-monad to implement a specific use case. I generated a list zipper of all the list zippers. Then I used regular list functions to go and find the thing I needed to find. As an example. So I say, find me all list zippers that have a focus adjacent to three, which is this one here where the focus is two, and this one here where the focus is four. This is all of those list zippers. Just for some reason I needed this, suppose. Using the co-monad. And another example. So there's two threes in this list zipper. This one and this one. And so these three list zippers are all the ones that come back. They all have a focus adjacent to three. Who wanted that in their text editor before? Think about what that operation is. Go to a specific character in my source file and do something just next to it. You have wanted that, right? I have. Put a left parenthesis there. I forgot to type it. For example. I think we should write programming languages this way, by the way. Just give me the zipper for the syntax tree. Stop typing text in text editors. That's a different talk. This is just another use of zippers. If you're not sure why I might use them. This is my workstation. And you can see I've got some windows open here. And I think this one here has focus. It's got a bit of red around the border there. That's the focus of the zipper. This is written using a zipper. Who uses X-monad? Who's heard of X-monad? That's a zipper. There's the focus. And I say, move to the neighbor. I change focus on the window. I start typing in another window or something like that. Well, I'm using a zipper when I do that. But an intuition for why would I actually use a zipper? Why wouldn't I use a lens? Who's heard of lenses? Cool. I'm going to contrast zipper use cases to lens use cases. You all right? Why wouldn't I just use a traversal and a lens? So lens gives us compositional properties. I can say navigate down the data structure by composing some lenses to get down the data structure to do whatever it is I need to do. But zippers give me context dependent updates. So that is to say I can look around me when I get there. Lenses don't give you that. Lenses just view a thing down in the data structure. And all you know is you're at that thing. You can't look around. So if you need to compute something that's dependent on where you are in the data structure, we would use a zipper. So lenses are when you have exactly one thing inside the data structure. For example, I'm viewing the y inside the triple of x and y and z. But that's all I get to look at. I don't get to look around me with a lens. Or a traversal is when I have zero or many y's. There's zero or many y's in here. All I get to look at is the y's. I don't know where they are. I don't know what's next to me. Traversals only give me that ability to target the y. Whereas a zipper allows me to go to a specific y and look around at the y's. I can move along the data structure and I've got context when I get there. All right, this is the fun bit. Who knows why algebraic data types are called algebraic? Or because we can do algebra with them. Let's do some algebra. Some types. If you have either A or B, algebraically this corresponds to A plus B. If I have A and B product types, the reason they're called product types by the way is because they're multiplication. I can do multiplication with them. It's A times B. Less well known is if I have a function from A to B I'm taking B to the power of A. I'll show you what I mean by this. We also have unit. Unit just means one. And we also have void. Void means zero. If you create a data type called void and you have no constructors, you can never construct it. That's zero. Or you can create one called unit. It has one constructor. That's all it has. That's one. Let's look at bool. Bool is unit or unit. So a constructor carrying nothing is the same as unit. It just means one. So we have one plus one. Bool equals two. It's either A or B. Unit or unit. One plus one. Two. Bool equals two. What about the maybe data type? Who's heard of the maybe data type? You've probably seen that before. Maybe A. This is carrying unit because it has no values in the constructor. It's one plus A. So for example, maybe bool is three. One plus two. Maybe A is one plus A. Algebraically. So let's just think of an example like either void A. Zero plus A. That is equal to A. And if you think about this intuitively, if I said to you construct me a value of that type, you will be able to do it in exactly the same way you could construct an A. That's the same number of things you could do. You're never going to call the left constructor and you can't get a void. It has no constructors. You're always going to call the right constructor. Either void A equals A. Zero plus A equals A. Zero times A equals zero. You'll never construct this. You need to give me a void and an A. You can't get a void. You'll never give me one of these. You can only do zero things. I find this an interesting way to demonstrate the algebra of algebraic data types. Here I have two times two. Here I have two plus two. And here I have two to the power of two. They are all four. There are four things. How many functions can you think of of the type bool to bool? There are four. There's the identity. Given a boolean, return it. There's negate. Negate the bool. There's always return true. Ignore the argument. And always return false. There are no other functions. Two to the power of two. Similarly, you can say left true, left false, right true, right false. Four. They're all four. So I use this algebra in my work. If someone says here's a data type, I calculate quite often, to figure out how many things fit inside this data type. It's a useful thing to know. It gives us the number of inhabitants. When we say there are four functions of the type bool to bool, I might say there are four inhabitants of the type bool. Let's just have a look at a few more examples. Here I have one plus two to the power of two plus one, nine. So you could sit down with a pen and paper and figure out all nine. And just to come up with a silly one, I can calculate. Imagine I handed you that data type and said how many of those are there? Well, there's 40. You can calculate it. What is a list of A algebraically? Well, it's either zero A's or one A's or two A's, right? It is, you know, one A or A plus A or sorry, A times A, etc. It's this series. And we also know that it simplifies to this. If you want to go back and do your algebra schools and figure it all out, it simplifies to this. We can see actually that this is nil or cons. It's the empty list, one or plus cons, the head and the tail. Who remembers calculus? Okay, for those of you who didn't put your hand up, me neither. I'm going to differentiate some of these things. Okay? Here is a data type which is similar to the one that you asked about. It's not quite the same but it's almost the same. I have x plus x times x. That's the data type that I have and I'm now going to differentiate this equation. So think about just try to get an intuition for this data structure first. I have either an x or a pair of x and x. What is it zipper? Walk along this thing and look around. What do you see? Just try to get an intuition for that. Next I'm going to differentiate this equation. So I do. I remembered calculus for one day while I write these slides and I forgot all over again. It turns out that the answer is one plus two times x or the partial differentiation. One plus two times x. That looks remarkably like the zipper. Right? Am I standing on the left or the right? And if I am standing on the right which of the x's am I standing on? It seems like the zipper except for the focus. Right? After even. So we can do this with algebraic data types. I think that's meant to be a bit to the right that tangent line there. Still another one. I have a pair of either xx and either xx. In other words I have x plus x times x plus x. We're going to differentiate it. And when I do I get eight times x. This one might be a bit more intuitive. Having a look at this data type walk along it or look around and what do you see? In order to denote that idea you're going to need the product of eight x's. I decided to write eight like this just I can write it anyway but that's eight. Two to the power of three or two to the power of one plus two. Here's a real simple one. Walk along this thing, look around and what do you see? Well if I was standing on the middle one I'd see an x and an x and the thing I'm standing on or I could just see two x's or I could just see two x's. When I differentiate this I'm going to get a data structure that is look around what do you see except for the focus. So I'll just see an x or an x or two x's or two x's. I don't get to see the focus. So x to the power of three differentiate it and I get three times x squared. Or in other words maybe bool three xx. Maybe bool tells me which x I'm standing on this one, this one or this one that's three and these two x's are my neighbors wherever it is that I'm standing. Every time I differentiate a data structure I get this thing that looks like a zipper. It turns out that that's how I calculate a zipper. Isn't that great? You might say, you know I've got this data type and I need to work out a zipper just do some calculus. Now you have it. The derivative of any data structure is its zipper. You've just got to put the focus back in. Isn't that cool? And if you're not sure I'm going to do it with a list. Remember a list and a list zipper? Okay, so we have a list of A, the zipper is the focus and two lists. This is the definition of a list. One or you know A to the zero plus A to the one etc etc. You do some working out and you end up with a result which is pretty obvious. It's either nil or it's cons with a head and tail. So you remember if we go back to the rules I gave you rules for addition, some types, multiplication, product types, exponentiation, functions. But when we do this we end up with one over one minus A. I didn't give you a rule for subtraction. But that's okay. We don't need it. And I'll show you why. I'm going to differentiate this equation. And when I do I end up with So I end up with this equation where U equals one minus A. Or in other words I end up with one minus A the reciprocal of squared. I simply end up with two lists. So that is the zipper without the focus. So all I need to do is calculate the differentiate the equation and put the focus back in and now I've got the zipper. If I wasn't sure what a list zipper was I could do it informally. I could say walk along this list and look around what do you see? Or I could just do some calculus and I should get the same answer. Isn't that cool? I think that's cool. There's just some good rules for working out a zipper. Just differentiate it. There's the zipper. It's the triple. So actually there's the derivative a pair of lists. List times list. Put the focus back in and now we've got the actual zipper. Okay? Put the focus back on. So I've arrived at the same conclusion. I did it informally and then I just did it with calculus. It gives me the same answer. So one day I really did have to calculate the zipper for JSON. I was working, you know, a Java company and they're like throwing JSON over the network and it keeps hitting me in the face for this stuff. I just used calculus because it was quite difficult. That's it. I've got a pen and paper. I'm going to differentiate this thing. Now I've got the zipper. The end. Thanks. Finished a bit early. Do we have any questions? Is there a tool to calculate? Like the derivative? Yes, there is. There's a library to do it. Actually it's called Zippers on Hackage. And all you do is just say here's my data type and it says here's the zipper. It actually will give you back the data type and just say here's the data type. Yeah. You asked about writing a function. I can write that if you like. We can take some questions before. Any other questions? Did you want me to write the code that you asked about? Yeah, I have actually a longer question related to that. Can zippers be used in place of lenses? No. Why not? It's about zippers having context. If I said to you let me come up with a really trivial example. Here's a list of numbers. Move to the first even number and when you get there then move that many places and add one. If I said to you move to the first even number you got to the number four and then move four places and then add one to whatever it is you're standing on I'm doing this with context. Now if I tried that with a lens I'd say find the first even number and all I'd get is the first even number. I don't have any context of where I am in the list. And then I'd say now move past it do find again move four places function and then do an update but I've gone across the list twice. I have to start at the list each time. Whereas a zipper gives me the context as I go through the list. So they're the two separate use cases for them. I guess my question was other way wherever you use a lens can you instead use a zipper? The downside of this we get the benefit of context depending on updates. Because we don't get compositional properties. So that is to say we might go across the list and when we get there there's like an object and we want to navigate then down that object. I can do that with a lens but I cannot with a zipper. I can use both. I can say move the zipper over here get to the context and then lens down onto my object. As long as I don't need to do anything context dependent down there and then come back up and do my context dependent updates back up here. So I get context dependence but I don't get composition like I can with lenses. It's an efficient way to do BFS I think. BFS? What's that? Oh yeah. I think it's one way to do the BFS in the tree. Yeah. I wrote a function to do that recently. What was that for? Ah, HTML. Yeah. Yeah. I literally wrote breadth-first search for HTML like last week. I can show you the code. Yeah. How did you end up finding calculus and work out here? How did I find it? I just stole the smart guys ideas. I didn't find it. It was it was this paper here. They're the people who found it. And I'm like that's cool. Now I don't have to imagine the zipper later. One more question. This is regarding the algebraic type. Yeah. Everyone speaks about some types and product types but never about subtraction or division. Yeah, subtraction and question. Yeah. Has anyone really used it? These two? Or is there any way to represent a subtraction or division? There do exist other type system where they have question types and things like that. Yeah, I tend not to use them but that's just my bias because I use Haskell a lot. But they do exist, yeah. Yeah. Hey Tony, you said that function invocation is exponentiation. Could you expand on that please? Sure. So to give you an intuition for it, like I'll tell you the fact, right, which is given a function a to b, there are b to the power of a inhabitants. If I said to you give me a function that takes bool to unit. That's one to the power of two. You're going to write one thing, unit. You're going to ignore the bool. Now write me a function that goes unit to bool. You're going to give me two to the power of one things, two things. You're either going to take the unit and return true or take the unit and return false. So given the function a to b, you can calculate its inhabitants by b to the power of two. Does that make sense? Just to clarify that, that's the maximum number of inhabitants. Now it's the exact number of inhabitants. I mean you can have a unit to bool function which always returns a true. Yeah, that's one inhabitant. Sorry. What's the partial function? Let's just write some code. How many functions have that type? Two to the power of one, right? There's one. There's two. There is one. And here is the other one. There are no others. There are two inhabitants. That's what I mean. Whereas if I said to you how many functions have this type, this is one to the power of two. One. There's only one function with this type. There it is. There are no other functions. Does that make sense? Hey, one question around the list. On the list? The list was actually, algebraically it says infinite series, right? One plus a. Yeah, one plus a times list of a, yeah. So every recursive data structure is like that, always an infinite series? No, so list is recursive in its definition, right? But say the triple of three x's, just like three x's, that's not recursive. So that's why we end up with a recursive answer. Say tree would also be a similar series, right? A tree, normal tree. The number three. Tree, tree. Yeah, tree ends up recursive as well. The question is, will every recursive data type end up as an infinite series? I don't know. Is that the question later? That is a really good question. I suspect the answers no, but that's just the feeling in my bones right now. I don't have a good answer. Yeah, good question. Let's figure it out. So if you, if I am having a list of zipper, zipper list, if I wanted to move left or move right, I have to modify both the iris. If you have a list of zipper or you just have a list zipper. List zipper. Yep, and if you want to move left or right, what happens? I have to modify both my iris. So my current focus, I have to add it in the right one. Yep. And remove an element from the end of the list of my left side. Yeah, you want to delete an element. Sorry. Oh, you want to rotate it around the other side. Or if I just want to shift to focus by one position. Yeah. So then I have to modify both the list. Yes, let's write the code. You'll see it's O1. Yeah. All right, that's a list zipper. I'm going to go move left. What move left is going to do is going to say list zipper A. It's going to give me a new list zipper. Okay. If the list zipper has nothing on the left, there are no lefts. There's nothing on my left. I cannot give you back a new zipper. But if it does have at least one left L, focus X, and the things to my right are, then I am going to return you a list zipper with those lefts. The focus will be L. I'm now moving on to L. And the rights, because I've moved to the left, the thing that I used to be standing on will go on the front of the rights. Okay. Does that make sense? So it's O1. I can move to my neighbors in O1. Okay. Are there any other questions? I'll ask mine. This learn your Haskell for greater good has a chapter on list zippers. Does it? It does. And while learning Haskell, I skipped it because it seemed too complicated. And I've been using Haskell without actually using zippers. So it's a bit of a complex question. So where are zippers actually sort of shine in what kind of application they shine? Second, do immutable data structures force zippers on us for certain computations? Are we forced to use zippers if we are using immutable data structures? I mean, I haven't heard zippers being used in Ruby or Python or anywhere else as such. I first came across them in Haskell which is immutable by default. Okay. I mean, if they're so useful, why doesn't the prelude have them? I just looked up data.list it has all sorts of functions it doesn't have a zipper. The answer to that question is quite simply history. The prelude is quite old now and zippers are not in terms of their usefulness. We only just found out I don't know what year it was but it was in the 2000s that the derivative of a data type is a zipper. That's just history. A useful example I can give you one that I've used so I was working for a Java company writing Java and people sending JSON over the network and they go, here's some JSON, great big blob what am I going to do? I wrote a JSON data type then I wrote a zipper and the reason I needed zipper is because once we have the JSON value, I need to convert it into my domain value so whatever it was bank account or whatever it might be and so in order to go from the JSON data type to the domain value I wrote another library that moves a zipper through the JSON, pulling values out and putting them into my domain value and not only that I can put retry on it as well so suppose you go down the JSON value and then you go I was expecting an X but I saw a Y so I can't make your domain value I would say, oh no that's just because I sent it wrong, I'd write a library and just say retry and do this instead and the zipper can just keep moving through the data type the user of this library never gets to see the zipper I'm just moving the zipper through making the domain data type Would some generic parsing library in Haskell be using zippers internally for backtracking parsing? That sounds like backtracking parsing No I don't think so I guess you could but they do keep some context that's how they do their backtracking Would you have done this differently if you were using a mutable data structure are zippers forced upon by immutable data structures I don't think they're forced upon you it's more like if you put a stake in the ground and say I'm going to use immutable data structures you're going to run into the use case where you say go down the HTML document you're going to see the first href take its value and use that to know where to move next you're going to do a context dependent thing and that's where a zipper just says I'm here and I'm very useful for doing that I think that happens I don't think it's necessary for immutable data types though so even if you had a HTML document and it was mutable I think you still want the same thing right like we've all used xpath HTML or something that's kind of what zippers do except you lose the context when you get there it'd be good if you still had the context once you got down there thanks I hope to talk to you more about zippers outside if you want to talk more about it it was good, cheers thank you so much