Why I (as of June 22 2019) think Haskell is the best general purpose language (as of June 22 2019)

Me and my close friends have been interested in starting a project together and I suggested we use Haskell. I do not think the suggestion was received well or perhaps in seriousness. I have a tendency to joke about almost everything and have put forward that we use many interesting but not practical languages in the same tone that I suggest Haskell. This was a tactical mistake. I find myself in despair at the idea I can’t convince my personal friends, who are curious and intellectual people, to use Haskell on a fresh start web project we have complete control over. What hope do I have in the world at large? This brain dump post is meant for them. My suggestion to use Haskell is not just me being an asshole, although that does make it more fun for me. I will now try to explain in all seriousness and in all the honesty that I can muster what my opinions on languages are and why I have them.

Pragmatically can you start a new project using a language you don’t know? This is a problem. A project always has some intrinsic difficulty. Not all projects will survive an extra layer of unnecessary speedbump. But when and how are you supposed to learn new languages? Never is one answer. I disagree with this answer. In this case we have the leg up that I do know Haskell. Perhaps this is a downside in that it will be extra frustrating? It is also easy for me to ask, as using Haskell is not a burden for me, I have already sunk the cost, but a massive learning burden for others.

Is Haskell actually practical for a web application? Short answer: yes. Expect pain though. If your web application is so simple you could rip it out in 100 lines of python, this is such a simple project that it is a good opportunity to learn something new. If it will become large and complex, then I believe Haskell does shine, keeping complexity under control. I base this upon the professional experience making a web application using a Haskell-Purescript stack. For honesty, it wasn’t all good. I recall ripping my hair out threading shit through monad stacks to where it need to go. Yet on the whole, it kept the project sane. I also believe this based on the word of mouth that I believe but could be just cultish ramblings.

I believe that truly dominating properties of Haskell appear in large complex projects. This is difficult to prove in any other way except empirically and the experiments will be so wildly uncontrolled in terms of the project and people involved that no conclusions can truly be drawn. And yet I have faith, and think that personal experience validates this opinion to myself at least. We have to live this life even though truth does not exist. Choices and opinions must be made.

For programs that are going to be a single manageable file and written in one night, it doesn’t matter much what you use in terms of being choked on your own code. At this scale, I still think Haskell is enjoyable and interesting though. Haskell was my doorway into the world of computer science as I now understand it. I hope there are more doorways.

Things about me that may be different from you. Decide for yourself if these aspects of me make our opinions fundamentally incompatible.

  • I do have a talent and a like for practically oriented mathematical topics (computational methods, linear algebra, formal methods, calculus, geometric algebra, projective geometry, optimization, etc.). I actually have very little taste at all for mathematical topics that I see no purpose to.
  • I do have some desire and taste for esoterica for its own purpose. I cannot exactly characterize what makes some topics acceptable to me and others not.
  • A hard learning curve is not necessarily a downside for me. I enjoy the challenge if it is overcomable and worth it on the other side.
  • I like weird and different. That is a positive for me, but a negative for many. I might just be a millennial hipster idiot.
  • I would LOVE to find a language I think is better than Haskell. I would LOVE to abandon Haskell. Perhaps this already makes me odd. Perhaps I think many people don’t consider the differences between languages to be worth making the switch and the wasted knowledge. The people with this opinion may or may not have tried enough languages.
  • I have “drank the koolaid”. I do read what comes out of the Haskell and functional programming community and have a tendency to believe things without strong empirical backing.
  • I have been more deeply entwined with Haskell than any other language. Perhaps if I had reached a level of familiarity in another language I’d be as fervent about that one? I don’t believe this is the case.
  • While I desire performance, I consciously curb this desire. I am strongly in favor of cleanly written, clear, principled code. This is of course a weighted judgement. I will probably use a 100x performance gain for a 2x decrease in clarity or reusability. This is a result of the problem domains and scale that have interested me in the past and that I anticipate in the future. I STRONGLY believe the world at large over values performance at the expense of other good qualities of code. Or at least over optimizes early.

A Biased List of Pros and Cons

What do I find bad about C++.

  • The feature set is huge and difficult to understand
  • Extreme amounts of legacy features that will be even recommended if you read legacy documentation. Kitchen sink.
  • The language appears to be almost entirely built out of footguns.
  • The syntax is too verbose.
  • I have a distaste for mutation.
  • I have a distaste for object oriented programming

