FWIW, this is also one of Rob Pike's rules of programming:
> Rule 1. You can't tell where a program is going to spend its time. Bottlenecks occur in surprising places, so don't try to second guess and put in a speed hack until you've proven that's where the bottleneck is.
It's implicit, but the "proven" part implies use of a profiler.
Also, bottlenecks happen in surprising places, and allowing slow/bad code just because the profiler doesn't scream about it on the development machine is a recipe for surprising performance issues in the future. The slow code might become a problem when a user has slightly different task for the program.
But I think the aphorism covers the case you’re describing too.
It’s possible that your loop is slow, but if you’re working on a program of sufficient size and complexity, you simply won’t know if it’s the bottleneck without using a profiler.
The purpose of the statement is to save you the trouble of 10xing performance of a function, so that it takes .1% of all execution time, instead of 1%. Do sufficiently complex programs, and without a profiler, you won’t really know if a loop is taking 1%, 10%, or 80%.
And there are also the 'thousand cuts' issues for which profilers are "useless"..
Types are a really good example of where you want to help the compiler. Type signatures let you define how the type can be used. By adding as much information about how the type should be constrained, you can help the compiler prevent you or someone else from doing something stupid and on occasion, you can earn some optimisations in the process.