If items ("fn" definitions) implemented type inference instead of requiring the programmer to manually document something the compiler can figure out, the learning curve would be easier.
Especially with tooling that shows the type of any given expression (integrated with an editor).
> If items ("fn" definitions) implemented type inference instead of requiring the programmer to manually document something the compiler can figure out, the learning curve would be easier.
No, it wouldn't. Not when the compiler is spewing error messages about types you didn't even mention, especially if the compiler inferred that type on the basis of code in some random other file you didn't know about.
Guess our experiences are different. In F# I do this all the time, and I've never had it be an issue. In Rust, if I'm trying to play around with something, I have to figure out the signatures even when there's only one option.
I hear this argument that the inferred types will be confusing (from C#, F#, and Rust communities; I'm sure it exists in others) -- but they will be accurate! It's something the human has to figure out anyways, except without computer assistance. All because of some misguided attempt at enforcing documentation guidelines and verbosity on programmers, sight-unseen.
I guess users can wait for IDE support with a "show inferred types" option.
Edit: And just as a note, I really love Rust. My only core complaint is the verbosity. And that's a small price to pay since I'd either be paying with perf/memory usage (more expressive languages) or bugs and far more verbosity (C).
Just as an anecdote, the fact that Haskell does this (infers type signatures for functions) is one of the things I don't like about it, because it seems to often infer things that are surprising to me. I think inferring types in most places, but enforcing explicit types at the level of method definition strikes a really good balance. I care about the types required to satisfy interfaces, but enjoy not needing to care so much in implementations.
IDE support for creating method signatures by inferring types would be neat though.
Haskell _allows_ it. The programmer decides if they want it. Requiring a full signature inhibits natural code writing by introducing a high amount of overhead per function. Writing a 1-line inner function is no longer an obvious win. The annotation requirement applies to nested functions in Rust.
I don't really understand this issue. If I write a one line function in rust, nested within another function, I will use a closure. Which, incidently, rarely requires me to annotate any types.
I can choose to use explicit type signatures for functions I write, but I can't choose to use them for all the functions I read. I read a lot more than I write.
We also may just disagree about what constitutes a "high" amount of overhead. Thinking about the contract of my method does not seem like overhead to me; I have to do that anyway.
> All because of some misguided attempt at enforcing
> documentation guidelines and verbosity on programmers,
> sight-unseen.
Characterizing the tradeoff in this way is very uncharitable. In Rust, function signatures are the absolute source of truth about the contract that a given function upholds. In systems with global type inference, the entire program is the source of absolute truth for any function whose parameters are inferred, and local reasoning becomes much more difficult.
My apologies, but that's what's been explained. Something to the effect of "it's best that people document/annotate their types, so we require it."
Your description of contracts in Rust vs other languages isn't reflective of how they can be used. With global inference, nothing prevents a programmer from deciding where the major boundaries of his program are and annotating where desired. This not only provides the benefits of both worlds, but allows the author to decide where the contract and documentation goes.
Nothing is gained by requiring the programmer to annotate every little helper function, nested or otherwise. And for people just playing around, it brings a significant barrier. They must not only sort of grasp how the borrow system works, they must be able to write a flawless annotation to boot.
At worst, lack of annotations should be a warning (the warning can include the inferred type!), like the casing/naming style ones. Perhaps with an option for public/exported functions only.
(Sorry if my tone comes off hostile; not my intention.)
> "it's best that people document/annotate their types,
> so we require it."
That may be how people interpret it (I'd be surprised to find that line in any official source), but the reason for this choice was ultimately technical, not philosophical. Having function signatures be the ultimate source of truth means that the typechecker can ignore function bodies entirely, which has large implications for the design of the type system and the layout of the compiler pipeline, and more importantly this feature enables fine-grained incremental recompilation at the function level (i.e., if the body of a function changes but its signature does not, then the compiler knows that consumers of that function do not need to be recompiled and can skip an enormous amount of work (assuming that inlining is minimal, which is indeed the case in debug mode, where incremental recompilation is intended to shine)). We're not taking advantage of incremental recompilation yet, but it (along with speeding up the compiler in general, as corroborated by the survey) is the primary goal of the compiler team this year (the prerequisite overhaul of the compiler middle-end is just about to land: https://github.com/rust-lang/rust/milestones/Launch%20MIR%20... ).
"it's generally regarded as best practice to write out the types of your functions, hence Rust's choice here. ... Rust follows 'explicit over implicit'"[1]
If it's a technical limitation then that's far more understandable. I've just not heard this explanation until now -- not that I really was seeking it I suppose. Thank you.
Especially with tooling that shows the type of any given expression (integrated with an editor).