upvote
> I could believe that type systems aren't particularly strong as an anti-bug layer.

They're absolutely huge for this, but you have to write code to take advantage of the guarantees that the type system can offer.

As Yaron Minsky at Jane Street put it, "make illegal states unrepresentable". Stronger type systems make it possible to make more states unrepresentable. You end up with what amounts to static debugging - you debug your code at compile time.

Sure, it's still possible for runtime bugs to occur, but entire classes of bugs are eliminated, plus it becomes possible to have static assurances about program states about things that most language don't even try to express in the type system, like security.

reply
Languages like C and Go are so weak in the type system that it barely feels better than fully dynamic languages.
reply
At least in C and Go, you can get structs where it's easy to reason about the fields.

In Python, a "class" is simply a dict under the covers and (by default at least) you can add attributes to it after definition (as well as things like properties). So it's difficult to reason about what the fields are at any given time. And that's assuming people USE classes! I've seen code where all the state is in one giant ever-changing dictionary and you have to pull out a debugger just to figure out what's IN the thing! God help you if you mispell a key!

Maybe you work with better quality code than I do, but I find Go's type system a lot easier to reason about than Python's.

reply
I don’t believe that “reasoning” is very useful in large code bases written by multiple developers. If you are trying to be axiomatic and prove to yourself that the code is correct, there are a thousand different ways the part of the code may not support your axioms in ways that are not apparent. It’s better to have a handful of invariants that are well communicated to the team and a lot of tests.
reply
I agree, I was referring to powerful type systems.
reply