Such inflammatory, much wow. Unfortunately, Haskell itself agrees.
Some languages naturally lend themselves towards adoption. Some don't. You'd expect after 30 years of Haskell, the community, tooling, and development environment would grow much more mature.
Spoiler alert. It did not.
Funnily enough everyone in the Haskell community blamed everyone else instead of doing a critical assessment of the language like what Perl did. I stifled a laugh when I see proponents of "Simple Haskell", implying that somehow the language is "too hard for people to learn".
If people can pick up F#, Scala and Clojure, all with their own brand of weirdness, both in syntax and environment while being functional programming languages, I don't really see how this statement holds any water.
Haskell is not too hard to learn. It is just a bad programming language.
One, programming languages are meant to ease the task of creating computer programs as opposed to writing assembly by hand. Thus, the most important part of programming languages is communication. If the language naturally lends itself towards making code easier for people to understand, it will succeed, even if it is weird. Look at Clojure. Weird parentheses, and yet it took the world by storm all because the programming language actually makes a lot of sense and facilitates communication both between programmers, and the computer.
Haskell proponents try to claim that type signatures are somehow documentation. Yeah, no matter how many times you claim this, it's really not true. We have had decades of experience in statically typed languages tell us that types are never replacement for clear syntax and documentation. Every few months some newbie comes along to the Haskell reddit and asks why is Haskell documentation so confusing, and the post get destroyed by people telling them to get good or just pointing at academic papers. Really?
What's even funnier is people saying that "Haskell doesn't suck, the development environment does". Haskell has had 30 years to improve itself and while there's some headway, growth is ridiculously slow. Guess what? If people can work with C++ and create amazing tools with it, I don't think that statement makes much sense.
Two, Haskell is a functional language that also convinces its users to commit the same mistakes as writing an OOP language. Very senior Haskellers calls for "type oriented programming" which goes like this: Write types and interfaces for the types and fill in the blanks. Sounds familiar? Because that's we've been doing with Java and the like using UML. Haskell barely benefits because it's a FP language but being a relatively unflexible language, it throws out all the things we've learnt as a software development community like focusing on loose dependencies and being constantly ready for change. Professional developers find themselves describing the system in such concrete ways using types that when the requirements change suddenly their precious castle is reduced to dust and they then have to restructure their types interaction again. This is the bad thing of top-down design. Bottom up design is something we've learnt collectively as a good way to be much more flexible in responding to change. Build simple parts, mix and match them to build complex parts.
Part of this has to do with Haskell's way of tricking people into thinking that more abstraction with higher level types is a good thing. There's two things wrong with this. One, types are a concretion. If you're looking for higher level of abstractions to get flexible behaviour, you're ultimately going to have a world of pain, because of two, abstractions ultimately leak, and when abstractions on abstractions on abstractions leak, it's not a pretty sight. Somehow Haskellers think that they are more productive with Haskell when the reality in the real world is that only a few languages can proudly make that claim, such as Python and Lisp. These are languages battle tested in actual software products that it is for a fact that people are simply more productive in it, not because they are easy, but they are simple.
Abstractions with types is a bad type of abstraction because it ignores the basic fact that programs deal with data, and data has no types. When you're reading this article, or talking to someone, do you claim that you're saying a string, a number, a Text, or something else? No! Data is simply data, and data is inherently dynamic. We add types to data to make it easier (not simpler!) to work with data. In most cases people are looking for schemas, not types. Types wrap data and treat it like a black box whereas schema describes the shape and content of data. As such haskell ultimately suffers a lot when they have to interact with the real world. Suddenly they are left reeling as they find out that the real world is, in fact, dynamic. And so you see people propose "boring haskell" where you basically write haskell like some functional C# program.
Three, Haskell doesn't suck because it does not have enough libraries, it sucks because working with other languages is a horrifying experience given that so many tricks are needed to make GHCJS. Look, even most haskellers would agree that purescript is a better choice compared to GHCJS. No man is an island, and yet Haskellers generally convinced themselves that other languages need to learn from Haskell, and not the other way around.
A very clear indication of this is how Haskell treats programming terms. Instead of explaining Monads like all other design patterns out there, they insist on using some obscure definition from category theory to explain it. Look, when monads are used without the infix notation, the result is horrendous and it looks like yet another callback chain. Functors are basically an Object with a internal state changing method in typical OOP terms. Haskell is not hard, the language itself is fairly easy to grok, but the terms people use are just plain ignorant of the other people in the software community. It is as if Haskell doesn't want "normal" people to understand it, and it lends towards a sort of elitist community where people claim they understand something when they don't. Don't believe me? Try asking people using Haskell about monads and watch as they gape as they give you a psuedo-explanation. I tried it myself. Of course, there are very smart people who do understand Monads, but most people would just tell you to "get an intuition for it", which to be honest is total BS.
Haskell would be better off if people stop thinking that it's a "beautifully designed" language and start critically examining how to improve core Haskell, in my honest opinion.
Top comments (1)
There are some valid points here, but a lot of this article reads like someone who either has never tried the language or has barely touched it. The claim that type signatures are documentation stems from all of the restrictions Haskell places on functions. It's unfair to group Haskell with every other statically typed language in terms of type signature expressiveness simply because there are very few other languages that give that guarantee. I can immediately identify side effects in a Haskell function just by looking at the return type whereas in C, C++, Java, C#, etc. I can make no such assumptions. Consider the strtok() function in C. There is no way to tell just by looking at the type signature that the function actually modifies data outside of its scope and thus might lead to improper usage. The equivalent Haskell function would have to reflect this behavior in the type signature.
I'm not quite sure what your definition of flexibility is, but many consider Haskell to be a very flexible language. It doesn't throw out all of the things we've learned in software development, and is actually very well suited for the examples you gave. The sbv library is a great example of a SMT Verification API that can easily switch out the solver being used in the backend. Refactoring is also much easier in Haskell than other languages, as the compiler points out every spot in the codebase that should be adjusted, whereas you'll play whack-a-mole at runtime in every dynamically-typed language, and might miss any interactions with mutable state even with a statically typed language. Haskell also doesn't particularly emphasize a top-down design, as combinators are a well and widely used technique. Megaparsec and other parsing libraries are great examples of this.
As you state in your article, too much abstraction is a bad thing, but the same could be said for every other language. In C you can abstract everything to void pointers, In Java you can create a nasty hierarchy of abstract classes, etc. Haskell tries to provide abstraction tools in a way that try to minimize the mess with typeclasses and parametric polymorphism. You highlight the difficulty of dynamic data, but you don't highlight the reason it is so difficult: Safety. Haskell makes a big effort to prioritize safety in the language, which means that you have to handle more edge cases. I can easily load any arbitrary JSON file into python or JavaScript, but I have no guarantees over what is even in the JSON file unless I manually check it myself -- which as can be seen in numerous applications is very easy to get wrong.
You also claim it is very difficult to work with other languages in Haskell and only give JavaScript as an example, but fail to mention the entire FFI dedicated to working with other languages. I myself don't use GHCJS, as I don't do much web dev, but would probably use a different language because there are other languages that do frontend better. There is no "one true language" that makes it easy to do everything.
Monads are both difficult to grasp and difficult to teach to others because of their abstract nature. The same goes for Applicative and Functor. Almost every language has a concept that is difficult to understand for the first time. For C/C++ it's pointers, for Rust it's the borrow checker, and for Haskell it's Monads. It is quite an alien concept, but there are several helpful sources on the internet that explain both their construction and how to use them without technical terms. Graham Hutton has a series of videos on YouTube which excellently explains the three Functor, Applicative, and Monad typeclasses.
It is definitely a difficult language to learn and the learning-curve doesn't help its popularity, but that doesn't make it a bad language. Haskell is battle-tested and in use by Google, Facebook, NASA, and even more companies because of the features it offers. It may not suit your particular needs and that's okay, but it doesn't make it a bad language.