What is a function's identity?
This is an episode of Thoughts on Functional Programming, a podcast by Eric Normand.
Some functions have identities, which are values that tell you where to start calculating. In this episode, we look at what identities are, some examples of them, and how you can use them in your own code.
Eric Normand: Is a function's identity? By the end of this episode, you'll know what an identity is and how to use them in your code. My name is Eric Normand. I help people thrive with functional programming.
This is an important topic because many common operations, operations we use every day, have identities. You might not know that term, but you've definitely used them. It's a fundamental idea from algebra, and it tells us where to start an operation.
Basically, it's the value you start with. When you're counting, you're going to start at zero. You don't start at one. Before you start counting, you're at zero, then the first thing you count down when it gets to one.
Counting is just adding one each time. Zero is the identity value of addition. Multiplication also has an identity value, it's one. If you multiply one times anything, you get that number. Same thing with adding zero. If you add zero to anything, you get the number back. That's what an identity means.
There's other identities all around. If you're adding letters to the end of a string, you're going to start with an empty string. If you're adding elements to an array, you're going to start with an empty array.
The same property holds, if you stake a string and you concatenate on an empty string to the end, you get the same string out. The same thing if you take an empty array and you concatenate them, you're going to get the original array out.
You can look at all sorts of operations and try to find if they have an identity. The ones that have an identity tend to be the more algebra feeling ones. I'm talking about hash map merge.
If you merge two hash maps, basically copying the keys and values from one into the other, the identity is the empty map. Another property of the identity is it has to work in both sides.
With addition, you can say, 10 plus 0 or 0 plus 10. The identity works in both positions. Same with hash map merge. If I have an empty hash map and I merge on a non-empty hash map, I get that non-empty hash map out. If I reverse the direction, and I start with a non-empty hash map and I merge in an empty hash map, I get the non-empty hash map out.
Another way to look at identities is that they are the empty value. That's the empty array, the empty hash map, zero empty string. Whatever kinds of data structures you're looking at, there's going to be some empty version of it.
It's important to remember that the identity is a property of the operation. It's not a property of the data type. I said data types have their empty version of the data type, but the identity is a property of the function, the operation on it.
That's why it's not part of the data type. That's why with addition, you have a different identity from multiplication. It's about the property. Additions identity is zero, and multiplications identity is one. It's not a property of numbers or integers or anything like that.
What's cool about this is when you're coding, making new functions, you can make an identity value. You could either start with an existing data structure that already has an identity and reuse that, or you can make a value that represents this place to start.
When I say, "Start," that's what you would initialize your variables to start at. Just like you usually initialize a number to zero or you initialize an array to an empty array, you would initialize your new type that you're making to this identity value.
The reason you might want to do that is, if you're trying to come up with some kind of algebra, you want to have some empty version that's a neutral value that you can start from.
One example, if you're making a graphics application, you could have the empty image. You haven't added any layers in yet, but you have an empty image that's ready to receive layers.
Or if you're making a video editing software, you would have a type that represents or a value that represents a video without any frames in it, without any video in it. It's just the empty video that doesn't have any image. It's not going to play. It's zero length, but it's ready to receive more.
The nice thing about this is you start to get some kind of algebraic ideas. You could say, "Well, if I have a video and this empty video, I can concatenate them and I have that original video out."
Just a nice little algebraic idea. When you're concatenating videos, and you say, "OK, take this one and paste it at the end of this one," you needed to find what it's like if you don't have any video yet in that type. You don't want to have that corner case.
Then, you'll notice that "Wow. This kind of empty one bubbles through and has a lot of interesting properties to it."
I'm going to leave it at that. I'll recap. The identity is a value that is a property of certain operations. These operations might have an identity value, and it's got that property that if you apply the operation to the identity value and a non-identity value, you get that non-identity value back no matter what argument position it's in.
If you're counting, you're going to start at zero. If you're adding letters to a string, you're going to start with an empty string, etc. It can be considered the place where you start that the neutral value that doesn't have any affect like if you add zero it has no affect. Or, it can be considered the empty value, ready to be added to.
Just remember, it's a property of the operation not of the type. You can have two different operations on the same type that have different identities. It's rare, but like with multiplication and addition, it happens.
You can make your own identity values. Your identity value in some might be null if you're using a language with null. Or, it could be some new value that you've created that's like, start, something like that. That doesn't mean anything, what it means, "I haven't done anything yet."
Do yourselves a favor, look over some of the existing functions. Not functions that you wrote but from libraries, your standard library, and try to find the identities in them.
I think it's one of the simpler properties that really shows that someone has put a lot of thought into their design if they have an identity. If they don't have an identity, it could be they haven't thought about making it into a nice algebra.
Please do me a favor, if you like this more algebraic notion in functional programming, please subscribe because there's going to be more like this. I've already done many algebraic property episodes and there's more coming.
If you have any questions, if you have comments, I'm always open for discussions via email, I'm firstname.lastname@example.org. You can also talk to me on Twitter, I'm @ericnormand with a D. You can find me on LinkedIn.
See you later.