Fully typed function signatures form a kind of contract you can program against.
Haskell and other extremely strongly typed languages can infer the types of function parameters, yet the community still agrees it is good practice to annotate your work.
Would Haskell be better off if the compiler enforced this community agreement, instead of letting users decide?
Also, the type annotations can be added on later. While you work and play with ideas, leave everything unannotated. After it's cemented and perhaps refactored a bit, add the "contract". In Rust, even while working things out, the user has to figure out and jot down the types.
> Would Haskell be better off if the compiler enforced this community agreement, instead of letting users decide?
Unequivocally, yes. My logic is that, while writing the function may be slightly quicker and more convenient if you can leave off the type, reading that same code is made at least an order of magnitude easier if the type annotation is sitting there in the code.
Actually, it gets better than that. Writing down the type of a function before writing the function often helps you write the function.
Protip: Use `ghc` with `-fwarn-missing-signatures -Werror`, or even better, `-Wall -Werror`. :-)
The thing is, with current tooling, the current design means that I can write a function, type a key combination, and have the type signature printed in a buffer (where I can then copy it into place). And until I do that, there is warning highlighting on the function.
Now in some ways this may seem silly - are you really going to understand code without understanding types? But especially for people new to the language, _or_ when you're dealing with new libraries (if you've ever written a little wrapper around a function from a complicated library, you know what I mean), it's nice to choose whether you want to work from values or from types (where undefined is your friend).
Which isn't to say that think rust's decision is bad, just that having flexibility makes this kind of tooling easier (and I'm assuming here that in all cases, the end result will be all annotated top level functions). And, part of rust's choice was probably to make type checking easier, which is an important thing (especially given how sophisticated the borrow checker is).
Typing should be a conversation with the compiler. If you have a strong understanding of what you are writing then, yes, writing the types first makes sense. On the other hand, sometimes I only understand how some particular pieces fit together—at this point, I want the compiler to throw its inference engine at my code fragment and tell me everything it can!
Typing and programming is exactly the same as theorem stating and proving in mathematics. It would be idiotic to have one-way information flow only.
That said, it's also practically criminal to just hand someone a proof without stating what you think it's supposed to be proving. Ultimately, that it where you must wind up.
Interesting point. Getting the type annotation inferred for you there is definitely useful. I've used it a few times myself.
The `undefined` trick is also immensely useful. I use it a lot when starting a new module. Rust also has a notion of bottom, indicated by `!`, which will unify with all types. I frequently use this in Rust in a similar way that I use `undefined` in Haskell. (In Rust, you would speak `fail!()` or `unreachable!()` or `unimplemented!()` or define-your-own.)
> (if you've ever written a little wrapper around a function from a complicated library, you know what I mean)
Yes, absolutely. I haven't really run into this problem with Rust yet though. Types are generally pretty simple. If and when Rust gets higher-kinded types, that would assuredly change.
Certainly the user should be allowed to decide when they feel the code needs further documentation to be readable. Trying to drag people into something seems unfriendly.
OCaml has a decent compromise between no signature at all and signatures everywhere: you put signatures in your interface. Works pretty well in practice, I find.
Haskell compilers can, and its probably better for production code to have them do it.
OTOH, it can be better for exploratory coding in some circusmtances not to. (For one thing, it can be a tool to find cases where you accidentally write something that is more general than the types you were thinking of, but perfectly valid for the more general type -- which, at least as someone fairly new to Haskell, I find myself doing a lot.)
Yes. Many times the compiler will actually infer a type different than the one you wanted. In my experience this just leads to confused programmers who have trouble deciphering what went wrong when presented with the error message.
Haskell and other extremely strongly typed languages can infer the types of function parameters, yet the community still agrees it is good practice to annotate your work.