What do I find good about C++

  • It is commonly used. Large community.
  • It is possible for it to be very fast
  • Kitchen Sink. You can find almost any feature you want here.
  • The high level goals of the mind-leaders sound good.
  • Very interesting projects are written in C++. HPC things. Scientific computation.
  • Template metaprogramming seems very powerful, but arcane.

What I find bad about Java

  • The syntax puts me off as being incredibly verbose
  • Extreme object oriented focus
  • Corporate/Enterprise feel. I am an iconoclast and see myself as a reasonable but slightly rebellious character. Java in my mind brings images of cubicles and white walls. Perhaps this is not fair.

What do I find good about Java

  • ?

I’m joking. Sorry Java. But I also kind of mean it. Yes, there are positive aspects to Java.

What I like about python

  • Very commonly used and understood. Perhaps the lingua franca
  • Incredible library ecosystem
  • Numpy and scipy in particular are marvels of the modern age.
  • Syntax is basically imperative pseudo-code
  • I am personally very familiar with it
  • python is the easiest to use language I know.

What I dislike about python

  • Python has no natural tendency for correctness due to the free wheeling dynamically typed character. This is patched up with testing, opt-in type systems.
  • I don’t know how to grow as a pythonista. The skill curve flattens out. For some this may be a positive.
  • The main way of building new data types is the class system. I think this is ungainly, overly verbose, and not always a good conceptual fit.
  • Despite being among the most succinct of common imperative languages, I still think it ends up being too verbose.
  • It is slow. This is a negative, although not high on my priorities.

What is bad about Haskell

  • Very difficult learning curve. Let’s get real. Haskell is a very confusing programming language to get started in for common programming tasks.
  • functional programming is weirder than imperative programming.
  • The monad paradigm, even once learned is ungainly. Tracking multiple effects is a pain that does not exist in most languages.
  • The pain is up front. It is easy to get a sketch of what you want ripped out in python faster than in Haskell (for me). If you want a web server, command line tool, optimization problem, curve fitter, I can rip all of these out faster in python than I can in Haskell. As a psychological thing, this feels awful. For a small scale project, unless toying with Haskell itself or one of its domain expertises like implementing DSLs, python is the easier and correct choice. Python is a scripting language. I’d make the switch at two screens worth of code.
  • I think laziness is confusing and easy to shoot yourself with.
  • Haskell is not the fastest language, although faster than python.
  • Concern for there not being jobs and interestingly on the converse side, no people to hire. There is a catch-22 there. There is a set of people that would KILL for a Haskell job.
  • There are vocal smug assholes who use Haskell and push it. I am smug, I hope only mildly an asshole.

