Comments are useful and type constraints are a better way to express specifications.
It varies on the level of expressivity and soundness of the type system employed as to how valuable comments are. In my experience there's an inverse relationship: the more expressive the type system, the less valuable are comments. This is true in so far as the types get richer the more they can express with less ambiguity than prose. In a way this makes the comments that do exist in such a code base even more valuable since they describe far less and are probably filled with interesting information such as why certain propositions are important, etc.
However when you're working in languages without a static type system or a rather weak one, comments can be necessary and invaluable.
Update
To clarify, in a type system as rich as a dependently typed language, given an inductive definition of vectors, and a type; Agda, for example, can often find the solution (the term) that implements the type. You could add a comment if you wanted to but you'd only be elaborating on what is already obvious by the type signature.
This does scale beyond trivial examples such as vector products and into the realm of business logic; it's possible to encode state machines this way. Code comments of this kind of code end up looking superficial.
In a more common FP language like Haskell, often derided (even by me) for it's lack of commenting and documentation, seems to be that way precisely because once you get used to understanding how to reason about types... well it gets redundant... and the compiler cannot check that comments are correct with respect to the term level code. The comments are sparse and rich instead of redundant and full of exposition.
That's not to say that comments don't exist! Other poster have given many good examples where they are definitely necessary.
I ascribe to the rule that there's a balance and too many comments are not helpful just as too few are as well.
It varies on the level of expressivity and soundness of the type system employed as to how valuable comments are. In my experience there's an inverse relationship: the more expressive the type system, the less valuable are comments. This is true in so far as the types get richer the more they can express with less ambiguity than prose. In a way this makes the comments that do exist in such a code base even more valuable since they describe far less and are probably filled with interesting information such as why certain propositions are important, etc.
However when you're working in languages without a static type system or a rather weak one, comments can be necessary and invaluable.
Update
To clarify, in a type system as rich as a dependently typed language, given an inductive definition of vectors, and a type; Agda, for example, can often find the solution (the term) that implements the type. You could add a comment if you wanted to but you'd only be elaborating on what is already obvious by the type signature.
This does scale beyond trivial examples such as vector products and into the realm of business logic; it's possible to encode state machines this way. Code comments of this kind of code end up looking superficial.
In a more common FP language like Haskell, often derided (even by me) for it's lack of commenting and documentation, seems to be that way precisely because once you get used to understanding how to reason about types... well it gets redundant... and the compiler cannot check that comments are correct with respect to the term level code. The comments are sparse and rich instead of redundant and full of exposition.
That's not to say that comments don't exist! Other poster have given many good examples where they are definitely necessary.
I ascribe to the rule that there's a balance and too many comments are not helpful just as too few are as well.