[HN Gopher] Leaving Haskell behind
       ___________________________________________________________________
        
       Leaving Haskell behind
        
       Author : mpereira
       Score  : 240 points
       Date   : 2023-08-24 09:51 UTC (13 hours ago)
        
 (HTM) web link (journal.infinitenegativeutility.com)
 (TXT) w3m dump (journal.infinitenegativeutility.com)
        
       | kajumix wrote:
       | I 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 wrote:
         | Agreed, I feel the same. It also allows for a smooth gradual
         | transition from imperative/oop code to a pfp style.
        
       | chpatrick wrote:
       | I 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.
        
         | nh2 wrote:
         | I 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
         | 
         | [2] https://github.com/nh2/haskell-jobs-statistics
         | 
         | [3] https://well-typed.com/blog/
        
         | Capricorn2481 wrote:
         | What were some things people were using?
        
           | chpatrick wrote:
           | Rust, TypeScript, C++.
        
             | [deleted]
        
       | lihaoyi wrote:
       | If 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
        
         | chriswarbo wrote:
         | Due to Scala's JVM heritage, it takes some discipline in order
         | to have confidence in Scala code (e.g. that it won't throw
         | exceptions, or return nulls, or do weird type casts, or
         | overflow the stack, or have spooky action-at-a-distance, or
         | have race conditions, or do inexhaustive pattern-matches, or
         | not actually accept/return the types in its signature, etc.).
         | This can be a tall order for shops which have a Java background
         | (e.g. my last job used Scala extensively, but most had a Java
         | background and treated Scala like a different syntax for Java;
         | I had written more Haskell and ML, and treated it like an ML
         | with JVM-gotchas). I highly recommend turning on all the scalac
         | -Xlint options, using other linters like WartRemover, and
         | treating the warnings as errors (annotations can silence the
         | rare cases of "I know what I'm doing"; but there had better be
         | a comment with a good justification, if you want it to pass
         | code review!)
         | 
         | Whilst it's nice that there are loads of Java packages to
         | import and use from Scala, it's usually a good idea to
         | encapsulate them in a more "Scala-friendly" wrapper; e.g. to
         | replace exception-throwing with `Try`, `null` with `Option`,
         | etc. in order to maintain confidence in our code. With a little
         | thought, and a sprinkling of Scala features (e.g. `lazy val`,
         | by-name parameters, implicit arguments, etc.) such wrappers can
         | end up being much easier to use than the original, too!
        
         | paulddraper wrote:
         | Scala 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
        
           | wavemode wrote:
           | Because 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 wrote:
             | I think that is less about Scala 3, and more that the
             | companies were not committed to the use of Scala, and would
             | eventually move to some other flavor of the month language,
             | such as Go or Rust.
             | 
             | The transition to Scala 3 at my current job has not been an
             | issue. Scala 3 is mostly the same language, with some nice
             | new features which are optional. Our old projects are still
             | on Scala 2, as there isn't a huge benefit from upgrading.
             | 
             | The main downside in upgrading was library support, but we
             | are now 2+ years since the release of Scala 3, the issue is
             | mostly solved unless you depend on unmaintained libraries.
        
               | chriswarbo wrote:
               | Library compatibility was preventing us upgrading from
               | 2.12 -> 2.13; Scala 3 wasn't even on our horizon :(
        
         | foderking wrote:
         | ...or f#, which is actually the "better ocaml"
        
         | jsbg wrote:
         | I found Scala to be missing too much of what I liked about
         | Haskell. If I'm gonna lose out on the niceties that are unique
         | to Haskell, then I'd rather go with something more pragmatic,
         | like Kotlin.
        
         | otter-in-a-suit wrote:
         | I agree. Scala is actually usable for real-world use cases on a
         | much broader scale, simply by virtue of being on the JVM. I
         | wrapped some of the (unergonimic-because-code-gen'd) AWS
         | libraries in cats-effect just the other day, matter of fact.
         | Some of the native libraries do suffer from this "stylistic
         | neophilia" too, imo, but maybe not to the same degree as
         | Haskell.
         | 
         | Also, Scala 3 made a lot of great improvements, although the
         | tooling and library support arguably regressed w/ IntelliJ (I
         | assume that's temporary) and some of the (on paper) positive
         | changes - especially the whole type class derivation topic -
         | make older articles and books _very_ confusing for people just
         | getting into the language. I'd say making that migration happen
         | in larger code bases and companies will continue to be a real-
         | world challenge, but hopefully in the shape of a one-time
         | effort, rather than constant changes.
         | 
         | Also, based on the username, I assume that the parent comment
         | is by Li Haoyi. Funny how small the scala world is - I tend to
         | see the same names (you, Alvin Alexander, Gabriel Volpe, John A
         | De Goes) over and over. :)
        
         | urthor wrote:
         | I 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 wrote:
           | JVM debugging+monitoring is leagues better
        
         | reidrac wrote:
         | Scala has mostly all the issues the post is discussing. Perhaps
         | once you're on Scala 3 you're going to enjoy stability, but
         | your dependencies most likely won't give you that.
         | 
         | And the JVM, and compilation times, and poor Scala 3 support on
         | editors / IDEs.
         | 
         | I prefer the Haskell tooling TBH.
        
           | yw3410 wrote:
           | The Scala community is incredibly committed to stability;
           | every open source maintainer I know of in that space checks
           | for binary compatibility when releasing as well as cross-
           | compiling for multiple targets (Node, Web, Native) and
           | versions.
        
       | jsjdjd37 wrote:
       | [flagged]
        
       | dncornholio wrote:
       | What are we even doing here.
        
       | pooya72 wrote:
       | _If 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.
        
         | dgb23 wrote:
         | Efficient immutable data structures are more important for FP
         | than most of the features you listed. What is Java providing
         | there?
        
         | xwowsersx wrote:
         | > The community went from Cabal (and the infamous Cabal hell)
         | to Stack, and back to Cabal.
         | 
         | I didn't know this. I've been away from Haskell for a couple of
         | years. When I last used the language, Stack seemed like
         | smoothest experience and solved many of the pain points with
         | Cabal. The community went back to Cabal? What did I miss? :)
        
           | aetherspawn wrote:
           | I currently maintain a Haskell package and I have been
           | assuming everyone is using stack? I'm also interested to hear
           | what is going on
        
         | pyrale wrote:
         | > 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.
        
           | nobleach wrote:
           | Perhaps, but what you may not understand is that not ALL
           | developers _want_ a purely functional language. For some,
           | things like Kotlin hit a sweet-spot. One can lean a bit more
           | into a functional style, or they can lean more into an OO
           | style and it's acceptable. Some are very interested in
           | thinking in terms of Functors, Applicatives, Readers, etc...
           | some just want map/filter/reduce. That's what the Streams API
           | did for Java devs. For me, Haskell isn't "the goal". It's
           | simply one way of solving problem-sets.
        
             | mrkeen wrote:
             | > Perhaps, but what you may not understand is that not ALL
             | developers _want_ a purely functional language.
             | 
             | The ability to use pure functions is one of those hills
             | I'll die on. Hearing that not all developers want a purely
             | functional language is like hearing not all surgeons want
             | to wash their hands, or not all accountants want to use
             | ledgers.
        
             | Tainnor wrote:
             | Kotlin doesn't get enough love. It gets derided by some
             | Java developers for being too cutesy and sugary and it's
             | not talked much about by the kinds of people who love to
             | talk about Haskell, Lisp or Rust (no shade to these
             | languages), but to me it's the most pragmatic language I've
             | used so far.
        
               | paulddraper wrote:
               | > Kotlin doesn't get enough love.
               | 
               | Really???
               | 
               | It's probably the #1 language for new Android projects.
        
               | xwowsersx wrote:
               | I presume they meant outside of Android development.
        
               | dkarl wrote:
               | Speaking as a lover of Scala who has seen Scala codebases
               | go wrong in the cliche ways, Kotlin would be the first
               | language I would consider if I were starting a new
               | commercial software codebase today. Kotlin seems to have
               | enough of the pragmatic elegance of Scala to get the job
               | done with clarity and accuracy, without the curse of
               | attracting the compulsive intellectual thrill-seekers
               | that will ruin your Scala team if you accidentally hire
               | one.
        
               | xwowsersx wrote:
               | This is exactly how I feel, having written tons of Scala,
               | some Haskell and a multitude of other languages. It's why
               | I recently decided to build most new, large projects with
               | Kotlin at $job
        
               | nobleach wrote:
               | Compulsive intellectual thrill-seekers... while I never
               | want to call names, this does seem to explain the
               | phenomena quite well. There are just some people out
               | there that need the world to know how smart they are.
               | 
               | Anecdotal: I do know one guy however who's just so
               | ecstatic every time he figures new things out. To his way
               | of thinking, everything that comes with "functional"
               | truly is simpler. He built a dependency injector based on
               | a Reader. He built a cool Result library where he managed
               | to get at the internals of the JVM. Never once did he
               | come off as holier than thou. I can appreciate and
               | respect that.
        
               | dkarl wrote:
               | IMO "compulsive" is the damning word there. People who
               | don't enjoy learning typically don't make good
               | programmers, but you have to show respect for your
               | coworkers when you choose your learning opportunities.
        
             | pyrale wrote:
             | The meaning of my message wasn't that everyone should move
             | to a functional language, but that Java devs shouldn't. The
             | language has some decent features. Under all the OO
             | patterns and abuses of framework, there was a decent core
             | to save. My issue is that the community has declined to
             | write their own "Java - the good parts", and tried to bolt
             | half a dozen pair of wings on their supertanker because
             | planes are faster than boats.
             | 
             | As a java-turned-haskell-turned-java dev, I can enjoy some
             | OO programing, even though I prefer FP, but I definitely
             | don't enjoy unprincipled FP riddled with side-effects, null
             | pointers and built upon the quicksands of frameworks that
             | are thoroughly unfit for that purpose.
        
           | freilanzer wrote:
           | Poetic truth.
        
           | harry8 wrote:
           | yeah 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.
        
         | AnimalMuppet wrote:
         | I mis-read that as "stylistic necrophilia", which... rather
         | changed the meaning.
        
       | 1letterunixname wrote:
       | "Worse is better" phenomenon.
        
       | lcedp wrote:
       | The page appeares to be hugged to death. Google cache:
       | https://webcache.googleusercontent.com/search?q=cache:uWo0Ni...
        
       | friend_and_foe wrote:
       | I 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.
        
       | mattgreenrocks wrote:
       | This 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).
       | 
       | 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.
        
         | runeks wrote:
         | > 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.
         | 
         | Early return is mandatory for readability sometimes. I suggest
         | using ExceptT for this: https://www.stackage.org/haddock/lts-21
         | .8/mtl-2.2.2/Control-....
         | 
         | You don't even have to expose ExceptT in your interface; you
         | can just use it internally for early return and have your
         | function return an Either.
        
         | GregarianChild wrote:
         | > _PL that is essentially OCaml but with a better syntax._
         | 
         | Scala 3!
         | 
         | Python-ish syntax, much larger library ecosystem (due to JVM)
         | than either Haskell or Ocaml. Better integration of OO and FP
         | than Ocaml. So similar to Ocaml that idiomatic Ocaml has a
         | simple transliteration.
        
         | girvo wrote:
         | > 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.
        
           | chubot wrote:
           | Me three! I came from Python (now with MyPy), learned OCaml
           | and liked some aspects, was intrigued by Reason -- and also
           | sad it seems to be in limbo.
           | 
           | I also miss early returns, and break/continue.
           | 
           | I would like "modern ML" / "Python with sum types" / "Rust
           | with GC" language (indentation/braces doesn't matter to me).
           | Many people seem to agree.
           | 
           | Recently I found TypeScript is kinda fun for this, at least
           | if you're starting from no code, without ecosystem baggage:
           | 
           | https://news.ycombinator.com/item?id=37171801
           | 
           | AFAIK TypeScript's type system can do everything in OCaml --
           | it's extremely expressive -- but it's dis-similar in that it
           | doesn't use the types to compile to native code. I view that
           | as a downside because JITs are unpredictable and also huge.
           | 
           | It has early return/break. The syntax is pretty conventional,
           | with the usual JS weirdness that everyone has to know.
        
             | zogrodea wrote:
             | I wanted to be a fan of TypeScript and get to use it daily
             | on my job, but actual experience made me dislike the
             | language. I think you already know the pain of external
             | libraries (Express in my case) since you mentioned the
             | ecosystem baggage, and the lack of pattern matching is
             | another big minus for me.
        
       | rvz wrote:
       | [flagged]
        
         | lemper wrote:
         | [flagged]
        
         | js8 wrote:
         | I have only skimmed the article, but IMHO this is a pretty bad
         | summary. (For those who want a summary, the reasons are also
         | outlined in the article.)
        
       | tempodox wrote:
       | > 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 wrote:
         | Haskell'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 wrote:
           | To clarify, it's not "avoid success (at all costs)". It's
           | "avoid: success at all costs".
        
         | jeremyjh wrote:
         | I 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.
        
       | beanjuiceII wrote:
       | "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 wrote:
         | It'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.
        
       | blagund wrote:
       | My 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 wrote:
         | Typed 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.
        
       | andrewstuart wrote:
       | TLDR: the Haskell programmer who gives a shit has stopped giving
       | a shit.
       | 
       | * http://steve-yegge.blogspot.com/2010/12/haskell-researchers-...
        
         | hackandthink wrote:
         | Seth Briars could be me.
         | 
         | really funny, thanks
        
         | neuromanser wrote:
         | My 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.
        
         | m1keil wrote:
         | thank you for that xD
        
       | rowanG077 wrote:
       | Interesting. 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 wrote:
         | You 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 wrote:
           | You 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 wrote:
             | If 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.
        
               | rowanG077 wrote:
               | Which requires sweeping changes... In most other
               | languages it's literally a one liner where you want to
               | log something.
        
               | consilient wrote:
               | It requires changing the places where you instantiate
               | your monad transformer stack, which you should have very
               | few of.
        
               | rowanG077 wrote:
               | I don't think having very few is a good scenario. I have
               | written a compiler and had about 10 different stacks.
               | Changing every single one just to be able to add a logger
               | to a single function somewhere is honestly insane.
               | 
               | What I see in the wild is having one huge kitchen sink
               | stack which sucks as well.
        
             | doyougnu wrote:
             | Does every usage site have to change? You would alter
             | fibonacci to be:                 fibonacci :: (MonadLogger
             | m, MonadState (Int, Int, Int) m) => m Int       fibonacci
             | ...
             | 
             | and now of course all callers must support MonadLogger. But
             | instead of using the MonadLogger (or any mtl constraint
             | directly) you should just be constructing an abstraction
             | boundary with a type class synonym:                 class
             | (MonadLogger m, MonadState s m) => MyMonads s m
             | 
             | and now you change fibonacci:                 fibonacci ::
             | MyMonads (Int, Int, Int) m => m Int       fibonacci ...
             | 
             | And now if you need to add a monad or add Eq or whatever
             | you just have to change your type class synonym rather than
             | every function. Its not a problem with the language its
             | just programing with modularity in mind, even in the type
             | system.
        
               | rowanG077 wrote:
               | I have seen this in the wild. The result often is that
               | every function has a kitchen sink MyMonads constraint of
               | which it only uses a tiny subset. It's death by a
               | thousand cuts. If you make such a class for every monad
               | combination you get insanely large amount of classes.
               | It's simply unworkable. Which is why you get the kitchen
               | sink monad pattern.
        
               | kccqzy wrote:
               | And what's wrong with the kitchen sink monad pattern?
               | I've certainly used exactly that. And I have no problems
               | with it.
        
               | rowanG077 wrote:
               | Because your code is very much overconstrained at that
               | point. For the same reason you don't add a `Num a`
               | constraint to list `head` function. You have now
               | essentially fused your function to your codebase.
        
               | kccqzy wrote:
               | That's not a problem in business logic heavy code.
               | Requirements change and you could use previously
               | unnecessary constraints at any time.
        
             | icrbow wrote:
             | Debug.Trace has a lots of stuff for that. You can even
             | generate charts from that when using eventlog-enabled
             | runtime.
        
             | jaspervdj wrote:
             | If you wanted to log from fibonacci, you would pass a some
             | logger instance down to this function. In Haskell, this
             | could be a record or a typeclass instance. In other
             | languages, it could be an object or a struct. There is no
             | fundamental difference. All the layers above would still
             | have to pass this through; explicitly or implicitly.
        
         | valcron1000 wrote:
         | In the general case, adding IO to any piece of code requires
         | changing all callers. I would argue that it's a feature, not a
         | bug: now `f x` is no longer a value, but an action: calling it
         | twice can result in duplicated logs, for example.
         | 
         | If you need that logging for debugging then you should use
         | `Debug.trace` though.
        
       | pyrale wrote:
       | As 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.
        
         | wslh wrote:
         | I wonder why this discussion about tooling does not include
         | .NET languages or Swift, even if the first class tooling are
         | IDEs such as Visual Studio or Xcode. Most probably because the
         | open source world escapes big tech dependencies?
        
           | pyrale wrote:
           | That's simply because I talk about my personal experience,
           | and there's only so many languages you can experience
           | professionally over a few years.
        
           | Tainnor wrote:
           | No idea about .NET, but XCode is a joke of an IDE.
        
             | bootsmann wrote:
             | I appreciate the "run app on any iDevice" with one click
             | that xcode offers, but yeah the rest of the UI is terribly
             | clunky (Try moving the boundaries of frames).
        
               | Tainnor wrote:
               | Not just the UI. The IDE barely has any functionality.
               | Automated refactorings? Nope.
        
           | paulddraper wrote:
           | Linux
        
           | bluk wrote:
           | As much as I like Swift, the tooling has been and still is
           | subpar. Swift package management is barely viable.
           | 
           | You have to use Xcode. You can try other IDEs but LSP
           | equivalent features are at the most basic level. Xcode is the
           | kitchen sink of IDEs which has led to many negative opinions
           | as it struggles under its own weight. Every other year
           | there's new UI for things like debugging which is fine but
           | what would be really nice is if the actual debugging worked.
           | Technically there are reasons why you can't print a local
           | variable sometimes when stepping through a program, but in
           | practice, I do not care and I want to know what the value is.
           | 
           | If you don't care about the "optional" tooling like the
           | dependency manager and LSP or a linter (which is closer to
           | ESLint versus Rust Analyzer), the required tooling leaves
           | much to be desired. The compiler sometimes gives up when it
           | takes too much time to process a complex type. It would be
           | understandable in some cases but most people encounter the
           | problem when just writing seemingly simple SwiftUI. Error
           | messages and auto fix-it suggestions are improving but still
           | disappointing. I remember when Apple switched from GCC to
           | LLVM and everyone was praising the error messages as a reason
           | to switch.
           | 
           | Swift is actually ambitious. The generics system is world
           | class. It has to support the legacy of a huge ecosystem on
           | multiple platforms. SwiftUI is one of those bets that you
           | might be surprised that Apple can still make. But whenever I
           | fire up that SwiftUI Preview, I am crossing my fingers that
           | maybe I'll see something instead of an error. Swift lives up
           | to its name in terms of moving quickly and the language
           | design is probably fine, but outside of that, the tooling is
           | still very immature for a decade old language which tons of
           | resources are invested in.
        
             | agos wrote:
             | this has been my experience as well. After being one of the
             | five people who liked using Objective-C I was eager to have
             | this new, incredible language to work with, and pushed to
             | adopt it as soon as reasonable on all the codebases I
             | worked with.
             | 
             | That enthusiasm has since waned when stuff happened like
             | compilation times slowing to a crawl because somebody used
             | ternaries extensively. I still think it's a great language,
             | but the tooling really makes it hard to love
        
         | friend_and_foe wrote:
         | Yeah most tooling sucks. I think tooling in general was a bad
         | idea. A compiler and an interactive shell/interpreter are all
         | you need, you look at NPM and the current state of the python
         | package management system, a total disaster. I personally would
         | rather use a language where I had to include all dependencies
         | within my program, rather than automatically fetching them from
         | a remote server, deal with versions and version locks, all that
         | stuff was a bad idea.
        
           | throwawaymaths wrote:
           | > A compiler and an interactive shell/interpreter are all you
           | need
           | 
           | You might also want a good testing in the lang or stdlib, and
           | a documentation system.
        
         | alex_smart wrote:
         | What is wrong with Java's tooling?
        
           | xmcqdpt2 wrote:
           | Too much XML?
           | 
           | Seriously though what's a decent Java build tool? Hacking on
           | Gradle means having to learn another PL entirely. Maven?
           | 
           | Then say I want to publish a library for others to use from
           | their own java project, how do I do that? I've never actually
           | done it, but that page
           | 
           | https://maven.apache.org/repository/guide-central-
           | repository...
           | 
           | seems awfully complicated compared to say
           | 
           | https://doc.rust-lang.org/cargo/reference/publishing.html
           | 
           | or even the pip equivalent.
           | 
           | Granted, working on a well set up java project is nice, but
           | the setup process is not simple.
        
             | paulddraper wrote:
             | So you don't like a config language like XML because _____
             | and you don't like a DSL like Groovy because _____.
             | 
             | What is acceptable?
             | 
             | P.S. For easier publishing, use a different repo e.g.
             | Artifactory instead of Maven Central.
        
             | alex_smart wrote:
             | That maven link is perhaps not the most useful, but it is
             | not hard to find better-written articles. For example-
             | 
             | https://docs.github.com/en/actions/publishing-
             | packages/publi...
             | 
             | The steps are roughly: 1. Configure the repository you want
             | to push to. 2. Set up your account with the repository. 3.
             | Configure your credentials. 4. Deploy.
        
             | pjmlp wrote:
             | Not only do Maven and Gradle support binary libraries
             | (including native code) instead of waiting to build the
             | whole universe on each checkout, their plugins for mixed
             | language development are way better than writing build.rs
             | scripts.
        
             | chriswarbo wrote:
             | I actually prefer using Maven and its giant XML files: at
             | least they're declarative, and are easily parsed,
             | transformed, generated, etc. by scripts. Most attempted
             | replacements (Gradle, SBT, etc.) stick with largely the
             | same model (i.e. no extra functionality) but use a full
             | programming language for their "config" (Groovy, Scala,
             | etc.).
             | 
             | The latter gives us a "config" that's subject to Rice's
             | theorem: it's essentially opaque, with no way of knowing
             | what it will do other than executing it. An example I ran
             | into at work: there's no way to list the dependencies of an
             | SBT project (in order to set up an offline sandbox, in our
             | case for reproducible building with Nix). SBT provides
             | commands which _claim_ to do that, but config files often
             | append dependencies based on arbitrary logic; e.g. we had
             | some like  "when running unit tests, add this mocking
             | plugin"; since "list dependencies" doesn't run the unit
             | tests, that plugin dependency was missing from the sandbox.
             | 
             | I can't speak to the "publishing" situation for Java, I
             | don't have any experience with it. All of our projects
             | transparently pushed/pulled via a Nix cache, whether we
             | used Java, Scala, Python, NodeJS, etc.
        
               | grumpyprole wrote:
               | Yep, SBT and Gradle make Maven look good.
        
               | twic wrote:
               | Gradle is declarative. The 'code' you write does not
               | conduct the build; it assembles an object graph which
               | describes the build, much like the one you get from
               | parsing the Maven XML. The advantage of using code for
               | this is that you the description can be more concise,
               | expressive, etc. But once it's run, the graph is built,
               | and you can explore that, list dependencies, etc, quite
               | safely.
        
               | grumpyprole wrote:
               | > Gradle is declarative
               | 
               | Gradles own docs say "Well-designed build scripts consist
               | mostly of declarative configuration rather than
               | imperative logic".
               | 
               | When it's up to the programmer to make a script
               | declarative, it's not a declarative language.
        
               | Tainnor wrote:
               | > there's no way to list the dependencies of an SBT
               | project (in order to set up an offline sandbox, in our
               | case for reproducible building with Nix)
               | 
               | Well, the same is true for Maven. I know because I've
               | tried. Plugins can download arbitrary dependencies at
               | execution time.
               | 
               | That's where the point about Rice's theorem falls apart:
               | it applies as much to maven as to Gradle because maven
               | plugins can do whatever they want.
        
               | chopin wrote:
               | But that can't be runtime dependencies to your code?
               | 
               | I've written a couple of Maven plugins and you must
               | declare your dependencies explicitely even for those.
               | Pulling in stuff dynamically would be possible but not
               | very clever.
        
           | layer8 wrote:
           | Maven is awfully slow and awfully stateful (plugins or
           | multiple executions interfering with each other), has too
           | many quirks, and documentation is lacking. Gradle is
           | imperative and also stateful.
           | 
           | Dependency injection and annotation-driven development is
           | "magic happens here" that is hard to analyze when something
           | doesn't work, and hard to reason about in the sense of
           | building a proof that it will always behave in the correct
           | and intended way.
        
             | grumpyprole wrote:
             | Don't forget Scala's SBT, an awful design with lots of
             | additional bad taste added on top.
        
           | pyrale wrote:
           | If you ask for my personal experience:
           | 
           | - The community leans a lot on configuration over code, and
           | that's annoying. Sometimes, a hardcoded string in your conf
           | could have been a hardcoded string directly in the code.
           | 
           | - Sometimes, dependency injection systems are so abstract
           | that knowing which class is depended on in a specific runtime
           | instance becomes a pain in the ass.
           | 
           | - Your idea just won't load class x, the obvious "clean
           | cache" doesn't work as advertised, and you're back to stack
           | overflow to know which couple of file you need to get rid of.
           | That stuff happens just often enough for you to have a
           | lingering feeling of annoyance, but not often enough for you
           | to remember the exact files.
           | 
           | - Sure, idea is great. But in <other language> I was fine
           | with just vim. The LSP was a great help, not a lifesaver.
           | 
           | - Unit testing is great. Annotations are great. Don't you
           | enjoy that unit test class with a dozen annotations spanning
           | 20 lines just above?
           | 
           | - Hibernate. Spring too, while we're at it. Not sure whether
           | you consider this one squarely fits the tooling box.
        
             | systems_glitch wrote:
             | These are job security features :P
             | 
             | Seriously though, the hours spent fighting dependency
             | injection and Hibernate issues alone, when working on a
             | really big Java project, could've been a full-time job.
             | 
             | For maximum fun, I once worked on a large ERP system that
             | started out as a Struts 2/Hibernate 3/Jetty project and had
             | an entire Rails app bolted on using JRuby. Some of the
             | stuff in the JRuby side was injected thru Spring.
             | ActiveRecord had to talk through Hibernate.
        
               | patmorgan23 wrote:
               | Gross
        
               | systems_glitch wrote:
               | I know, right? Hundreds of millions of dollars flowed
               | through that system every year. I got the ball rolling on
               | killing that design with fire after we hit one of the
               | pathological limits in IIRC Hibernate 3 and thread
               | safety.
        
             | Tainnor wrote:
             | I agree with some of that criticism (although I haven't had
             | issues with having to manually delete files - if you do, I
             | suspect it's a project that hasn't been set up with a
             | proper maven/gradle setup but where all the build info is
             | in some IDE config. that's an antipattern at this point but
             | used to be very common).
             | 
             | But I don't think it's necessarily about the tooling.
             | 
             | And yes, Hibernate is just horrible.
        
               | pyrale wrote:
               | Everything is in Maven and works fine in CI, which
               | definitely does not use idea. But in some situations Idea
               | believes the pom isn't as fresh as its rendition,
               | unfortunately. I can live with some caching, but
               | everytime that happens and the "clean cache" option
               | doesn't work, I weep.
        
         | swader999 wrote:
         | I haven't seen better tooling than what's available for C#.
         | Curious to hear from others who strongly disagree.
        
         | lovasoa wrote:
         | > I simply wanted to filter job offerings based on social
         | utility rather than language stacks
         | 
         | I wish more people did that.
        
           | ParetoOptimal wrote:
           | In my experience the organizations that claim to have social
           | utility fail at it _and_ don 't pay well.
           | 
           | Language stacks are much easier to fact check.
        
             | pyrale wrote:
             | You don't have to listen to orgs to make your opinion.
             | 
             | There are plenty of orgs that obviously produce a vital
             | service for society, and they are usually starved of good
             | IT people: health care, social services, logistics,
             | electricity production & distribution, industry,
             | agriculture, emergency responders, etc.
             | 
             | > and don't pay well.
             | 
             | :(
             | 
             | Well, the comp is still high enough to live a comfortable
             | life, I just won't be able to bankroll a political party in
             | the near future.
        
           | Eddygandr wrote:
           | I think this happens with experience - I've recently done the
           | same after spending years chasing languages to work in
        
           | Symmetry wrote:
           | I good place to start looking:
           | 
           | https://jobs.80000hours.org/?int_campaign=job-board
        
         | otikik wrote:
         | > filter job offerings based on social utility rather than
         | language stacks
         | 
         | Any pointers on how to do this? A person that close to me is
         | thinking about entering the High Frequency Trading world, and I
         | would like to give them some alternatives.
        
           | RhysU wrote:
           | Pushing advertisements to people who don't want to see them?
           | /s
           | 
           | Every trade matches two parties who came to the market to
           | trade.
        
         | jgwil2 wrote:
         | Haskell's tooling has put me off ever really trying to get into
         | it again. However, I've dabbled in Purescript a few times and
         | it always seems to offer a pretty smooth experience, especially
         | if you're familiar with JS tooling.
        
           | george_____t wrote:
           | It has been rapidly improving over the last few years, though
           | this can mean it's difficult to keep up.
           | 
           | HLS (the LSP implementation) in particular is a pretty young
           | project, and key compiler improvements which will help it
           | improve are still landing.
        
         | Tainnor wrote:
         | I'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.
        
           | grumpyprole wrote:
           | Having developed Haskell professionally for many years, I've
           | spent the last two years programming OCaml professionally.
           | I've been really enjoying the OCaml tooling: dune, Merlin and
           | ocamlformat work extremely well for me. Dune especially is
           | packed full of features, for example a file-watch mode for
           | tests. Merlin doesn't choke on large codebases like some of
           | the Haskell tooling did and ocamlformat works better than any
           | code formatter I have ever used. The tooling is so good, I
           | can forgive the rather minimal standard library. OCaml is
           | also very good regarding backwards compatibility, new
           | releases don't break our builds.
        
           | revskill wrote:
           | Not quite. I'm not sure about how Ruby with Bundler related
           | to each other.
           | 
           | Recently, i upgraded Ruby, but then what's to do about
           | Bundler then ? I'm confused.
        
             | Tainnor wrote:
             | Bundler is Ruby's dependency management tool, basically
             | like npm or similar. It's come preinstalled with Ruby for a
             | while now.
        
           | js2 wrote:
           | It's weird how personal this is. Sometimes I wonder if it
           | comes down to familiarity.
           | 
           | I've been using Python professionally since 2000 and have
           | never run into issues with its tooling. It's even easier
           | these days: "python -m venv" and then pip are all I need in
           | 99% of use cases. For local development I use direnv + pyenv.
           | I typically develop on macOS and deploy to either macOS or
           | Linux. I previously gave pipenv a try but found it to be
           | brittle and more trouble than it was worth. I haven't used
           | poetry just because I haven't had the need.
           | 
           | Conversely, I regularly run into trouble with ruby. Here's a
           | recent example where I had to contribute a patch to pre-
           | commit to get ruby to install gems where pre-commit wanted it
           | to:
           | 
           | https://github.com/pre-commit/pre-commit/pull/2905
           | 
           | I got so annoyed with bundler I wrote a simple shell script
           | to provide the moral equivalent of Python venvs to gem:
           | 
           | https://gist.github.com/jaysoffian/3c67711d3f00c364365905d87.
           | ..
           | 
           | All that said, these are just minor annoyances. The only
           | tooling I truly despise is Gradle and especially everything
           | around the Android Gradle Plugin.
        
             | scruple wrote:
             | I've used Python intermittently throughout my career but
             | today it is my primary language. I've also never really had
             | issues and have pretty much always stuck with the basics.
             | I'm not on a very large team, though. Only 5 developers
             | will ever touch the Python we're writing. I've only ever
             | worked on Python on very small teams, so I wonder if that
             | factors in?
        
             | movpasd wrote:
             | I don't have any issues with Python's packaging ecosystem
             | anymore, having settled comfortably into a
             | pyenv+virtualenv+pip-tools as my "stack" after going around
             | the block a few times.
             | 
             | But even so, I must recognise how awful the experience is
             | for new users. It's taken me years to settle into this
             | system, and it can take half a day to get someone up to
             | speed with these tools if they haven't used them.
             | 
             | I also work a lot with non-developers who need to use or
             | contribute to Python models, so that doesn't help -- but I
             | bet it would take an order of magnitude less time to get
             | them up to speed with something like cargo. Coaching them
             | has helped me see how user-hostile the process is to
             | beginners.
             | 
             | It also doesn't help how infectious "all-in-one" Python
             | distributions like Anaconda can be, to the point that
             | whenever anyone has an unexpected issue one of my first
             | reflexes is to check their PATH. The fact that Rust has a
             | widespread default toolchain multiplexer completely solves
             | this issue.
             | 
             | I appreciate that maintaining such a toolchain is work, and
             | there is value as well in the diversity and choice of an
             | open ecosystem. But perhaps building is one place where
             | first-class support by the reference implementation creates
             | a worthwhile tradeoff.
        
               | kevin_thibedeau wrote:
               | I have issues precisely because of the misguided
               | preference for virtualenvs in favor of traditional system
               | package installation. It's obnoxious that pip now
               | admonishes you for installing into site-packages even on
               | a Debian system where that can't cause massive breakage.
               | When you need isolated containers it's great. Everyone
               | doesn't need a webdev focused, reproducible build for
               | everyday shell life.
        
               | dcow wrote:
               | You really shouldn't, though. If you use a dependency
               | manager for some deps you should use it for all deps.
               | Using a global/system cache would be great if
               | dependencies were versioned and each script could specify
               | which version is needed, but they're not to my knowledge.
               | And it's all fun and games until some random install
               | script somewhere updates a global dep and your stuff
               | breaks and you don't know where to even begin looking.
        
               | dcow wrote:
               | As someone new to using Python professionally after
               | having used it here and there over the course of 15+
               | years, I've run into exactly this problem. It's pretty
               | standard for a language these days to bundle the
               | dependency manager and build tooling. Python still does
               | this via shell infection. And since there's 5 different
               | ways to do it it can leave someone trying to figure out
               | what the right vibe is in 2023 spending hours reading
               | about the pros and cons of everything. And all that just
               | to land back on venv+pip+requirements.txt.
               | 
               | Python needs a cargo. Is Poetry it? I've been meaning to
               | try it...
        
               | systems wrote:
               | why do sometimes people say things like "and it can take
               | half a day to get someone up to speed with these tools if
               | they haven't used them"
               | 
               | half a day is like almost no time at all
               | 
               | half a day is just few hours, how is this a long time ..
               | how is this any time at all
               | 
               | makes me doubt myself a bit, am i too mediocre to think
               | that way
               | 
               | the previous line make more sense to me "It's taken me
               | years to settle into this system" , now this is more like
               | it
        
               | carbotaniuman wrote:
               | I don't think it's half a day to get proficient, it's
               | half a day to hack something half working together so
               | they're unblocked and can do the other stuff they want to
               | do.
        
               | throwawaymaths wrote:
               | And then another half a day to get pissed off because you
               | don't remember what settings are/are not in your venv and
               | trying to exit and/or get back into the venv (assuming no
               | prior experience with venv)
               | 
               | Fundamentally venv breaks your conceptions of what a
               | shell is through cleverness, and that's a problem for
               | people who are new.
        
               | codeflo wrote:
               | Half a day to get something running that's a "one off"
               | for you is insane. With a compiled language project, I'd
               | download a binary. In Python, I need to reproduce the
               | developer's setup. And I've yet to find two different
               | Python projects where the official build instructions are
               | compatible -- each one recommends a different environment
               | virtualizer, a different runtime, different settings, and
               | different C libraries that aren't part of the virtualized
               | environment.
        
           | bradrn wrote:
           | > I'm always confused about whether I should have ghcup or
           | stack manage my Haskell versions (and what the benefits and
           | drawbacks are)
           | 
           | There was a long and drawn-out transition, but these days
           | it's quite simple: use GHCup to manage your tooling, and
           | Cabal to manage your packages. At one point Stack was the
           | best option, but no longer: it's not as well maintained, and
           | is missing a lot of features (see e.g.
           | https://discourse.haskell.org/t/6849/23).
        
             | Tainnor wrote:
             | You say "don't use stack" and the other person in this
             | comment thread says "use stack". Do you see the issue?
        
               | bradrn wrote:
               | Fair enough, though I'll note that only I've given an up-
               | to-date reference.
        
               | nonameiguess wrote:
               | You posted a link to a forum. The official Haskell
               | language "get started" page says to use both:
               | https://www.haskell.org/get-started/
        
               | george_____t wrote:
               | It's listed after Cabal as an "alternative", so a lot of
               | people will presumably ignore it if they don't see any
               | reason why they'd want anything else.
               | 
               | I personally wish that page were even more opinionated,
               | but it's politically tricky.
        
               | Eddygandr wrote:
               | Stack vs Cabal was a huge argument where I worked with
               | multiple teams using different build tools. Add Nix and
               | nix2whatever, and it was more fun. Spent half my time
               | debugging build instructions
        
               | pastage wrote:
               | It is not that much better in Java land. Getting builds
               | right takes lots of resources, keeping new and old things
               | running is not trivial.
        
               | mrkeen wrote:
               | Yes. I've been in teams where there has been gradle vs
               | maven arguments.
               | 
               | Right now the Mac (M1 or M2) users in our team can't run
               | our integration tests. It has been suggested that if we
               | migrate our 50-100 services to Java 17 then the tests
               | will work for them again. Trying to do this breaks the
               | Gradle scripts, and the errors are so vague I can't tell
               | why it's complaining.
        
               | Tainnor wrote:
               | I haven't had that experience for newer code bases. Yes,
               | there's some ancient "works only in my IDE" stuff but
               | that's really not how modern Java is written.
               | 
               | Yes, there is a disagreement about whether to use maven
               | or gradle, but IMHO they both work reasonably well out of
               | the box.
        
               | twic wrote:
               | Right now, things are pretty good. But this is
               | surprisingly recent. Gradle and Maven have both been good
               | at managing dependency versions for a long time. Gradle
               | has also been good at managing the Gradle version, via
               | the wrapper, for a long time; Maven has equivalent
               | wrapper now, but it's quite new, and support in the wider
               | ecosystem is patchy (eg a TeamCity Maven build step can't
               | use a wrapper, i don't think). Meanwhile, there is no
               | standard way to manage JDK versions; there are SDKMAN!
               | and asdf, and they work fine, but they aren't de facto
               | standards. Gradle lets you specify the JDK version to
               | build with via toolchains, but this is quite new (6.7 in
               | 2020). I have no idea if Maven has an equivalent.
        
               | Mateon1 wrote:
               | In my experience, if you have to build an older maven
               | project, you have to go through a lot of painful hoops,
               | mostly around HTTP vs HTTPS repos and java
               | source/compiler versions. I have encountered many old
               | projects that don't build out of the box, and of those,
               | I've only managed to get about half working.
        
               | Tainnor wrote:
               | In that same thread that you've linked, other people have
               | later replied arguing for why they prefer Stack so... I
               | don't really think that you've given an argument that is
               | persuasive enough to someone who is new to Haskell.
               | 
               | (And I'm not even that new to Haskell. It's just that I
               | don't use it every day and when I come back to it and
               | have to remember the weird incantations and dances I have
               | to perform to make HLS not crash or want to overwrite my
               | stack-installed Haskell version, I'm usually rather
               | annoyed.)
        
           | pyrale wrote:
           | I'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.
        
             | mananaysiempre wrote:
             | > haskell is a small enough community that finding
             | mentorship is not always evident
             | 
             | I don't know about today, but ten years ago the answer was
             | to hop on IRC and you'd get all of your IRC-sized non-FAQs
             | answered, however difficult they are.
        
               | pyrale wrote:
               | There's libera chat now. But not everyone has the idea of
               | looking there.
        
               | bradrn wrote:
               | I'm not on IRC, but the subreddit, the Discourse forum
               | and the Discord server are all pretty good for this kind
               | of thing too.
        
               | tome wrote:
               | It's still the case, as far as I know. Big list of
               | channels: https://www.haskell.org/irc/
        
           | talideon wrote:
           | I expect that now that things are settling down around
           | pyproject.yaml, Python's tooling will settle down. I've been
           | settling on Hatch for most projects rather than using Poetry
           | these days and Flit for smaller projects. It's managing to
           | replace the mess of makefiles and shell scripts I used to
           | have and supports standardised metadata. These days, I mostly
           | use a combination of hatch, pip-tools (mostly when I'm
           | dealing with lambdas and Django projects), and pipx whenever
           | I'm doing anything with Python. it's not perfect yet, but
           | it's much improved. The new pip dependency resolver still has
           | its issues though if you haven't clamped your dependencies
           | sufficiently and its solver can get caught in loops of
           | excessive backtracking. Hopefully that'll improve too. pyenv
           | is still somewhat hit-and-miss though.
           | 
           | What's really surprised me lately is how much better OCaml's
           | opam tool has gotten! Last time I was using OCaml in anger,
           | the experience was very, very clunky, but these days it's
           | quite smooth.
        
             | pdonis wrote:
             | _> I expect that now that things are settling down around
             | pyproject.yaml, Python 's tooling will settle down_
             | 
             | First, a nitpick: it's pyproject.toml. YAML was considered
             | for the language of this file and rejected in favor of
             | TOML.
             | 
             | Second, unfortunately, I'm not sure I share your optimism.
             | This is an area where IMO the Python developers have never
             | been able to do things right. In fairness, they are trying
             | to support a lot of very different use cases, but the
             | proper way to do that would have been to let the
             | communities surrounding each of those use cases invent
             | their own tools, while focusing the standard tools in the
             | Python standard library on the vast majority of Python
             | projects that are pure python code--no extension modules,
             | no weird compilation issues, just pure Python modules and
             | packages for which build and install ought to be simple and
             | straightforward. But even that simplest use case was never
             | quite properly and standardly supported.
             | 
             | Even pyproject.toml illustrates this pattern: a _new markup
             | language_ was adopted, one which has _no_ support in Python
             | 's standard library, which has no obvious advantages over
             | previous file formats, and which now creates ambiguity
             | between pyproject.toml and the previous supposed "standard"
             | for declarative project metadata, setup.cfg. Which do I use
             | now? I can't just use pyproject.toml because it doesn't
             | include everything that setup.cfg does; and I can't just
             | use setup.cfg if I want my project to be compliant with the
             | latest build tool specs because setup.cfg alone is now
             | considered a "legacy" build format. So now I have to use
             | both, even for pure Python projects where this should have
             | been a solved problem years ago.
             | 
             | At least the actual installation of pure Python projects is
             | now a lot easier; once you have a properly built sdist or
             | wheel, pip install will put it wherever you need. But the
             | "properly built sdist or wheel" part is still IMO a lot
             | harder than it needs to be for most projects.
        
         | mberning wrote:
         | I'm a bit incredulous that Java's tooling is in the "sucks"
         | category. You could say a lot of negative things about Java,
         | but the tools available freely and commercially are in a league
         | of their own.
        
           | Tainnor wrote:
           | I think it's nuanced. IDEs are great, but there's often a
           | lack of good CLI tools and they often show their age. For
           | example, I find checkstyle rather annoying to configure and
           | use.
        
             | CraigJPerry wrote:
             | If you're looking for alternatives, SonarQube has jumped
             | quite far in the last few releases. I like the coherence of
             | the platform now and i find the default gates aren't
             | oppressive like they were in days gone by.
             | 
             | I've gone all in on them these days, the feedback from
             | sonarlint in the IDE is usually useful.
        
               | Tainnor wrote:
               | Last I checked, configuring stuff in SonarQube still
               | involves fiddling with the UI instead of config files.
               | And you need to host it somewhere.
        
               | [deleted]
        
           | pyrale wrote:
           | Well, it really depends on what you value in your tooling I
           | guess. I tend to appreciate minimalist tooling, and Java
           | definitely doesn't fit that bill.
           | 
           | To be fair, the language _needs_ that tooling to be
           | practical, and the quantity of it isn 't helped by its long
           | history so it isn't necessarily the tool makers that are to
           | blame.
        
           | dkarl wrote:
           | What Java build tool would you say does dependency management
           | decently? Most people are still using Maven or Gradle.
        
             | Tainnor wrote:
             | Depends on what you call "decently". Maven and Gradle do
             | the job, but the bigger problem is the ecosystem:
             | 
             | Libraries don't declare version ranges for their transitive
             | dependencies (like they do e.g. in Ruby), instead they just
             | depend on a specific version. Of course, because two
             | different libraries may depend on the same subdependency
             | but in different versions, you will just get one version
             | and you have no way of knowing whether it will work
             | correctly.
             | 
             | That isn't a problem in 90% of cases, but sometimes it is
             | and you'll notice it when you're suddenly getting
             | ClassNotFound exceptions.
             | 
             | There are some solutions to this, e.g. bigger frameworks
             | like Spring publish BOMs, which are just sets of library
             | versions known to work together, but they don't cover
             | everything.
        
               | dkarl wrote:
               | > Libraries don't declare version ranges for their
               | transitive dependencies
               | 
               | That's the behavior that Maven itself recommends, so
               | Maven is at least part of the problem.
               | 
               | Maven could also sanity-check your build for these issues
               | by default, but it doesn't; it leaves that up to plugins,
               | which you have to configure (in XML) in your build file
               | every time you set up a new project.
        
               | tadfisher wrote:
               | You can depend on version ranges with Gradle, and those
               | ranges are transitive if the library is also using
               | Gradle; otherwise, you can override a library's
               | transitive dependencies pretty easily with component
               | metadata rules.
               | 
               | You can do so much with Gradle, but 90% of learning it is
               | figuring out what knobs you need to twist; there's a lot
               | of feature overlap and second-system-effect going on.
        
             | pjmlp wrote:
             | Rightfully so, most of the alternatives are found lacking
             | in feature parity.
        
             | paulddraper wrote:
             | Maven or Gradle
        
               | dkarl wrote:
               | I feel like Maven is doomed by its history. When Maven
               | was created, expressing dependencies with version ranges
               | was encouraged. But there was no lockfile concept, so
               | that did not work well. Instead of adding lockfiles, they
               | decided to leave the tool as it was but encourage people
               | not to use dependency ranges. But dependency ranges are
               | still supported, so you need a plugin to check your POM
               | files and make sure you aren't using them. Dependency
               | resolution is recursive, so indirect dependencies might
               | still use version ranges, so you need a plugin to detect
               | those ambiguities so you can pin those versions yourself
               | in your own POM. If, despite your best efforts, you end
               | up with an indirect dependency being specified with two
               | different versions, Maven doesn't mind that at all (by
               | default, if will package both, and leave it up to chance
               | which one gets loaded at runtime)[0] so you need a plugin
               | to detect that situation as well.
               | 
               | To sum up, we realized the default behavior was wrong
               | over a decade ago, but rather than change the default
               | behavior of the tool, maybe add a new version of POM
               | files where sanity is the default (it's a versioned
               | format! c'mon!) or a new non-XML file format that
               | triggers a new mode of operation, they stuck with the
               | legacy behavior, forcing every new project to include a
               | bunch of XML boilerplate just to get the behavior that
               | they realized should have been the default 15+ years ago.
               | 
               | That was the situation last time I used Maven, anyway.
               | I'd love to hear that Maven has since added a new mode of
               | operation that is sane by default, without needing extra
               | plugins and configuration, and doesn't use XML.
               | 
               | I can't comment on Gradle. I've worked on a couple of
               | Gradle projects, and the build files were a mess, but I
               | don't know if they needed to be a mess or it was just bad
               | luck.
               | 
               | [0] Actually I don't remember if the default is to pick a
               | version at build time or to package both, but I know the
               | latter is possible because I saw it cause many production
               | issues before we configured a plugin to prevent it.
        
               | yw3410 wrote:
               | Also, Mavens metadata model is recursive. You want need a
               | dependency? You're going to have to pull in the parent,
               | which is probably an Uber pom. Take a look at your M2
               | cache, it's probably got a kubernetes pom even if you've
               | never touched it before because your logging library uses
               | an Uber pom...
        
               | TJSomething wrote:
               | Gradle can be quite good, but it's also really easy to
               | make a completely unmaintainable Gradle file.
        
               | twic wrote:
               | Gradle is expressive and extensible, but unfortunately,
               | that encourages programmers to express themselves and
               | extend it.
        
               | paulddraper wrote:
               | > expressing dependencies with version ranges was
               | encouraged
               | 
               | In years of Java development, I've seen that only once,
               | maybe twice.
               | 
               | And this was 8+ years ago.
        
               | dkarl wrote:
               | The v1 release of Maven was in 2004. But it's unfortunate
               | that Maven moved away from ranges. The "problem" with
               | ranges was that they created non-reproducible builds,
               | because different dependency resolutions could change the
               | build. Every new release of a third-party dependency had
               | the potential to invalidate a tagged and tested version
               | of your application.
               | 
               | Other build tools in other languages decided to use
               | lockfiles to achieve stable builds with dependency
               | ranges. If your application depends on libraries A and B,
               | and A and B depend on library C, then the build tool can
               | check that the lockfile specifies a version of C that
               | fits the ranges specified by A and B, or, if library C
               | isn't in the lock file, find an appropriate version of
               | library C and add it to the lock file.
               | 
               | But not Maven. Maven's solution is for A and B to declare
               | dependencies on exact versions of library C, and then to
               | pick one or the other depending on many degrees of
               | transitivity separate your project from A or B.
               | Seriously:
               | 
               | "Maven picks the 'nearest definition'. That is, it uses
               | the version of the closest dependency to your project in
               | the tree of dependencies. You can always guarantee a
               | version by declaring it explicitly in your project's POM.
               | Note that if two dependency versions are at the same
               | depth in the dependency tree, the first declaration
               | wins." [0]
               | 
               | So if A depends on C 1.2 and B depends on C 1.5, and A
               | appears before B in your pom file, Maven will bundle 1.2
               | with your application and not fail the build.
               | 
               | I don't know the history of how anybody ever thought that
               | was a good idea. Anyway, they quickly realized that
               | pinning versions in the build was the right solution
               | after all, but instead of adding a separate lockfile,
               | they decided to make you list all the versions in the
               | project file itself. Which is exactly where you want all
               | your transitive dependencies listed, right in your build
               | file, taking up half a dozen lines each because it's XML,
               | right?
               | 
               | Of course Maven is still happy to fall back its "pick the
               | first nearest" algorithm if you fail to pin one of your
               | transitive dependencies, which means your builds might
               | not be reproducible. My boss (quite sensibly) said our
               | builds had to be reproducible no matter what Maven
               | allowed or encouraged, so I had to write a plugin to
               | check for that.
               | 
               | The real tragedy is that because library publishers no
               | longer use dependency ranges, you get to debug and
               | discover violations of semver yourself. Does library A,
               | which specifies C 1.2, also work with C 1.5? The
               | publishers of library A might know that it doesn't, but
               | they don't publish that fact with their library. Jackson
               | plugins were especially prone to semver-unexpected
               | breakage because Jackson didn't have any stable API for
               | plugins. Jackson plugins typically had to use private
               | implementation details of Jackson to work at all, so they
               | sometimes broke on patch releases of Jackson. Library
               | publishers could have encoded knowledge about this kind
               | of breakage in their dependency declarations, but "best
               | practices" said to specify a single version, so that's
               | what they did.
               | 
               | [0] https://maven.apache.org/guides/introduction/introduc
               | tion-to...
        
           | pooya72 wrote:
           | Yes, it's definitely much easier to get up and running with
           | Java than it is with Haskell. This includes everything from
           | setting up the JDK, setting up your IDE, to building and
           | deploying your applications.
        
         | mymac wrote:
         | If only Python would be able to really solve their dependency
         | and backwards compatibility issues, those are really holding
         | the adoption back. Though there is a good chance that even if
         | they fixed those that people burned in the past will never go
         | back into it.
        
           | boxed wrote:
           | > [python] backwards compatibility issues
           | 
           | What issues? A lot of problems with Python is due to keeping
           | compatibility with Python 2.0. Implicit string concat bites
           | me fairly often for example, and it has never been useful.
        
             | mymac wrote:
             | 2->3 has been a complete disaster, anything older than a
             | few weeks tends to randomly break with some kind of
             | dependency issue, sometimes requiring multiple
             | installations of python on the same machine which will bite
             | each other in hard to predict ways. Python is a wonderful
             | idea but I've yet to be able to write something in python
             | and call it 'finished' because it never ever continues to
             | work in the longer term. Highly frustrating and in my
             | opinion unnecessary.
        
               | boxed wrote:
               | > 2->3 has been a complete disaster
               | 
               | It WAS a long slog yes. But now it's pretty much done.
               | And there really was no way to fix the unicode issue
               | without a big painful transition.
               | 
               | > anything older than a few weeks tends to randomly break
               | with some kind of dependency issue
               | 
               | I absolutely do not have this issue. Maybe you're using
               | libraries very different from what I do? But I do think I
               | have pretty wide interests/projects...
               | 
               | > sometimes requiring multiple installations of python on
               | the same machine which will bite each other in hard to
               | predict ways
               | 
               | I don't know what you're talking about here. Do you have
               | an example?
               | 
               | > I've yet to be able to write something in python and
               | call it 'finished' because it never ever continues to
               | work in the longer term.
               | 
               | I don't have this experience.
        
           | paulddraper wrote:
           | What dependency and backwards compatibility issues does
           | Python have?
           | 
           | That other languages don't?
        
             | mymac wrote:
             | Python software simply rots while you're not watching it.
             | Either you make it a full time occupation, every time some
             | library gets an 'upgrade' (with a ton of breaking changes)
             | you get to rewrite your code, sometimes in non-obvious and
             | intrusive ways. And every time the language changes in some
             | breaking way you get to spend (lots of) time on debugging
             | hard to track down problems because the codebases they
             | occur in are large enough to mask the problems that would
             | have come out if the same situation had occurred during
             | development.
             | 
             | And that's before we get into the various ways in which
             | python versions and library versions can interfere with
             | each other. You couldn't have made a much bigger mess if
             | you tried. And I actually _like_ the core language. But so
             | many projects I wrote in python just stopped working. I
             | remember having a pretty critical chunk of pygame code
             | written for a CAD system that just stopped working after an
             | upgrade and there was no way it was ever going to run again
             | without rewriting it. That 's the sort of thing that really
             | puts me of an I remember it long after. Machine learning
             | code is still so much in flux that it doesn't matter. But
             | hardware abstraction layers such as pygame should be long
             | lived and stable between versions. And that really is just
             | one example.
             | 
             | Anyway, I think asking 'That other languages don't' doesn't
             | really matter. But Haskell (see TFA) is one language that
             | always tried hard not to be successful so breaking changes
             | would be permitted (which is fair). Python tries both to be
             | popular and to allow for major stuff to be broken every now
             | and then and that is very rough on those that have large
             | codebases in production.
             | 
             | By contrast, COBOL, FORTRAN, LISP, ERLANG, C and C++ code
             | from ages ago still compiles, maybe you'll have to set a
             | flag or two but they're pretty careful about stuff like
             | that.
        
               | aidos wrote:
               | Are you pinning your dependency versions? If so, things
               | should all still work later.
               | 
               | If you upgrade libs then sometimes you need to do some
               | work. I've found python libs to be pretty stable though
               | so it's never too bad.
        
         | regularfry wrote:
         | Cargo is an evolution of older ideas from Ruby's bundler, so in
         | a sense it does have a longer pedigree than most other tools of
         | that ilk. Bundler _mostly_ doesn 't suck. There are design
         | choices I disagree with but there's a happy path to using it
         | that gets a lot right. There are ways to do language tooling
         | that don't suck.
         | 
         | Without much direct experience of cargo I can't say whether
         | that carries across, but I wouldn't be surprised if it was
         | genuinely the best of breed _and stays that way_.
        
           | paulddraper wrote:
           | All I know about Ruby is that I always seem to download three
           | versions of documentation
        
             | nobleach wrote:
             | Back when I used to use Ruby 10 years ago, I got used to
             | doing the "no docs" args when I'd do a gem install. I
             | always thought it was a cool idea to have local docs but, I
             | never had an occasion to actually USE them. (never was I
             | stuck in a non-internet-connected zone, wishing I had
             | documentation)
        
             | regularfry wrote:
             | Adding `install: --no-document` into ~/.gemrc is something
             | of a reflex for me. Should only be getting `ri` docs these
             | days by default though.
        
           | saurik wrote:
           | FWIW, the thing which really sucks about cargo is how it
           | handles cross-compilation. Most "professional" workflows are
           | _always_ cross-compilation: even if you are technically on
           | Linux already you don 't want to build for the exact version
           | you have so you create a sysroot and cross compile towards
           | it... and cargo is somehow so bad at this that increasingly
           | large numbers of projects are being forced to turn on a
           | environment variable that has in the name of the variable
           | DO_NOT_USE to shift cargo stable into accepting nightly flags
           | so we can activate a patch that they begrudgingly committed
           | to fix the behavior of targets to not get infected by host
           | configuration if they happen to look similar. The goal was
           | that this would eventually become the default but it's been
           | years now and the related bugs are just stacking up. As a
           | package manager I'm sure it's great... as a build system? Not
           | so much.
           | 
           | The situation frankly really just sucks: as far as I am
           | concerned--from the shear number of bugs I have run into
           | trying to do what should be table-stakes, and which even
           | autoconf handles trivially: doing deterministic builds across
           | platforms of a library to be embedded into another language's
           | build system--cargo optimizes for extremely simple use cases
           | (hell: ones so simple they lead to the wrong mental model of
           | compiling in the first place! like, people seem to seriously
           | think you need to compile for old systems ON old systems
           | using old tools as cross-compilation is somehow treated as
           | esoteric) while throwing the people who know what they are
           | doing under the bus, which isn't at all how one should build
           | tooling; instead, the goal should be to make extremely
           | difficult things easier to pull off, even if it means the
           | simple things have to be a bit harder, as your overall
           | workflow is then easier to manage and you can better grow
           | with your tooling rather than having to eventually throw it
           | away entirely.
        
             | 15155 wrote:
             | Does `cross build` not work for your use cases?
        
             | twic wrote:
             | Just do the build in a container modelling the appropriate
             | environment. You don't need cooperation from the build
             | tools (apart from controlling instruction selection), and
             | you also don't need to trust that the build tool has
             | implemented this feature correctly!
        
             | kibwen wrote:
             | You can set a default build target for a Cargo project with
             | two lines of configuration, no nightly features necessary:
             | https://doc.rust-
             | lang.org/cargo/reference/config.html#buildt...
             | 
             | Can you clarify what this is referring to?
             | 
             |  _> the goal should be to make extremely difficult things
             | easier to pull off, even if it means the simple things have
             | to be a bit harder_
             | 
             | There are dozens of existing build systems that have this
             | philosophy, and personally I appreciate the default system
             | being optimized for the average use case. The fact that the
             | happy path is so easy is the reason that people
             | overwhelmingly choose to use Cargo; we can lie to ourselves
             | all we like about the appeal of things like memory safety
             | and type safety, but at the end of the day Cargo is the
             | reason that Rust is popular. (And to be clear, I'm not
             | trying to say Cargo is perfect; I have a slew of my own
             | bugs and feature requests filed against it.)
        
             | regularfry wrote:
             | Yeah, that tracks. That sort of cross-compiling isn't
             | something you'd ever see in the Ruby world, as far as I can
             | recall, so I guess it's a reversion to the mean.
        
           | pyrale wrote:
           | > so in a sense it does have a longer pedigree than most
           | other tools of that ilk.
           | 
           | That's true of most new languages. It seems like most
           | projects these days can produce a LSP with minimal effort,
           | make the obvious choice of sandboxing every project
           | separately to avoid dependency hells across projects, have at
           | least basic distribution systems even with small communities,
           | etc.
           | 
           | The community learned _a lot_ from the mistakes of yore.
        
       | JackMorgan wrote:
       | Many 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.
        
       | xwowsersx wrote:
       | 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. 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.
        
         | mrkeen wrote:
         | > 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/
        
         | BellsOnSunday wrote:
         | There 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 wrote:
         | > 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/...).
        
       | yakshaving_jgt wrote:
       | It'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.
        
       | regularfry wrote:
       | Hm. 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.
        
         | paldepind2 wrote:
         | You're absolutely right. That is particular example is bad
         | because you don't actually need the power of flapMap/bind. But,
         | if the available containers depended on the flavor and the
         | available toppings depended on the flavor and/or container,
         | then you would need flapMap/bind and do-notation would pull its
         | weight.
        
         | Tainnor wrote:
         | The 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).
        
           | regularfry wrote:
           | The 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.
        
             | Tainnor wrote:
             | > The thing is, none of those other examples cause
             | indentation depth problems in other languages
             | 
             | They do, I've seen it happen before. Callback hell was a
             | thing in JavaScript, before Promises happened (and later
             | async/await). And if you've ever written in a functional
             | programming style in a language that doesn't have a first
             | class abstraction for monadic code, then you might have
             | seen cascades of flatMap and map.
             | 
             | FWIW, do notation is not the only option, Scala has for
             | comprehensions that accomplish the same goal.
        
             | twic wrote:
             | "Haskell is best at solving problems that Haskell invented
             | and other languages do not have." -- Jon Harrop
        
           | asplake wrote:
           | To me the 'product' in the Ruby example above is helpfully
           | explicit and could be changed for something else.
        
       | joeyh wrote:
       | This 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 wrote:
         | Do 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 wrote:
           | https://www.well-typed.com/blog/2015/11/implementing-a-
           | minim...
        
       | pmarreck wrote:
       | For anyone new-language-curious, Idris is a very interesting
       | project that is inspired by Haskell but which seems to have less
       | design drawbacks
        
       | lykahb wrote:
       | I'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.
        
       | IceDane wrote:
       | I 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.
        
       | runeks wrote:
       | > 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...
        
         | mrkeen wrote:
         | > 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.
        
         | tinco wrote:
         | > 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?
        
       | hardwaresofton wrote:
       | Site got HN hugged (probably):
       | 
       | https://web.archive.org/web/20230824095246/https://journal.i...
        
       | d_burfoot wrote:
       | As 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 wrote:
         | If 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.
        
         | Tyr42 wrote:
         | When 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.
        
       | kagevf wrote:
       | > 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 wrote:
         | I 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)
        
       | Pannoniae wrote:
       | Basically, 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.
        
         | consilient wrote:
         | > Basically, the author's criticism is that the language is too
         | powerful, too expressive, people try very abstract things
         | 
         | I think this is a bit unfair. The author's criticism is that
         | people try very abstract things _and don 't stick the landing_.
         | And to an extent I agree, but the problem isn't that Haskell is
         | too powerful, it's that it's _just barely powerful enough_ for
         | too many things. Contra the author, GADTs are not one of those
         | things, and snoyman can pry them from my cold dead hands. But
         | singletons clearly are. So are impredicativity, open type
         | families, type level arithmetic, and Template Haskell.
         | Idiomatic Haskell practically writes itself, but type-level
         | Haskell is at least as hard as C, and it 's almost entirely
         | because of how terrible the ergonomics are.
         | 
         | > Third, about backwards compatibility
         | 
         | Strongly agree here, if anything GHC doesn't break backwards
         | compatibility enough. `Num` is an abomination.
        
           | jerf wrote:
           | I think one of the problems that people who get overexcited
           | about functional languages and all the strong typing and such
           | have is that they generally start out in a bad place.
           | Imperative programs with every flaw in the book, threading by
           | locks, for loops that try to modify the index mid-loop,
           | mutation running rampant, all the bad things they complain
           | about. I've worked in those code bases in industrial
           | contexts, they can be nightmares for sure.
           | 
           | So they discover functional programming, and they just get
           | hammered with so very many different ways of doing things. At
           | first it all seems impossible, but then it slowly unlocks
           | itself, and look! All the problems with imperative programs
           | went away! You didn't even properly perceive them before, but
           | they're gone.
           | 
           | You can't hear me, so my tone here is completely serious. I
           | strongly recommend any professional programmer spend some
           | time with a language like this and attain enough fluency to
           | write real, non-trivial code in it, not just map a few lists
           | and maybe use a monad or two. Get something that hits the
           | network or something.
           | 
           | And the problem is, too many of them stop here. Conventional
           | programming sucks. Functional programming rules. Anyone who
           | doesn't use functional programming languages is a loser still
           | wandering blind in the wilderness.
           | 
           | However, there are in fact a lot of practical problems with
           | functional programming languages too, many in the original
           | blog post, others expressed elsewhere. It can be as simple
           | as, that critical library I need is not available in my
           | obscure niche functional programming language, but alas, in
           | the real world, that's enough to be a determining factor.
           | 
           | Where the religious-level advocates of FP lose contact with
           | reality is that there's a third option: You take what you
           | learned in the functional programming world and come back
           | into conventional languages. And I don't mean "use a few maps
           | and jam a monad in to your language even though it completely
           | fails to fit"; that's actually still completely missing the
           | point of functional programming. I mean, you start writing
           | "conventional" code except you pay attention to mutation. You
           | may not write completely pure code everywhere, but the more
           | you mix in the more characteristics of pure code, the more of
           | the benefits you get. (I do think there's an interesting
           | discontinuity at 100% pure, when you can 100% count on it and
           | then build further on that ability to be _sure_ all code is
           | pure, _but_ you do still get a gradient of benefits the more
           | purity you put into your conventional code.) You pay
           | attention to side effects and start isolating them into units
           | instead of mixing them in. You learn how to multithread with
           | messages instead of memory sharing and locks. You don 't drag
           | in inappropriate APIs from a foreign paradigm; you take the
           | fact your eyes were opened, and you write code with those
           | now-opened eyes.
           | 
           | And it is not perfect. You will still occasionally have the
           | original imperative problems. But you will have radically,
           | radically fewer of them, so few that the cost/benefit
           | analysis of using the super-strong stuff becomes very
           | difficult to justify, especially over the advantages of being
           | able to use that library you really need. (And see the
           | library has a mutation problem and wrap it in a way that
           | solves it for you, instead of letting it drag the rest of
           | your code base down, etc.)
           | 
           | I have ridden the mighty moonworm... errr... I have fiddled
           | with the Haskell type system and done some interesting things
           | with it. But by and large they really weren't worth it, not
           | in the sense that they don't solve some problem, but in the
           | sense that back in the conventional programming world, I
           | really don't _have_ those problems anymore. No credit for
           | solving problems I don 't have.
           | 
           | This is where I diverge with people complaining about not
           | using functional programming. They are comparing writing
           | imperative crap with writing pristine functional code. In
           | this context I don't deny I'd take the functional code too.
           | But I am comparing writing eyes-open conventional code with
           | writing normal functional code. In this context the
           | advantages are a _great_ deal more muted and it isn 't
           | anywhere near the day-or-night level of difference... and I
           | gotta say, pitching me back on full-on functional programming
           | by claiming I just don't get it and I just want to write bad
           | code and enable bad code and in general be lazy and bad is
           | bad advocacy in almost every possible sense of that term.
        
             | consilient wrote:
             | > And it is not perfect. You will still occasionally have
             | the original imperative problems. But you will have
             | radically, radically fewer of them, so few that the
             | cost/benefit analysis of using the super-strong stuff
             | becomes very difficult to justify, especially over the
             | advantages of being able to use that library you really
             | need.
             | 
             | This has unfortunately not been my experience. Working
             | alone, sure, I can write acceptably pure code in a
             | conventional language. But generally the issue isn't what I
             | _can_ do, it 's what my coworkers _will_ do. Even if almost
             | everyone manages to maintain strict discipline without the
             | support of the language, it really only takes one
             | "productive" cowboy to create a disaster. The biggest
             | advantage of pure functional programming is that taking the
             | path of least resistance produces code that's still sort of
             | ok.
        
             | behnamoh wrote:
             | This is amazing! Thank you for writing it. Maybe you should
             | write a blog or something.
        
             | Pannoniae wrote:
             | I apologise for the comparison, as your thoughts are very
             | well-structured, and in my head it almost sounds like an
             | insult. But this kind of thinking ("more discipline
             | minimises the problems related to suboptimal languages") is
             | kind of like Uncle Bob's test-zealotry - i.e. you don't
             | need static typing/AOP/linting/any kind of bug-reducing
             | feature, _because you can just write more tests_ (even if
             | it 's painful or spurious)
             | 
             | Sure, it _is possible_ to be very disciplined, avoid messy
             | control flow, be careful with mutation, etc.... then good
             | luck trying to get everyone else to get on board with a
             | very niche coding style, unless if you have the strict
             | authority to enforce it. Sadly, in most cases you don 't,
             | so you are stuck with the non-verifiable madness.
             | 
             | In an ideal world, this would work - but in an ideal world,
             | we would also be using better languages with way better
             | guarantees and compile-time checks.
        
               | jerf wrote:
               | I don't really get your point, other than trying to
               | insult everyone. It's fairly well established that in the
               | real world, strict functional programming languages
               | aren't an option. So who really cares that you keep
               | railing on about them? Until they're an _actual_ option,
               | we are not being  "zealots" when we _can 't_ use them...
               | not "refuse" to, _can 't_... and, yes, you're just being
               | an insulting jerk with no real options to offer anyone.
               | 
               | If you want to be wistful for a world where we could use
               | better languages... get in line. It's a long one. But
               | stop expressing it in the form of insulting other people.
               | 
               | You are not the smartest in the room, you are not the
               | only one who has grappled with the issues, and if you'd
               | stop going out of your way to insult everyone else, maybe
               | you could listen to and learn from people offering
               | solutions. Even if they aren't perfect; it's hardly as if
               | you're offering a perfect one either. You aren't offering
               | one _at all_.
        
               | yakshaving_jgt wrote:
               | > It's fairly well established that in the real world,
               | strict functional programming languages aren't an option.
               | 
               | This just isn't true.
               | 
               | We write essentially 100% Haskell where I work. All day,
               | every day. Have done for years.
               | 
               | We have a "real world" business, with real customers, who
               | pay real money.
        
         | xedrac wrote:
         | > 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.
        
           | Pannoniae wrote:
           | Sure, it might help with industrial adoption, but the more
           | you commit to backward compatibility, the more mediocre your
           | language becomes. (You can't really adapt new things if you
           | have to keep everything around.)
           | 
           | What's the point in creating the N+1th generic blub language?
        
             | [deleted]
        
             | xedrac wrote:
             | What's the point of creating a language that isn't used? If
             | the goal of the language is to academically research new
             | programming techniques, then fine. Other languages will
             | eventually adopt some of the more useful ideas and industry
             | development will improve because of it.
        
               | Pannoniae wrote:
               | Not creating something because people don't want to use
               | it is really myopic thinking in my opinion. That's like
               | not creating art because no one buys it. Deliberately
               | aiming for something worse in hopes of public/industrial
               | acceptance is not a good approach IMO.
        
               | runeks wrote:
               | > Deliberately aiming for something worse in hopes of
               | public/industrial acceptance is not a good approach IMO.
               | 
               | It's not "worse", it's a tradeoff between backwards
               | compatibility and fixups. Backwards compatibility is a
               | really useful feature in and of itself, and the question
               | is whether this outweighs the usefulness of all the tiny
               | fixups. In my opinion it mostly does.
        
               | Pannoniae wrote:
               | I agree with you, it's a tradeoff. I definitely don't
               | want to say that backwards compatibility is not
               | important..... but when you have N other languages
               | priding themselves on that, what is the value add in
               | creating another stagnant but stable language like that?
               | 
               | I think the reason why this is not emphasised more is
               | because breaking compatibility is a visible cost (program
               | broke, time to investigate and fix it) while the pains
               | from maintaining backwards compatibility is an invisible
               | cost. (you can't easily quantify the wasted hours and
               | extra bugs from unintuitive/broken language features)
               | This is kind of a natural consequence of the incentives,
               | so I understand why it happens. I'd be happier if it
               | wouldn't.
        
         | bigbillheck wrote:
         | > Sure, your code will compile in 5 years most likely without
         | changes,
         | 
         | Five years goes by a lot faster than you might think.
        
         | mathisfun123 wrote:
         | > Second, this is similar to the "equalise things by dragging
         | everyone down to the same level"-type of thinking.
         | 
         | > and not allowing for an opportunity to write really good
         | code. Basically, enforced mediocrity.
         | 
         | > straightforward, laziest, zero optimisation code, and giving
         | themselves an excuse for that.
         | 
         | > justify their laziness,
         | 
         | Jesus christ you have so much disdain for such a large set of
         | people. Have you ever considered that you might have a chip on
         | your shoulder about Haskell adoption?
         | 
         | > There should be a place for languages which are ambitious and
         | aren't afraid to break things.
         | 
         | There is - it's research and hobby, not production. Like
         | literally "not afraid to break things" is the antithesis of an
         | industrial language.
         | 
         | Sometimes I wonder if some language communities really are
         | cults. It's the same with Lisp - replace "type system" with
         | "homoiconic" and you have the exact same mantras about ultimate
         | supremacy and "intellectual" superiority. But the proof of the
         | pudding is in the eating and across probably 10 computing
         | devices in my home, not a single one has any Haskell or Lisp
         | programs running on it. Lots of Java, C, C++, Python, Rust,
         | Bash, JavaScript, even Perl (probably) but not a single binary
         | compiled from Haskell or Lisp interpreter to be found. To any
         | reasonable person, that should be a strong signal about the so
         | called "power" and value of their sacred cow.
         | 
         | Put another way: the word language in the concept of
         | programming language isn't accidental and learning a niche
         | programming language is comparable to learning a niche human
         | language - have fun, expand your horizons, but don't pretend
         | it's useful.
        
           | Pannoniae wrote:
           | "Jesus christ you have so much disdain for such a large set
           | of people." - Correct. I kind of hate myself too. If everyone
           | is afraid to say these things or afraid to have a disdain for
           | bad things, nothing will improve. Things improve because some
           | people are pissed off enough to do something about it, not by
           | just going along with whatever.
           | 
           | "Have you ever considered that you might have a chip on your
           | shoulder about Haskell adoption?" - No. I barely use Haskell
           | myself. This could have been written about any other
           | language, my opinion would have been similar. I don't have a
           | strong emotional attachment to Haskell specifically.
        
           | yakshaving_jgt wrote:
           | Haskell isn't just used for small programs for computer
           | nerds.
           | 
           | Haskell is successfully used in industry, in some cases with
           | billions of users.
           | 
           | https://engineering.fb.com/2015/06/26/security/fighting-
           | spam...
        
           | vaibhavsagar wrote:
           | I personally use Vim, but Emacs alone is IMO the strongest
           | counterexample to your claim about Lisp interpreters
           | (followed by all the programs scriptable with Guile).
        
             | mathisfun123 wrote:
             | I mean I'm aware of emacs but I am also a vim user so I
             | proudly stand by my claim.
        
           | jamincan wrote:
           | > Sometimes I wonder if some language communities really are
           | cults. It's the same with Lisp - replace "type system" with
           | "homoiconic" and you have the exact same mantras about
           | ultimate supremacy and "intellectual" superiority. But the
           | proof of the pudding is in the eating and across probably 10
           | computing devices in my home, not a single one has any
           | Haskell or Lisp programs running on it. Lots of Java, C, C++,
           | Python, Rust, Bash, JavaScript, even Perl (probably) but not
           | a single binary compiled from Haskell or Lisp interpreter to
           | be found. To any reasonable person, that should be a strong
           | signal about the so called "power" and value of their sacred
           | cow.
           | 
           | Xmonad and pandoc are probably the most heavily used Haskell
           | programs. Not necessarily contradicting your overall point,
           | just exhibiting the two examples that someone might
           | reasonably be expected to run into.
        
             | mathisfun123 wrote:
             | fair enough - i don't use xmonad but i do use pandoc on
             | occasion. in full transparency: it occurred to me that i am
             | familiar with postgrest, though i've never run it
             | personally. still no lisp programs though!
        
               | littlestymaar wrote:
               | Isn't HN written in lisp?
        
               | Pannoniae wrote:
               | Arc, but I think it counts because it's a lisp-like....
        
               | mathisfun123 wrote:
               | and <looks around> what can we conclude from this?
        
             | doktrin wrote:
             | > xmonad
             | 
             | I got rid of xmonad in favor of i3 ages ago - precisely
             | because it doesn't force me to edit a Haskell script just
             | to change a keybinding. Obviously just my personal
             | anecdote, but this 'feature' alone probably accounts for a
             | significant % of users either jumping ship, or never
             | boarding it in the first place.
        
         | ceddiexd wrote:
         | Why use a programming language at all? Why not write everything
         | in machine code for that matter?
         | 
         | The point is that Haskell's position on the abstraction
         | spectrum is no less arbitrary than that of Go or C++. You
         | cannot divorce the relative advantages and disadvantages of
         | various levels of abstraction from the realities of
         | maintenance, development time, readability, complexity, and
         | yes, the fact that not everyone is as big brained as you,
         | because by not writing machine code, you have already
         | acknowledged that these realities matter.
         | 
         | I can just as easily come up with my own programming 'language'
         | where there's a 1-to-1 mapping between a countably infinite set
         | of characters and every unique Turing machine. Want to write a
         | program? Find the right character. This is the most terse, most
         | elegant programming language ever, but clearly helps no-one.
         | 
         | The best abstraction is the one that is the most universally
         | understood.
        
         | AnimalMuppet wrote:
         | Some programs live for _decades_. Some programs get worked on
         | after the original authors are gone. Code is written once, but
         | (if the program is worth keeping) read many times. Optimizing
         | for  "easy to write" is optimizing the 10% and ignoring the
         | 90%. Optimizing for "easy to read and understand by someone who
         | is not the original author" is _critical_ for important, long-
         | lived programs.
         | 
         | It's not "laziness". It's understanding that maintaining
         | software long-term is a really significant problem.
        
           | HelloNurse wrote:
           | Even when the maintenance is short term, there is also
           | optimization for making the expected type of changes quick
           | and/or easy to perform, something that appears particularly
           | hit or miss with language specific problems: having to fit
           | monad square pegs into typeclass round holes when two
           | libraries need to be used together, unexpectedly needing a
           | significant increase of sophistication and/or boilerplate to
           | support a generalization that should be small, finding a
           | compromise between conflicting preludes or incompatible
           | extensions.
        
           | erik_seaberg wrote:
           | The thing to optimize for is letting experts communicate with
           | each other clearly and concisely. I'm only going to be a
           | newcomer to a system for a short time, and any work while I'm
           | ramping up is not going to be very valuable.
        
       | xedrac wrote:
       | As a Haskell developer, this was hilarious! Thanks for the
       | laughs.
        
         | keyle wrote:
         | I'm not sure I follow, could you expand for non-Haskell
         | developers?
        
           | xedrac wrote:
           | Oh wow, when I originally clicked on the link, it took me
           | here:
           | 
           | http://steve-yegge.blogspot.com/2010/12/haskell-
           | researchers-...
           | 
           | I see why you were confused.
        
             | tuukkah wrote:
             | That submission is (now?) here:
             | https://news.ycombinator.com/item?id=37247754
        
       | porcoda wrote:
       | I 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 wrote:
         | For 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 wrote:
           | I'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.
        
       | draw_down wrote:
       | [dead]
        
       | agentultra wrote:
       | The 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 wrote:
       | This 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
       | 
       | 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 wrote:
         | The 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.)
        
           | chubot wrote:
           | Ah thanks for the answer, funnily enough that's what I
           | recently read here -
           | https://dev.realworldocaml.org/gadts.html
           | 
           | They have a bool / int expression language example. (And
           | funny thing I'm coding up such a type checker and evaluator
           | right now in TypeScript. TypeScript union types seem to be
           | pretty expressive and useful for this problem.)
           | 
           | However I'm STILL confused ... Admittedly I skimmed through
           | the GADT chapter and I didn't follow all of it, but I don't
           | understand why the answer isn't:
           | 
           | 1. have a untyped representation that allows (Add (Num 2)
           | (Bool False))
           | 
           | 2. write a type checker on that representation
           | 
           | 3. The output of the type checker is a new IR, which can only
           | express (Add 2 3) => Int and (Eq 5 (+ 3 2) => Bool
           | 
           | Is the more abstract GADT solution supposed to "save" you
           | some work of writing a type checker by somehow letting you
           | reuse Haskell or OCaml's type system to express that?
           | 
           | That's a little weird to me ... it seems to be confusing the
           | metalanguage and the language being implemented.
           | 
           | It's not surprising to me that this would go awry, because in
           | general those 2 things don't have any relationship (you can
           | implement any kind of language in OCaml or Haskell).
           | 
           | ---
           | 
           | Hmm OK I actually DID run into the issue where you need
           | dynamic checks in the evaluator, that should be impossible
           | BECAUSE the previous the type checking phase passed.
           | 
           | i.e. some of the rules you already encoded in the type
           | checker, end up as "assert" in the evaluator.
           | 
           | Hm I will think about that. There is some duplication there,
           | sure. But I still think there's a weird confusion there of
           | the language the compiler is written in, and what the
           | compiler DOES
           | 
           | You're kinda coupling the 2 things together, to avoid a
           | little duplication.
           | 
           | I also wonder how all that is actually implemented and
           | expanded into running code. The GADT syntax seems to get
           | further and further away from something I imagine can be
           | compiled :)
           | 
           | ---
           | 
           | edit: Thinking about it even more, although I did run into
           | the dynamic checks issue, I think it's because my type
           | checker only CHECKED, it didn't LOWER the representation. So
           | I think what I originally said was true -- if you want more
           | type safety, you introduce another simple IR. What's the
           | benefit of using GADTs ?
        
       | steno132 wrote:
       | If 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.
        
         | friend_and_foe wrote:
         | You'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.
        
         | yakshaving_jgt wrote:
         | This is nonsense.
        
       | rg111 wrote:
       | I 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?
        
         | iainctduncan wrote:
         | Dissenting vote: Scheme (or Racket).
        
         | yakshaving_jgt wrote:
         | Haskell.
        
           | GregarianChild wrote:
           | Among 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 wrote:
             | I 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...
        
         | rg111 wrote:
         | Thanks to everyone who answered.
         | 
         | And I now notice that autocorrect made Project -> Program. :/
         | 
         | I will keep a watch here for more responses.
        
         | consilient wrote:
         | Functional programming is not really a single paradigm. In
         | particular lisps and ML style languages are very different and
         | you should try both. Scala is still a C-style language at
         | heart, it's just much further along the borrowing ML features
         | path than most.
         | 
         | I'm not super familiar with the contemporary lisp landscape but
         | scheme is the traditional choice for teaching.
         | 
         | Among MLs I would definitely pick Haskell.
        
         | valenterry wrote:
         | Haskell. I prefer Scala as a language to do productive things.
         | But if you want to learn a pure functional style (that you can
         | apply in Scala later as well) then Haskell is better becaue it
         | _forces_ you into this style. Few other languages do that.
        
         | habitue wrote:
         | Learn 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"
        
       | nicechianti wrote:
       | [dead]
        
       | [deleted]
        
       | greydius wrote:
       | Anyone hiring Haskell devs?
        
         | icrbow wrote:
         | Yes. The amount of job postings raises year to year.
        
       | Shumer666 wrote:
       | First 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.
        
       | Shumer666 wrote:
       | First 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 wrote:
         | [flagged]
        
         | rendall wrote:
         | Definitely worth repeating!
         | https://news.ycombinator.com/item?id=37251323
        
       ___________________________________________________________________
       (page generated 2023-08-24 23:00 UTC)