What I find good about Haskell

  • The number one reason is that there is something ephemeral that I just like. I am not naturally inclined to analyze such things. When I like a movie or don’t like it, it just happens, and if forced to explain why, I’ll bullshit.
  • Errors and bugs are to a shocking degree caught at compile time. More than any other language I have experience with does Haskell code run correctly without hidden bugs if it compiles. I am not claiming this is absolute but it is all the more incredible the degree to which it is true since it didn’t literally have to be this way. I have done major rewiring of a data structure in a project. The compiler guided my hand to exactly the positions that needed to be adjusted. Could C++ do this? Yes, to some degree. I believe that the tendencies of C++ programming make it less satisfactory on this point.
  • Types are an incredible design tool. I find designing the types of my program to be an extremely enjoyable and helpful activity. Much more so than box and wire class and interface diagrams. A good function name and a type signature basically entirely constrains the behavior of a function. Types can be quickly and completely be given to the compiler and machine enforced.
  • The pain that Monads cause are pains you should be feeling. They are the pain of explicitness which I 70% choose over the pain of not knowing what the fuck a function might do, and not enabling the compiler to enforce that. If something is capable of mutating state, it should say so in goddamn huge purple letters.
  • Haskell is more than fast enough. It isn’t that even people don’t care. The Haskell community at large cares a lot more for performance than I do, and I reap the dividends. The people in charge of the compiler and the main libraries are goddamn wizards who’s work I get to benefit from. This is true of all languages perhaps.
  • Laziness is very cool. At the beginning I thought it was INCREDIBLY awesome and inconceivable that I could manipulate an infinite list.
  • The way of specifying new data types is so succinct and so incredible. Pattern matching is SO GODDAMN good for some tasks.
  • Haskell has a paradigm of small combinators. It is common to build a sequence of very small natural functions for the domain and then build larger and larger things out of them. This is good for reusability and conceptual clearness.
  • Extreme preference for Immutability. As part of keeping what you must keep in your head or remember small while programming, immutability is an insane win. You think you know what you want now. You know you could just tweak this variable here, make a special variable over here. You can reason about how to make this all work and be correct now. You will not in a month. Your coworkers will mess it all up too.
  • Haskell code is generic by default. This allows the same code to be reused in many situations
  • The standard typeclass hierarchy is extremely well thought out and powerful. To some degree it is unnecessary in other languages. The difference between Functor, Applicative, Monad, and Traversable makes little sense in languages with unconstrained mutations and effects.
  • Haskell paradigms are inspired by mathematics, and I have great faith in mathematics. The concepts behind Haskell feel closer to discoveries rather than inventions. Imperative programming speaks in a language formed for the accidental nature of the machines we have. Functional programming is a language closer to mathematics, which I believe is closer to how the human mind works, and closer to what the problem at hand actually is.
  • Complexity scales. It is my belief, perhaps unverified, that as a project grows larger, the insane miserable churn and mental overhead grows slower in a Haskell project than in other languages. I do not have strong empirical evidence to this assertion. Word of mouth (of Haskellers).
  • The ceiling on Haskell is extremely high. You can continue to learn and get better, gaining more and more power. I do not currently see the end of this.
  • When I do reach for some new library, I am very often impressed by how thoughtfully built it is. Haskell itself is INCREDIBLY thoughtfully built.
  • The haskell community is very excited and they have many things to teach. There are many Haskellers out there who are very welcoming, kind, and intelligent.
  • Haskell does have some cache. I am not immune to wanting to seem smart. If the world thought that only idiots use Haskell, that would offput me some. That the world things that only impractical ivory tower smug weenies use Haskell does offput me, although I perhaps embrace it belligerently.
  • The Haskell library ecosystem is strong. Less strong than python, but much better than some of the other languages that intrigue my eye. There is functionality somewhere for most common tasks.
  • Haskell is used industrially. I live in an echo chamber, but by and large the industrial users of Haskell sing its praises.

For context, this is my programming journey:

I first learned BASIC in middle school. I wrote a computer game in Visual Basic. I toyed with the TI-83. I went to a summer camp in high school where I learned the extreme rudiments of C++. Did a small web business with some friends. Did really bad work with big dreams. I took a fairly poor Java course in high school. I learned MATLAB in college. I doinked around with Arduino level C projects. I learned python in grad school I think. I think I got far more proficient at python than any other language before. At this point, I was on board for object oriented programming, albeit not at a deep level (design patterns or ilk), just as light organizational principle. Did some Android projects, really didn’t like Java there. Did a small business with my friend and got deep in Javascript. As our web application got bigger, this really start to hurt. Errors all over the place. Unknown junk in objects. Who has access to what? We tried our darndest to read and follow best practices as we could find them, but it felt like we sinking in quicksand. More and more effort for more and more bugs and less and less progress. It was around this era that I first even heard of Haskell. I was intrigued immediately for some reason, maybe for just how weird it was. It took probably 2 years of forgetting about it and going back to tutorials every 6 months. I didn’t necessarily KNOW that this was a thing that I wanted, I just found it interesting. Currently I am fairly proficient at some things in Haskell (unfortunately I am more proficient at esoterica than more practical things). I have had a professional job writing Haskell, and it seems like my like of Haskell is working out very well for me professionally. Passion in all forms is powerful.

My history may not be as convincing as someone who spent 20 years as a professional C++ dev and then switched, but I have at least experienced different paradigms and languages and found Haskell the most to my liking.

Random Thoughts

I am now trying to push myself into comfort in Julia, Rust, Agda, Coq, OCaml, all languages I feel show promise for different reasons. To my knowledge Haskell is a better choice than these as a general purpose tool for pragmatic reasons. Haskell’s library ecosystem is strong and performance is good. These are points against agda and coq. Julia has a focus on scientific programming.

