This. Remember that to be functioning in Python, C++, and many other languages you don't need to learn most if not all concepts. That is not true for Haskell where if you know a lot but not everything, you are likely running into trouble quickly.
Example from my own experience: I've read 1/5 of "The Haskell Book" and know the essentials pretty well, but throw mature Haskell code (as in "something people made for a real purpose") at me, let alone monads, and chances are I'm blown away.
But it I throw mature Python/C++ code at you, with concepts you don't know, how is it easier?
Those Haskell threads are full of exaggerations. I don't know/use a lot of Haskell concepts and I can still produce software with it. You can be just fine with IO and passing everything as arguments. Which is, well, what article is talking about.
It's easier because Python/C++ have huge communities at this point and Haskell does not. It's also easier because most people learn some variety of Java/Python/etc as their first language. So languages with similar structures and conventions are easier to grasp.
Every time someone has suggested I learn Haskell the discussion goes similar to suggesting I learn German. Sure German from a language perspective has some advantages over English in some situations. Some even argue that it's an objectively better language. But I live in Pennsylvania and speak English as a first language. Outside of moving to Germany/Switzerland/Austria, how do the advantages of German provide enough benefit for me to invest the massive amounts of time to become fluent?
Sure if we could turn back the clock on Computer Science education and have everyone learn lisp as their first language maybe we'd all be avid Haskellers these days and be better off for it. But given how history went it is "harder" to learn and less productive to work in due to external factors alone, regardless of how intrinsically easy/hard the language may be (which is entirely subjective).
There's still plenty of value in learning Haskell even if you're not going to use it daily.
I'd go as far as saying it's essential for anyone who likes programming beyond just a profession. Same with lisp.
You don't need to learn all of the language extensions or how to architect serious applications with free as the OP said but it's very useful
knowledge and one of the pedestals from which all other languages should be judged.
Plus you'll understand why Idris and dependent types are an interesting future development in safety and language design. While also understanding the source and inspiration of many features in far more popular languages like JS and Rust. And there may be a real future in it via PureScript and other similar projects.
Why do you write Python and C++ in one line? C++ is an extremely hard and esoteric language. Python is very easy language. They are like two opposite points.
C++ can be quite manageable in a professional setting, where you get Qt or boost. Then it's like any other programming language.
I think the major troubles for beginners with C++ is that you can't do anything out of the box like work with files, create a directory or perform a HTTP request. Whereas python or java are ready to use.
Eh, I strongly disagree with this characterization. I did c++ for a few years at Google and am now back to developing in it, and I'd say it's probably my favorite language to work in a codebase that sets the right constraints on it. But that doesn't change the fact that it is replete with unintuitive footguns even for those comfortable/experienced with it, in a way that Python or Java absolutely isn't.
The closest thing i can think of in Python is passing a mutable object (like an empty list) as a default param value. C++ is littered with bug-prone landmines like that.
>Python is anything but easy, it is the same caliber as C++, just lacking implementations able to execute as fast.
Yeah, that's stretching it to absurdity.
Python is easy to get started, and easy to adopt any of the extra features (e.g. slots, metaprogramming, async, etc) piecemeal. And easy to read most codebases.
Haskell is not easy to get started, not easy to adopt the extra features piecemeal, and not easy to read most codebases.
While it looks like piecemeal to adopt metaprogramming, decorators, multiple inheritance, slots, operator overloading, extension of built in types, generators, async/await, their use combined in the hands of clever programmers, is anything but easy.
Hmm ... debatable. I have to dig in to the implementation of Python libraries and Haskell libraries regularly. I'm much more confident that I'll come away understanding the latter than the former!
> not easy to adopt the extra features piecemeal
I can't see any evidence of this. Can you name a few Haskell features that can't be adopted in the absence of other features?
I didn't say that they "can't be adopted", but that it's "not easy" to adopt them (and specifically it's not as easy as Python or even Java, C#, Lua, whatever) -- because they come with a bigger mental burden...
How do you functionally manipulate an indexed mutable structure like a vector?
How about the common task of CSV file manipulation? Database access? (Simplest of FFI.)
Not reopening nor reparsing the file every time you want to do something? At the same time, with known upper bound on memory use?
Note how almost none of standard CRUD and web stuff is easy to write in Haskell from scratch and libraries do not help a lot.
You always end up in some variant of IO monad, typically multiple incompatible ones at the same time, making the pure functional nature of the language moot. You get to glue the various kinds of IO explicitly.
Haskell feels like writing a CPU (high level state machines everywhere), except with less readability and more verbiage than Verilog. The propensity of Haskell programmers to abbreviate everything and add redundant "helper" functions under different names does not help.
Programming is stateful because world has a state, and Haskell's handling of state is annoying at every step even for someone versed in it.
Firstly, the question was very specifically to coldtea to help flesh out his/her claim that it is "not easy to adopt the extra features piecemeal". So far that claim doesn't seem to have be substantiated.
Secondly, are you really saying you believe that Haskell doesn't have all these features? That there aren't good ways of mutating arrays, writing CRUD apps, combining effects, etc.? Presumably then, your jaw would hit the floor if I could demonstrate that everything you believe is false.
There's plenty of shade you can throw at the good old snake, be it package management, performance / speed, formatting peculiarity but this one is the most unlikely I can think of.
Python allows for very creative programming, just because every feature looks easy in isolation, when used together they can open the door to some head scratching.
Ever mistyped an output file name in Haskell? This is one of those myths about static typing that really gets under my skin. I worked in a large, hardcore Haskell production environment for several years. There was no difference in the amount “silly typo breaks something later at runtime” types of mistakes, none, between that and the decade or so of production Python experience I have.
These bugs enter your system and manifest in such weird ways that it always will be the job of unit and integration testing, not static typing, to catch them. Not with modeling states in the type system. Not with phantom types. Just nope. Frankly to me this is what distinguishes a senior engineer from junior engineers in statically typed languages. Do they understand the language design faculties don’t actually protect them, abandon the misguided idea of encoding protection into the language’s special faculties, and instead put that effort towards making the testing infrastructure easy to understand and update and very fast to run.
> There was no difference in the amount “silly typo breaks something later at runtime” types of mistakes, none, between that and the decade or so of production Python experience I have.
This is fascinating. You are basically the only person I know who has used Haskell extensively who claims this. Have you considered writing up your experience as a blog post (or even more formally as a technical report)? I think it would be extremely helpful to the programming community and particularly the Haskell sub-community for you to share your point of view.
Briefly, there is something very similar to Amdahl’s Law for parallel speedup but for removing the thin layer of defects checkable by static typing. Most defects in any real system aren’t like that, to such a degree that the whole correctness bottleneck is concentrated so heavily in unit and integration testing and the extra language complexity, extra lines of code for type annotation or registry of type system designs, slow compile times or constraints on mutation imposed by the static typing don’t pay for themselves through meaningful defect reduction. It’s like the cost of shipping data to a GPU. The efficiency gained by processing it in parallel on the GPU device must be much greater than the transport cost, or it’s not worth it.
But in terms of me ever wanting to write this up with rigorous technical examples, I mean, just look at the level of discourse and tribal downvoting in a thread like this.
Even setting aside that this experience was spread across a quantitative trading company and in a large public financial technology company, meaning I definitely can’t publicly share a lot of details of those systems (which adds tons of required effort to convert examples into totally isolated tutorial-like standalone samples), why would anyone with a valuable technical dissenting opinion about Haskell want to open themselves up to that kind of religious backlash?
It’s demoralizing and discouraging for me even just in a thread like this one, where I’m just some mostly anonymous commenter talking subjectively about my experience in small comments.
There’s no way I’m sticking my neck out on a big technical blog post or technical paper about why leveraging a static type system doesn’t meaningfully reduce defects in real systems.
Also to be clear, I think static typing is fine. Some people enjoy it a lot or have clever ideas about using it for expressiveness. Some people also write amazingly concise dynamically typed code that covers a huge variety of use cases in a safe way with pretty much no overhead code to register anything at all about those use cases. People are free to choose their tools and whatever gets a job done is totally fine.
The part I find disingenuous is that it seems like only the static typing zealots are trying to come up with a reason to think a certain way of doing things strictly dominates or supersedes a different way of doing things, and it’s totally disingenuous to act like the benefits of static typing on defect rates would be such an argument for “universal” applicability of one certain paradigm.
To be fair, you are expressing an allegedly subjective account of your personal experience in what to me sounds like an overly assured and conclusive manner, coupled with expressions like "static typing zealots". It reads a bit like you are imply that there are only zealots and then there is this account you're sharing, which is the definitive truth.
It similarly turns me off into trying to discuss this constructively, even though my experience of Haskell is almost a complete opposite of what you're saying here. I guess that leaves space for only low-effort discussion and people happy to hear that Haskell turns out to not be worth it after all.
My opinion is not allegedly subjective, it is subjective. I don’t expect anyone to do anything with the comments I write. They don’t prove anything, but someone may find it useful to hear that a person with experience decided to have a dissenting opinion of Haskell in practice.
I will say, however, that just as I mentioned in my comment, I’m willing to say static typing is fine. There are lots of tools in a toolbox. It is one of them.
I don’t believe a lot of commenters who seek out this discussion would give a similarly charitable view of dynamic typing, and in my real life experience, these are people who superficially dismiss projects written in dynamic languages, especially Python, on parochial grounds not rooted in reality.
In other words, I see a lot of people in the Python community in real life saying, “Haskell is cool, you can do expressive things in it, but it makes certain other things hard and so for a wide range of tradeoffs I wouldn’t pick it.” But I see people in Scala, Haskell, Clojure, F# etc., communities saying, “Python is crap, so unsafe, so many bugs, it’s just a categorically wrong way to design and write programs.”
So the discussion is (in my experience) extremely asymmetrical along these programming religion lines.
> I don’t believe a lot of commenters who seek out this discussion would give a similarly charitable view of dynamic typing, and in my real life experience, these are people who superficially dismiss projects written in dynamic languages, especially Python, on parochial grounds not rooted in reality.
Fine, but that's a criticism of the people not the language. I'm interested in the latter and not really in the former, unless you're trying to say that they are somehow linked.
> “Fine, but that's a criticism of the people not the language.”
I totally agree, and my dissenting opinion of Haskell is not based on anything about people or communities, just on ergonomics of using it and working on a big legacy codebase of it in production.
I mentioned the asymmetry of people who can be zealots about only one paradigm being The One True Way only in response to the parent comment I was responding to.
> It similarly turns me off into trying to discuss this constructively, even though my experience of Haskell is almost a complete opposite of what you're saying here. I guess that leaves space for only low-effort discussion and people happy to hear that Haskell turns out to not be worth it after all.
Let's hope there's another alternative: that those of us with seemingly opposite experience and opinion to mlthoughts2018 can encourage him/her to share more so that we can all learn something beneficial to our lives.
Yes. Especially because I am sure Haskell and similar languages have failure modes, in which the seemingly magical sauce I've personally experienced might not work, for one reason or another. I do believe that mlthoughts2018 worked in such an environment/codebase and it would be extremely useful to figures out what variables are involved in that.
Thanks for your comments. There does seem to be three languages sure to engender disparate opinions: Lisp, Prolog, and Haskell. I suppose that their advocates can be forgiven for their enthusiasm. They are all quite remarkable languages.
I am unqualified to assess the benefits of an advanced type system, after all, I've only worked through examples in a few Haskell books. I've never used Haskell professionally. Haskell is a lovely language. Its compiler is a remarkable achievement of computer science, mathematics, and engineering. Simon Payton Jones deserves the notable accolades and awards that he as received.
In my opinion, Haskell's most important contribution is in pushing the state of the art of programming languages forward. Is it practical? Yes, that too, but after all these years, it hasn't really become popular because being "practical" wasn't the main goal for Haskell. Haskell was designed to explore the non-strict functional landscape. Haskell's designers made good choices and were able to expand our understanding of non-strict functional programming (e.g. see Miranda [1]).
In the past I did years of research in program verification, so I'm naturally skeptical of the widely repeated claim that "Once your code compiles it usually works" (it's even on the haskell.org site). In what universe is this true? Verification that a program meets its specifications is quite difficult. In general, no compiler for Haskell can even verify that a program will terminate (the Halting Problem). I don't believe that real programmers are using Haskell's type system to formally verify total correctness (which includes freedom from deadlock, etc.) or even partial correctness (the weaker condition that if a program produces an answer that it is the correct answer).
I frequently write Python programs that work the first time; of course they are little scripts. It isn't dynamic typing that is keeping my programs from working more often. Consider the errors that I do make, syntax errors are caught by my IDE, I don't count those kinds of errors as real bugs. Next there are "type" errors, these aren't really troublesome even when I'm not using Haskell. I can find these almost immediately by testing or even using the REPL. (Every so often, I've heard of, say, a ruby program crashing once deployed because there is an untested path through the code that has a type mismatch between an argument and a function parameter. Haskell would catch this type of defect at compile time. That's good.) However, the really troublesome bugs are more subtle. Do the distributed parts have some kind of race condition? Am I handling the various spans of data within some vector correctly? Can an index touch memory outside of my memory segment? Is the floating point arithmetic doing what I think it should be doing? Have I translated the mathematics of wavelet compression correctly? Do I understand the Vandermonde matrix used in fast decoding of Reed-Solomon error correction codes--I don't! Haskell might be able to help with some of these harder bugs if the concepts can be properly represented in the type systems, but I believe that what mlthoughts2018 is saying is that this is often too hard to be worth it.
Haskell is a pioneering approach to programming, and the next frontier could be dependent types (see [2]). My own feeling is that someday programming will involve a dialog with a proof checker while coding. Writing proofs is hard, it seems harder to me than writing the program, so having an AI assistant that aids with the proof checking might make it more useful than simply struggling to encode a proof in the program's (dependent) types (see the Curry–Howard correspondence[3]).
In my experience, dynamic typing has not caused unforseen bugs at run time.
What it does do, is it causes large codebases to become extremely difficult to reason about, as you could get very little information about what types are needed or received where, and program flow, from the code.
Where I work, the managers decided that everything shall be python or ruby. So we have some 10,000+ line codebases, which are very hard to reason about. Including industrial control programs. "garbage collection pauses? What are those?"
This just happens in every programming language. I can tell you because the large Haskell systems I worked on were also incredibly hard to reason about. The analog of garbage collector pauses was accidental misuse of eager evaluation, but buried in misdirection through a sequence of specialized implementations that get called due to type class.
Big codebases becoming ugly messes is sociological and pressured by bureaucracy. It is not something that stricter language designs can seriously mitigate, even a little. Meanwhile, very disciplined and experienced teams can avoid it in virtually any programming language.
Some of the cleanest and safest huge software systems I’ve ever worked with were written in C, C++ or Python. Also some of the worst huge systems I’ve seen were written in C, C++ or Python.
I find getting as much tooling as possible that will tell you about types is pretty important with a large code base. For example in the Python code getting type annotations along with mypy up and running tends to be a big win.
That's a shame. There are numerous voices clamouring "Haskell's too much effort for its benefits to be worth it". You are basically the only voice saying "Its benefits aren't even benefits". It feels like you could really add something beneficial. If only there were some middle ground between carefully considered and reasoned critique and vague and unsubstantiated sniping on message boards, but so be it.
fwiw, I didn't read "it's benefits aren't even benefits". I read something more like "static typing helps with some problems, but those problems are just a sliver of the real problems." I also heard something like "static typing not worth the ceremony to me". Also, a general frustration with the ability of people of dissenting opinions to communicate meaningfully with each other.
I've not worked on Haskell but while reading about it I've always been suspicious that its type system is actually effective at preventing integration bugs. It's nice to hear this echoed.
I'd love to read more about this experience (good and the bad).
Well, I'm just pointing out that "easy" is not something that can be attributed to a programming language based on cute, pseudo-code like samples online.
You don't see "Python is easy" examples with full test suite attached to them, explaining that, well, you are in for a ride without those.
As for your comment: I can believe that production breaking typos may have been at a similar level. I don't believe that the effort to reach that level was the same, though.