4 ms·
> 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 d
by 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.