Rust might be a good compromise. I consider it a trojan horse for useful programming language features that I associate with functional languages. It claims to performance and being an acceptable systems level language, which appeals to some. The syntax does not scare anyone off. The library ecosystem seems good and the community strong. I did find myself missing Haskell features in Rust though, am personally much less familiar with it. I think the design of Rust weights more to performance than is warranted in most applications and has less descriptive and abstraction power than Haskell, qualities that I prioritize. This opinion is not strongly held.

What makes Haskells types any better or worse than C? At the beginning many of the features of Haskell seem like magic. But as time has worn on, I can see how the features can be emulated with just some slight syntactic and conceptual overhead in other languages. This slight overhead is enough though. A language is more than just it’s syntax. It is also its idioms. It is also they way it makes people think. Language is almost a prerequisite for thought. You cannot even conceive of the ways there are to express yourself before learning.

What exactly makes a language “good”? This is a question poorly phrased enough to have no answer. Excel can be an excellent language for many tasks. Easy to learn. Very powerful. Yet, it is not considered a good general purpose programming language. Library ecosystem is extremely important. Specialized languages are often the best choice for special problem domains, at the expense of learning them, or eventually finding incompatibility of what you want from what they designed for.

What makes abstractions “good”. Why do I have queasiness about object oriented-programmming. Java, I think basically. I, overeagerly have gone down the road of trying to design deep subclass hierarchies, which is not OO at it’s best. Zebra is a Quadruped is an Animal is Alive kind of stuff. I believe object oriented in an interesting principle. I hear about SmallTalk and Common Lisp doing object oriented right and I am duly intrigued. There has been some recent work in Haskell about how to do objects in a way aesthetically compatible with Haskell. I think object oriented has been over used and abused. I think it is a poor conceptual fit for many situations. I think it tends to make non reusable code. I think the form that it takes in C++ and Java development is arcane horseshit.

I deserve almost no opinion about Java or C++, having not done sufficient that much in them. Yet, I must state my opinions, take them as you will, for I do in fact hold them strongly. I have worked on a network simulator and a robotics framework in C++, but begrudgingly. I have done a very small amount of Java development for a personal project and some Processing sketches. My coworker was a 10 year professional Java dev before switching to Scala then Haskell. He despises Java now. Highly anecdotal, and he is a similar iconoclastic character like me. Nevertheless, this also informs my opinion. I have been reading Bjarne Stroustrup’s book (his stated goals and what he claims C++ achieves are admirable and one can’t argue he hasn’t changed the world) and actually find C++ rather interesting, especially in the sense that many projects that I find interesting are written in C++, I just don’t want to myself work in the language.

Haskell love:

Haskell Criticism (perhaps warranted)

https://news.ycombinator.com/item?id=17114308 Ah Hacker News. Always a sunny worldview.


Hacker news discussion of this post:


