1. 5

    I’m not sure why fewer than 200 people said they use Haskell at work in the previous question but more than 600 said they use Haskell at work at least some of the time in this question.

    Was the question “Where do you use Haskell?” multiple choice, or was the survey using radio buttons? Could be the source of the discrepancy.

    1. 5

      The “where do you use Haskell” question was multiple choice (check boxes). The “do you use Haskell at work” question was single choice (radio buttons).

      1. 3

        I had this same problem with State of Elm. The first go ‘round people told me that the binary yes-or-no was unclear because they felt they had to be using it in production. But that wasn’t my intent, so this year I tried to fix it by making the “where are you using Elm” question have the following choices:

        • I’m just tinkering
        • Don’t feel ready for production
        • No code in staging or production but feel capable
        • In development towards production
        • In production on a side project
        • In production at work (internal)
        • In production at work (user-facing)

        Next year I’m going to break it down even more. It turns out that a lot of things I thought were yes/no initially are actually sliding scales. (Except for “can I have your email” or really really specific and leading questions.)

        1. 1

          That is actually quite interesting, I’ve been tinkering with both Haskell and Elm at work but haven’t used them on any project meant for production.

          I usually experiment with a lot of languages for smaller side projects and when architecting a new product and evaluating tech choices, many of these are never put into production usage while some do.

    1. 15

      I was disappointed that there were no demographic questions - that’s a vital area which the Rust survey creators put a lot of work into. I expect it was due to the survey creators not seeing it as important enough to justify the effort of doing it right, which I know is considerable. I understand that decision, but it’s frustrating, because it’s very important to some of us.

      1. 16

        I agree that demographics are important! I definitely want to include them in next year’s survey. This is the first survey I’ve ever published. I didn’t want to get the demographic questions wrong or otherwise mishandle them. That’s why I decided to focus on the technical questions. The survey was developed in the open (see this issue); next year’s will be too. I would be delighted to have you help out with the demographic questions.

        1. 13

          Just copy ours :).

          Jest aside, we’re cool with anyone taking these questions like all our other open source output.

          Also, there’s a huge problem currently: most languages don’t run these kinds of surveys and then many don’t share a common core. It’s hard to read a lot from them.

          In case of Rust, we’re in the lucky position to actually have run two of them, so we can at least put this year’s number in relationship to last year’s.

          But for the rest? Are we doing better then language X? Worse? Only gut feeling.

          I don’t see this as a competition, there’s rarely been a structured approach to mapping communities.

          In any case, if you’d like to exchange experiences, please feel free to contact community-team@rust-lang.org

          1. 8

            I’m happy to hear that! And I’m also happy to be contacted to comment on concrete proposals, when next year’s survey is at that stage; I don’t have the bandwidth to be involved more than that.

            I suspect the team that did the Rust survey will also be happy to advise about these topics. I know they’ve talked about it a bunch here on lobste.rs, and those old discussions are still in the archives somewhere.

          2. -2

            You mean the part about “underrepresented groups” or whatever on the Rust survey? Why do you think that is important?

            One of my favorite things about the Haskell community is that everyone is too busy doing actual technically impressive stuff to worry about e.g. how many gay people happen to be using it.

            To be blunt, I think that sort of thinking (obsessing over whether an organic community follows one’s arbitrarily constructed ideals for what it should look like) is a cancerous mind-suck that detracts from actually productive work.

            To be a little more blunt, I think the fact that Haskell has a reputation as being extremely technical has actually helped the community a great deal, at least just by virtue of the fact that it scares away people who are primarily involved in software as a means to push some political agenda.

            Late edit: feel free to respond instead of just downvoting, would be happy to be wrong here.

            1. 33

              This is downvoted already, I’ll bite anyways. First of all, I think your comment shows that you have no idea what we are doing there.

              Gathering demographics questions is much more then what you narrow it down to. It’s telling that the only thing you can come up with is “how many gay people happen to be using it”? It’s also: where do people live, would they want to travel to a conference, etc… It cuts out the guesswork. You know what? When you measure, you also sometimes find out that things are just okay. No need to do something. Great! Sometimes, you find something odd. Then you might want to investigate. It’s a community survey. We want to know about people, not about technology. But social groups are also a thing to check.

              The Rust community also does production user surveys, which are die-hard technical and very detailed, usually specific in certain areas like embedded and or gaming. We seek out users willing to do that and set up meetings to figure out the issues.

              To be blunt, I think that sort of thinking (obsessing over whether an organic community follows one’s arbitrarily constructed ideals for what it should look like) is a cancerous mind-suck that detracts from actually productive work.

              To be blunt too: It’s shit that you call my work “not productive”. Here’s a thing: I don’t want to contribute to rustc or Servo. Why? I code all day, I don’t want to code at night. I’m happy that other people want to. I still want to contribute to FOSS. In the last 5 years, I’ve set up 2 foundations, 11 conferences and managed around 250000 Euros to run all these things. I signed leases that could have bankrupted me. I managed to find ways to run 2-days conferences that cost 100EUR and still cover all expenses of speakers, attendees and those that cannot pay 100 Euros. I love that work. People are indeed very fair about this. Those that have more give, those that don’t, don’t. And I want everyone to benefit from that. My whole work revolves around the question “Who’s not here, and why?”. It’s my hack. Nothing of that is fundamentally special, other people could have done it.

              And you know what? We measure. We don’t go out “hey, please do X because I think it works”. No, we go “hey, we did X and metric Y improved”.

              It’s also amazing how many people just need a “have you considered programming might be something for you?” and then just head of and learn it. But the question needs to be asked a couple of times.

              It’s shitty to go on an concern troll around people doing precisely that to better do “productive work”.

              There’s no way to get me to work on other things without paying me. And you know what I like about the Rust community? They don’t concern troll me. They go: cool, if that’s what you want to do, please do it for us. It’s not like I bind a lot of resources. Community work works best if you don’t have many cycles. We align on a goal and then we do a lot of footwork.

              Sure, there are cases where issues arise and social work becomes focus, but that’s fine. Interestingly, the work of community workers is often to talk about issues before they come a trashfire, go to reddit and subsequently to 4chan.

              There’s also the “fixed cake” fallacy at work here: The belief that if we expand our community beyond a certain group, another group has to take the impact. That isn’t the case. The cake is not fixed. The market for programming languages is growing in absolute terms, also our communities are growing in absolute terms. These are effect to be appreciated and taken into consideration.

              Different folk need to be addressed in different fashion and thats fine. These surveys give us a bearing in where we want to invest our time or where things just work.

              If you absolutely want to talk in programming terms, we’re profiling our work. I find it amazing that there is so much pushback when we actually check on our successes.

              It’s shitty of people to devalue that work. A work, which has to be said, is more often done by women and people of color in many communities. Many of which are masters of it.

              There’s two options here: I do this work within a community or I don’t. It’s as simple as that. No “more productive” trolling.

              I structured work on these issues is still “cancerous mind-suck” for you, then go ahead. But say it to my face when you meet me.

              To be a little more blunt, I think the fact that Haskell has a reputation as being extremely technical has actually helped the community a great deal, at least just by virtue of the fact that it scares away people who are primarily involved in software as a means to push some political agenda.

              I just leave this here:

              So I just met Simon Peyton Jones (creator of Haskell) and chatted with him for a bit. Asked him his thoughts on Rust and he said he thinks it seems exciting and he was jealous of the great community we have. Just thought I would let you guys know :)

              (From: https://www.reddit.com/r/rust/comments/5yo24a/meta_rust_jealousy/)

              This was, by the way, the best compliment I ever saw, I respect Simon very much.

              We have an awesome many people primarily interested in software working in the Rust community. But they don’t throw the community workers under the bus like you do. That’s why I run a 6-monthly Rust conference and not a 6-monthly Haskell conference.

              I love Haskell, but there’s reasons I’m not active there. Still, for anyone that wants to learn techniques and procedures, by all means get in touch.

              Communities don’t happen at random. They work through network effects and feedback and these can be moderated and improved.

              Finally, to be very blunt: you just cost me 45 minutes of community work, which I’d have preferred to fill with something productive.

              But I also think it’s worth putting it out for others to read.

              EDIT: I’d also like to state that I know quite some people in the Haskell community caring very deeply about this. haskell-cafe is still one of my inspirations for a cool space to make. But that space is intentional, not organic.

              1. 10

                Thank you very much for writing this. It will serve as a great resource the next time I spot a similar comment in the wild.

                1. 4

                  Found this thread late, but wanted to say thanks @skade for the consistently insightful commentary on community here, and for you work in the Rust community. I don’t work with Rust much, but on the occasions when I’m working on community-building, the Rust community is one of the first places I go to for examples of how to do it well.

                  1. 1

                    Thanks for responding.

                    It’s telling that the only thing you can come up with is “how many gay people happen to be using it”?

                    That’s the only demo data you put on https://blog.rust-lang.org/2017/09/05/Rust-2017-Survey-Results.html

                    Please, tell me how you thought that was “telling”.

                    But social groups are also a thing to check.

                    Check and… what?

                    The Rust community also does production user surveys,

                    Do you see me objecting to those?

                    To be blunt too: It’s shit that you call my work “not productive”.

                    Sorry you feel that way. I think a lot of things aren’t productive, including some things I do, so you shouldn’t take it personally.

                    In the last 5 years, I’ve set up 2 foundations…

                    Cool, but you don’t need to justify your relevance because I called one of your interests into question.

                    It’s shitty to go on an concern troll around people doing precisely that to better do “productive work”.

                    Actually, I wouldn’t say anything if I just thought you were just wasting your own time; further than that, I think obsessing over demos is actively counterproductive. The utility to the community is negative, not zero.

                    There’s also the “fixed cake” fallacy at work here: The belief that if we expand our community beyond a certain group, another group has to take the impact.

                    It’s not so much “taking the cake” as “ruining the cake”. If you “expand your community” to include demo-obsessed identity politicians, the community is going to become actively worse.

                    A work, which has to be said, is more often done by women and people of color in many communities.

                    Why did you feel this comment was relevant to the conversation? I have several hypotheses, but I’d prefer not to assume your motivations.

                    I structured work on these issues is still “cancerous mind-suck” for you, then go ahead. But say it to my face when you meet me.

                    Sure. I don’t have an aversion to arguing about the social costs of different activities in person any more than I do online.

                    That’s why I run a 6-monthly Rust conference and not a 6-monthly Haskell conference.

                    Right, that’s what I said earlier; something about Haskell pushes away people with demographic planning aspirations, which I like a lot.

                    Communities don’t happen at random… these can be moderated and improved.

                    This is just fundamentally untrue; most of the best communities are more or less spontaneous. Many communities I love (such as lobsters) are good precisely because they’re minimally moderated.

                    haskell-cafe is still one of my inspirations for a cool space to make. But that space is intentional, not organic.

                    The list is, afaik, unmoderated, and the Haskell IRC (one of the best chats on freenode) is also totally unmoderated. Your example is evidence against your claims.

                    1. 6

                      Communities don’t happen at random. They work through network effects and feedback and these can be moderated and improved.

                      This is just fundamentally untrue; most of the best communities are more or less spontaneous. Many communities I love (such as lobsters) are good precisely because they’re minimally moderated.

                      This is false for Lobsters, both historically and currently.

                      Speaking historically, you cut out the key phrase “network effects” from the quote. The Lobsters of early 2014 was a very different, nearly empty place. The current state of Barnacles is quite similar: low activity by any metric you care to measure (traffic, stories posted, comments, votes, etc.) and a negligible sense of community. Online communities start as failures and have to overcome the chicken-and-egg problem that it’s a waste of an individual’s time to participate until quite a lot of other people are already participating.

                      And on an ongoing basis, Lobsters requires daily attention to moderation and maintenance. Most of it is design, small edits, comments, and private messages. The rare, exciting things like deleted comments and banned users are the tip of an iceberg. It’s all the small, constant attention that keeps the positive feedback loops working to power a successful community instead of killing it. This is also true of Haskell-cafe.

                      The theme I take from your comments seems to be that the work you are unaware of doesn’t exist and, if it does, it must be worthless. I don’t understand that dismissive cynicism well enough to respond meaningfully to it, so all I can do is point out these surface-level inaccuracies.

                      1. 2

                        Lobsters requires daily attention to moderation and maintenance.

                        I seem to recall jcs saying that he never deleted anything if he could avoid it, and indeed that seemed to be the case. It seems that you are now taking a somewhat more active stance, but historically lobsters has had very little/none of what I would call active moderation.

                        Most of it is design, small edits, comments, and private messages… This is also true of Haskell-cafe.

                        SPJ sending out an email about being nice isn’t community moderation or management. Neither is general site maintenance. I’m not sure how you would conclude that I disagreed with any of these things unless we’re using very different definitions for a number of words.

                        The theme I take from your comments seems to be that the work you are unaware of doesn’t exist

                        I’m aware of all the examples you gave; they just aren’t the kind of obsessive, inorganic micromanagement I was objecting to.

                      2. 4

                        That’s the only demo data you put on https://blog.rust-lang.org/2017/09/05/Rust-2017-Survey-Results.html

                        I don’t get it. That page contains a bar chart with all sorts of demographic categories on it, just above “Diversity and inclusiveness continue to be vital goals for the Rust project at all levels.”

                        1. -2

                          Me:

                          e.g. how many gay people happen to be using it.

                          Guy who responded to me:

                          where do people live, would they want to travel to a conference, etc…

                          What kind of demo data do you see them sharing on that page? I’m not really sure what you’re confused about; you seem to be agreeing with me.

                          1. 7

                            The blog post is an editorialised overview, the 2016 one covers that. https://blog.rust-lang.org/2016/06/30/State-of-Rust-Survey-2016.html#survey-demographics

                            There have not been notable changes, so it wasn’t mentioned again.

                        2. 4

                          As the person who started the Haskell IRC channel and as an active moderator of said channel, moderation happens often. There’s a team of motivated users on the #haskell-ops IRC channel and we have to step in more than I’d prefer.

                          Good communities require much work and regular feedback.

                  1. 4

                    So far the comments I’ve shown have been personal attacks

                    Only 2 of the 6 comments up to the point this comment is made have anything personal in them. They seem to be “attacking” the concepts, not the person.

                    1. 6

                      Hi! Author here. Now that I’ve had some time to mellow, I wouldn’t call those “personal attacks”. At the time I was excited about functional pipelines (probably thanks to Elixir). No Haskell libraries provided the (|>) pipeline operator. I created Flow to fill that gap. I shared it on Reddit because I wanted to know why pipelines weren’t popular in the Haskell community. It got over 100 comments, which is huge for r/haskell. In my opinion, most of the comments were negative. They derided the library by calling it “backwards” or a “hurdle” or a “crutch” or “exactly what functional programming is trying to avoid”. I took those comments personally when I shouldn’t have.

                      These days I just import Data.Function ((&)) and wince a little every time I write (&) instead of (|>). It’s definitely not as popular as ($) and (.), but it’s hard to call it non-standard when it’s in the base package.

                      1. 2

                        I’ve always found the “backwards” notation of & a bit odd, but as you say in your post, different notations have different uses or people who prefer them. I know haskellforall has done some stuff with & around the “make Haskell look like OOP” experiments.

                        I mean, >>= is in this direction as the “default” so that’s not uncommon at all. I wonder if you could do some fun stuff with >>= and Identity

                        1. 2

                          I usually prefer (&) because it encourages iterative development. Start with some value, transform it, and keep doing that until you have the result you want. That’s how I usually work in GHCi. The alternative is to start at the “outside” and keep working in until you’re at the bottom. I find that way of developing to be better when I already have the type signature and I’m filling in typed holes.

                          Fun fact: You can use do notation with pure computations in Haskell.

                          f :: Int -> Int
                          f x = do
                            let y = x + 2
                            let z = x * 2
                            y + z
                          
                          1. 2

                            Yes, you can have non-recursive let!

                            test = runIdentity $ do
                                 (x,s) <- return $ foo 1 []
                                 (y,s) <- return $ bar x s
                                 (z,s) <- return $ baz x y s
                                 return (z,s)
                            
                            1. 2

                              I don’t understand what the big deal is, we read from left to right not right to left. It’s just a notational convenience I really don’t understand how people could get so conservative that they can’t even handle a different direction of function composition. If you wrote right to left, I could see that being a serious inconvenience though.

                        1. [Comment removed by author]

                          1. 10

                            The article would be half the length if I had skipped explaining the problem. I don’t see a good way around it. I did include a disclaimer early though. It kinda doesn’t help to explain the faster code if you don’t understand what the slower code did.

                            no good advice

                            Maybe you can tell me how to make the code faster? What are some general performance tips you commonly use that aren’t listed here.

                            This code has to be pure python and isn’t allowed any imports. Let me know if there’s something huge I missed.

                            You’re the second person to mention clickbait title. I’m curious what you were expecting when you clicked on the link. It’s about me making a function 5x faster in python when my main language is Ruby. I wrote it to be fairly literal.

                            1. 14

                              I don’t like the title because it’s phrased in a way that implies you’ve optimized Python code in general, when you’ve really just optimized a specific script. It also implies that it was your Ruby experience specifically that helped you optimize, but most everything you covered would apply in general.

                              I’m also always skeptical of blog posts like this that don’t make their full code available. Especially when the author is comparing between two languages, which you’ve implicitly done by constantly mentioning Ruby.

                              1. 6

                                Interesting. I had never even considered the title would make people think that. Did you think by “some Python code” I meant a specific subset?

                                The point of the article is that optimizing code is a general skill that can be applied to other languages. It’s supposed to be advise that applies to both languages.

                                Or at least that was what was in my head when I wrote it. I might have not mentioned those words.

                                The code I provided in the article is fully executable.

                              2. 7

                                I’m sure you know this, but for folks who don’t: in your code sample you have, for testing for ‘None’

                                if not value:  # <---------- aaaaaaaaaaaaaaaa noooooooooooo!
                                  return
                                my_list = [value]
                                

                                it should be

                                if value is None:  # <---- this is what you mean
                                  return
                                my_list = [value]
                                
                                1. 3

                                  Good catch, you want to be as specific as possible. The way I used would have caught False in addition to None.

                                  In ruby would be the difference between

                                  if value
                                  

                                  and

                                  if value.nil?
                                  
                                  1. 1

                                    Mostly. Except that non-nil values can define nil? as true in Ruby ;)

                                    1. 2

                                      Though in practice people don’t actually do that. Or rather I’ve never come across it in the wild in the last 10+ years of Ruby.

                                    2. 1

                                      also catches 0, [], {} etc. etc. all of which are not None. Importantly, different objects can have different rules as to when they evaluate to be False. I was bitten by this at work

                                      1. 2

                                        There’s also this related bug, which is a fascinating look into the perils of both implementing rules of thumb without thinking about them, and not thinking sufficiently about how time works.

                                  2. [Comment removed by author]

                                    1. 3

                                      if I knew you wrote that article I wouldn’t have made that comment.

                                      You’re not the only person to make this comment, so I appreciate the response. This is like the rabbit/duck image. I didn’t even realize there was another way of reading the title.

                                      I used to work phone support at my first job we were always trained “under promise over deliver”. It doesn’t do me any good to make you think I did something AMAZING then when you click the post it was really just okay. So it’s good feedback that the title is ambiguous.

                                      I tried to workshop the title a bit the best I came up with is “Lifelong Rubyist makes a Python script 5x Faster” still seems equally problematic though.

                                      I added a note early on to help maybe clarify things earlier hopefully.

                                      Several people have mentioned they thought the post was about me making the Python interpreter faster. That would have been pretty dang cool, but is not the case. This article is about how to write faster code using an interpreted language.

                                      1. 2

                                        I think the title is fine. It says “some Python code”, not “all Python code”.

                                1. 4

                                  I’m the author. Thanks for posting this! It’s not super useful right now because there are no GHC release candidates to test. But the general idea should be applicable when the GHC 8.2.2 release candidates roll around.

                                  1. 6
                                    1. 4

                                      While I don’t have a particular problem with these newsletters, I have heard feedback before that it isn’t appropriate to post them on a regular basis.

                                      1. 7

                                        I hear you! The last one of these I posted was issue 32, which was 24 weeks ago. I’d hardly call that regular ;)

                                        1. 12

                                          That seems reasonable to me. I have read this site many times a day for 3 years and hadn’t heard of this newsletter before. It seems really cool so thanks for the submission.

                                      1. 5

                                        For example doing this explicitly in Python is cumbersome:

                                        data = {"a": 1, "b": 2}
                                        
                                        if data["a"] is not None:
                                            return data["a"]
                                        else:
                                            return 0 # default return value    
                                        

                                        This is not how we do it in Python. if data["a"] is None is going to break if “a” is not in the dictionary, so instead we do:

                                        data = {"a": 1, "b": 2}
                                        return data.get("a", 0)
                                        

                                        … which returns the default if the key is absent and only does one look up.

                                        1. 4

                                          I was going to point this out as well. Unfortunately even get with a default value can still return None. For example, {'a':None}.get('a',0) is None, not 0.

                                          1. 2

                                            Ah thanks, I haven’t done Python in a while. I’ll update the article.

                                          1. 14

                                            I write Haskell for a living and prefer to use hspec. Less boilerplate, seems to incorporate different types of tests (unit, property, etc.) with less ceremony and hassle.

                                            1. 2

                                              I also prefer Hspec. I tried to use Tasty for a while because conceptually I like it better. Having separate providers (Hspec, QuickCheck, golden, …) and “ingredients” (formatters and runners) feels nice. Ultimately Hspec does everything I want and has better ergonomics.

                                              1. 1

                                                hspec is my favorite, too

                                              1. 5

                                                Can you guess Haskell’s type with the next shortest name (hint: three letters)?

                                                Pedant note: actually, there’s another two-character type, which is ->, i.e. a -> b is (->) a b.

                                                1. 5

                                                  There’s also ().

                                                  1. 5

                                                    Yep. And IO, ST.

                                                  2. 4

                                                    Nowadays, you might also consider *.

                                                  1. 6

                                                    The very same test, written in Haskell, wouldn’t compile!

                                                    That’s because the author used shouldBe, which (as they noted) is pure. If they wanted to do the same thing as the Python version, they could have used shouldReturn.

                                                      1. [Comment removed by author]

                                                        1. 1

                                                          Agreed! It makes a lot more sense to parse the JSON into some internal structure, then serialize that as XML. And for this particular example, you only need from_json and to_xml.

                                                        1. 9

                                                          So… a schism? A fork? A squabble?

                                                          Something is rotten in the State of Haskell?

                                                          Is this about people arguing about the website design or about cabal vs Stack?

                                                          1. 7

                                                            The sponsors are FP Complete and the Commercial Haskell Group, which are responsible for Stack and other industry docs/tools. The site announcement says:

                                                            In the opinion of the team behind haskell-lang.org, the tooling story and general ecosystem infrastructure for the Haskell community has accumulated enough baggage that a clean break is the best use of everybody’s time. We intend to streamline the on-boarding process for new developers, move away from infrastructure that is showing its age, and embrace newer approaches to facilitate open collaboration. Similar decisions have already been made in creating the Stack build tool and Stackage.

                                                            For the subreddit, one site creator writes:

                                                            Because /r/haskell has become a place of constant flamewars. We need a clean break. A new subreddit provides a fresh start allowing to mold a new community based on better principles. Everyone who wants to be part of the new community is invited to join the new Haskell movement. Troublemaker will hopefully stay behind

                                                            But earlier another said:

                                                            Just to give one concrete example to hopefully clarify a bit: the new subreddit is intended as a place to discuss topics specific to haskell-lang.org. I have full intentions of still being a participating member of /r/haskell, and (AFAIK) everyone else on the haskell-lang team feels the same way.

                                                            There’s some older conversation here, plus a current reddit thread and YC news thread.

                                                            1. 3
                                                              1. 2

                                                                I was confused by the confusingly similar name, shit. I can’t edit the post or I would. I’m sorry to anyone misled by my mistake.

                                                                Thank you for the correction.

                                                                1. 2

                                                                  Rabble_of_One ain’t me. I asked them why they chose a name similar to one I use.

                                                                  I didn’t make the site either.

                                                            2. [Comment removed by author]

                                                              1. 2

                                                                I’m FPComplete people now?

                                                                1. [Comment removed by author]

                                                                  1. 3

                                                                    OCaml is a little odd community-wise in that the official development is done pretty in-house by one tight-knit team (the one at INRIA). It’s getting more open now, but for years it was difficult to contribute if you weren’t part of the INRIA team, so it was basically expected that if you wanted to do significant development and were a third party, you’d do your own thing in your own repository. So Jane Street doing things separately didn’t break any implicit norm that you’re supposed to contribute to the main community effort.

                                                                    1. 2

                                                                      I’ve never been employed by them, but they do (useful) stuff and we seem to care about similar things.

                                                                      I’d noted how the OCaml community seemed to regard Jane Street before, the difference is astounding. I think OCaml being comparatively less popular and less of a totem for “gee I’m smart I use ${LANG}!” means that they’re more grateful when a company shares stuff with them.

                                                                      1. 1

                                                                        OCaml has room to improve. Haskell is already perfect, so this is an insult.

                                                                1. 5

                                                                  Is an ADT the same as a GADT?

                                                                  1. 11

                                                                    GADTs are what you get when you add non-syntactic type equalities to ADTs.

                                                                    Normal equality on types is generally considered to be syntactical equivalence modulo beta-reduction. Beta-reduction is the reduction rule (λx. e) e' → e[x/e'], aka function application. So for example, the types list a and list a are equivalent. So are the types (λx. list x) a and list a.

                                                                    Non-syntactic type equality is when the context influences type equalities. Let’s say in our scope we have a variable co with type (a ~ b), and we want to know if list a and list b are equivalent. The answer is yes, because we can use co to rewrite a to b. Types like (a ~ b) are called coercions, and if you have one in scope, that is proof of a particular equality.

                                                                    Here is an example from the link that @taylorfausak posted:

                                                                    data Expr a where
                                                                        I   :: Int  -> Expr Int
                                                                        B   :: Bool -> Expr Bool
                                                                        Add :: Expr Int -> Expr Int -> Expr Int
                                                                        Mul :: Expr Int -> Expr Int -> Expr Int
                                                                        Eq  :: Expr Int -> Expr Int -> Expr Bool
                                                                    

                                                                    This is syntactic sugar for the following:

                                                                    data Expr a = I Int (a ~ Int)
                                                                                | B Bool (a ~ Bool)
                                                                                | Add (Expr Int) (Expr Int) (a ~ Int)
                                                                                | Mul (Expr Int) (Expr Int) (a ~ Int)
                                                                                | Eq (Expr Int) (Expr Int) (a ~ Bool)
                                                                    

                                                                    That is, when you create an I, you have to supply a proof that the type variable a is Int. When you create a B, you have to supply a proof that the type variable a is Bool. Etc. When you perform a case on an Expr a you then get the appropriate coercions in scope for rewriting. This is how the evaluator from the link works:

                                                                    eval :: Expr a -> a
                                                                    eval (I n) = n
                                                                    eval (B b) = b
                                                                    eval (Add e1 e2) = eval e1 + eval e2
                                                                    eval (Mul e1 e2) = eval e1 * eval e2
                                                                    eval (Eq  e1 e2) = eval e1 == eval e2
                                                                    

                                                                    When we perform a pattern match and the case is I n, we return the Int n. But, we needed to actually return an a, per the type signature! No problem, we have a coercion from a ~ Int handy in our scope, and can use that to rewrite, and thus make the example type check. The other cases work similarly.

                                                                    Misc facts:

                                                                    • You can build coercions in languages with higher-kinded polymorphism. a ~ b can be represented using a Leibniz equality ∀f : ⋆ → ⋆. f a → f b.

                                                                    • Adding coercions to the type system makes type inference undecidable. This is why you generally have to supply a type signature on a function that uses GADTs.

                                                                    • Proving that two types are equivalent modulo a context is undecidable in the general case. Consider equalities between type functions, or, equivalently, between polymorphic types (a proof that ∀x. e = ∀x. e' isn’t much different than a proof λx. e = λx. e')

                                                                    For more information, System F with Type Equality Coercions may be useful.

                                                                    1. 4

                                                                      GADTS are Generalised ADTs, so they’re a more flexible version of the same idea.

                                                                      I’d like to do a follow-up on GADTs, but I want to find a good concrete example first. (One that isn’t a parser!)

                                                                      1. 1

                                                                        Heh… Every example I can think of is a parser. :)

                                                                      2. 3

                                                                        I can’t say I fully grok GADTs, but conceptually they seem similar. This page does a good job explaining the differences between ADTs and GADTs in terms of a concrete example.

                                                                        1. 1

                                                                          The way I understand it, all the “cases” in a regular ADT all have the same type. A GADT lets you define the “cases” such that different cases might appear differently to the type system, which allows you to make stronger guarantees (since you can, for example, abstract over subsets of the cases).

                                                                          For example, in @cmm’s expression example, you can tell the type system that a particular Expr “case” can only be built out of other Expr cases parameterized upon Int, rather than accepting any Expr case (and hoping for the best).

                                                                        1. 6

                                                                          I like that Jasper classified avoiding language extensions as a mistake. As he mentions, GHC is the de facto standard. And many of the useful extensions, like OverloadedStrings, are basically source transformations. My only complaint is that the Haskell language standard hasn’t kept up with the extensions, so you have to enable a lot to work in a comfortable environment. As Gabriel says:

                                                                          An idiomatic Haskell program is 20 lines of imports, 6 language extensions, and 1 line of Perl.

                                                                          1. 17

                                                                            they are still shipping a version of my software that I released in 2014

                                                                            That’s… not that old? Especially for a screen saver program. That’s been around since 1992.

                                                                            1. 9

                                                                              If memory serves, in the last year or so, there was at least one bug in the lock dialog that was fixed.

                                                                              When software has a critical vulnerability that is patched in a newer release, it becomes old instantly.

                                                                            1. 5

                                                                              From last time this was posted:

                                                                              If you’re a Haskeller interested in Frege, I compared them on my blog. My takeaway was this, more or less: “Frege is an interesting and well-executed idea that ends up being less useful than you might think.”

                                                                              1. 4

                                                                                I think that saying “algorithms that operate on the Virtual DOM” are a feature is analogous to saying “virtual DOM is a feature”. If the only way to do this stuff in a usable and fast way is to use a virtual DOM, then that’s a feature.

                                                                                1. 5

                                                                                  Thanks for the comment!

                                                                                  To your second point: The thing that surprised me and lead me to write this up is that Virtual DOMs are not “the only way to do this stuff in a fast and usable way”, they are the only way to build declarative UIs on the web, period. The declarative UI is the feature there to me, not the Virtual DOM implementation detail.

                                                                                  I don’t know about your first sentence – do you consider algorithms that operate on an Array features of the Array, or features themselves? The algorithms React uses to make diffing fast are not a necessary part of using Virtual DOMs, they’re the tech React brings to the table to make sure your UI can become very complex and remain very responsive.

                                                                                  1. 2

                                                                                    do you consider algorithms that operate on an Array features of the Array, or features themselves?

                                                                                    Both, in a way. If an algorithm requires a feature that arrays provide, like fast random access, then I would consider it a feature of an array. But if an algorithm works on linked lists the same as arrays, then I’d consider that a feature by itself.

                                                                                    1. 1

                                                                                      I can get on board with that. I updated the post title, and if I could fix the title on lobsters I would :)

                                                                                  2. 2

                                                                                    “Feature” is hard to define. :) But I still found this piece to be a really nice explanation of the motivating pressures for the virtual DOM to exist.

                                                                                    1. 2

                                                                                      Thanks! And yeah! “feature” was probably a poor word choice. “Virtual DOM is not an optimization” is really what I mean.

                                                                                      edit: updated the post’s title, but can’t find out how to change it on Lobsters. Do you know where I can find that button?

                                                                                      1. 1

                                                                                        Yeah, Lobsters doesn’t have that sort of edit feature, though jcs is active and can change things when it’s important. This probably doesn’t really affect anything, but shrug.

                                                                                  1. 3

                                                                                    His rationale makes sense, but I don’t understand why he returns an HTTP 500 error instead of a 400.

                                                                                    1. 1

                                                                                      His article is exactly about this: he doesn’t want to maintain the code distinguishing between the two because the distinction, while being marginally useful to the client, is also dangerous for the server. And the context of the whole exercise is that the client is expected to be evil, so there’s no point in helping it in the slightest.

                                                                                      More often than not the aversion to 500 errors is based on the premise that it’s a server programmer’s error and is thus embarrassing. This leads to attempts to carefully validate all inputs before any underlying framework/library code and respond with a “proper” 400. But this is just needless extra work: if you have a 500 error than something in your stack is already refusing the user input, and there’s no security hole as there’s no meaningful action arising from it.

                                                                                      1. 6

                                                                                        I agree that returning a 500 isn’t a security hole.

                                                                                        I don’t avoid 500s because I think they’re embarrassing. I avoid them because they’re the same as returning ? to the client in that they don’t tell you anything. As others in this thread have pointed out, that’s probably fine if you’re the only client. But if I’m writing an integration, I want to be able to tell the difference between sending an invalid request and the server exploding.