I feel like part of the problem is Haskell's extremism towards purity and immutability. I find some code easier to express with procedural/mutable loops than recursion, and I believe the vast majority of programmers. I think that one thing that makes Rust so successful is its capable type of system and use of many functional idioms, but you can use loops and mutability when it's more comfortable. And of course, the borrow checker to ensure that such mutability is sound.
Haskell doesn't stop you from mutation, it just makes you explicitly mark it, like types of inputs/output are explicit in statically typed languages instead of being implicit or borrowing is explicit in Rust.
Mutations becomes first class values like numbers or arays, and hence can be primitives for more complex mutations, whose types can be inferred from the types of primitive mutations.
This means that the we have compile time guarantees that certain piece of code wont change anything in certain part of the state - This function wont change anything in that part of the data.
It is no joke, though not strictly true, that Haskell has been called the world's best imperative language.
> I find some code easier to express with procedural/mutable loops than recursion, and I believe the vast majority of programmers
I think this comes from early and continuous exposure to some forms of programming, rather than inherent to pure functional programming.
I personally find it much easier to use recursion and other functional techniques because it composes better. This probable comes from my exposure to Haskell much earlier than most.
> I find some code easier to express with procedural/mutable loops than recursion
This is what I was talking about in the section "Unlearning and relearning". While there are _some_ domains (like embedded systems) for which Haskell is a poor fit, a lot of the difficulties people have with it (and with FP in general) is that they have been heavily educated to think in a particular way about computation. That's an accident of history, rather than any fundamental issue with the programming paradigm.
How does one go from years and decades of imperative programming to becoming fluent in Haskell's style of functional programming? It feels like a steep price to pay when most over languages don't require such substantial re-learning.
I don't think it's specifically Haskell's style of functional programming. It's just functional programming.
Any paradigm shift requires re-learning I think. I don't actually think that's particularly hard, nor do I think it means the paradigm isn't a good one, it's just an inevitable consequence of a paradigm shift. Some shifts are easier than others, if the paradigms are closer together, but functional and imperative programming are quite distant in my view.
Nevertheless, I've seen some people find this easy, others find it hard. YMMV I guess.
> I feel like part of the problem is Haskell's extremism towards purity and immutability
Eh. Elm has achieved quite a bit of success just by having good tooling and a good ecosystem. Says something about people's willingness to learn pure functional programming, if the situation is right.
> I find some code easier to express with procedural/mutable loops than recursion
This is usually a familiarity problem, IMO.
I often say: people think mastering Haskell is about mastering monads. But it's actually about mastering folds.
the best intro to writing Haskell for me was writing Elm. The best intro to writing Elm was writing pointfree Codewars kata solutions in JS using
with(require("ramda")) fn = pipe(…)
And yep, you end up with a lot of folds (well, reduces) where that ellipsis is. Or related functions that are really folds.
For those wondering `with` in JS is a bit like `extract` in PHP except it creates a new context right after itself rather than modify the context it finds itself in. It's super deprecated because it's inscrutable and silly except in this case and/or when you need to solve Codewars katas in a limited number of characters.
That's a problem no haskell user has, honestly. Your issue seems to be about getting your feet wet. Could you imagine people saying the issue with Java is its extremism towards objects and method calls?
Sure, a determined Fortran programmer can write Fortran in any language, but if they have trouble doing so, maybe the issue isn't the language.
> Could you imagine people saying the issue with Java is its extremism towards objects and method calls?
I think exactly that all the time. It’s ridiculous.
> That's a problem no haskell user has, honestly.
I had this problem all the time when trying to write games in Haskell. Not every subject matter decomposes into semirings. Just like not everything decomposes nicely into objects.
People tried to fix this with FRP or lenses. Both are worse than imperative programming for games imo.
In a sense, that's true: people who do have this trouble constantly (e.g. me) very quickly cease being Haskell users. But that's hardly an argument for TFA's claim that "Haskell is probably the best choice for most programmers, especially if one cares about being able to productively write robust software, and even more so if one wants to have fun while doing it"; if anything, it's a counter-argument.
> I feel like part of the problem is Haskell's extremism towards purity and immutability
You missed "lazy evaluation by default" in that list ;) Those properties are kind of the definition of Haskell, so without all of them you'd have another language.
Like the sibling commenter mentions, this seems more of a "I'm unfamiliar with this" thing rather than a problem with Haskell...