63 ms·
Leaving Haskell behind
- nicechianti 3y ago[dead]
- rvz 3y ago[flagged]
- andrewstuart 3y agoTLDR: the Haskell programmer who gives a shit has stopped giving a shit. * http://steve-yegge.blogspot.com/2010/12/haskell-researchers-announce-discovery.html?m=1 http://steve-yegge.blogspot.com/2010/12/haskell-researchers-...
- m1keil 3y agothank you for that xD
- hackandthink 3y agoSeth Briars could be me. really funny, thanks
- neuromanser 3y agoMy two decades of professional programming suggest that it's way easier to find a $fringe-lang programmer who stopped giving a shit than a mainstream programmer who's ever given one. "The worldwide programming community met up over beers today to celebrate their unprecedented discovery of an industry programmer who gives a shit." I'm a huge Yegge Stan btw, his post is funny AF (as always), don't read this as a knockdown! Edit: tweaks, grammar, autocomplete fails.
- hardwaresofton 3y agoSite got HN hugged (probably): https://web.archive.org/web/20230824095246/https://journal.infinitenegativeutility.com/leaving-haskell-behind https://web.archive.org/web/20230824095246/https://journal.i...
- Pannoniae 3y agoBasically, the author's criticism is that the language is too powerful, too expressive, people try very abstract things, tooling is bad and no one cares about the language. There is something sinister in this - first, in the author's lamentations about bad tooling. Other languages require linters, formatters, static analysers, etc. because the language's built-in features and type system are sub-par. In Haskell, that's not true, so the lack of "sophisticated" tooling is way less painful. Second, this is similar to the "equalise things by dragging everyone down to the same level"-type of thinking. It "makes maintenance a chore" because the language allows you to be creative and shoot yourself in the foot! Sure, you can have languages like Go where the language is simple and it's hard to write "unreadable" code, but that comes at a cost of being very verbose, and not allowing for an opportunity to write really good code. Basically, enforced mediocrity. "Hard to maintain" is also used as an euphemism for "this is too complex and I can't be bothered to try to understand it" sadly. I find that quite ironic in the face of all the needless complexity in the software industry (just look at k8s, terraform plugins or the web development stack)... I know way too many programmers like that, who argue endlessly about what is the "most readable", which in practice just means to write the most straightforward, laziest, zero optimisation code, and giving themselves an excuse for that. Even if a less-capable language hinders development (either by making things non-verifiable like no proper optional/nullable handling or simply by making the code more verbose and/or less readable) their advocates justify it on the basis of being standard or "best practice". I think Haskell and similar languages intimidate similar people because they can't shrug and say "well the language can't do that" to justify their laziness, but would have to actually make a reason up to why they don't want to write sound, safe and performant programs. Third, about backwards compatibility.... this is a "damned if you do, damned if you don't" situation. On one hand, you have languages like C++ and JavaScript which are really backwards compatible, and have really sizable drawbacks because of it. Sure, your code will compile in 5 years most likely without changes, but the language as a whole suffers because of it. There should be a place for languages which are ambitious and aren't afraid to break things. Backwards compatibility is simply a design aspect, not some holy commandment you must adhere to all times.
- xedrac 3y ago> lamentations about bad tooling I think it's less about linters and more about basic tooling for toolchains, dependencies, cross compiling, lsp, etc... compare the Haskell tooling to Rust tooling and it's easy to see how deficient it is. > Backwards compatibility is simply a design aspect, not some holy commandment you must adhere to all times. It's also something that has enormous influence on industry adoption. I adore Haskell the language. I use it daily. But I make no excuses for its many shortcomings. I would love to see Haskell prioritize industry needs over academic purity.
- xedrac 3y agoAs a Haskell developer, this was hilarious! Thanks for the laughs.
- keyle 3y agoI'm not sure I follow, could you expand for non-Haskell developers?
- xedrac 3y agoOh wow, when I originally clicked on the link, it took me here: http://steve-yegge.blogspot.com/2010/12/haskell-researchers-announce-discovery.html?m=1 http://steve-yegge.blogspot.com/2010/12/haskell-researchers-... I see why you were confused.
- tuukkah 3y agoThat submission is (now?) here: https://news.ycombinator.com/item?id=37247754 https://news.ycombinator.com/item?id=37247754
- draw_down 3y ago[dead]
- jsjdjd37 3y ago[flagged]
- 1letterunixname 3y ago"Worse is better" phenomenon.
- mattgreenrocks 3y agoThis really resonates with me. I’ve been using it in a decidedly industrial application for about 1.5 years now. I had some fairly significant experience with it prior (https://github.com/mattgreen/hython https://github.com/mattgreen/hython). For the first time in a long time (20 years experience) I’ve needed to learn a significant amount of things. It’s a combo of the domain and the language. It’s rather exhilarating, and also exhausting. Could also be a lot to bite off on with a busy home life too. Regardless, the language is brilliant. My manager exhorts me to generally write in a top-down manner a lot because Haskell’s flexibility really conveys dev intent well, so think hard about how it should read, and start from there. This is a huge mindset shift from most langs, where you can feel your brain shut off to save cycles as you type “function” over and over. It really feels like it is meant to be write-friendly. Point-free functions are wonderfully terse to write. I joke that TH is my favorite language: a type-checked macro language that lets me write almost anything I want. And there’s the rub: even with controlled effects via monads, the syntax is still hard for me to scan and read. I don’t know if this comes eventually or what, but this feels like a function of how dense a line could be. I miss early return dearly, and understand why it isn’t a thing (except if you have a MonadZero at hand) but I know it’s a syntactic transformation that won’t make it in. I really miss the amazing Rust LSP. Haskell’s recently lost the ability to flesh out pattern matches due to Haskell internals shifting with 9.x. I still hate and screw up stacking monads. Compile times can be brutal, esp if you hit the lens library. Finally, I’m not a big fan of pervasive laziness: the community has sort of admitted that Haskell programs are far more prone to space leaks developing from this default to the point that many programs may have them go undetected for quite awhile. The systems programmer in me screams out. I really think the community is one of the strongest group of programmers I’ve ever seen. I don’t want to belabor this and dwell on the big brain memes, it’s more that they think hard on this stuff and actually push forward, vs just telling each other that web frameworks are rocket science and it’s impossible to do better than what it exists. Ultimately, Haskell fits like a glove for our domain of program analysis. Beyond that, I’d still be a bit wary. I’m still thirsty for a PL that is essentially OCaml but with a better syntax. But that’s just me.
- girvo 3y ago> I’m still thirsty for a PL that is essentially OCaml but with a better syntax. But that’s just me. Not just you, me too! In fact it’s why I went in deep on Reason when it arrived initially. Shame it never really got traction.
- dncornholio 3y agoWhat are we even doing here.
- pooya72 3y agoIf I had to choose the three big factors that contributed to my gradual loss of interest in Haskell, they were these: * the stylistic neophilia that celebrates esoteric code but makes maintenance a chore * the awkward tooling that makes working with Haskell in a day-to-day sense clunkier * the constant changes that require sporadic but persistent attention and cause regular breakages Valid points. Back in 2010-2012, I spent a lot of time learning Haskell. The language itself is great, but the documentation and tooling was challenging to work with. The community went from Cabal (and the infamous Cabal hell) to Stack, and back to Cabal. Overall, the situation has improved. On the other hand, other programming languages have incorporated elements of functional programming. Take Java, for instance. It has added features like Streams, functions, lambdas, algebraic data types, records, and pattern matching. While Java's syntax isn't as elegant as Haskell's, it does include the fundamental concepts of functional programming.
- pyrale 3y ago> Take Java, for instance. It has added features like Streams, functions, lambdas, algebraic data types, records, and pattern matching. In a doomed attempt to escape the prison in which they were locked, the inmates defiled their language and adopted grotesque rituals inspired by the light they saw through the bars of narrow windows. They created an endless pit of suffering of their own, which is made tolerable only because the light shafts are too high for them to see the colors created by light on trees outside. Those that came from outside quickly lose sanity, constantly being by torn between a dialect adapted to self-imposed darkness, and a dialect that could thrive in the light but is stiffled there.
- freilanzer 3y agoPoetic truth.
- harry8 3y agoyeah sure, maybe, but when I look at software i can install which has a purpose other than programming a computer there's a metric f.ton() written in Java (a language I don't like much) and we can count the items on our fingers written in haskell (a language I greatly prefer for aesthetic reasons). Xmonad, pandoc and there are more. Let's list everything we can. We can scream at anyone who points this out or face up to it and work out /why/ and how to actually /fix/ that issue. When i mention it here it's about 50/50 which way it goes.
- beanjuiceII 3y ago"I also… don't really want to deal with them on a day-to-day basis. My personal experience has been that very often these sort-of-experimental approaches, while solving some issues, tend to cause many more issues than is apparent at first." This one really hits home for me
- kstenerud 3y agoIt's a similar issue with frameworks in imperative languages. Everything's fine until one day you find that you have to step outside of its envisioned bounds in some way. Then the sadness begins.
- pyrale 3y agoAs someone that has also written haskell for about a decade and moved away from it as a breadwinner recently (but for other reasons - I simply wanted to filter job offerings based on social utility rather than language stacks), I definitely agree with the author's first point: the Haskell community values learning extremely strongly. That's great because you work with curious people that have always something to teach and learn. But the community is not so strong when it comes to discard ideas after trying them, and so a professional haskell codebase, if not curated strictly, often ends up with lots of things that you can do but that you probably shouldn't use. I, however, disagree about tooling. Haskell's tooling sucks, but having used several other languages since (python, js, java, rust, elm), most tooling sucks. After this tour, I miss the Haskell toolchain. Sure, cargo is great, but that's one in many, and most older languages don't have this. I wonder whether Rust can escape this fate as it ages. The author also mentions being dismayed by Python, so I guess that's mostly me seeing the glass half-full though.
- Tainnor 3y agoI've also used several languages and IMHO, Haskell's tooling is some of the worst. Language server breaks with random errors all the time for me, I'm always confused about whether I should have ghcup or stack manage my Haskell versions (and what the benefits and drawbacks are), and so on. I have a project I work on from time to time, and I'm 100% sure that the next time I'll open it up, it will stop working again. Python's mess of dependency and venv management system is probably equally bad, although my experience was that Poetry is decent. By contrast, Ruby tooling usually works well (you can choose between chruby, rbenv and rvm, but they all work similarly, and Bundler just works(TM)), and Java has its warts but one of the best IDE experiences I've ever seen. Maybe the refactorings aren't as safe as in Haskell, but they're extremely easy to do.
- pyrale 3y agoI've used stack+stackage, and I can still run all of my older projects. I agree that as a newcomer the choice is not evident, haskell is a small enough community that finding mentorship is not always evident if you don't know where to look.
- regularfry 3y agoHm. Not really convinced by either Ruby counter-example. The first one's ok, ish, but doesn't take advantage of the fact you can pass a block to `zip` so you don't need the `map` call. The second one's just wrong. You wouldn't use `flat_map` for that if you didn't want indentation, you'd use `Enumerator#product`: def all_flavors flavors = [:vanilla, :chocolate, :strawberry] containers = [:cone, :cup] toppings = [:sprinkles, :nuts, :fudge] flavors.product(containers, toppings).map { |flavor, container, topping| ["a #{container} of #{flavor} ice cream with #{topping} on top"] } end While that's not quite doing the same as what `pure` and `<>` do in the Haskell example, the complaint was in terms of visual layout and in that respect it's very similar.
- Tainnor 3y agoThe point is that Haskell's do notation works for every monad, whereas "product" in Ruby works for just a cartesian product of sets, and not any other use of monads (e.g. generating random values, async code, operations that might return errors, IO operations, and so on).
- asplake 3y agoTo me the ‘product’ in the Ruby example above is helpfully explicit and could be changed for something else.
- regularfry 3y agoThe point is more specific than that: the claim here against this example is that Haskell's `do` notation uniquely lets you avoid indentation depth. The thing is, none of those other examples cause indentation depth problems in other languages because they don't force you through type system hoops to get useful work done. Besides, you can (ab)use Enumerator for all sorts of monadic things if needs be and end up with something quite terse. A random number generator is trivial, for instance. I'm not saying that `do` notation isn't a neat trick, it just tends to be a trick other languages don't need. Its generality is both a blessing and a curse.
- 3y ago
- IceDane 3y agoI could have written this article. I discovered it around the same time, and it was my go-to language for years and years. I had a brief stint where I wrote it professionally too, but nothing serious. Eventually I really really got going in the industry and had to use other technologies, namely TypeScript and others. I became pretty fond of those, after getting over the initial hurdles, and didn't really spend time using Haskell at all. After a while away, I went back to it. One time for a job interview, too. It just .. really lost its shine for me. It just all felt like such academic, ivory tower circlejerk. The ecosystem is still relatively small, the packages in it not always great and almost always have only a single or a couple of maintainers. There are still things missing from the Haskell ecosystem that people wanted over a decade ago. Hell, things like Streaming are still barely a solved problem. There are still popping up new libraries to solve it, and each does more arcane things than the previous in some attempt at getting streaming to be nice, type-safe while also not leak memory and what have you. Most of these end up leaking GHC-isms into their code. For the most part, I've just taken what FP or Haskell has taught me to other language. Use the type system(but not too heavily) to help maintain your invariants at compile-time. Write small, pure functions as much as you can and compose them to build more complicated functionality. I've still sort of kept on top of how haskell has been moving, and it seems to me that a lot of Haskell shops have dropped it as well. I think many may have moved to Rust. I don't see myself ever using it for anything serious again. I would much rather use Rust and get much better DX and performance while still being able to write mostly functional code.
- greydius 3y agoAnyone hiring Haskell devs?
- icrbow 3y agoYes. The amount of job postings raises year to year.
- lcedp 3y agoThe page appeares to be hugged to death. Google cache: https://webcache.googleusercontent.com/search?q=cache:uWo0NiOzW_UJ:https://journal.infinitenegativeutility.com/leaving-haskell-behind&cd=8&hl=en&ct=clnk&gl=uk https://webcache.googleusercontent.com/search?q=cache:uWo0Ni...
- kajumix 3y agoI have been using Scala. I have found that it can give you the best of both worlds. You can reason algebraically, and often after a refactor, if it compiles, it works. Type inference and monads works great too. You also get to benefit from being in the java ecosystem. In instances where it gets too esoteric, I can break rules and code more like java. I am curious what others think.
- valenterry 3y agoAgreed, I feel the same. It also allows for a smooth gradual transition from imperative/oop code to a pfp style.
- inickt 3y agoI have really enjoyed Scala for the same reasons. Has some escape hatches if needed, and a large ecosystem. sbt drives me insane though, and is probably my least favorite part of the development experience.
- rowanG077 3y agoInteresting. I use Haskell professionally and this article doesn't touch on the most fundamental problem I have with Haskell at all: Function coloring. Basically every monad transformer is different. Just calling basic function from somewhere else can involve lifting. Refactoring is a total pain. Oh you just want to log here but your concrete monad doesn't have a logger? Too bad... I understand an effect system alleviate this somewhat, so I hope to try this in the future. But holy shit is working with monads annoying.
- consilient 3y agoYou should generally be writing code against typeclasses, not a particular monad transformer stack. For example: fibonacci :: MonadState (Int, Int, Int) m => m Int fibonacci = do (prev, prev2, n) <- get if n > 0 then put (prev + prev2, prev, n - 1) >> fibonacci else return prev2 concreteFib :: ReaderT String (StateT (Int, Int, Int) (ExceptT String Identity)) Int concreteFib = fibonacci
- rowanG077 3y agoYou misunderstand my problem. Add a logger to that fibonacci function. Potentially EVERY usage site now has to change, maybe even multiple layers. Adding a log in most languages is a local transformation. In Haskell it isn't, it can have codebase wide consequences.
- consilient 3y agoIf you just want to add logging to existing operations, reinterpret them at the call site. Something like this newtype LoggedStateT s m a = LoggedStateT (WriterT s (StateT s m) a) instance (Monoid s, Monad m) => MonadState s (LoggedStateT s m) where get = LoggedStateT $ do val <- lift get tell val return val put s = LoggedStateT $ tell s >> lift (put s) (which is basically an ad hoc effect system) If on the other hand you want to reproduce the behavior of other languages, throw everything in `MyAppMonad` give it whatever capabilities you need.
- runeks 3y ago> The way that Haskell-the-language evolves — well, the way that GHC evolves, which is de facto Haskell since it's the only reasonable public implementation — is that it gradually moves to correct its past missteps and inconsistencies even in pretty fundamental parts of the language or standard libraries. I would say that the biggest problem is that GHC is tied to a particular version of base (the standard library). So when changes are made to base, and a new version of GHC comes out that supports only this and not earlier versions, you're forced to change basically all of your dependencies, if you want to use this newer GHC version, as they all depend on base. I still don't understand why this is necessary. Why must code compiled with GHC 9.6 use base version 4.18.0.0? Why should the binary that is GHC care about which version of the Data.List module the code that it compiles uses? I understand that all the GHC-specific stuff exposed by base is tied to a particular GHC version, but why all the rest? There is, however, work in progress to split base into multiple packages to fix this (as I understand it): https://gitlab.haskell.org/ghc/ghc-wiki-mirror/-/blob/master/split-base.md https://gitlab.haskell.org/ghc/ghc-wiki-mirror/-/blob/master...
- mrkeen 3y ago> I still don't understand why this is necessary. Why must code compiled with GHC 9.6 use base version 4.18.0.0? It's hinted at in the section you quoted. A newer ghc might reject older base code as invalid.
- runeks 3y agoThat GHC might reject an older version of base isn't a reason to switch for every GHC release, is it? I mean, if it breaks then sure, require a newer base. But in my experience GHC (thankfully!) doesn't change the semantics of Haskell often enough to warrant a new version of base for every new GHC version.
- tinco 3y ago> I still don't understand why this is necessary. Why must code compiled with GHC 9.6 use base version 4.18.0.0? Why should the binary that is GHC care about which version of the Data.List module the code that it compiles uses? Because the underlying data types might be different, so if different libraries linking to different `base` implementations pass each other instances of `Data.List`. Imagine for example a Data.List Data.List, could you append the results of functions out of two different libraries to that list?
- joeyh 3y agoThis is a pretty good post. The weak part of it to me is that I have never felt pushed to use any particular new fancy type stuff if I don't want to. Don't want servant's type-level http apis? Drop down a level and use warp. Libraries are often layered this way because it's understood that excessively complicated types can be a trap. One does have to develop an intuition for how far to go, which will involve making mistakes.
- cflewis 3y agoDo you know of a good "I don't know Haskell well but this Servant idea sounds incredible, please educate me?" article? I read the Servant docs and they (rightfully) assume I have more Haskell understanding than I do :(
- mrkeen 3y agohttps://www.well-typed.com/blog/2015/11/implementing-a-minimal-version-of-haskell-servant/ https://www.well-typed.com/blog/2015/11/implementing-a-minim...
- chpatrick 3y agoI recently went to one of the largest Haskell meetups in Europe and pretty much no one used Haskell any more (including some formerly core people), it was almost just a social gathering. I think in 2023 many of the things that made Haskell appealing compared to other languages before have been widely adopted, while the developer experience and ecosystem for Haskell is as bad as it was. I wouldn't use it for a new project outside of some specific areas.
- Capricorn2481 3y agoWhat were some things people were using?
- chpatrick 3y agoRust, TypeScript, C++.
- deleted 3y ago[deleted]
- nh2 3y agoI went to the same meetup (ZuriHac), and arrived at the opposite conclusion. I gave a lightning talk there on how the Haskell job market has been growing steadily since 2008 [1] [2]. The GHC bug tracker is full of new people filing bugs from production environments. Consultancy blogs such as [3] regularly show industry-sponsored improvements to GHC, which was much more infrequent 10 years ago. A this year's ZuriHac, around 50% of attendees were new to Haskell / had never visited ZuriHac before (this was an audience question). In the past, there were a few well-known companies that used Haskell, in specific niches. Today, the big niches are diminished, and there are more companies that use it in more niches. > the developer experience and ecosystem for Haskell is as bad as it was The developer experience improved significantly over the last years. Today, you can get a good quality IDE environment with VSCode and Haskell-Language-Server that works in both simple and complex environments, and includes all the features you'd expect (completions, immediate type error checking, scoped renames, go-to-definition, find-all-references, call hierarchy, docs-on-hover). [1] https://news.ycombinator.com/item?id=36742311 https://news.ycombinator.com/item?id=36742311 [2] https://github.com/nh2/haskell-jobs-statistics https://github.com/nh2/haskell-jobs-statistics [3] https://well-typed.com/blog/ https://well-typed.com/blog/
- lihaoyi 3y agoIf you like Haskell but want something else, you really should consider Scala. It's not the same. But it has many of the same niceties around the rich type system, but with generally good tooling, the amazingly rich JVM ecosystem (tooling, libraries, learning materials), and a somewhat more pragmatic bent to it. Scala has a bad rep, justifiably so, due to a lot of its problems in the past: community, libraries, tools, etc. But many of those past problems are much better today. Scala today is a much better platform than it was at peak-hype circa 2015, despite some ongoing warts. Nowhere near perfect, but pretty good overall I see people in the comments looking for a "better OCaml" or a "industrial Haskell", those folks should definitey try Scala
- urthor 3y agoI find the issue is most of the niceties are also built into Rust. Scala's perfectly good though, there's very little to complain about.
- paulddraper 3y agoJVM debugging+monitoring is leagues better
- paulddraper 3y agoScala 3 was a massive step forward. Though for whatever reason it seems that its popularity is declining. [1] [1] https://twitter.com/jdegoes/status/1656566825356754945 https://twitter.com/jdegoes/status/1656566825356754945
- wavemode 3y agoBecause Scala 3, as great as it is, has fractured the community and caused a lot of churn. Twice, just in my recent job history, have I worked for companies that were using Scala 2 for a long time but are now deciding to develop new projects in Java and/or Kotlin instead.
- kagakuninja 3y ago
- tempodox 3y ago> the constant changes that [...] cause regular breakages Wow, for a language as mature as Haskell I find that surprising. I never really got into Haskell for other reasons, but this one warns me to stay away for the foreseeable future.
- habitue 3y agoHaskell's motto is "avoid success at all costs", and part of this is making these kinds of backwards incompatible changes to clean things up.
- yakshaving_jgt 3y agoTo clarify, it's not "avoid success (at all costs)". It's "avoid: success at all costs".
- jeremyjh 3y agoI Haskelled quite a lot from 2014 to 2017 on a futile side project, and developed/extracted and maintained a few libraries on Hackage and a couple that were included on Stackage. In my experience most of the breakage comes from dependencies, not the language. The biggest shift in my time was the Functor-Monad-Applicative Proposal and I don't think that broke anything for me. Technically it was not even a change in the language but in core type-classes distributed with GHC and used in every Haskell program. As far as I know, Haskell 98 still compiles most of the same programs it did 25 years ago. Some extensions that are commonly used have introduced breaking changes I believe, but I don't remember the details. But I gave up maintaining my projects because 1. I wasn't using them (because I moved away from Haskell, for mostly the reasons in the OP which I feel like I could have written myself almost) and 2. my dependencies kept breaking them.
- agentultra 3y agoThe schism created by the Simple Haskell folks in the community is a rather unfortunate one. For context, Haskell used to pride itself on being a language where researchers could experiment with industry users on an industrial-grade compiler without interfering with one another. Industry users get new features sooner, researchers get feedback faster, etc. No long revisions of the standards and waiting for implementations to catch up. The evolution of language extensions, specifications, and the standard base libraries have a long history of success with this approach. However, in the last few years, a group in the Haskell community has felt like they had to push back against the work of these researchers and "protect" the language from adopting them. You end up with folks like the author who feel exhausted by having to argue against adopting these features in code bases they're working on and you have the researchers who also feel exhausted getting constant push back on their ideas and hard work. As this schism has developed it has left people feeling exhausted on both sides where there was once collaboration and community. Write a style guide. This isn't a problem that's unique to Haskell. You get it in C++ and even Javascript too. If using the entire language is not feasible for your project then state it clearly in a guideline. At the very least it requires contributors to seriously consider their reasons for going against the guide and forces them to justify their changes. The nice way Haskell has done it, from my perspective, is that you basically don't pay any cost for not using those features (caveat being Linear Haskell, but they made it a goal to minimize the impact and I think the cost has been amortized by performance gains in recent versions of GHC at least). Towing the line against progress in the language seems counter-productive to me. I think there are plenty of language extensions in Haskell to work around the lack of expressiveness in the type system that wouldn't be necessary if the language had dependent types. Learning how to use those extensions and which ones work well together is a whole art that could be greatly simplified by a more expressive type system. To be fair, I almost never use dependently typed Haskell. And I rarely reach for type level programming... until I can't; usually when I'm writing library code that needs to do stuff with user types... even then, quite rare in practice. If you sympathize with the author then adopting Haskell may not work for you but I would still consider that there are many technical reasons to use it on a project. Also, I would also advise folks to avoid telling people they should learn Haskell in order to become better programmers. It's true you have to learn a lot more to go from Java -> Haskell than you would from Java -> C#. However there are practical reasons to be using Haskell that aren't about self-improvement: - GHC is a battle-tested compiler with decades of industry use that produces some excellent code, has an excellent manual, and has an active community of contributors that are always improving it and making regular releases. - The concurrency story in Haskell is hard to beat: you want immutability-by-default and STM on green threads. It's excellent. - The type system is a feature: inference, typed holes, type classes... if you don't have a ton of domain expertise you can still arrive at solutions to complex problems using algebraic reasoning. Clash, Crucible... there are many projects that benefit from having a good industrial-grade compiler that also has an expressive type system. However I have been using Haskell professionally for a number of years, I maintain a couple of libraries, and I stream myself working on non-trivial Haskell projects for fun and there certainly are drawbacks that I would call out: - On projects that get into 5000+ modules, build times become difficult to manage and require extensive tooling to stay productive. Haskell does a lot more work than many other language compilers and you have to avoid a lot of features that might be convenient in order to keep build times under control - Modules are fine but type class constraints can "leak" outside of your API boundaries which can lead to a fair amount of coupling if you're not disciplined about how you approach the design of your type classes.. not really a thing you'll be worried about off the bat though, more of a nitpick - If you interact with SaaS services chances are you will have to write your own client libraries. For things like amazon AWS you're covered but there are a lot more out there and people don't publish SDK's in Haskell.
- chubot 3y agoThis part is interesting: A good concrete example here is a compiler project I was involved in where our first implementation had AST nodes which used a type parameter to represent their expression types: in effect, this made it impossible to produce a syntax tree with a type error, because if we attempted this, our compiler itself wouldn't compile. This approach did catch a few bugs as we were first writing the compiler! It also made many optimization passes into labyrinthine messes whenever they didn't strictly adhere to the typing discipline that we wanted: masses of casts and lots of work attempting to appease the compiler for what should have been simple rewrites. In that project, we eventually removed the type parameter from the AST which also seems to conflict with this: Using data structures indexed by compiler phase is a good example of a “fancy type-level feature” that I've found remarkably useful in the past. Both of these sound like the "AST typing problem" - https://news.ycombinator.com/item?id=37114976 https://news.ycombinator.com/item?id=37114976 which I admit I'm a bit skeptical of, because the problem is type safety, and not the compiler's actual algorithm or actual performance. But I guess the first one is for syntax trees, and the "trees that grow" paper (linked in the article) is for back end passes? Does that change the problem so much? I'm not experienced with back end passes for compilers, but I personally don't see the problem of using either a Map<AST, ExtraInfo> or a nullable field. I just hacked on a toy codebase that had the Expr<void> and Expr<T> type safe solution, and it's interesting. But my first impression is that it causes more allocations and makes the code a bit longer. --- I guess another way to justify the Map is that it's like math -- a "typing relation" is an association from expr to type, so a map or multi-map seems natural to model it.
- andolanra 3y agoThe former is referring to representing an AST using a GADT in order to include the typing discipline of the target language in the host language. For example: data Term t where Num :: Integer -> Term Integer Bool :: Integer -> Term Integer Add :: Term Integer -> Term Integer -> Term Integer IsZero :: Term Integer -> Term Bool IfThenElse :: Term Bool -> Term a -> Term a -> Term a With this AST, you can express well-typed programs like `Add (Num 2) (Num 3)`, but the Haskell type system will stop if you express an incorrectly-typed program like `Add (Num 2) (Bool False)`. The "Trees That Grow" paper, on the other hand, is about reusing the same AST but gradually adding more information to the nodes as you progress through the compiler. For example, you might want to start with variable names being raw strings (so that a term corresponding to `lambda x: lambda x: x` looks like `Lam "x" (Lam "x" (Var "x"))`) but eventually replace them with unique symbols so that shadowed names are non-identical (so that under the hood it looks more like `Lam 1 (Lam 2 (Var 2))`, although in practice you'd want to keep the old name around somewhere for debugging.) One way to accomplish this is to introduce an explicit type-level notion of compiler phases, give your terms a type parameter which corresponds to the phase, and use the phase to choose different representations for the same nodes: data CompilerPhase = Parsed | Resolved data Expr (phase :: CompilerPhase) = Lam (Name phase) (Expr phase) | App (Expr phase) (Expr phase) | Var (Name phase) type family Name (t :: CompilerPhase) :: * type instance Name Parsed = String type instance Name Resolved = Int Using this example, an `Expr Parsed` will contain variables that are just strings, while an `Expr Resolved` will contain variables that are integers, and you can write a pass `resolve :: Expr Parsed -> Expr Resolved` which just modifies the AST. (This is a toy example: in a real compiler, you'd probably want to create a new type for resolved variables that still keeps a copy of the name around and maybe some location information that points to the place the variable was introduced.)
- rg111 3y agoI want to seriously invest some time into properly learn a functional language. My goals are simple- write small scripts, solve programming problems in sites like Codewars, Leetcode, Euler Program, etc. And yes, having the "functional enlightenment" or something similar. Which language should I learn and invest time into? Scala, Clojure, Haskell, OCaml?
- yakshaving_jgt 3y agoHaskell.
- GregarianChild 3y agoAmong the ML descendants, I suggest Scala 3, because it has essentially all the power that we like in Haskell, (HTKs, good support for ad-hoc polymorphism), but runs on the JVM, a mainstream platform with a vast library ecosystem.
- yakshaving_jgt 3y agoI haven’t used Scala in a long time, and I’m guessing it isn’t as gross now as it was in 2014. Your point about the vast library ecosystem might be valid. Personally, there has only been one time in several years working with Haskell I’ve wanted to use a library that I couldn’t find an analog to in Haskell. It was WeasyPrint which is a Python thing, and there was no problem to run it from my Haskell program as an external process. Although thinking about this some more, I probably could have just used Pandoc…
- habitue 3y agoLearn Haskell, it's the most elegant, and if you're using it for LeetCode / project euler you can have the experience of polishing a simple elegant program until it shines. It's a very satisfying experience. Also, Haskell is lazy, which is fun and very different from other languages you'll use. If you become a Haskell afficionado, it also kind of acts as a secret handshake in interviews. Like, you aren't going to be programming in Haskell here, but "you get it"
- 3y ago
- JackMorgan 3y agoMany of these reasons are why I moved to F# and haven't looked back (much). I sometimes miss Higher Kinded Types, but F# still has generics and if I'm being honest it forces me to write even simpler code then I would have in Haskell. I generally prefer this outcome. However F# never feels "leet" like Haskell does. It's like Haskell, but all business. I get a lot done in F# and really enjoy it, but I'll catch myself looking back wistfully, like Haskell why couldn't we make it work. Sigh, the one that got away I guess.
- xupybd 3y agoI'm glad to read this. I'm new to FP and enjoying F#. Because it's terse and down to business. I've often wondered if I'm missing out by not using Haskell. It seems, for my purposes, probably not.
- xwowsersx 3y agoIt seems to me that the stewards and maintainers of the language actually _intend_ for Haskell to be friendly to research, experimentation and academic pursuit. That is fine, as far as it goes, but obviously this will, at some point, be at odds with the interests of programmers looking to use Haskell as a practical, stable tool. It sounds to me like what is needed is the ability to mark all the experimental, envelope-pushing bleeding edge stuff to a different track (whether through pragmas or even a package level declaration) so that programmers know just by looking at the package whether it's something they want to pull in. This would allow practically-minded developers to adopt a policy along the lines of "we only use Haskell stable" or whatever it'd be called. The dynamic I'm describing is the "Avoid success at all costs" phrase, right? The idea being that if Haskell adoption gets "too high" then the language will become inertial and be unable to continue pushing bleeding edge concepts. What I'm proposing is a way to allow that to happen but also maintain a separate track at the level of the language stewardship that formally acknowledges and recognizes that day-to-day programmers need some way to opt out of some of the edgier stuff and to stay within a more limited subset of stable Haskell.
- BellsOnSunday 3y agoThere is the Simple Haskell initiative, which encourages what you're talking about, but no flag or pragma that says "this project uses simple Haskell". Obviously, simplicity is in the eye of the beholder. Fancy type features do have their use cases where they make types more expressive, the code safer and even simpler, so long as you've internalised how they work.
- DonaldPShimoda 3y ago> It seems to me that the stewards and maintainers of the language actually _intend_ for Haskell to be friendly to research, experimentation and academic pursuit. Yes, this is explicitly stated as a core principle in "A History of Haskell: Being Lazy with Class" (2007) (direct PDF link: https://www.microsoft.com/en-us/research/wp-content/uploads/2016/07/history.pdf https://www.microsoft.com/en-us/research/wp-content/uploads/...).
- mrkeen 3y ago> That is fine, as far as it goes, but obviously this will, at some point, be at odds with the interests of programmers looking to use Haskell as a practical, stable tool. That's what Stackage is. Stackage provides consistent sets of Haskell packages, known to build together and pass their tests before becoming Stackage Nightly snapshots and LTS (Long Term Support) releases. [1] Java will never get this. [1] https://www.stackage.org/ https://www.stackage.org/
- yakshaving_jgt 3y agoIt's strange that under any article like this, there's always commentary along the lines of "Hmm, yes, indeed $LANG is bad. What shall we all migrate to instead?" Reminder that this post represents one person's opinion. Haskell is still just fine as a programming language for getting actual work done.
- steno132 3y agoIf you want to get things done, don't use Haskell. You'll be fighting against the type system constantly. You'll be asking questions on Stack Overflow only to get no response. You'll be rewriting software that's in other language's standard library. Productive programmers don't use Haskell.
- yakshaving_jgt 3y agoThis is nonsense.
- friend_and_foe 3y agoYou're not wrong, but the thing to know about the type system is once you get it it's like this amazing thing. You start to think about your program in terms of the data it manipulates, you'll find yourself just without effort writing the code that does exactly what you intended, it's pretty wonderful. But on the way there it is painful.
- antod 3y agoThe bathed in a suffusion of blue phase. (or should that be purple?)
- theCodeStig 3y agoThe compiler/type system is your friendly assistant. Learn to use it, and it's your greatest asset.
- porcoda 3y agoI had a pretty similar experience: spent a decade (2007-2017) working professionally in Haskell and just got completely fed up with the state of the language, ecosystem, and community. I migrated most of my new work to Ocaml and haven’t looked back. For me I think the failure of the Haskell Prime effort to establish a successor standard to Haskell 98 was a big factor: the language and ecosystem became more chaotic and inconsistent over time as people drifted away from any hint of a common standard. Add to that the changes in the community when there were big changes in the cohort of “leaders” who had driven things from the 90s until the early 2010s (eg, when both Simons changed their roles). The folks who took their place haven’t done good things for the language in my opinion.
- icrbow 3y agoFor the reference, 2017 was the year of GHC 8.0. Since your decision to never look back there were a lot of good things. The standard didn't come out because of some failure to make it. It was mostly the lack of interest that killed it. I wouldn't be betting that some alternative universe where Haskell Prime pulled through had a noticeable increase of adoption because of this. Looking at proposals, arguments "from standard" don't tend to generate enough support. What wins hearts is alleviating someone's pain without taking disproportionate externalities.
- porcoda 3y agoI’ve paid attention to the language since 2017 (it’s kind of impossible not to if you work in the PL research field). I just consider it dead for my own work - that’s the sense in which I haven’t looked back.
- kagevf 3y ago> the experience of code refactors via algebraic manipulation is still possible in other languages, especially in non-pure functional languages like Scheme or SML Wouldn't "code refactors via algebraic manipulation" require static types? How would this work in Scheme?
- mrkeen 3y agoI think the requirement would be purity not static types, but I agree with your overall objection. (Then again, you need static types if you want to have pure functions, IO functions, and not mix them up)
- kagevf 3y ago> I think the requirement would be purity Well, yeah, I think if I had instead said "if not static typing, then how would it be possible?" ... I had no idea how it could be done, but with something like purity - by which we mean deterministic functions, right? - I can at least start to see how it would be possible with Scheme.
- deleted 3y ago[deleted]
- Shumer666 3y agoFirst off, learning Haskell's like trying to decipher an alien language. If you're used to plain ol' if-else loops and straightforward variable assignments, prepare to have your brain twisted into knots. Haskell's got monads, and no, they're not some new type of space monster – they're these weird abstract things that'll leave you scratching your head and questioning your life choices. Now, I know we all love libraries that make our lives easier. But with Haskell, you might find yourself on a treasure hunt for a library that actually does what you need. The Haskell library scene's like a half-empty thrift store – you gotta sift through a bunch of outdated, half-baked options before you stumble on something that kinda works. And don't get me started on documentation – it's like reading hieroglyphics half the time. Oh, and performance? Sure, Haskell's got that reputation for being all slick and optimized. But in the real world, you might end up scratching your noggin over why your code's chugging along slower than a snail on a summer day. Lazy evaluation sounds all fine and dandy until your app's gobbling up more memory than it should and moving slower than molasses in January. Let's talk job prospects, shall we? Unless you're hoping to work on some super niche project for a company that's all in on Haskell, you're gonna have a tougher time finding a gig than a polar bear in the Sahara. It's like showing up to a party where everyone's talking about the latest celebrity gossip, and you're there with your collection of 19th-century poetry – cool, but outta touch. And let's not forget debugging. Imagine trying to find a needle in a haystack, except the needle's your bug and the haystack is a jumbled mess of functional hieroglyphs. Good luck trying ^^
- dado3212 3y ago[flagged]
- rendall 3y agoDefinitely worth repeating! https://news.ycombinator.com/item?id=37251323 https://news.ycombinator.com/item?id=37251323
- physicist1337 3y ago[flagged]
- Shumer666 3y ago[flagged]
- blagund 3y agoMy notes on using Haskell: mostly agree with the article, but I came to embrace rolling my own tooling, some abstraction on top of cabal. I use my abstractions, not what whoever would force on me. Use Haskell as your typed lisp.. with all the pros and cons. On production use... Don't even get me started. Will work, but need shedding blood.
- massysett 3y agoTyped lisp? Unlike Lisp, Haskell has enormously complex syntax, so generating code in it is a huge hassle. Template Haskell is something to use only when absolutely necessary, while Lispers write macros without a second thought. I considered your method of writing my own tooling, but have had a vague feeling that Lisp works better for this frame of mind.
- spopejoy 3y agoHaskell has almost no syntax, even `$` is a userland function. Are you arguing against the feature of allowing ad-hoc infix operators in userland?
- massysett 3y ago"almost no syntax" is, I suppose, a matter of opinion. I wouldn't consider these sections from the Haskell 2010 Report to have "almost no syntax." https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-220003 https://www.haskell.org/onlinereport/haskell2010/haskellch3.... https://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-620004 https://www.haskell.org/onlinereport/haskell2010/haskellch4.... https://www.haskell.org/onlinereport/haskell2010/haskellch5.html#x11-980005 https://www.haskell.org/onlinereport/haskell2010/haskellch5.... Dealing with this in Template Haskell is unwieldy at best.
- friend_and_foe 3y agoI just started learning Haskell last year (at my own pace on my own time) and from the minute I wrote a recursive function I understood how freeing and smooth writing in Haskell was going to feel. Once I got used to the new concepts this was going to be like butter... The two problems I have with it are the archaic standard library and the tooling. Because everything is atomic and strongly typed, you basically have to rote memorize the standard library before you can use any of it. The tooling is just clunky, I can't come up with a better term. The author is right IMO. I haven't been writing it long enough to get the rug pulled out from under me with regard to breaking changes and that, I guess we will see how that goes. But the language itself... It's like finding this magical thing. I wish Haskell had better tooling and at least more approachable documentation for the prelude.
- pmarreck 3y agoFor anyone new-language-curious, Idris is a very interesting project that is inspired by Haskell but which seems to have less design drawbacks
- lykahb 3y agoI've maintained a Haskell library for databases for over ten years. Here is my take: Haskell is a complex and a flexible language. It pushes you toward correctness, but in other dimensions is less opinionated than other languages. If you choose to stay away from the low-level Template Haskell (the types for it are updated often) and the bleeding edge type system tricks, Haskell would be quite stable. The idea to use only the simple parts of Haskell is great - but what is simple is a rather subjective judgment. Oftentimes the technical choices would be made before the the impact on dev ux and effort to maintain becomes clear. Luckily, doing large refactoring in a complex Haskell project is safe, and improving over the initial choices is easier than in most other languages.
- d_burfoot 3y agoAs someone who uses a lot of "core" Java (ie not the messy ecosystem), and gets a lot of really complex stuff done with it, I read these articles about high-tech language features like algebraic data types and ultra-strict typing, and I think, what are these people actually doing? The vast majority of software engineering consists of simple operations that move data from one place to another - from a DB to a JSON file, from a REST endpoint to a browser screen. Is all this machinery really helping? Are you sure?
- grumpyprole 3y agoIf Java is so great at solving these "simple" problems, then why do hugely complex frameworks like Spring exist? The language features of Haskell that you mention can describe your "simple operations" symbolically, you then just need to write a few different interpreters, one for real services, one for testing etc. No dependency injection, aspect-oriented programming or AbstractSingletonProxyFactoryBeans needed. You might feel that the complexity has just moved, but I'd much rather invest my time in solutions that are not ad-hoc.
- gmfawcett 3y agoStrawman? Spring was not designed for solving simple problems.
- grumpyprole 3y agoMaybe. I've seen few Java apps that don't use Spring or something similar. The parent described a simple domain, arguing it is the common case, but nonfunctional requirements like testing typically make the problem more complex. So I dispute that Java is good enough for the common case and that nothing from Haskell would be beneficial. Incidentally, Java's leadership agrees.
- Tyr42 3y agoWhen writing a compiler it helps for sure. Though most of my time is protobuf in Java, I still wouldn't mind having an ADT or two for when I got lists of things and the things aren't exactly uniform but I don't want to make a type hierarchy.
- ryukoposting 3y agoIn terms of tooling, Haskell has one thing that AFAIK no other language can compete with: Hoogle. Hoogle is amazing. You tell it, in Haskell, what you want, and it tells you, in Haskell, what you can do. It's extraordinary. Someone attempted something similar with Rust, and I even tried to make a Noogle (Nim), but it just doesn't work the same in languages where there's a clear divide between "passing arguments to a function" and "calling a function." I find myself looking at tangles of Rust code with all its Result<Option<Box<SomeEnum<Nonsense>>>, Box<dyn Error>> and I yearn for a Roogle that provides the same level of utility as Hoogle. Other than that, Haskell's tooling has no redeeming qualities. Nothing (pun intended). A lot of that can be blamed on the community's instinct to make something "innovative" instead of improving what already exists. I feel the author's pain.
- runeks 3y agoHard agree on Hoogle — it's amazingly useful. But wrt. other tooling, I use haskell-language-server every day and it makes me so much more productive. Sure, it isn't perfect, but so much better than what we had just five years ago.
- deleted 3y ago[deleted]
- Dobiasd 3y agoHoogle is really amazing! Inspired by it, I implemented something similar for FunctionalPlus (a functional-programming library for C++): https://www.editgym.com/fplus-api-search/ https://www.editgym.com/fplus-api-search/ I'd love to see more projects taking this path too. :)
- solidsnack9000 3y agoThe author does a good job summarizing ways in which thinking through your Haskell programs is easier than in many other languages. There is a certain straightforwardness to it that, once grasped, is eye opening, appealing and fun. Haskell opened the door for me to much more rigorous reasoning about correctness.
- jokethrowaway 3y agoI tried to make Haskell work as a product language for a long time - and, until Rust was around, there was really nothing better than Haskell in terms of guarantees. Haskell is a research language: it's supposed to change and experiment with new things; the permanent in-flux state is by design albeit I wish we crystallised more of the good PRAGMAs as default.
- anacrolix 3y agoCompletely agree with the author. Haskell is a great language but the ecosystem sux. I have a small project that breaks every time I update stack. It really lacks some high quality, bomb proof libraries, like for http for example. Cross compilation is next to impossible, stack also recently broke for using Docker for that. Cabal is a mess, as is its weird AF format. cargo is a dream by comparison. I am not happy with some things about Rust either but by comparison it has amazing tooling, and some incredible solid libraries. It also helps that you don't have to be a wizard to get extremely good performance.
- spopejoy 3y agoHaskell continues to punch above its weight in divisiveness. When was the last time you saw an article hating on F#, OCaml or some lisp get this kind of attention? Haskell hate has an distinguished history. In the 2000s OCaml was "winning" in FP-for-production-apps land, which for no good reason resulted in an outpouring of vitriol for Haskell. Steve Yegge's joke article comes right at the inflection where Haskell "grows up" and starts offering compelling advantages for production apps, but nobody knows it yet. The 2010s see real adoption and fervor but no drop in click-grabbing haskell hate. If anything it increases, although the OCaml community buries the hatchet. So it almost warms my heart to see this still getting attention in the 2020s. Switching to Haskell a decade ago changed my life for the better in every way, so I'd of course rather see Haskell love climbing the charts. But this trend instead supports the thesis that Haskell has "stayed weird", which is probably a good thing.