16 thoughts on “Why I (as of June 22 2019) think Haskell is the best general purpose language (as of June 22 2019)”

    1. I very much like Purescript. Last I was checking, using purescript on the backend would be a touch unusual, but possible if that’s what you’re into. Purescript has the most joyful FFI I’ve ever experienced. I do suggest purescript for frontend work. I have not tried ghc-js. I have barely tried Elm, which I think at this point may not have the feature set to make me happy, but might be a much more acceptable place to on board people.

  1. I think someone like you might like Scala because of the familiarity with functional programming, but with a huge ecosystem and decently sized community. Also Clojure might be worth checking (functional, immutability-first, friendly community, same huge ecosystem of Clojure and Java libraries).

    1. Thanks for the suggestions!
      Scala and Clojure do seem worthy of exploration. I’ve given them a small shot a couple of times. I am not eager to enter the Java ecosystem given the choice, despite how well developed it is. This is not really a technical opinion, it is pure bias. If however, I had to go to a platform that uses the JVM, I would almost certainly pick Scala.

      Scala scares the shit out of me. It seems like perhaps the most complex language on the planet, truly embracing the abstraction complexity of functional programming and object oriented programming and imperative programming. My coworker mentioned above does not speak well of it compared to Haskell. Anecdotally, due to the bubble that I live in, I hear scala people pine for Haskell. I think due to it’s tie ins to the Java ecosystem, more compromises had to be made on the functional programming front.

      Lisps in general interest me. It is a very natural language. The top lisp on my list is Common Lisp. I want to see if the legends spoken by the grey beards are true.

      1. I also think that you’d like Scala, since you seem to lament that writing Haskell is less productive than writing Python for fast prototyping or scripting. You can basically write Python-style in Scala, but with static types, good performances, and pattern matching!

        Nowadays Scala has excellent IDE/editor support with the metals language server and IntelliJ, which should make it less scary. In particular, the later now help you visualize implicits, which is a game changer for learning and understanding them.
        Installing the tools required for Scala is generally as simple as downloading a JDK and SBT, the Scala Build Tool, which will do all version management for you in a sane and reproducible way, per project (no global state). You can clone almost any Scala project on github, run `sbt console` and start hacking right away.

        1. Another proponent for Scala! This is definitely bumping Scala up in my give another shot list.
          My inability to whip out things as fast in Haskell as I do in python may in fact be a function of my lesser experience in Haskell, and that I reach for python for those kinds of tasks. I had been programming python for quite a whiles before I had even heard of Haskell.
          I am not entirely on board for IDEs. Currently I’m a vscode boy (which is debatably an IDE at this point). I might be insane on that point, or have just have gotten used to working without them, or don’t know what I’m missing. I don’t use one for other languages either. I find them rather disorienting.

          1. Scala metals works great in VS Code! Just have a look at the demos: https://scalameta.org/metals/

            Of course, you’d be more productive in Haskell if you were just as familiar with it as you are with Python. But I’d argue that Haskell is “asymptotically” harder to prototype with, regardless of expertise.
            This is mostly because Haskell forces you to write things in the Rigth Way from the outset. But while prototyping, you don’t care that much about the Right Way since you’re likely to scrap and rewrite the code N times before it finally stabilizes anyways.
            A concrete example: in Scala, if I have an algorithm that maps some function over a list, and I later realize that I’d also like to accumulate some additional info while traversing the list – I can just use a side channel and mutate some local ListBuffer to implement that. The point is that the state is completely local and hidden; the interface of the function is still pure. So it’s likely not going to cause problems. Sure it’s not the best way to write the code, but it does it job well, and with minimal friction. In Haskell, I would have to reorganize the algorithm itself just to achieve the same result (of course, it’s easy in this trivial example, but it becomes harder as the algorithm becomes more complicated).

        2. I’d argue that he wouldn’t like Scala, as someone who went from it to Haskell, you’re gonna have a bad time.

          Unless you _really_ want to do something in an object oriented way the type system is terrible compared to Haskell. Countless times I’ve fallen between the gaps and just had to fiddle around with the code just to make the compiler happy.

          SBT is way inferior to modern cabal (or stack if that’s your thing), just look at the project definition for any sizable Scala project and see the nightmarish hacks which are all pretty much custom for each project.

  2. I value myself as an average developer, not the smartest, but honest, like testing unusual approaches, at least just for the mental challenge. I liked many aspects when learning haskell, having used non-pure functional languages in the past (scheme and caml), its typing and its lazyness, among others.
    However, anyway I tried, any tutorial I read, whatever approach I tried, monads were a real blocker. It was like trying to spring something that couldn’t fit into my brain. I tried hard and struggled, I really wanted to like it. In the end I promised myself not to try haskell ever again, feeling it’s a waste of time for people dumb like me, who can’t grasp monads.

    1. I’m sorry to hear that. I too have had my challenge with the inevitable monad problems, but I don’t think I ever got to the point where I felt fundamentally bad about myself for not understanding, and I hope you don’t continue to feel that way. That you gave Haskell a fair shake is more than enough for me. Maybe it really isn’t a good fit for you.

      The monad stuff is largely confusing and difficult and unergonomic. A necessary evil in my opinion to achieve purity (a worthy goal) while still interfacing with the outside world. Once you’re familiar enough with the pattern, and you can use them without really thinking too hard, at that point they can turn into a useful convenience. It’s like a playing a violin or something. I would never say playing the violin is easy for anyone, but it does eventually flow. I think the ability to understand Haskell concepts really does grow with time. I can learn new Haskell things now that I would have struggled for hours to understand, if at all, in the beginning.

      In my mind, strange as this may sound, the monad is not a significant fraction of what I think of as Haskell. A monad to me is a programming pattern to guarantee that pipework is always applied between functions. You always want to check for nulls, check for errors, log everything that is happening, or thread state. The pattern makes it so the type system will make your program fail to compile if you don’t do any of these things, which is better than having the null unchecked or an error uncaught at runtime. I strongly recommend spending some time thinking about the Maybe type (called Option in many languages) if you’re ever up for another go at the idea, in Haskell or otherwise.

  3. Hi Philip,

    One thing which helped us was to use simple “record of functions” to structure our applications instead of typeclasses (cf. https://jaspervdj.be/posts/2018-03-08-handle-pattern.html for the original idea). I have also created a library to do the “wiring” for you and replace any dependency for testing: https://github.com/etorreborre/registry.

    I think that overall this removes a big difficulty for newcomers at the expense of a bit more boilerplate to pass parameters around instead of using constraints.

    1. Oh ho, baby! Thank you very much! This is my among my top reasons for writing blog posts, that someone will teach me something.

      I’ve been investigating what is a good way to structure apps and come off pretty confused. Some of the main suggestions are the ReaderT pattern https://www.fpcomplete.com/blog/2017/06/readert-design-pattern and some associated FPComplete ecosystem and the “three layer cake” https://www.parsonsmatt.org/2018/03/22/three_layer_haskell_cake.html

      Similarly I was investigating alternate preludes, all with the intent of trying to make the introduction to Haskell smooth. I really don’t want to run into weird walls or hangups while guiding beginners and skeptics.

      The situation from perusing the internet is so unclear, fractured, and opinionated that I have no way of knowing which is good without trying them all. So if anyone wants to shoutout, I’d appreciate it.

      1. That’s why I am proposing yet another alternative :-). If you try it out and face any issue don’t hesitate to ask me.

  4. Funny to me for reasons far to long to explain given I have a couple decades on you with very different histories. I think I was one of the only two people in my CompSci classes that actually “got” LISP. It melted my 18 year old brain, especially given the age of it. Four decades later… I still have no idea why anything but LISP has ever been used for just about anything. In my own personal career journey I never even got close to using LISP even though I had many opportunities to make that decision (as I was a development executive implementing projects with armies of developers)

    In many ways I implemented many functional concepts (as well as a lot of other things) no matter what the implementation environment had to be or the particular skillset base the resource pool had. Of course I always used LISP for my own one-off use, I used it to describe things to teams of software architects, I used it to solve meta problems of the project itself.

    Bottom line. You would LOVE LISP. I like Haskell for all of the reasons I love LISP. Beware of CL though (IE your comments re OO = CLOS), it’s certainly real LISP but it’s after a committee got it’s hands on LISP . Translation = kitchen sink. Of course most of that is not only optional but actually implemented in LISP itself (CLOS = just lisp implementing “objects”). You might feel a little uneasy with a few basic things at first when coming from Haskell (types, mutability if you desire, lexical AND dynamic scoping and binding) but you will also recognize and understand where a lot of thinking with haskell comes from and when the light bulb goes off I think you will enjoy each equally as I do but LISP is my first love and very different than anything else – pay very close attention to reader, compile/eval, runtime that many of the better tutorial/books will focus on very early. It may seem to be kind of ridiculous that so much focus at the very beginning is on REPL as you’ll kind of think “big deal everything has a read eval print capability now — so what”. Put that thought away and be open minded as it’s one of the very basic keys to “getting LISP” and one of the properties that is so far different than other languages. Until that light bulb goes off simple examples will give you the impression that all languages can do that… reason = you will not “get it”.

    1. Thank you for the comment! It’s really interesting.
      It sounds like you were making decisions at a fairly high level in the hierarchy. Why didn’t you push for what you felt was a superior choice? I am seeking sound explanations for why the world is the way it is, technical, economic, or social.
      I have been poking around in lisp. My most recent stab was at common lisp. I keep bouncing off it though (as I did with Haskell for the first couple times) not necessarily seeing where the magic comes in. Haskell had the benefit that I associated functional programming in general with it, a concept that it of course does not solely own. I do get the feeling that lisp macros will be a bountiful play field. That the lisp syntax is an AST makes it a perfect Pareto point in the space of programming languages and opens up many possibilities. I fully am ready to believe that lisps are languages ripe with power.

Leave a Reply

Your email address will not be published. Required fields are marked *