I just don't understand why there has to be a tradeoff. I just don't get why the compiler should decide on such a large thing, instead of letting the programmer do it. One can always be more explicit if one feels they're getting value from it. If someone wants to write a bunch of terse code, why stop them? Does the compiler gain a large benefit from not having to include this feature? Who loses by allowing users to do what they want?
Comparing C# and F#, the extra annotations change the frequency in which I'll introduce an inner (local) function. For instance, here's a little helper in a piece of code I'm writing at the moment. It's part of a larger function and isn't exposed beyond 5 lines of code.
let runWithLog f name =
try run f name with ex -> logExn ex
Used in:
runWithLog "sessions" collectSessionStats
runWithLog "visitors" collectVisitorStats
Having to add "(f: string -> RunParams -> Whatever -> unit) (name: string)" almost doubles runWithLog helper yet provides no benefit. And this an extremely simple case! Once the arguments are generic, higher-order functions themselves, it gets quite noisy.
Sure, if it's a top-level export, then maybe annotating is a good idea. But if it's limited in scope then what's the harm?
Not that it'll change when I use Rust - there's nothing competing in this category. It'd just be nice if the language let the user decide on the style.