Yes, Haskell has those gotchas like "don't use lazy IO", "there are partial functions on the Prelude", "String is slow", and "code may throw exceptions where you don't expect".
They are there mostly because of history and the language would be better without them. Yet, they are easily avoided and aren't that many (those above are most of them). If you rage quit every toolset that has problems, I have some really bad news for you.
https://guide.aelve.com/haskell/alternative-preludes-zr69k1h...
This directly means "a problem with the lanuage" to any beginner with the language. Since it's the default Prelude. So a beginner has to somehow learn that there are issues with Prelude, that there are other preludes, find the differences between them, select one, and then reconcile the inevitable differences between those preludes and the official one when reding various docs.
...
And then figure out wich of the two dozen language extensions you need to use to even write something useful beyond a "Hello, world".
You're not doing Haskell any favors by comparing with "the times when STL was no good" (when was this? 20 years ago? 30?).
> Why should the situation with Haskell be different?
Because the world has moved on and expects languages, their libraries and runtimes to become better.
Huh, why not? He's comparing not equating, after all.
> And Prelude's problems are way less severe than the problems the STL used to have
For a language to be adopted it must be beginner friendly. And by beginner friendly, I don't mean easy. It can have a steep learning curve as long as it enables the user to be productive, otherwise the beginner will give up quickly.
For the experienced user things like, "don't use lazy IO", "there are partial functions on the Prelude", "String is slow", and "code may throw exceptions where you don't expect", may be obvious, but are not for the beginner. I don't remember exactly how I ended up using "lazy IO", but trust me it wasn't because I ignored a big fat warning that I should NOT be using it.
It's gotchas like these that prevent the beginner from being productive.
Then the beginner reaches out to the community sharing his experience and gets a defensive and passive aggressive reply like yours. It's enough to make them not want to touch that language ever again.
You think you are defending your favorite language, but actually you are doing more harm.
once you are the expert, you would waste your time to use other programming languages.
also - the post you are replying to isn't condescending. the haskell community just doesn't treat beginners like infants who need coddling. haskellers tend to give the nuanced & truthful answer to questions.
Expert in what? Programming? Lambda calculus? Category theory? Let’s not pretend that you are simply an expert in something randomly, it takes a lot of practice, mistakes, and actually being a beginner before being an expert. Even if you are an expert in the above you still are a beginner when learning Haskell the first time, and you will make mistakes, so having beginner friendly resources is important.
Quite frankly, it’s this kind of gatekeeping attitude - that Haskell is meant for “us” and to become one of us, you have to be an expert, and we aren’t going to coddle you - is a kind of attitude that significantly contributes to the lack of good and welcoming beginner resources and causes very few people to actually pick up and stick with the language. You can be a “language for experts” and still have good, beginner friendly learning resources to welcome more into some community.
There are plenty of beginner-friendly resources already (more & more every year), but they can't erase worse ones from the Internet. The Haskell community lacks the sort of strong-fisted leadership to accomplish that by design.
That said, acting like a tutorial mentioning lazy IO or partial head/tail is a killer is a little ridiculous. Neither of those things are atrociously problematic, so learning about them early is fine. You may get cut due to them, but getting cut is okay if you don't flip the table.
Also I (and most of Haskell posters) do not gatekeep. The community will go well out of its way to respond to any questions beginners have with blog-post-quality comments in the various forums (mailing list, reddit, irc, slack, github issues, etc) There is definitely a teaching culture, which is the opposite of gatekeeping.
We could special-case it, but on the other hand, there are already multiple other solutions in this space that are more generally useful. Alternate Preludes (and compiler support of -XNoImplicitPrelude) `hlint` can also be customized to do exactly what you're asking for as well.
That's going to make it very hard for me to run a business, which involves sourcing, hiring, and training a potentially large number of people. Hiring only experts is a tremendous business cost.
Haskell is first and foremost a gigantic personal productivity booster. It allows me to do bigger and more complex projects on my own or with one or two others. These projects are not for corporate interests although that can be for personal profit. I am pretty confident I will be able to stop giving my labor to any corporation within the 10 year mark of my career, and Haskell will be a big reason why.
But I still try to convince corporations to use Haskell since then we offload the cost of learning onto a corporation instead of an individual. That feels like a worthwhile re-allocation of capital to me! Corporate Haskellers get paid to gain expertise and keep it forever, leaving corporation with nothing besides their direct labor. Luckily it's easy to convince a corporation of anything with what amounts to propaganda & politics.
How very modest of you, if only they could listen.
That said, none of that applies to those gotchas. They are clear problems with the language. None of them are obvious, but all of them are widely discussed so you will see them early when learning the language. Learning the gotchas of an ecosystem is a central part of learning any tool on informatics, and as gotchas go, one of the strong points of Haskell is that there are very little of them.
You are making a very common complaint, that comes from ignoring the problems of the tools you know while making a fuzz over anything you find on the new one. It's almost certain that whatever languages you are used to, they have a much larger pile of gotchas than Haskell (because Haskell has an atypical small number of them), but that doesn't stop them from being useful.
Some of the "C++ contenders" (besides Rust) like Nim, Zig, and potentially Swift seem to balance this line well: simple to start using, but grow with one's expertise.
"Yeah well your language isn't good either" isn't a very good argument for why a language is _better_. If the idea is "Haskell works better than other languages as long as you happen to know how to make it so", isn't that just every language that exists? Due to Haskell's branding, I was under the impression that the issues the above user is describing should be impossible. If Haskell doesn't even make good on those guarantees, but instead shifts that guarantee as "Things you should've known not to do" onto the user, how is that different from any other language?
edit And since this thread has a lot of tension and vague hostility, I will add, I am not attacking you or the language you enjoy. I legitimately would like to better understand.
" < language > is only safe if the authors of such code take advantage of the features that the language provides to write safe code "
But "you won't be able to use it well if you don't learn how to use it" does indeed apply to all languages. Yet, it's more relevant for some, and Haskell is one of those more affected by it.
It is a fact that Haskell is not beginner friendly. Your first program on it will suck, whatever proficiency you have with other languages (there are some people that argue that it is easier if you know less beforehand). It takes some learning before you are able to get the better safety, high productivity and easy collaboration people talk so much about (and even then, you won't get those for every problem, the language has limitations too).
1 - The statement is false anyway. There's no such language one can single out there without more context.
As someone who has tried to learn Haskell twice and failed (and trust me I went way beyond the second page of a tutorial ;-), I don't think the issue is that Haskell has problems. As you hinted every language has problems. The issue is that for a lot of people Haskell requires significantly more effort to learn than other languages and doesn't have a lot publicly available software to show off for. So when we learn Haskell and stumble on problems, we are less forgiving than with other languages because we have spent more effort and we don't have enough examples of useful software made with Haskell to reassure us that our efforts will eventually pay off.
We loose confidence because it seems that the promises of correctness aren't fulfilled and we don't have enough evidence that we aren't wasting our time. We would need at least to see the light at the end of the tunnel to keep us motivated. The sad thing is that if we decided to spend long hours of our free time learning this language instead of doing other things it's because we really believe in ideas behind it. What we have read about the language obviously speak to us but at some point we loose motivation because we don't get any tangible results.
I'm pretty sure that a good part of why it clicks for some people and not others is due to the amount of mathematical literacy. I don't have a strong mathematical background so the amount of effort for me to learn the language is probably much higher than it is for someone better at math. I have to invest more so I expect more in return, which in my personal experience Haskell fails to deliver. To appeal to a wider audience Haskell needs to be pretty much flawless and also to have more public software to showcase.
Sometimes you go into the tunnels that are not tunnels but rather mines, and you go there not to see the light at the end of it, but rather to dig diamonds.
Lazy IO, like the partial functions in Prelude, is a convenience hack for making some very low-complexity things easy. I don't have a problem with it existing, because I am fine with matching my tool complexity with the problem complexity.
And also, I understand what it does. I'm surprised I'm the first person to point out that your assertion is not an accurate description of anything that actually happens.
The promises aren't “using Haskell magically causes correctness”, but “Haskell provides powerful tools that most other languages don't that enable correctness”.
But, you know, the people that need to telegraph “rage quitting” a language are usually the people chasing an unreasonable silver bullet and misinterpreting things through that lens to start with.
The complaint is that with lazyIO, even if your code does the write before closing the file, the actual order the operations occur in could change, to put the close first.
If you look at the lazyIO documentation, you will see:
>Although this module calls unsafeInterleaveIO for you, it cannot take the responsibility from you. Using this module is still as unsafe as calling unsafeInterleaveIO manually. Thus we recommend to wrap the lazy I/O monad into a custom newtype with a restricted set of operations which is considered safe for interleaving I/O actions.
https://hackage.haskell.org/package/lazyio-0.1.0.4/docs/Syst...
TLDR, don't use lazy IO.
I don't know which people you are talking about, but it clearly was in this specific subthread which started with a complaint about “LazyIO”, not “lazy IO”, and where the only use of “lazy IO” in a post before yours was in a post where all previous references were to “lazyIO” and it's specific package documentation, and contextually the “lazy IO” references was about the same thing, not something else.
One of Haskell's known weaknesses is that there are no curated catalogs of high quality libraries. The industrial strength stuff sits on package servers alongside the broken toys.
I once got an apology from a major luminary in Haskell, author of dozens of high quality packages, because I used a package he wrote that turned out to be an abandoned broken experiment, but not documented as such.
There are other strange things in the IO monad, such as the ability to observe evaluation orders by throwing exceptions.
That's not specific to IO; you can more or less always observe evaluation order by throwing exceptions:
bar = error "bar"
baz = error "baz"
foo = (bar,baz) :: (Int,Int)
main = print foo -- well, I guess you need IO to run anything at all
`bar` is evaluated first (at least on my machine), as evidenced by: $ ./test
test: bar
CallStack (from HasCallStack):
error, called at test.hs:1:7 in main:MainIts a bit more that that. You need to be in IO in order to catch an exception.
That is to say, if you have:
bam :: (Int, Int) -> String
There is no way to write: bam (x,y) = "bar" if x is called first
"baz" if y is called first.
However, if you were to instead have: bam :: (Int,Int) -> IO String
Such a function is possible to write, as you can now catch the exception and do something with it.In this case the Haskell program itself does not observe the order, as it crashes, but the order is printed as debug inormation.