> Knowing the type of a variable is not always helpful during normal reading (e.g. the types of iterators in C++ or Rust).
Not only that, but there are some types in Rust that you _can't_ even specify; closures specifically don't have concrete types that can be specified in a Rust program.
Perhaps it's due to the fact that you can't really have type-generic closures in Rust: once the compiler has inferred one type, the closure cannot be used with another type. In contrast, inner functions can have any number of additional type parameters.
This is mistaken. Rust has explicit type declarations, augmented with type inference. Furthermore, unlike popular statically-typed functional languages, Rust's type inference is deliberately restricted to only operate within functions (intraprocedural) rather than between functions (interprocedural), which means that one always has explicit types available in the function signature when reading code.
> In Rust and Haskell you have to at least annotate the parameter types and return type of functions. Type inference is only for variable bindings inside the function body.
> With an interface, anyone else could come along and create their own implementation.
Not true in Rust, because the type returned by the function is a concrete type.
I think we may be overloading “name” here, a bit. If you return an “impl” in Rust, you have to name an interface, but you can’t actually create new instances of the concrete type returned by the function.
> every method on collections like `map` or `filter`
I think you're remembering the various iterator adaptors, but they aren't methods on collections, they work on Iterators as their name implies. Somebody else explained why these methods can't all just return "Iterator" (that isn't a type) but just thought I'd mention you won't find map and filter in Rust's Vec or HashMap types, those methods live in the Iterator trait.
This seems like too narrow a reading of OP's point. Rust imposes not only types, but also a particular tree-like program structure which makes it awkward to express lists, upward references, and other constructs.
> What problem would higher kinded types solve in Rust?
You don't have a way to say in Rust 'this functions works on types similar to an 'Option<T>' for all types T. Or 'this functions works on types similar to a 'LinkedList<T>' for all types T. Which actually is more or less the same, we can therefore name both 'Option' and 'LinkedList' for example, well, 'Mona'.
> Like, if I want to parse command-line arguments.
What command-line parsing libraries have “a bunch of unnecessary type parameters”?
Only library I can think of which even has them would be structopt, and that’s not unnecessary, the entire point of the library is to deserialise to a structured type.
And of course rust was designed from the ground up to leverage generics, e.g. by design it does not have reflection / RTTI, interactions with variable or foreign types are thus generics based (often, sometimes trait objects will do though they have their own tradeoffs), or it doesn’t have overloading so while not handing all overloading use cases by a long shot it uses conversion traits (aka generics) for “convenience” overloads e.g. foo(string) and foo(path) become foo<T>(_: T) where T: AsRef<Path>.
You're not wrong, but I don't really see the problem? Even well before async Rust, closures worked the same way with not being able to specify a concrete type, and `impl Trait` syntax didn't even exist for a while. Annotating local variable types is a way to fix certain things that would otherwise be ambiguous; it's a means to an end, only an end itself.
Rust has actual type inference. It just happens to be a local affair. For example, you can create a vector, even an empty one, without explicitly specific its element type. But, somewhere in the current function, you have to provide information about the element type, say, by inserting elements into the vector, or by using an element in a way that constrains its type.
Closure type inference doesn't work well enough in Rust, so your refactoring will not compile unfortunately. Rust needs the closures to be used inline.
> there is no general type of Rust lambdas that take an A and return a B other than the trait object type `dyn impl Fn(A) -> B` (Or FnMut or FnOnce);
I don't understand the issue (and I know very little of rust), but isn't `dyn impl Fn(A) -> B` exactly that type? Any language with first class function parameters and objects, but type erases them (unlike rust and c++) would implement them pretty much like the dyn impl above under the hood.
If it's not clear that the compiler will infer the correct type, you can be specific. From the context, there's only one possible type though so that's redundant. Unlike C, older C++, or older Java, Rust expressions aren't necessarily fully typed in isolation. It's quite normal for a function to have an independently-generic return type and for the final type to be provided solely by context. Type inference only happens within named functions though: you need to specify your function signature.
Even if you find yourself wanting to know what the type actually is, the compiler (in its guise as a language server) can tell you that and let your IDE show you, rather than requiring you to type it out yourself.
Although that's true, and potentially useful as a feature (not sure I want it, but pretty sure I wouldn't be angry if it was added)..
I don't think that's what your parent was talking about when they say "couldn't name the actual type".
They're saying, suppose I have a function that says it return an Iterator and I realise ah, it's not really returning an Iterator, but some subtype of Iterator - or, in Rust where subtypes don't exist, a type which merely implements Iterator. I now can't talk about the actual type being returned, because that's hidden from me, and it needn't be.
Not only that, but there are some types in Rust that you _can't_ even specify; closures specifically don't have concrete types that can be specified in a Rust program.
reply