But I’ve seen way more useful software fall down the show off well in C++ than in Haskell.
I think it was Thompson or Ritchie who said: “debugging code is twice as hard as writing it, so be half as fancy when writing as you could be.”
But I’ve seen way more useful software fall down the show off well in C++ than in Haskell.
I think it was Thompson or Ritchie who said: “debugging code is twice as hard as writing it, so be half as fancy when writing as you could be.”
And your spot on with the C++ reference, but there its more the case the language was adopted in industry then it expanded into intellectual twiddling, Haskell has that as its starting point.
Don't get me wrong I like programming in Haskell, C++ and others, I enjoy going beyond what I need to get the job done and amusing myself in doing things 'clever' ways. But no longer being paid to write the code and having different concerns to manage, its hard to qualify Haskell as a good choice.
I never agreed with the conclusion. Clearly the observation implies that you should use all your brain power to write your code in such a way that it is easy to read, understand and debug.
That often means using eg the right abstraction for the job. Not the dumbest one.
The problem really nice abstractions have is that they encode too much into too little code. They are very concise, and people who aren’t as knowledgeable (avoiding the word “smart” here as I think it’s wrong) will treat it as “magic”. Magic in code is a really bad idea when you need to debug it. The ML type system can create these magic moments that make someone who actually wants to understand how the hell that works have to go down a multi-hour rabbit hole just to figure it out. The best example of this that I’ve directly worked with is Finagle. If you look at the code for it, you’re very often left scratching your head trying to understand how it manages to get so much done with so little code. Having been there while it was developed, I will say it didn’t start off that “pretty”, it got there over 3 fairly major revisions to the underlying type abstractions. The result is beautiful, but opaque to most of the mere mortals that use it.
I would argue that Go has been successful largely because everything that’s happening is “out in the open”, where the average developer can see it. It’s a very different philosophy, one that I think the quote-creator aligns with better than your typical Haskell devotee.
Sorry, I don't think I made myself very clear. I wasn't talking about concise code. I was talking about designing your system right, and deciding where you want to set boundaries and what you want to keep flexible. And sometimes: what do you want to encode in types, and what do you want to check at runtime?
Also what properties and invariants do you want your system to have? (See also property based testing.)
Calling all of this a design of abstractions was not the most clear word choice on my part. Sorry for that.
However, to defend a point I didn't make:
Sometimes it does make sense to shorten your code a lot. If you can express your solution in 10% of the lines, it might be worthwhile, even if each line is twice as hard to understand now.
That code might benefit from some explanation, and generous annotations, though. And plenty of properties tested.
This is why I like Go. It makes it difficult to write code that doesn't take basically the same approach any other, similar code would. When you start trying to get abstract or do anything cute, it hurts just enough that you won't do it unless there's an actual need, not just some aesthetic preference.
Consequently, I can hop in to just about any of my dependencies and read them immediately. No, "huh, I haven't seen that language feature before" or "WTF is that symbol even?" or "... but where does it actually do anything?" or "oh great they've imported a library that basically turns it into an entirely different language".
The community's also been really good at avoiding adding abstractions through libraries, so you don't end up with the mess that Javascript had for years with multiple competing Promise libraries in wide use or a dozen competing module systems or any of that crap. There's some experimentation but it rarely gets out of hand.
The problem is when the magic isn't happening. How do you convince yourself or someone you work with to take off the wizard hat, come down out of the clouds and implement the naive/verbose/ugly solution because the elegant stroke of genius hasn't come and the feature is taking forever?
This is where Go and PHP shine, less temptation to guild the lily.
s/guild/gild/
Akka comes to mind as another example of what you said about Finagle. It works great and even has voluminous documentation. But every time I try to click through it in Idea to see how it works I kind of don't see it. This contrast with most other libraries is very real. From speaking to other people I know that I'm not the only one who feels this way. Broadening horizons aside, I'd rather not have production issues with such a codebase.
Personally I don't doubt that Haskell developers are smarter than me. Though I strongly suspect that they come from a hard to reproduce background (PL theory majors? CS postgrads? theoretical physicists?). And not that many companies require this level of sophistication.
There's a huge disconnect I see in the real world. Intellectual bottom scrapers such as JS/golang are increasingly popular. Yes, we see golang catching up with Java ten years later than was necessary but it only confirms the observation. Scala and even Kotlin (F# too?) are not that widely used for how practical they are. In this world I see no place to be found without a looking glass for something as esoteric as Haskell, lazy evaluation and all. And we've had this exact conversation for a decade already.