What does it mean for a function to have a zero?
This is an episode of Thoughts on Functional Programming, a podcast by Eric Normand.
Some functions have a special value that will stop computation. For instance, multiplication will stop if you multiply zero by anything. We can use this property to our advantage.
Eric Normand: What does it mean for a function to have a zero? By the end of this episode, you'll be seeing zeroes everywhere, and you'll know how to use them in your functional programs. Hi. My name is Eric Normand. I help people thrive with functional programming.
Zero is an important algebraic property that we use probably more than we realize. What it does is it lets you build operations that have a short-circuited ending.
The name zero, for this property, comes from multiplication, where the zero value actually is the number zero. When you're multiplying and you have a zero in there, say you have this really long list of numbers to multiply. Let's say, it's like 20,000 numbers and you get 20 or 30 numbers in, and you say, "Hey, there's a zero in here."
You're done. Because when you multiply it all out, it's going to be zero, you know that. You don't have to do the rest of them. There's this advantage of being able to short-circuit your operation.
The zero value of a function, it's a property of a function, it basically tells you where to stop calculating, and you know the answer already. The zero value becomes the answer. Like I said, it comes from multiplication. The property is pretty simple. If you do A*0, the answer is 0, no matter what A is. If you do 0*A, you'll get a 0, no matter what A is.
This property is the same. You just swap out the operations. The zero value operated on some other value, it's always going to be the zero value. It doesn't matter what position they're in.
Not all functions have them, that's important to say. It's not as common as the identity. We went over the identity value in another episode. The zero is a lot less common. It's less common to be able to just stop like you can with multiplication, but we'll go over some that are...We use them all the time in programming.
If you get one of those, anything you do to it, any other mathematical operation, also yields Not-a-Number. You can basically stop. If you have a Not-a-Number, that Not-a-Number will be your final answer.
Let's say you had an object and you call the method on it, and the method returned null, and you're chaining. Now, you're going to call a method on that null. Then it's just going to say, "Operation not found," which returns null, and then you're going to get an operation not found on that.
It's just going to be over, you're done. You're going to get a null out. Then the problem is, where did the null come from? Just like, where did the zero come from when I was multiplying [laughs] or where did the Not-a-Number come from? You lose track of where that answer comes from.
Sometimes you'll have an error value that becomes a stop to the whole thing. In Haskell, you have nothing as a zero. If you have a function that returns a maybe or that operates on a maybe value, once you have nothing, there's no more operations to do when you're dealing with nothing as a zero of the operation.
Once you get a nothing, you're always going to have a nothing. You can't get a value back. You could make an operation that doesn't use nothing as a zero. There's that. If you are using nothing as a zero, once you get a nothing, you're just going to have nothing forever.
That's important to emphasize because it is a choice that you have when you're programming. Is this going to be the end or am I going to use some like let's say, a default value, if I don't know the answer to something? If I get a null, maybe I want to check, and I'm going to replace it with some other value that I know, not let the no bubble out.
This is probably kind of controversial, but you could look at something like an exception, which, if you're on a loop and you're multiplying numbers together, and you hit a zero, how do you get out of that loop? You could have a check or you could throw an exception, and that would just bubble you out of the loop.
You could do something similar where you say that exception stops all calculation. You're going to have to catch the exception somewhere, but it's a similar idea, that this is where we stop. By throwing an exception, I'm just not going to continue anymore.
There's also this idea in a system like a message passing system. Let's say, you have a worker thread doing work for you and you want to tell her, "OK, let's stop. It's done." There's no way to communicate out of that message channel that you've got for that worker. You can't just stop the thread because some systems don't let you stop a thread from the outside.
You need some message that says stop, that you're done. This actually has a name. It's called a poison pill. You're passing all these values down into your worker, and then at some point, you say, "OK, I'm gonna put a poison pill in there, and that's going to kill the worker."
It's going to consume it and kill it. All it is is a value. You might say kill or die or quit, and the worker knows about this. The code in the worker has a condition for it. It's just going to end, it's just going to stop.
This is the same idea. You have all these messages. These are just normal values, and then you have the zero value. It's like, "I'm done. I'm gonna stop." It's the poison pill. This is translating this algebraic idea into a more imperative time-based idea where you're doing message passing.
Let me recap. The zero of a function basically tells you what values you can stop on, where you don't have to do anymore calculation. If you're doing dynamic programming, you can just stop and say, "I have zero, I don't need to run through the rest of the list."
That becomes the final answer. The property is very simple, 0*A is going to give you 0 and A*0 is going to give you 0. That means zero is a zero of multiplication. Once you have that zero, you can stop. Not all functions have them. It's a choice that you can make. You can make a special zero value for your operation that will have this property.
If you need something to say, "Hey, I've got a problem. I want the problem to bubble out to the next thing. I don't want this to be operated on anymore." That's a use for it. It's used a lot in monads and things like that to say, "OK, we're done with this [laughs] monad. We're getting out of here. We got an error, let's just get up to the top. We're gonna stop all calculation."
No matter how many thens you put on there, they're just not going to run, so it's going to stop the calculation. In the message passing domain, there's the zero called the poison pill.
It's a cool idea to think like there is some value that when I get to, I know how to stop. I think you could do yourselves a favor and just look at your existing operations with this eye for thinking, "When could I stop?" It doesn't make sense to have some value that is the end of the calculation. That could really clear up a lot of code.
Do me a favor, please. If you like this idea, Exploration of Algebraic Properties...This property is important to know but it's probably not as important as something like the identity or communitivity or associativity, but all the same, it's very, very good to know and very simple use of property.
If you like these things, please subscribe, because then you'll get the other ones as they come out. If you have a question, if you like to get into discussion with me, if you have some disagreements, I'd love to get into discussions over email, firstname.lastname@example.org.
You can also find me on Twitter, @ericnormand with a D. I'm also on LinkedIn. You can find me there, and let's connect. Just send me a message about the podcast. All right. See you later.