4 ms·
I think Rust borrows enough from ML to give you the skill he is pointing at. Static types with plenty of places where type is inferred.
by ozten 10y ago
I think Rust borrows enough from ML to give you the skill he is pointing at. Static types with plenty of places where type is inferred.
- catnaroek 10y agoRust is wonderful, but inference is actually one of its weakest points. It has only one feature that's incompatible with global inference (multiple types can have methods with the same name), but sadly that's enough to require you to manually annotate `Foo<Bar<Qux<T>>, Herp<Derp<U>>>`s in a lot of places. Rust arranges things so that these places are often, but not always, function type signatures. In Haskell and ML, you can write tricky recursive functions without annotating a single type at all. Often, I couldn't even infer the type on my own in a reasonable amount of time! (By which I mean “under 5 seconds”, since my patience for these things is rather limited.) The type checker does it for me.
- vvanders 10y agoThat's not been my experience so far, mind providing a more concrete example? Only place I've had to annotate is when I'm using dynamic dispatch(&mut io::Write for instance) or collect() where I don't have enough information to determine type.
- catnaroek 10y agoIn Rust, function types need to be annotated. In Haskell or ML, I can have functions, especially recursive functions, with monstrous inferred types (although, of course, one then makes type synonyms for the sake of a more readable API) that would have to be explicitly annotated in Rust. The reason why this isn't much of a problem for Rust programmers, is that idiomatic Rust code uses vectors and slices much more often than recursive data structures. But if you tried to roll your own recursive data structures, like those from Okasaki's book, you'd quickly feel the pain.
- caconym_ 10y agoI like this about Rust. Functions (top-level, at the very least) should always have their types annotated, as it makes the code easier to read and understand. The fact that it makes type inference easier (does it?) for the compiler is just icing on the cake. I consider myself to be a decent Haskell programmer and it has been a while since I wrote a function whose type I could not figure out. I suppose it is convenient to have the compiler be able to give you hints, especially when learning, but overall I find that when my types start getting really strange it's time to take a step back and see if there isn't a more straightforward way of doing it that'll lead to less headache down the road. Also, I haven't dug into Rust that deeply but I've implemented some data structures for fun (working on an `Rc`-based rope with persistence right now) and I would not agree that working with types in Rust is fundamentally, significantly more onerous than in e.g. Haskell. There are other things that make implementing e.g. structures from the Okasaki book more difficult, like the need to work with the ownership model and various provided pointer types rather than simply relying on garbage collection.
- catnaroek 10y ago> Functions (top-level, at the very least) should always have their types annotated, as it makes the code easier to read and understand. I prefer to annotate definitions only at module boundaries, because that's precisely where an inferred type might be more general than what I actually want to expose. But not all functions are exported to other modules. > I consider myself to be a decent Haskell programmer Incidentally, Haskell's modularity story is very weak. > and it has been a while since I wrote a function whose type I could not figure out. Oh, I certainly have an idea of what type I'm expecting a top-level function to have when I define it. But I want the type checker help me write my program, not just confirm that what I've written is good. This is why, for example, GHC provides typed holes. > but overall I find that when my types start getting really strange it's time to take a step back and see if there isn't a more straightforward way of doing it that'll lead to less headache down the road. If everybody thought like that, then Haskell's `lens` and `pipes` libraries wouldn't exist, and that would be a great loss. > Also, I haven't dug into Rust that deeply but I've implemented some data structures for fun (working on an `Rc`-based rope with persistence right now) and I would not agree that working with types in Rust is fundamentally, significantly more onerous than in e.g. Haskell. No higher-kinded types or ML-style functors means that you can't: (0) Parameterize recursive data structures over whether type recursion happens via `Box`, `Rc` or `Arc` pointers. (1) Parametrically bootstrap complex data structures from simpler ones, Okasaki-style. And no global type inference means that whatever little you can implement will be infinitely more verbose than its ML or Haskell counterpart.