1. 34
  1.  

  2. 20

    I’m a bit confused by the conclusion of this article.

    At this point I think it is actually pretty stable. I consider the project a big success.

    A huge part of this has been due to Haskell and its excellent ecosystem

    But throughout the article, you see the failings of the haskell ecosystem: no IDE, poor refactoring tools, ridiculously slow compile times, a poor standard library, and unmaintained libraries. What exactly is the “excellent ecosystem” here? It sounds like this project succeeded despite haskell being the main language.

    Personally I think it’s fine to use whatever you want, but this article reeks of a rose-colored reimagining of what haskell is because the author enjoys coding in haskell. Haskell isn’t typically used in production systems for projects like this and this seems to be another anecdote as to why it isn’t production-ready rather than a success story.

    1. 18

      Haskell is in kind of an odd place, there are some things that the author calls out that are problems (and thankfully the community has been taking great strides recently in starting to address a lot of them) but for a lot of people the benefits outweigh the problems. The challenge of course is that a lot of the things that are great about haskell don’t exist in other languages at all, and that makes it particularly hard to tell a compelling story about it. “Everyone” knows you need an IDE to be successful in writing code, but nobody misses tooling like hoogle, because just doesn’t exist outside of the haskell ecosystem. “Everyone” knows that build times are important, but haskell is one of the few communities that have really embraced nix (although that’s not a haskell specific tool) to widely use it for getting distributed caching, builds, and reproducibility.

      I don’t claim haskell is the best language, or that it’s right for everyone, but there are good reasons to use it in production. The particular strengths and weakness of haskell mean you’re paying quite different costs than you would with some other more mainstream languages, but for a lot of people that really is worth it, and I don’t think it’s just for the rose colored glasses.

      1. 10

        It was hard to include everything I wanted to say as it is already quite long. I’m trying to offer an evaluation of using Haskell in prod. As such I am making sure to point out all the pain points, but I also point out some really strong areas.

        I guess what I don’t spell out is that Haskell the language (and many of the libraries) are what I would describe as ‘best in class’. You write less code, that is simpler (once you learn Haskell) and has much less scope for bugs to creep in, compared to popular programming languages. Despite the warts in Haskell + ecosystem, it is stellar. And my conclusion is that it works well in prod too.

        1. 5

          Thanks a lot for this article! That’s exactly why I found it so interesting, a really practical and nonobvious list of pros & cons. It’s not often that I see articles like this. If you disregard the flamewar, the article got quite many upvotes, which means a lot of people found it interesting too :)

          1. 2

            Thanks!

      2. 15

        Haskell is awesome, but like most languages there is cruft and legacy to be avoided. Haskell has a standard library known as base which unfortunately has a fair amount of unsafe or unperformant functions included. As such I went with an alternative standard library relude that builds on and improves base. On top of this, there are many core libraries that are not part of the standard library I wanted to use and have nice patterns around.

        Maybe I’m spoiled working in the .NET ecosystem, but large amounts of the standard library being unusable shouldn’t be considered par for the course when working with a language. This reminds me of PHP.

        Parsing Libraries […] Why is this nice in Haskell? The ‘monad’ abstraction is excellent for dealing with code with a lot of failure conditions (ie. parsing) and avoids ‘pyramid of doom’ type code. Haskell worked out really well in this key area.

        The author doesn’t really explain how monads help with parsing, but I’ve written parsing logic in C# that didn’t result in a “pyramid of doom”. I don’t think the pyramid of doom is a language issue, but an architecture issue.

        Compile Times.. Were Fine

        I thought I’d call this out as it is a common complaint I see around Haskell. […] Compile dependencies from scratch Time: 17m44s

        A 17 minute compile time is considered fine? Even the 1 minute development build time seems slow for such a small project.

        Between the compile time, the library issues, and the issues with the official standard library, I don’t understand how the author can claim that Haskell and it’s ecosystem is production-ready. Production-ready isn’t a term that means someone, somewhere, has used it in production. Also it’s important to understand that not only the language and runtime need to be ready for production use, but also the ecosystem. Without all three being stable, other languages become the wiser and more logical choice.

        I like Haskell. I’ve built several hobby projects in it. I think it’s a great language to learn to extend your development skills and think about problems in different ways. But never would I consider pushing it to be used in most production applications as it stands right now. For most companies, using it right now would be a mistake.

        Five years ago, when I first started working in it, I had hoped the language and ecosystem would mature to a point where it could be recommended for most serious projects, but seeing the lack of progress since then I’ve since set my sights on other functional languages like F#.

        1. 11

          Maybe I’m spoiled working in the .NET ecosystem, but large amounts of the standard library being unusable shouldn’t be considered par for the course when working with a language.

          The .NET standard library also has the same kind of unsafe and unperformant functions the author is talking about, the type of runtime safety he’s talking about just isn’t really a focus when working with .NET. He’s referring to functions like head which throw an exception if passed an empty list instead of returning a Maybe a, and I think we can agree that there are plenty of .NET functions that throw exceptions on invalid input.

          The author doesn’t really explain how monads help with parsing, but I’ve written parsing logic in C# that didn’t result in a “pyramid of doom”. I don’t think the pyramid of doom is a language issue, but an architecture issue.

          I agree that the author greatly exaggerated how parsing code in non-functional languages usually turns out, but if you haven’t written a parser in Haskell or using something like FParsec in F#, it really is worth it to see how nice a more functional parser library is to work with. Definitely one of the places Haskell shines.

          A 17 minute compile time is considered fine? Even the 1 minute development build time seems slow for such a small project.

          Agreed, Haskell build times are bad. Hopefully they’ll get there someday.

          1. 3

            The .NET standard library also has the same kind of unsafe and unperformant functions the author is talking about, the type of runtime safety he’s talking about just isn’t really a focus when working with .NET. He’s referring to functions like head which throw an exception if passed an empty list instead of returning a Maybe a, and I think we can agree that there are plenty of .NET functions that throw exceptions on invalid input.

            Right, but even the community explicitly mentions not using base in Haskell. With .NET that is not the case. It’s an important distinction; the community expects the .NET stdlib to be “first class” in .NET development, the Haskell community does not have the same expectation with base.

            1. 3

              Right, but even the community explicitly mentions not using base in Haskell.

              Maybe? Basically all Haskell code is still written targeting base. People have feelings about things like head and maximum and foldl, but in practise it’s at most a “maybe avoid those” tip from people with those feelings.

              1. 3

                Right but that adds a barrier to entry for new folks. There are good reasons not to use Prelude (and OP’s article brings up some of these good reasons imo), but if I were a new programmer learning Haskell, it would be get another thing I need to learn and understand. Why should I use an alternate Prelude? When? Which Prelude is better than others? Haskell has long prioritized progress and innovation over production stability which I think is a very reasonable for a language like Haskell but isn’t always the best fit for being productive.

                Edit: FWIW I think developing in Haskell is great (oh and thanks so much for working on JMP @singpolyma!). I’m just trying to say I’d love to see these barbs in the ecosystem fixed a bit. Good on the Haskell Foundation for pushing this forward, and I’d love to see more production-oriented advice (and reports, like the OPs) with Haskell.

          2. 5

            The author doesn’t really explain how monads help with parsing,

            That’s true,

            but I’ve written parsing logic in C# that didn’t result in a “pyramid of doom”

            But it’s worth reading up on the monadic parsing approach before declaring an opinion on the matter. The search term you want is “parser combinators”. It really is a fantastic approach.

            1. 2

              For what it’s worth I wasn’t really declaring an opinion, I was just saying that if they only thing you’re attempting to avoid is a pyramid of doom, there are ways to do that in other languages. I haven’t looked at Haskell parsing logic but it sounds like there are some interesting advantages it offers.

              1. 1

                There a various ways in other languages to avoid the ‘pyramid of doom’, but they are much more situational. For example, ruby has &. for null safe access ie. person&.pet&.num_legs which avoids the pyramid. However, they are very specific and break down quite easily.

                Say, you want person&.pet(if pet_type == 'cat')&.is_purring which you want to return null if any of these objects are null (or the pet is not a cat), or true/false if they are not null and the pet is cat. Probably you can do something like this in ruby, but Haskell via ‘monad’ (and friends) has highly generic and composable techniques like this that are very clean to use.

                I’m glossing over ‘monad’, it is not complex, but you need to learn the prerequisites before it makes sense. Actually I thought https://www.youtube.com/watch?v=J1jYlPtkrqQ was pretty good as a shotgun explanation if you are somewhat familiar with ruby.

                1. 2

                  person&.pet(if pet_type == 'cat')&.is_purring

                  This looks more like a place where I’d use a prism, in Haskell with lens I imagine it’d be person ^? pet . asCat . isPurring :: Maybe (). I’d like to know how this is a parsing issue, it looks more like a object traversal problem.

                  1. 1

                    Yes not a parsing problem. Just trying to explain how Haskell avoids the pyramid of doom problem in a general way that is very flexible. Whereas other languages solutions are very specific and situational.

            2. 3

              What progress were you hoping for but didn’t see? The Haskell Foundation was created to work on ways to improve the Haskell ecosystem and I’m always looking for more improvement ideas myself.

              1. 2

                It’s worth stressing that that 17m compile time is a one off cost. GHC is of course an incremental compiler, so you only pay for the graph of modules affected by a change when developing which is significantly quicker, on the of seconds, not minutes.

                1. 1

                  I don’t think the pyramid of doom is a language issue, but an architecture issue.

                  I haven’t seen it come up in the context of parsing but instead in chaining together asynchronous operations in languages that lack coroutines, so it’s most common in JS where nearly all IO is forced to be async. In C# you can just do normal IO so it’s not surprising it doesn’t come up. (or maybe because C# has coroutines? honestly not that familiar with it)

                2. 7

                  r/haskell discussion on this post.

                  1. 3

                    This is a great article and a great way to draw attention to your product. Do you think using servant was a mistake?

                    1. 2

                      Thanks! No, actually servant worked great once I figured out how to use it. My servant logic is very simple though. Also https://hackage.haskell.org/package/servant-github-webhook was great for handling and authenticating the requests from github.

                      1. 1

                        There is a meme that fancy types are the downfall of practical oriented haskell projects, because of the added complexity or getting too far out on the bleeding edge. My understanding is that servant definitely pushes in the direction of fancy types and that is why I was asking. I’m glad that wasn’t the case.