Isn't it redundant to have a function that returns a simple public variable like this?
It's not necessarily so simple.
Suppose the token decayed over time. (I.e. demurrage) A reasonable contract design would have the actual balances lazily evaluated, by only subtracting the decayed tokens once the contract is accessed. The default getter would not be able to do this, and would return an inaccurate value.
There's plenty of other systems with similar complexity requirements, or even ones without a single number to represent the balance. In these cases, it's better that the interface makes no requirement as to how the balances are stored.