10 comments

[ 0.13 ms ] story [ 36.0 ms ] thread
Funny enough, six months in I've found nearly the same experience with Rust. There's still logic bugs and interface expectations to deal with (accidentally broke an implicit contract in some code last week!) but my confidence in the code is extremely high.

I've found this to be interesting when jumping back to Java code - it's nowhere near as likely that the code just works if it compiles (though that was lightyears ahead of other programming languages).

Even though they hide it by using different names (probably to avoid scaring off people), Rust is heavily inspired by Haskell, so that doesn't surprise me at all.
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).

  tl;dr type-lovers are also bug-aversive
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.

Though this undermines the thesis.

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.

Except when it comes to File IO, I think you need to use bracket pattern for lack of linear types, but maybe this is fixed now?
I think a lot of these people go to Haskell direct from scripting language backgrounds, and thus have little experience of static type systems before that. You can see the same thing with Go: it's very apparent a lot of programmers praising how productive and consistent it makes their codebase are comparing it to something like Python or JavaScript.

In fact the top answer says:

Look, I have a lot of experience using Haskell. I understand how often code doesn’t really work after it typechecks. I never say “it typechecks so it works” with a completely straight face. But I also have a lot of experience with Python and JavaScript.

So these comments aren't really about Haskell in my view. People would get the same feel from lots of languages with decent type systems if they came from a scripting language background. I often find my code works first time in Kotlin, and the times when it doesn't only rarely things that a more sophisticated type system would have caught.