I've often had this experience, even in Java's less expressive type-system.
Following dynamic typing folks, I checked and I found that most of the type errors wouldn't have mattered anyway. I was mostly "pleasing the compiler".
So I wonder if some correlation is going on as well, to do with personality or development style, to cause this experience?
Perhaps... people who like types are extra finicky/perfectionistic, so their code tends to more carefully thought-out (which takes longer). And they try to structure code so it can be verified as they go along.
Also, each time you fix a compiler error, you are engaging with the codebase, making it easier to spot logic/semantic errors.
e.g. for myself, I like to have a complete mental model before major coding; break it down into simpler parts; do experimental coding to check ideas I'm not sure of; and try to avoid complex and difficult-to-track-down bugs by coding a little at a time (so if there is a bug, it's related to what I just added).
It's not necessarily so much about the coding. It's about the maintenance and refactoring. The people who like types aren't so much the implementors who dictate the original full view of the system; the people who like types are the janitors who have to understand and clean up and extend the system down the road.
Suppose you're writing an e-commerce system. It's fast and convenient to just stick a value in a Price field and not worry about whether it's a float or decimal or even concatenated as a string somewhere, if everything seems to work.
Now two years later you or some poor successor is tasked to implement a feature that Price not be a single value, but a list or some other structure, say it's keyed with different values over time or per market segmentation or A/B testing or whatever. That engineer will be really glad to have a strong type system that can catch every reference to Price being a single numeric value.
Having programmed both in Haskell and Java, my experience is very different.
In Java you have to "please the compiler" all of the time. Most of the types you add don't help in finding bugs. The type system is not expressive enough for real general types, because subtyping gets in the way.
In Haskell, the experience is very different: Writing down a general type first guides you in writing the code. Or, conversely, writing down the code first and then looking at the inferred type sometimes gives you clues to modify your code to make it better. The Haskell syntax is more terse, so a lot more trivial errors (typos etc.) are caught by the type checker. And the type checker really shines when refactoring code.
And my code is actually not "bug-aversive", I do make a lot of trivial mistakes all of the time. And I'm glad when the type checker catches them.
And my code is actually not "bug-aversive", I do make a lot of trivial mistakes all of the time. And I'm glad when the type checker catches them.
I'm in this camp too. I love strong static types because I know I'm not particularly obsessive about fine details and can sometimes be sloppy in that respect. Compilers pick up the slack where my attention to detail falls short.
I make a lot of silly mistakes too. But because I understand the code (I'm careful there, bug-aversive), the cause is (almost always) instantly obvious.
Following dynamic typing folks, I checked and I found that most of the type errors wouldn't have mattered anyway. I was mostly "pleasing the compiler".
So I wonder if some correlation is going on as well, to do with personality or development style, to cause this experience?
Perhaps... people who like types are extra finicky/perfectionistic, so their code tends to more carefully thought-out (which takes longer). And they try to structure code so it can be verified as they go along.
Also, each time you fix a compiler error, you are engaging with the codebase, making it easier to spot logic/semantic errors.
e.g. for myself, I like to have a complete mental model before major coding; break it down into simpler parts; do experimental coding to check ideas I'm not sure of; and try to avoid complex and difficult-to-track-down bugs by coding a little at a time (so if there is a bug, it's related to what I just added).